LDC指令代码的负值是什么意思?

Kri*_*nom 3 java jvm bytecode jacoco java-11

我对Java字节码世界非常陌生。我有一些涉及字节码的调试任务。在浏览时,我注意到一些看起来可疑的值,但我不确定。这是完整字节码的一部分

// 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
Run Code Online (Sandbox Code Playgroud)

最关心的LDC -1475355800743669619。到目前为止,我了解到的是,这是一个类中用于常量值的字段。

如果LDC值可以为负,我会感到困惑吗?

我遇到的另一个问题是,对于JDK-8,同一类的LDC值为正,但是对于JDK-11,它为负。所以我的问题是,它也依赖于JDK吗?

Hol*_*ger 5

Java程序集没有标准化的格式,因此,可能会有所不同,具体取决于您用来获取文本形式的工具。

显然,您使用的工具不会打印LDC指令使用的常量池索引(确实必须为正数),而是打印池中的实际常量值。最强的指示符是显示实际String值的后续指令,而不是恒定池索引。

这与随后的调用相符getProbes(JLjava/lang/String;I),后者在堆栈上期望a long,a String和an int

  • LDC -1475355800743669619将文字long值压-1475355800743669619入堆栈,该值-1475355800743669619long值范围内有效(已签名)
  • LDC "ClassUnderTest"推到一个参考String表示"ClassUnderTest"到堆栈
  • 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
Run Code Online (Sandbox Code Playgroud)

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.