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

3

我对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个回答

5
Java汇编没有标准化格式,因此可能存在差异,具体取决于您用于获取文本形式的工具。显然,您使用的工具未打印LDC指令使用的常量池索引(必须为正),而是实际的常量值。最强的指示是后续指令显示实际的String值而不是常量池索引。这符合随后调用getProbes(JLjava/lang/String;I)的情况,该方法在堆栈上期望一个long、一个String和一个int。
  • LDC -1475355800743669619 将字面值 -1475355800743669619 推入栈中,这是有效的,因为它在 long 值范围内(有符号)
  • LDC "ClassUnderTest" 将一个代表 "ClassUnderTest"String 引用推入栈中
  • BIPUSH 64 将字面值 64 推入栈中作为 int 类型的值

这样,为调用 getProbes,栈上有一个 long、一个 String 和一个 int

由于 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提供详细的答案。它真正提高了我对字节码指令的理解。 - Krishnom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接