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

时间:2019-05-06 10:34:17

标签: 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

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

我对LDC值是否可以为负感到困惑?

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

1 个答案:

答案 0 :(得分:5)

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

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

这与随后的getProbes(JLjava/lang/String;I)调用相符,该调用期望堆栈上有longStringint

  • LDC -1475355800743669619将文字long-1475355800743669619推入堆栈,当-1475355800743669619符合long值范围(带符号)时有效
  • LDC "ClassUnderTest"将对表示String的{​​{1}}的引用推入堆栈
  • "ClassUnderTest"将文字BIPUSH 64int推入堆栈

因此,您在堆栈上有一个64,一个long和一个String用于调用int

由于getProbes值是long第一个参数的参数,因此方法getProbes确定其含义以及负值或正值是否是合理的参数,以及JDK 8或JDK 11的值必须相同。

https://www.jacoco.org/jacoco/trunk/doc/implementation.html说:

  

在运行时加载的每个类都需要一个唯一的标识才能将coverage数据与之关联。 JaCoCo通过原始类定义的CRC64哈希码创建此类身份。

如果这是我们在这里看到的getProbes值,只需重新编译具有不同JDK版本的类可能即可更改实际值,并且负值完全合理。

请注意,如果您改用long来获取文本输出,则它看起来更像

javap

的意思是在行的末尾以注释形式显示正常数池索引和实际值。当然,由于我没有原始班级文件,所以我只补了数字。这只是为了说明答案开头所述的事实,没有Java程序集输出的标准化形式。您可以在实际的字节码上运行 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