Java initialization bytecode skipped
According to the bytecode of the class file javap -c ...
, there is a block of code that is responsible for initializing a static field within the class. However, there are two if statements, ifne
and ifeq
, which are next to each other:
27: ifne 120
30: ifeq 119
The initialization block is located between offsets 37 and 115 and is required to initialize a static variable contained within the class. I understand that it ifne
will branch if the value on the stack is not 0, and that it ifeq
will branch if the value on the stack is 0, which means it will branch independently.
My question is, if the initialization block is just skipped by these branches, then why is the variable initialized later? I can't find any branches in the block, so how can this be triggered if the code disconnects elsewhere?
Edit: more bytecode
0: getstatic #602 // static integer field
3: istore 25
...
25: iload 25
27: ifne 120
30: ifeq 119
33: goto 37
36: athrow
37: new #6 // class java/io/File
40: dup
41: getstatic #615 // static string containing filename
...
56: invokespecial #9 // Method java/io/File."<init>":(Ljava/lang/String;)V
...
112: putstatic #14 // static File referenced later on
source to share
Java is not the strongest VM, but I usually understand opcodes.
27: ifne 120
30: ifeq 119
The conditional branch pops the top value off the stack. So it is not an unconditional branch, it is two branch instructions based on two different (consecutive) stack values. In short, it consumes 2 different values.
So, if you have 0s and 1s on the stack, it will fail without forking.
Also, static field initialization is not guaranteed right away, the JVM spec I have (the old one) says it will execute lazily the first time a non-persistent class is accessed. This may not be relevant to your question, but worth mentioning.
Last but not least, not all bytecodes are valid. Obfuscators insert invalid / dead code that is unavailable, redundant, or "obfuscated" by definition.
source to share