【问题标题】:What do we mean with Negative Value of LDC instruction code?LDC指令代码的负值是什么意思?
【发布时间】:2019-05-06 10:34:17
【问题描述】:

我对 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?

【问题讨论】:

    标签: java jvm bytecode jacoco java-11


    【解决方案1】:

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

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

    这符合getProbes(JLjava/lang/String;I) 的后续调用,它需要堆栈上的longStringint

    • LDC -1475355800743669619 将文字 long-1475355800743669619 压入堆栈,这是有效的,因为 -1475355800743669619 适合 long 值范围(已签名)
    • LDC "ClassUnderTest" 将代表 "ClassUnderTest"String 的引用推送到堆栈
    • BIPUSH 64 将文字 int64 推入堆栈

    那么,您在堆栈上有一个long、一个String 和一个int,用于调用getProbes

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

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

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

    如果这是我们在此处看到的 long 值,那么只需使用不同的 JDK 版本重新编译一个类可能会改变实际值,负值是完全合理的。

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

     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
    

    确实在行尾以注释形式显示了正常量池索引和实际值。当然,我只是编了个数字,因为我没有原始的类文件。这只是为了说明答案开头所述的事实,Java汇编输出没有标准化的形式。你可以在实际的字节码上运行javap

    【讨论】:

    • 感谢@Holger 的详细回答。它确实提高了我对字节码指令的理解
    猜你喜欢
    • 1970-01-01
    • 2015-06-17
    • 1970-01-01
    • 1970-01-01
    • 2012-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-24
    相关资源
    最近更新 更多