i dont have my laptop with me so i will try to explain in english. i have a paint program. it works fine unless the user draws freehand for a long time. then it runs out of memory. calling gc() doesn't help. here is how it goes(simplified).
BufferedImage temp;
mouseDragged() //mostly done in PaintComponent()
{
draw temp if it is not null
draw a line
create image by painting the JPanel to a BufferedImage
assign it to temp
}
mouseReleased()
{
add temp to the ImageStack
}
as you can see many BufferedImages are created just so they can be drawn on the JPanel. only on mouseReleased() does one get saved. the others are all garbage. as far as i can tell they are no longer referenced, but the garbage collector just lets them run the app out of memory. any ideas?
i dislike gc() more and more. it just lets the program crash rather than reclaiming garbage. i know that usually there is a better way to write your code to avoid this, but i have no idea how to do it in this circumstance. in C++ we had to do it ourself(long time ago, can't remember how). can't we do that in java too? there might be a better way to do what i am trying to do, but i don't see it.
Randall Twede wrote:i dislike gc() more and more. it just lets the program crash rather than reclaiming garbage. i know that usually there is a better way to write your code to avoid this, but i have no idea how to do it in this circumstance. in C++ we had to do it ourself(long time ago, can't remember how). can't we do that in java too? there might be a better way to do what i am trying to do, but i don't see it.
The garbage collector will not throw an out-of-memory error, unless it runs a full GC and can't reclaim the memory needed. And this is regardless of whether you call the gc() method or not.
Henry
William Brogden
,
Author and all-around good cowpoke
Henry Wong wrote:
The garbage collector will not throw an out-of-memory error, unless it runs a full GC and can't reclaim the memory needed.
It can calso throw one if the JVM is spending more than 95% of its cycles doing GC and reclaims less than 5% of the heap as a result. Or something like that. The numbers are configurable by JVM startup args.
y'all have been very helpful. especially William. that is probably my problem. although i do have a line g2d.dispose().
i will post some code when i am here at the library with my laptop.
Henry, maybe i just think the images are available for collection, i think they are. i will post some code when i can.
I might be wrong, but I'm looking at the API, and it seems like ImageStack does exactly what it says on the tin:- It keeps a stack of Images. So, if you add the image to the stack every time the mouse is released, the number of images in the stack would grow over time until you run out of memory
Not saying that there might be other memory leaks. But, this could be also a potential issue where your application will hog memory. This is something you wil run in C++ too. If you keep building images in a stack, you won't be able to release them, and then you will run OOM
i'm sorry i did not realize java had a class called ImageStack. i wrote my own. when i first discovered this problem i did limit it to 50 images. i don't think that is the problem though(limiting it did not help). i think it is the intermediate images i create just to display in the JPanel, not the stack. i could be wrong, maybe even 50 images are too many.
Randall Twede wrote:what happens if the JVM finds two classes with the same name?
Depends on the classloader. The "normal" ones just take the first one they find in the classpath. You could write your own classloader though that takes the last one, or throws an exception if the classpath contains multiple classes with the same name.
And note that for this question to make any sense, "name" has to mean "fully-qualified name." Two classes called "List" is not a problem for the JVM, as long as they're in different packages, though it might be confusing for a human programmer.
Java provides some excellent options and utilities to analyze such issues (OutOfMemoryError).
Personally, I prefer to use JVM option which gives a heap dump if OutOfMemoryError occurs (-XX:+HeapDumpOnOutOfMemoryError).
Further, this dump can be analyzed by jhat utility. This gives a nice overview of various objects and memory consumed by them (at the time of OutOfMemoryError).
Also, you can have exactly same package structure and same class name (in two separate jars). During such case, the class which appears first in classpath will be loaded by class-loader. However, it is not recommended to reuse same class names.
With enough "points" / lines, the code could run out of memory in mouseDragged. You may need to limit the number of points / lines to be added, or increase the amount of JVM memory available.
well, the Image Stack was the culprit. i tested it again. maximizing the program to make large images, and it added 49 of them before it ran out of memory
the ImageStack is for the undo button. nobody will hit that 50 times in a row, so 20 or 15, or even 10 will be ok
i should have never doubted the garbage collector. it is doing a fine job of cleaning up the temporary images. drawing freehand actually had nothing to do with the problem.
Yes this is why a lot of old school apps limited the number of times you could undo. There is just not enough space to keep the undo buffer
You might want to rethink your design a bit. Keeping the entire image in the undo buffer seems overkill. You can just keep a vector of points in your undo buffer, and redraw everything when the user undoes. OR you keep an image for every 10 items in the buffer, and the vector for the 10 items. If you refrain from keeping a huge stack of images, you will need less memory.
Post by:autobot
Every time you till, you lose 30% of your organic matter. But this tiny ad is durable:
a bit of art, as a gift, that will fit in a stocking