Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

java.lang.OutOfMemoryError:Java heap space

 
Jc Frane
Ranch Hand
Posts: 42
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Good day!

I am currently working on a project, and I am using JavaFX.

I have my interface which has 5 transitions into it. And these are follows:

Home Screen: Which contains few components
Maintenance Screen: Which contains many components such as accordion, table views, tabbed pane and many more
Transaction Screen: Contains of 3 buttons with Images embeded onto it.
Reports Screen: Contains of buttons which have css embedded into each.
Settings: Which currently, do nothing significant yet.

NOTE: every screens(panes including panes inside my accordion) contains 600 x 400 png image as its background

(I am sorry, I really want to get into details)

What handles my transitions is a HashMap. So heres the code for the Transition Class:




And this is the code for maintenance button:



I really think, that every time I load these screens into HashMap it consumes a large amount of memory. Actually I also keep track of it.

This is the actual memory details before my programs generate an OutOfMemoryError:

Used Memory: 253244032
Free Memory: 6278208
Total Memory: 259522560


So my question is this:

How can I free Memories that have been used which I dont need anymore, every button click?

Thank you so much!



 
Roger Sterling
Ranch Hand
Posts: 426
Eclipse IDE Fedora Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Set all your local variables to null after you are done. If you do not do this, the garbage collector won't clean them up. You must do this for all referenced references (ie. those objects you store in a HashMap need to be cleaned up (nulled out) before you null the HashMap; which implies you have to iterate through the contents of the HashMap, removing each object and nulling it out).

http://stackoverflow.com/questions/5690309/garbage-collector-in-java-set-an-object-null

http://www.glenmccl.com/perfj_010.htm

http://www.ibm.com/developerworks/library/j-jtp01274/index.html

These days object scopes are static or otherwise broadly scoped and nulling is necessary in these situations, which is often. The old timers that claim this is not necessary do not understand the root cause of the problem, which in more modern JVMs (6&7), the gc is not sure which objects are still reachable and which objects are no longer reachable. This means if your code worked in JVM V5, it will likely fail with out of memory exception in V6 or V7.

Rewrite this function to use variables instead of directly instantiating:



new KeyFrame is a heap memory leak because you don't clean it up.

Use MAT to help you see other leakage (works only on Sun JVMs not IBM : IBM has its own toolset).
 
Paul Clapham
Sheriff
Posts: 21581
33
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What you say about assigning null to variables to help out the garbage collector may or may not be true -- I'm one of those old-timers who you diss there so what do I know? And also we're talking about JavaFX, which might work differently. However in this code:



it's extremely likely that the Timeline object created there stores references to those KeyFrame objects, so describing that as a "memory leak" is quite misleading. And creating new variables which also refer to the KeyFrame objects can hardly speed up their garbage collection, since then you have more rather than fewer references to them to deal with.
 
Roger Sterling
Ranch Hand
Posts: 426
Eclipse IDE Fedora Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul Clapham wrote:What you say about assigning null to variables to help out the garbage collector may or may not be true -- I'm one of those old-timers who you diss there so what do I know? And also we're talking about JavaFX, which might work differently. However in this code:



it's extremely likely that the Timeline object created there stores references to those KeyFrame objects, so describing that as a "memory leak" is quite misleading. And creating new variables which also refer to the KeyFrame objects can hardly speed up their garbage collection, since then you have more rather than fewer references to them to deal with.


The key to the puzzle is visibility into the heap, using the linked tools. Once you understand the classes that are leaked, you will know what nut to crack to solve the problem.

No offense intended, so please don't ascribe any. JRE 5 does things one way, JREs 6/7 do things differently and make different assumptions than previous JREs. This demands more work (less laziness) from software developers in that you cannot instantiate objects in-line any longer, and must be diligent about explicit cleanup. Some people don't accept this, and those people generally encounter OOM sooner rather than later.
 
Paul Clapham
Sheriff
Posts: 21581
33
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roger Sterling wrote:The key to the puzzle is visibility into the heap, using the linked tools. Once you understand the classes that are leaked, you will know what nut to crack to solve the problem.


This part I agree with completely. If you're out of memory then fire up the tools to find out what is filling up the memory.

JRE 5 does things one way, JREs 6/7 do things differently and make different assumptions than previous JREs. This demands more work (less laziness) from software developers in that you cannot instantiate objects in-line any longer, and must be diligent about explicit cleanup. Some people don't accept this, and those people generally encounter OOM sooner rather than later.


This is something I hadn't heard about, and I've been hanging about Java forums for a long time. Do you have links to any papers about the subject? (Apart from the Stack Overflow link you posted, which doesn't mention this feature, the other two links you posted were extremely ancient and didn't mention it either.)
 
Jc Frane
Ranch Hand
Posts: 42
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can I know If I could solve this problem by increasing the heap size?

Thank you so much for your answers, really appreciated it.

I think I should be careful enough in coding, maybe my code structure is the problem and I instantiate too much objects without freeing them up.
 
Paul Clapham
Sheriff
Posts: 21581
33
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Increasing the heap size? That might help, or it might not. If the memory required increases continually over time, then you've got what is loosely called a "memory leak" and no value of heap size will be large enough. And yes, a common way of achieving that is by putting an unbounded number of entries into a container. On the other hand it might be the case that the maximum memory required is finite, but just happens to be more than what you're currently assigning to the heap. It shouldn't be hard for you to use a larger heap size and see what happens, should it?
 
Roger Sterling
Ranch Hand
Posts: 426
Eclipse IDE Fedora Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jc Frane wrote:Can I know If I could solve this problem by increasing the heap size?

Thank you so much for your answers, really appreciated it.

I think I should be careful enough in coding, maybe my code structure is the problem and I instantiate too much objects without freeing them up.



Increasing heap size will only create a bigger window, but not solve the root cause. You need to use the toolset linked above "MAT" to actually do "troubleshooting and analysis" to determine which parts of your code are ill-formed (we already let you know about the ills of instantiating).

You actually need to do real work to get the right answer. That is, you need to run the MAT tools and examine the output of the MAT tools then hypothesize based on which classes are leaking memory.

Developing good software involves alot more than actually writing the application code. You not only need to write the code for the application, but you must also test that code in a variety of environments to see how it performs. When you have tested it, you should go back and amend your code based on the test results, in this case the test revealed that you are leaking memory. So you need to fix that problem.

Taking a wild swing at changing the heap size without actually thinking through the problem does nothing but distort your view of the problem. Don't use a shotgun to kill an ant or a fly. Shotgunning wild ideas usually only makes things worse (leaves big gaping holes in your code that shouldn't be there). DO your homework, come up with a hypothesis as to root cause based on empirical evidence gathered in your troubleshooting phase, and then make a small code change to see if the situation improves, worsens or stays the same.
 
Roger Sterling
Ranch Hand
Posts: 426
Eclipse IDE Fedora Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul Clapham wrote:
Roger Sterling wrote:The key to the puzzle is visibility into the heap, using the linked tools. Once you understand the classes that are leaked, you will know what nut to crack to solve the problem.


This part I agree with completely. If you're out of memory then fire up the tools to find out what is filling up the memory.

JRE 5 does things one way, JREs 6/7 do things differently and make different assumptions than previous JREs. This demands more work (less laziness) from software developers in that you cannot instantiate objects in-line any longer, and must be diligent about explicit cleanup. Some people don't accept this, and those people generally encounter OOM sooner rather than later.


This is something I hadn't heard about, and I've been hanging about Java forums for a long time. Do you have links to any papers about the subject? (Apart from the Stack Overflow link you posted, which doesn't mention this feature, the other two links you posted were extremely ancient and didn't mention it either.)



There are ample documents available, and Google works wonders.

Beginning with the J2SE 1.2, the virtual machine incorporated a number of different garbage collection algorithms that are combined using generational collection. While naive garbage collection examines every live object in the heap, generational collection exploits several empirically observed properties of most applications to minimize the work required to reclaim unused ("garbage") objects. The most important of these observed properties is the weak generational hypothesis, which states that most objects survive for only a short period of time.
Short period of time means its up to the developer to terminate the life of objects he or she is no longer using.

http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html

Typically some fraction of the surviving objects from the young generation are moved to the tenured generation during each minor collection. Eventually, the tenured generation will fill up and must be collected, resulting in a major collection, in which the entire heap is collected. Major collections usually last much longer than minor collections because a significantly larger number of objects are involved.


Thus, the problem becomes a lack of diligence from the developer that forces memory to remain reachable (tenured) by not setting the object to null. Another form of laziness by developers is the practice of using 'static' keyword everywhere. Developers should be skilled at using Singleton patterns for many places where they use 'static'. But that's another story...

Analyzing and troubleshooting the heap requires effort :
If garbage collection becomes a bottleneck, you will most likely have to customize the total heap size as well as the sizes of the individual generations. Check the verbose garbage collector output and then explore the sensitivity of your individual performance metric to the garbage collector parameters.


The default settings are only a starting point.
The command line option -verbose:gc causes information about the heap and garbage collection to be printed at each collection. ... A number of parameters affect generation size.


Other tools one can use to see the gc in action are jconsole and How to Find Memory Leaks.

Java™ SE 7 Update 4 Release Notes wrote:
New Supported Garbage Collector: Garbage First (G1)

Starting in Java SE 7u4 the Garbage First Collector is fully supported. The G1 collector is targeted for applications that fully utilize the large amount of memory available in today's multiprocessor servers, while still keeping garbage collection latencies under control. Applications that require a large heap, have a big active data set, have bursty or non-uniform workloads or suffer from long Garbage Collection induced latencies should benefit from switching to G1. For more detailed information about G1 see the G1 documentation page and command line options.


Getting Started with the G1 Garbage Collector

Understanding G1 GC Logs


Check when an object will be reclaimed.


 
Paul Clapham
Sheriff
Posts: 21581
33
Eclipse IDE Firefox Browser MySQL Database
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm sorry, but nothing I saw there supported the idea of assigning null to local variables to help out garbage collection. And nothing I saw supported the idea that garbage collection was "improved" in Java 6 in such a way that unreferenced objects would now fail to be collected, where they would have been collected in Java 5. I'm sure there's a lot of information out there but these were the two assertions you made which I was questioning.

So if you could point out some specific sources for those assertions I would be grateful.
 
Roger Sterling
Ranch Hand
Posts: 426
Eclipse IDE Fedora Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul Clapham wrote:I'm sorry, but nothing I saw there supported the idea of assigning null to local variables to help out garbage collection. And nothing I saw supported the idea that garbage collection was "improved" in Java 6 in such a way that unreferenced objects would now fail to be collected, where they would have been collected in Java 5. I'm sure there's a lot of information out there but these were the two assertions you made which I was questioning.

So if you could point out some specific sources for those assertions I would be grateful.


I'm just too tired this Friday afternoon to do your leg work for you. You'll have to fire up Google for yourself, or actually study the links I already provided. G1 was introduced in JRE 7 which changed the way gc works and arguments you use to customize what you want.

As for nulling :

Assign null to Variables That Are No Longer Needed

Sun Java System Application Server 9.1 Performance Tuning Guide wrote: Explicitly assigning a null value to variables that are no longer needed helps the garbage collector to identify the parts of memory that can be safely reclaimed. Although Java provides memory management, it does not prevent memory leaks or using excessive amounts of memory.

An application may induce memory leaks by not releasing object references. Doing so prevents the Java garbage collector from reclaiming those objects, and results in increasing amounts of memory being used. Explicitly nullifying references to variables after their use allows the garbage collector to reclaim memory.

One way to detect memory leaks is to employ profiling tools and take memory snapshots after each transaction. A leak-free application in steady state will show a steady active heap memory after garbage collections.



Use MAT (for Sun JVM) or IBM Support Assistant (for IBM JVM) to analyze your memory situation and learn what classes are creating leakage.

Here is some commentary by the Performance Lead developer that worked on G1, Monica Beckwith :



About the Author

Monica Beckwith is the performance lead for Garbage First Garbage Collector. She has worked in the performance and architecture industry for over 10 years. Prior to Oracle and Sun Microsystems, Monica lead the performance effort at Spansion Inc. Monica has worked with many industry standard Java based benchmarks with a constant goal of finding opportunities for improvement in Oracle's HotSpot VM.



If you are still having difficulty, type http://www.google.com in your browser, and then the little white box in the middle, type this : ' g1 jre 7 '. Life is a box of chocolates. That's all I have to say about that.
 
Paul Clapham
Sheriff
Posts: 21581
33
Eclipse IDE Firefox Browser MySQL Database
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Any advice which suggests assigning null values to variables to help out garbage collection which fails to discuss the difference between class-level variables and local variables, is not very helpful advice in my opinion. There's a significant difference in the way the two types of variable work. Class-level variables generally have a much longer life span than local variables.

And there's still nothing in anything you posted which suggests that a Java application will fail with an OOM exception under the new-style garbage collection but would not have failed under the old-style garbage collection. There's a lot of talk about the timing of collections but nothing at all about failing to collect objects which are in fact unreferenced.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic