What do we mean with Negative Value of LDC instruction code?

Krishnom :

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?

Holger :

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 literal long value -1475355800743669619 on the stack, which is valid as -1475355800743669619 fits into the long value range (which is signed)
  • LDC "ClassUnderTest" pushes a reference to a String representing "ClassUnderTest" to the stack
  • BIPUSH 64 pushes the literal int value 64 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.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=90729&siteId=1