I can see this curious behaviour from the garbage collector
public class A {
public static void main(String[] args) {
String foo;
try {
foo = "bar";
int yoo = 5; //1
} catch (Exception e) {
}
int foobar = 3;//2
}
}
if I go to debug and put a breakpoint on //1 foo is not null and its value is "bar" but in breakpoint //2 foo is null, this can be difficult to understand while you are debug. My question is if there is any specification that says that this is a legal behaviour from the garbage collector
With this small variation it doesn't get Garbage collected:
public class A {
public static void main(String[] args) {
String foo;
try {
foo = "bar";
} catch (Exception e) {
throw new RuntimeException(e);
}
int foobar = 3;
}
}
Why?
Final variables cannot be changed after initial assignment (enforced by the compiler). This does not change the behaviour of the garbage collection as such. Only thing is that these variables cannot be nulled when not being used any more (which may help the garbage collection in memory tight situations).
When a JVM runs out of space in the storage heap and is unable to allocate any more objects (an allocation failure), a garbage collection is triggered. The Garbage Collector cleans up objects in the storage heap that are no longer being referenced by applications and frees some of the space.
Java garbage collection is an automatic process. The programmer does not need to explicitly mark objects to be deleted. The garbage collection implementation lives in the JVM. Each JVM can implement garbage collection however it pleases; the only requirement is that it meets the JVM specification.
An object is eligible to be garbage collected if its reference variable is lost from the program during execution. Sometimes they are also called unreachable objects. What is reference of an object? The new operator dynamically allocates memory for an object and returns a reference to it.
In this case, you don't use the foo variable after setting it, so it would even be legal for the JVM to completely ignore the variable as it is never used and that would not change the result of your program.
However that's unlikely to happen in debug mode.
In your case, foo should not get GC'ed as long as it is in scope or you hold a reference to it, which includes the section after the try/catch block.
EDIT
Actually I get the same behaviour as what you describe in Netbeans 7.1.1 with Java 7.0_03...
One problem might be that because you don't set a default value to foo
, you can't use it after the try/catch block (it would not compile).
Bytcode
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String bar
2: astore_1
3: iconst_5
4: istore_2
5: goto 9
8: astore_2
9: iconst_3
10: istore_2
11: return
String foo = null;
as the first statement, in which case the debugger see the value after the try/catch block:public static void main(java.lang.String[]);
Code:
0: aconst_null
1: astore_1
2: ldc #2 // String bar
4: astore_1
5: iconst_5
6: istore_2
7: goto 11
10: astore_2
11: iconst_3
12: istore_2
13: return
I'm not a bytcode specialist but they look very similar to me...
CONCLUSION
My personal conclusion is that for the debugger to show the value of foo
, it has to run a foo.toString()
of some sort, which is not a valid statement after the catch block as foo
might have not been initialized. Adding a System.out.println(foo)
in that section is not legal (does not compile). The debugger is a bit lost as to what the value is and shows null
.
To convince yourself that this has nothing to do with GC, you can try the following example:
public static void main(String[] args){
String foo;
char[] c = null;
try {
foo = "bar";
c = foo.toCharArray();
int yoo = 5; //1
} catch (Exception e) {
}
int foobar = 3;//2
}
On the foobar
line, you can see that c
holds bar
but foo shows as null
. So the String is still there, but the debugger can't show it.
Even funnier example:
public static void main(String[] args){
String foo;
List<String> list = new ArrayList<String>();
try {
foo = "bar";
list.add(foo);
int yoo = 5; //1
} catch (Exception e) {
}
int foobar = 3;//2
}
On the foobar
line, foo
shows as null
, but list
contains "bar"
... Nice.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With