1

I'm creating a service that will run constantly, each day at a specified time it will run the main body of the program.

Essentially:

while(true){
run();
Thread.sleep(day);
}

After a while, I'm getting OutOfMemoryHeapExceptions. After reading about this a little I'm thinking its because any objects created inside the run() method will never be garbage collected.

Therefore I have done something like:

public void run(){
Object a = new Object();
a.doSomething();

a= null; //Wasn't here before
}

My question is, will this solve my problem? I'm under the impression that once an object is null, the object it previously referenced will be garbage collected? Also is this a good idea? Or should I look at doing something else?

Thanks

trincot
  • 317,000
  • 35
  • 244
  • 286
  • Something nobody noted in answers, though it is a faint possibility: you may have hit a bug in the VM or GC. It's unlikely but not impossible. – Romain Dec 15 '11 at 12:10

8 Answers8

2

Adding a = null will almost certainly be insufficient to fix the problem (since a is about to go out of scope anyway).

My advice would be to use a memory profiler to pinpoint what's leaking and where.

I personally use YourKit. It's very good, but costs money (you can get a free evaluation).

Another recently-released tool is Plumbr. I am yet to try it, but the blurb says:

Try out our Java agent for timely discovery of memory leaks. We'll tell you what is leaking, where the leak originates from and where the leaked objects currently reside - well before the OutOfMemoryError!

NPE
  • 486,780
  • 108
  • 951
  • 1,012
1

That might indeed help, in some circumstances the GC algorithm needs a little help to perform, but it doesn't guarantee to solve your problems, merely delay them.

My advice: Simulate the same behavior with a lower time period, so you can force the error to happen. Run it with a profiler and see where all that memory is going, and work from there.

pcalcao
  • 15,789
  • 1
  • 44
  • 64
0

Your impression is incorrect. Objects created inside the run() method will be garbage collected provided they 1) go out of scope, and 2)have released any native or remote system resources they are using.

What functionality are you actually performing inside your run() method call? Are you reading files, making database calls, writing to sockets? Without knowing the details its very difficult to provide a better suggestion.

mcfinnigan
  • 11,442
  • 35
  • 28
  • So, what if `a.doSomething()` adds references to the object referenced by `a` that will remain valid after exiting the scope of `run()`? – Romain Dec 15 '11 at 12:05
  • I'm extracting information from files and then inserting them into a database. –  Dec 15 '11 at 12:08
  • @Romain - provided those references were outside the scope of run() and isolated from any other live code and didn't hold any system resources, I would expect them to be GC'd normally. In this case I'm guessing there are file or DB handles which remain unclosed. – mcfinnigan Dec 15 '11 at 13:01
  • @mcfinnigan In the general case, people could have added, for instance, entries in a global map, or any other object that lives in the PermGen and is never GC'd. – Romain Dec 15 '11 at 15:13
0

You should get a memory dump and analyze that using tools like JConsole JVisualVM.

The scope of the run() method is left before the Thread.sleep(day); and thus any variables inside that method are destroyed. After that a won't exist any more and thus the object referenced by that variable might be eligible for garbage collection provided there's no other reference to it.

Analyzing a memory dump should allow you to find any references to those object if they still exist.

It might as well not be those objects but others that are kept alive and which eat up the memory. That depends on what you're actually doing and might be hard to analyze here. Thus look out for huge object graphs in terms of memory usage.

For instance, we had a problem with database connections that were created frequently (XA recovery mechanism) and we thought they'd be destroyed once the method scope is left. However, the server put those connections into a static list and never cleared it and thus we ended up with no memory really soon. What helped us identify that case was analyzing a memory dump. :)

Thomas
  • 87,414
  • 12
  • 119
  • 157
0

No. You don't need to set the variable to null. The VM knows that you exit that scope and that the variable a no longer exists, so it automatically decrements the reference count and your object is elegible for garbage collection if it had no other references.

The error is somewhere else.

Romain
  • 12,679
  • 3
  • 41
  • 54
SJuan76
  • 24,532
  • 6
  • 47
  • 87
0

Setting references to null depends if your object is still in scope in a long time consuming process, though theoretically it will mark the reference as null you cannot guarantee when it will be garbage collected.

You need to check if your objects are being held in long scope somewhere in your code.

Found a nice explanation of setting references to null : Does setting Java objects to null do anything anymore?

In order to corner out your issue you need to profile your application.

Searching SO gave so many pointers on Garbage Collection that I have decided to just place the search string here:

https://stackoverflow.com/search?q=Java+Garbage+collection+and+setting+references+to+null

http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html

Community
  • 1
  • 1
mprabhat
  • 20,107
  • 7
  • 46
  • 63
  • WOuld the VM not try to run the GC before it throws the `OutOfMemoryException`/`OutOfMemoryHeapException`? – Romain Dec 15 '11 at 12:08
  • The answer is unfortunately it depends, its just another thread which may or maynot get a chance to execute – mprabhat Dec 15 '11 at 12:09
  • I'd have though the VM spec would say you need to let the GC run before you can throw `OutOfMemoryException`s, but I'm no expert on that aspect of the Spec, so it's pure speculation :) – Romain Dec 15 '11 at 12:11
0

Local variables should be collected by GC. So, you don't need to put obj=null;. Because Object is also stored in Heap area.

alishaik786
  • 3,696
  • 2
  • 17
  • 25
0

In the short term a pragmatic approach to keeping your application stable is to exit the JVM after each execution. Use a batch scheduler (e.g. cron on *nix, at on Windows) to execute your application just once every day. Any memory leaks will be cleaned up when the JVM exists for sure. However you may have to be careful you're not leaving database connections open, etc.

This will give you time to troubleshoot and fix the underlying memory leak issues while keeping your production code running and not requiring support staff to restart servers, etc.

I'm assuming you're not running out of memory on a single execution

Brad
  • 15,186
  • 11
  • 60
  • 74