Community
Participate
Working Groups
Using latest: Test case: import java.util.*; public class X { static private ResourceBundle bundle = null; static { try { bundle = foo(); } catch(Throwable e) { e.printStackTrace(); } } static ResourceBundle foo() { return null; } } Dumped bytecodes: static {}; 0 aconst_null 1 putstatic X.bundle Ljava/util/ResourceBundle; [11] 4 invokestatic X.foo()Ljava/util/ResourceBundle; [15] 7 putstatic X.bundle Ljava/util/ResourceBundle; [11] 10 goto 18 13 astore_0 [e] 14 aload_0 [e] 15 invokevirtual java/lang/Throwable.printStackTrace()V [20] 18 return Exception Table: [pc: 4, pc: 13] -> 13 when : java.lang.Throwable Line numbers: [pc: 0, line: 4] [pc: 4, line: 7] [pc: 13, line: 8] [pc: 14, line: 9] [pc: 18, line: 3] Local variable table: [pc: 14, pc: 19] local: e index: 0 type: Ljava/lang/Throwable; Note that e is visible till 19, where it should be 18. You can return without initializing e. javac 1.5.0 correctly ends the visibility of e at pc 18.
Interestingly, if converting the <clinit> into a static method, then the attribute is correctly generated.
The problem with the incorrect ranges only appears when we are debugging a method. Our aggressive local mapper will correctly identify abandoned local variables, but in debug mode, we add the Local Variable Table information to maintain variable life to the semantic range. the problem appears when a GC (garbage collection) occurs while we are at the return bytecode. WE could have reached the bytecode without even having used the local variable. Using the Local Variable Table information, we declare that slot zero is an object and attempt to walk it in the GC, however, the contents of the local variable is garbage - a problem (possibly fatal).
Problem occurs anywhere we expand the local var visibility range to include trailing instructions, e.g.: void bar(boolean b) { if (b) { try { int i = 0; } catch(Exception e) { e.printStackTrace(); } } else { int j = 0; } } // Method descriptor #33 (Z)V // Stack: 1, Locals: 3 void bar(boolean b); 0 iload_1 [b] 1 ifeq 17 4 iconst_0 5 istore_2 [i] 6 goto 19 9 astore_2 [e] 10 aload_2 [e] 11 invokevirtual void Exception.printStackTrace() [36] 14 goto 19 17 iconst_0 18 istore_2 [local_2] 19 return Exception Table: [pc: 4, pc: 9] -> 9 when : java.lang.Exception Line numbers: [pc: 0, line: 6] [pc: 4, line: 8] [pc: 9, line: 9] [pc: 10, line: 10] [pc: 17, line: 13] [pc: 19, line: 15] Local variable table: [pc: 0, pc: 20] local: this index: 0 type: LX; [pc: 0, pc: 20] local: b index: 1 type: Z [pc: 6, pc: 9] local: i index: 2 type: I [pc: 10, pc: 17] local: e index: 2 type: Ljava/lang/Exception; Our expansion should only consider first level scope.
Added TryStatementTest#test026-027. Changed range extension to accept scope param to only modify variables in that scope; and thus avoid messing up with subscope contents. Fixed
Releasing for M6
Verified in 20050401-1205