I am very new to java bytecode world. I have some debugging task which involves bytecode. When going through that I noticed some values that look suspicious but i am not sure. here is a part of full bytecode
// access flags 0x100A
private static synthetic $jacocoInit()[Z
GETSTATIC ClassUnderTest.$jacocoData : [Z
DUP
IFNONNULL L0
POP
LDC -1475355800743669619
LDC "ClassUnderTest"
BIPUSH 64
INVOKESTATIC org/jacoco/agent/rt/internal_1f1cc91/Offline.getProbes (JLjava/lang/String;I)[Z
DUP
PUTSTATIC ClassUnderTest.$jacocoData : [Z
L0
Here LDC -1475355800743669619 is what i am concerned with. What i have learned so far is that this is a field for Constant values in a class.
I am confused if LDC value can be negative or not?
Another issue that I encountered is that, with JDK-8, the LDC value for the same class is positive but with JDK-11 it is negative. So my question is, Is it dependent on JDK also?
There is no standardized format for Java assembly, hence, there might be differences, depending on which tool you used for getting the textual form.
Apparently, the tool you used, does not print the constant pool index used by the LDC
instruction (which indeed must be positive), but the actual constant value from the pool. The strongest indicator is the subsequent instruction showing the actual String
value rather than a constant pool index.
This fits with the subsequent invocation of getProbes(JLjava/lang/String;I)
, which expects a long
, a String
, and an int
on the stack.
LDC -1475355800743669619
pushes the literallong
value-1475355800743669619
on the stack, which is valid as-1475355800743669619
fits into thelong
value range (which is signed)LDC "ClassUnderTest"
pushes a reference to aString
representing"ClassUnderTest"
to the stackBIPUSH 64
pushes the literalint
value64
to the stack
So then, you have a long
, a String
, and an int
on the stack for the invocation of getProbes
.
Since the long
value is the argument to getProbes
’s first parameter, the method getProbes
determines its meaning and whether negative or positive values are plausible arguments, as well as whether the value has to be the same for JDK 8 or JDK 11.
https://www.jacoco.org/jacoco/trunk/doc/implementation.html says:
Each class loaded at runtime needs a unique identity to associate coverage data with. JaCoCo creates such identities by a CRC64 hash code of the raw class definition.
If that’s the long
value we see here, just recompiling a class with a different JDK version might change the actual value and negative values are entirely plausible.
Note that if you used javap
instead, to get the textual output, it looked more like
0: getstatic #42 // ClassUnderTest.$jacocoData : [Z
3: dup
4: ifnonnull 22
7: pop
9: ldc2_w #43 // long -1475355800743669619l
11: ldc #44 // String ClassUnderTest
13: bipush 64
15: invokestatic #45 // org/jacoco/agent/rt/internal_1f1cc91/Offline."getProbes":(JLjava/lang/String;I)[Z
18: dup
19: putstatic #42 // ClassUnderTest.$jacocoData : [Z
indeed showing the positive constant pool indices and the actual values in a comment form at the end of the line. Of course, I just made up the numbers as I don’t have the original class file. This is just for illustration of the fact stated at the beginning of the answer, there is no standardized form for Java assembly output. You may run javap
on the actual byte code.