File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Java in General and the fly likes Java Memory Puzzle Big Moose Saloon
  Search | Java FAQ | Recent Topics
Register / Login
JavaRanch » Java Forums » Java » Java in General
Reply Bookmark "Java Memory Puzzle" Watch "Java Memory Puzzle" New topic
Author

Java Memory Puzzle

Vijay Bhuruk
Greenhorn

Joined: Feb 28, 2008
Posts: 28



Java Memory Puzzle
Instead of telling you some mystery of Java memory, it is time for you to put on your thinking caps. I had a discussion a few weeks ago with one of my subscribers of whether you should null your local variables, to make things easier for the garbage collector. His understanding was that the local variables will be stored on the stack and thus popped off at the end of the method call anyway, so nulling them was a waste of time. In almost all situations, he is right. However, he had a class that did something most peculiar, something like this:




When you run this you will always get an OutOfMemoryError, even though the local variable data is no longer visible outside of the code block.

So here comes the puzzle, that I'd like you to ponder about a bit. If you very politely ask the VM to release memory, then you don't get an OutOfMemoryError:




Copyright Heinz Kabutz 2009
Aristotelous 84, Korakies, Akrotiri, Chania, Crete, 73100, Greece



Why does this work?
Dmitry Mamonov
Greenhorn

Joined: Dec 24, 2008
Posts: 28
Don't know but:

is also failed, BUT:

works fine.
Dmitry Mamonov
Greenhorn

Joined: Dec 24, 2008
Posts: 28
Here is bytecode difference;

// Method descriptor #8 ()V
// Stack: 1, Locals: 3
public void f();
0 aload_0 this
1 getfield sys.JavaMemoryPuzzle.dataSize : int 24
4 newarray byte 8
6 astore_1
XX iconst_1 <<<difference
XX istore_1 i <<<difference
7 aload_0 this
8 getfield sys.JavaMemoryPuzzle.dataSize : int 24
11 newarray byte 8
13 astore_2 data2
14 return


My suggestion is:
when code walks out from nested {} block it will not assign null values to variables in such block.
We just will not see them in java code.

Second example of code works fine (marked with XX in bytecode list) cause
the value=1 is stored into variable name = "i" exactly into the same place (index=1)
where variable name="data" was stored before.
This breaks reference to first allocated array so it could be collected with GC.
Saifuddin Merchant
Ranch Hand

Joined: Feb 08, 2009
Posts: 576

Looks like the Garbage collector just does not get time to kick in - in the first case. In the case where you loop 10 times the garbage collector kicks in and does its work.

Of course the Garbage collector could run in the first case too - but mostly probably wound not get time. Maybe if you run a million times you might see that it runs fine some times - with no exception!

P.S - Setting it to null would not help either.


Cheers - Sam.
Twisters - The new age Java Quiz || My Blog
Srinivasa Chebrolu
Greenhorn

Joined: May 29, 2009
Posts: 4
To me this sounds like JVM implementation issue in the way they handle stack. Once local variable out of scope stack pointer decremented but the reference still exists causing GC to not clear this array object. By adding for loop (or an other local variable in between) we are forcing JVM to use prior Stack location (where data byte array reference used to be) and now no reference to that allocated memory.

Take a look at my code (I used to test my theory):



I also tested this by declaring byte array allocation in a function and stack handling seems to work fine in this scenario.

Thanks,
Chakri
Jaswinderji Singh
Greenhorn

Joined: May 31, 2009
Posts: 1
Then why the below code is working.

public class Testting {
private final int dataSize = (int) (Runtime.getRuntime().maxMemory() * 0.6);

public void f() {
{
byte[] data = new byte[dataSize];
}
String strTest = new String();
byte[] data2 = new byte[dataSize];
}

public static void main(String[] args) {
Testting jmp = new Testting();
jmp.f();
System.out.println("DONE");
}
}
Srinivasa Chebrolu
Greenhorn

Joined: May 29, 2009
Posts: 4
Then why the below code is working.


Thats the whole point. The moment you add local variable before 2nd memory allocation you use last stack location (which was holding reference to first byte array 'data') and with local variable introduction and assignment you freeing 'data' obect reference, no reference to 'data' means that object can be GC'd.

 
I agree. Here's the link: http://ej-technologies/jprofiler - if it wasn't for jprofiler, we would need to run our stuff on 16 servers instead of 3.
 
subject: Java Memory Puzzle
 
Similar Threads
A flatland puzzle
Puzzle for JavaProgrammers
java memory puzzle
Scope variable usage
Out of memory