Trying to find memory leak in my java swing code - java

I have a sizable Java app that creates complex data structures describing a drawing, starting with the raw time-stamped data points and displaying the drawing, analyzing it, etc.
When I try to process a series of these drawings, I'm clearly hanging on to memory in the form of a JScrollPane that's used to hold the drawing, but I cannot figure out why. The variable holding the scroll pane is reassigned with each new file loaded, but I noticed that the swing RepaintManager is maintaining a list of the previously displayed panes in its invalidComponents list. This seems then to hang onto the storage for each drawing, and before long I've got 1GB of memory in use when I'm processing files serially and should thus never have more than one drawing's worth of memory in use.
I got a memory dump and have analyzed with the Eclipse memory analyzer and with YourKit.
Here's what I believe to be the smoking gun as displayed by Eclipse's memory analyzer:
Have spent quite a while trying to drill down into this problem. I would be most grateful for any suggestions about where my error may lie or how to work around the problem.
I realize it's difficult to tell without being able to dig into the code, but if there are even any general suggestions/cautions about where to look, that would be great.

As #MadProgrammer suggests, your present code presumably replaces the existing JScrollPane instance:
scrollPane = new JScrollPane(view);
Instead, update the viewport component via setViewportView():
scrollPane. setViewportView(view);
Even better, update the content of view directly. Details would depend on your implementation, but validate() and repaint() represent one approach.

Related

Avoiding out of memory in Codename One

I am in the same situation as the one depicted in this SO question. Indeed my app relies massively on URLImage and also uses SidePanel for navigation. After a while it becomes unusable because of OOM thrown when I press the back button (Android).
So I need advices to avoid these OOM errors. A first advice was given in the above mentionned question, that is to not pass reference to any element from the previous form.
Indeed I was passing the whole form because I wanted to know from where the "generic" next form was called (to know where to go when the user clicks on the back button). So I changed that and now pass the Form's class (myForm.getClass()). However the performance monitor still shows more than 200 MB as "image memory overhead".
So maybe the problem is elsewhere since I need to also pass custom objects. Indeed I have a form A which lists all Reports in an InfiniteScrollAdapter. The Reports are fetched from a server. Then when the user clicks on a row, it opens the selected Report details (date, image, location, ...) in another form (B), and finally if the user clicks on the image or on the location it opens another form with the image in big size or a Google Map of the location.
If it is not possible to pass in those Reports, how can I do, or does the problem really come from these passed in references ?
Any help really appreciated ;-)
I'm guessing you are using problematic images and too many of those without releasing them. A good tool to use is a memory profiler, I use the one in NetBeans which allows you to dig thru the allocation stack and see which code allocates which memory block.
I'd also suggest reading about the various types of images in the developer guide graphics section and the performance section (which discusses memory too). To sum this up make sure your images are sized correctly and are EncodedImage or a variation of those. You might want to unlock() unused encoded images so the GC can act more aggressively on them.
Once you narrow the leak to a specific set of images it should be much easier to give specific advice on how to manage this.

Large amount of data deletion

I have a program with GUI with segment that can be large and contain a lot of objects. One of the features of my program is to "close" that segment and create a new one.
This whole segment is attached to the program by only one JPanel and an ArrayList. If I dispose of/set those two to null there should be no way to access the any of the JPanels childen (one of which are complex object extending GUI components, but also containing a lot of variables).
If I'm correct, all of JPanels childeren will be collected by garbage collector.
However, what happens to the children of the children? I have some "families" that go up to 5-6 "generations". Will they be deleted only upon GC's 5th (or 6th) pass, or will it detect the whole "family" as unacessible and collect it all at once (or upon it's first pass)?
EDIT: Another minor question: Is there a method for swing component that will remove all of it's children?
For an empirical approach, exercise your program repeatedly and look for the pattern shown here, in which the memory consumed fails to return to baseline.
In contrast, this example returns to the baseline after each cycle.
The comments to your question do a good job of addressing the deletion issue. But, if you're still curious about removing a component's children without removing the component, the answer is no, as seen in the JComponent documentation (I'm assuming you're on Java 7, if not you can easily change to the proper version of Java). If you want to quickly and easily remove just the children from a component without removing the component itself, I recommend just re-initializing the component.

high cpu load during rendering

I am rendering rather heavy object consisting of about 500k triangles. I use opengl display list and in render method just call glCallList. I thought that once graphic primitives is compiled into display list cpu work is done and it just tells gpu to draw. But now one cpu core is loaded up to 100%.
Could you give me some clues why does it happen?
UPDATE: I have checked how long does it take to run glCallList, it's fast, it takes about 30 milliseconds to run it
Most likely you are hitting the limits on the list length, which are at 64k verteces per list. Try to split your 500k triangles (1500k verteces?) into smaller chunks and see what you get.
btw which graphical chips are you using? If the verteces are processed on CPU, that also might be a problem
It's a bit of a myth that display lists magically offload everything to the GPU. If that was really the case, texture objects and vertex buffers wouldn't have needed to be added to OpenGL. All the display list really is, is a convenient way of replaying a sequence of OpenGL calls and hopefully saving some of the function call/data conversion overhead (see here). None of the PC HW implementations I've used seem to have done anything more than that so far as I can tell; maybe it was different back in the days of SGI workstations, but these days buffer objects are the way to go. (And modern OpenGL books like OpenGL Distilled give glBegin/glEnd etc the briefest of mentions only before getting stuck into the new stuff).
The one place I have seen display lists make a huge difference is the GLX/X11 case where your app is running remotely to your display (X11 "server"); in that case using a display list really does push all the display-list state to the display side just once, whereas a non-display-list immediate-mode app needs to send a bunch of stuff again each frame using lots more bandwidth.
However, display lists aside, you should be aware of some issues around vsync and busy waiting (or the illusion of it)... see this question/answer.

Understanding Java Swing screen buffer memory usage (reading materials would be welcome)

So I need to understand how swing allocates memory for buffering screen rendering. Obviously there are duplicates if you have double/tripple/etc buffering. However I would need to know when swing allocates memory and how much of it. Very helpful to know if I have multiple windows open (launched from the same jvm) how much memory is needed depending on windows being maximized to one screen, multiple screens (I need it to go up to 6 screens), etc.
Does anyone know of any good readings or maybe have answers for how Java Swing/AWT allocate memory for rendering buffers.
End of the day, I am looking for a definitive formula so that if I have a number of windows opened, number of buffers in each window, location of windows, and size of each window I can get an exact byte count required to render the application (just the buffering part, the rest of the memory is another problem)
I was assuming it was (single buffered) x by y of each window = 1 buffer, add those together and you have all memory requirements, but profiling the data this appears to be far from the truth, some buffers are weak/soft references, some strong, and I cannot determine the way to calculate (yet :)).
Edit: I am using JFrame objects (for better or worse) to do my top-level stuff.
Double buffering is a convenient feature of JPanel, but there will always be a significant platform-dependent contribution: Every visible JComponent belongs to a heavyweight peer whose memory is otherwise inaccessible to the JVM.
If you're trying to avoid running out of memory, pick a reasonable value for the startup parameters and instruct the user how to change them. ImageJ is a good example.
I'd recommend JConsole and the Swing Source code fro this kind of precision.
I assume you realize this will be extremely tedious to calculate since you have to consider every object created somewhere in the process, which of course will depend on the controls involved in the UI.
I am not aware of any automatic screen buffering support in Swing. If you need double buffering, you need to implement it yourself in which case you will know better how to calculate memory requirements :-)
See this answer: Java: how to do double-buffering in Swing? for more information and good pointers.

Swing: what to do when a JTree update takes too long and freezes other GUI elements?

I know that GUI code in Java Swing must be put inside
SwingUtilities.invokeAndWait or SwingUtilities.invokeLater.
This way threading works fine.
Sadly, in my situation, the GUI update it that thing which takes much longer than background thread(s). More specific: I update a JTree with about just 400 entries, nesting depth is maximum 4, so should be nothing scary, right? But it takes sometimes one second! I need to ensure that the user is able to type in a JTextPane without delays. Well, guess what, the slow JTree updates do cause delays for JTextPane during input. It refreshes only as soon as the tree gets updated.
I am using Netbeans and know empirically that a Java app can update lots of information without freezing the rest of the UI.
How can it be done?
NOTE 1: All those DefaultMutableTreeNodes are prepared outside the invokeAndWait.
NOTE 2: When I replace invokeAndWait with invokeLater the tree doesn't get updated.
NOTE 3: Fond out that recursive tree expansion takes far the most time.
NOTE 4: I'm using custom tree cell renderer, will try without and report.
NOTE 4a: My tree cell renderer uses a map to cache and reuse created JTextComponents, depending on tree node (as a key).
CLUE 1: Wow! Without setting custom cell renderer it's 10 times faster. I think, I'll need few good tutorials on writing custom tree cell renderers. Sadly, I need a custom cell renderer.
This tutorial involving lazy loading might help, I'll work this through.
[There are some details missing, such as: what type of processing is happening each time the user updates the JTextPane? Is the whole tree being rebuilt?]
Anyway, what has worked for me in the past (when I experienced significant slowdown due to JTree updates) is that I rolled out my own TreeModel.
Most programmers choose to use DefaultTreeModel. This is indeed an off-the-shelf solution that works well in most cases. However, it is quite slow when significant parts of the tree needs to be updated. Obviously, Writing your own TableModel is more work than using a canned solution, but it is much less painful than you think.
In particular, my custom tree model is fast because it does not build any tree, per-se. It just observes my domain model and computes the answers to the method invoked on it (getChild(), getParent(), ...) by extracting the relevant information from that model. Try it. It works like a charm.
I do not know why it only works with invokeAndWait() (this is strange), but a simple hack would be to invoke this method in a new background thread.
I would also advise you not to populate all the tree at once. This is often a huge amount of work that just cannot be easily sped up. Instead, update only those nodes that are visible and update more nodes as the user expands them.

Categories

Resources