LDC 指令代码的负值是什么意思?
What do we mean with Negative Value of LDC instruction code?
我对 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 是我关心的。到目前为止我了解到的是,这是 class 中常量值的字段。
我很困惑LDC值是否可以为负数?
我遇到的另一个问题是,对于 JDK-8,相同 class 的 LDC 值为正,但对于 JDK-11 则为负。所以我的问题是,它是否也依赖于 JDK?
Java 程序集没有标准化格式,因此,可能存在差异,具体取决于您用于获取文本形式的工具。
显然,您使用的工具不会打印 LDC
指令使用的常量池索引(确实必须为正数),而是打印池中的实际常量值。最强的指标是显示实际 String
值而不是常量池索引的后续指令。
这与后续的 getProbes(JLjava/lang/String;I)
调用相符,后者需要一个 long
、一个 String
和一个 int
在堆栈上。
LDC -1475355800743669619
将文字 long
值 -1475355800743669619
压入堆栈,这是有效的,因为 -1475355800743669619
适合 long
值范围(即签名)
LDC "ClassUnderTest"
将代表 "ClassUnderTest"
的 String
的引用推送到堆栈
BIPUSH 64
将文字 int
值 64
推入堆栈
那么,您在堆栈上有一个 long
、一个 String
和一个 int
用于调用 getProbes
。
由于 long
值是 getProbes
的第一个参数的参数,方法 getProbes
确定其含义以及负值或正值是合理的参数,以及JDK 8 或 JDK 11 的值是否必须相同。
https://www.jacoco.org/jacoco/trunk/doc/implementation.html 说:
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.
如果这是我们在这里看到的 long
值,只需用不同的 JDK 版本重新编译 class 可能 更改实际值和负值是完全合理的。
请注意,如果您使用 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
确实在行尾的注释表单中显示了正常量池索引和实际值。当然,我只是编造了数字,因为我没有原始 class 文件。这只是为了说明答案开头所述的事实, Java 汇编输出没有标准化形式。您可能 运行 javap
实际的字节码。
我对 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 是我关心的。到目前为止我了解到的是,这是 class 中常量值的字段。
我很困惑LDC值是否可以为负数?
我遇到的另一个问题是,对于 JDK-8,相同 class 的 LDC 值为正,但对于 JDK-11 则为负。所以我的问题是,它是否也依赖于 JDK?
Java 程序集没有标准化格式,因此,可能存在差异,具体取决于您用于获取文本形式的工具。
显然,您使用的工具不会打印 LDC
指令使用的常量池索引(确实必须为正数),而是打印池中的实际常量值。最强的指标是显示实际 String
值而不是常量池索引的后续指令。
这与后续的 getProbes(JLjava/lang/String;I)
调用相符,后者需要一个 long
、一个 String
和一个 int
在堆栈上。
LDC -1475355800743669619
将文字long
值-1475355800743669619
压入堆栈,这是有效的,因为-1475355800743669619
适合long
值范围(即签名)LDC "ClassUnderTest"
将代表"ClassUnderTest"
的String
的引用推送到堆栈BIPUSH 64
将文字int
值64
推入堆栈
那么,您在堆栈上有一个 long
、一个 String
和一个 int
用于调用 getProbes
。
由于 long
值是 getProbes
的第一个参数的参数,方法 getProbes
确定其含义以及负值或正值是合理的参数,以及JDK 8 或 JDK 11 的值是否必须相同。
https://www.jacoco.org/jacoco/trunk/doc/implementation.html 说:
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.
如果这是我们在这里看到的 long
值,只需用不同的 JDK 版本重新编译 class 可能 更改实际值和负值是完全合理的。
请注意,如果您使用 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
确实在行尾的注释表单中显示了正常量池索引和实际值。当然,我只是编造了数字,因为我没有原始 class 文件。这只是为了说明答案开头所述的事实, Java 汇编输出没有标准化形式。您可能 运行 javap
实际的字节码。