| 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.
|
 |
 |
|
|
subject: Java Memory Puzzle
|
|
|