1

我试图找出类文件中常量池部分下的以下两个条目:

int foo(int x) {
    return x;
}

#11 = Utf8               foo
#12 = Utf8               (I)I        // 1   
#13 = Utf8               x
#14 = Utf8               I           // 2

条目 (1) -> (I)I 是否表示函数的开始,条目 (2) -> I 是否表示函数的结束。

这个编译器是特定的还是可能因一个编译器而异?

Lambda 函数也有类似的问题。

interface I { int foo(int x); }
class X {
I x = (int x1) -> 0;
}

 #15 = Utf8            lambda$new$0
 #16 = Utf8            (I)I
 #17 = Utf8            x1
 #18 = Utf8            I

抱歉,在 JLS 文档上找不到任何内容。

谢谢

4

1 回答 1

4

常量池没有“方法开始”和“方法结束”的概念。

您在这里实际看到的是字符串常量,它在常量池中具有“Utf8”类型。从池的角度来看,这些只是字符串——但是,它们是编译器生成的字符串,表示各种事物。这些字符串是必需的,它们的格式在 JVMS 中进行了描述。有几种类型。从您的 lambda 示例中:

  • lambda$new$0- 这是一个签名,在4.3.4中描述。
  • (I)I- 这是一个方法描述符(与签名不同),在4.3.3中描述
  • I- 这是一个字段描述符,在4.3.2中描述。

简单的I条目只是一个类型的字段int

对于您的(I) I输入,之间的字符串(..)是参数类型。它可以是一个列表。I是原始类型int。外面的字符串(..)是返回类型。所以(I) I描述了一个带有参数列表的方法,它接受一个int和一个返回类型int

具体来说,从 JVMS 来看,方法描述符字符串具有以下格式:

MethodDescriptor:
    ( ParameterDescriptor* ) ReturnDescriptor

ParameterDescriptor:
    FieldType

ReturnDescriptor:
    FieldType
    VoidDescriptor

VoidDescriptor:
    V

其中FieldType是(来自表 4.2):

字符类型解释
B 字节 有符号字节
Basic 中的 C char Unicode 字符代码点
                           多语言平面,用 UTF-16 编码
D double 双精度浮点值
F float 单精度浮点值
我 int 整数
J long long 整数
L 类名;引用类 ClassName 的实例
S 短 有符号短
Z 布尔值 true 或 false
[引用一维数组

但是请注意,这些仍然是与其他字符串一样的字符串。当您实际调用这些方法时,常量池中会出现一种不同的条目——方法引用。javap用“NameAndType”类型标识这些(而不是字符串的“Utf8”),它们将采用如下形式(使用您的第一个示例):

#123 = NameAndType      #11:#12;   // "foo":(I)I

它们引用方法名称字符串以及描述符字符串。

javap文档本身相当稀疏,仅包含命令行信息。JVMS 是最接近详细手册的东西javap

于 2014-04-10T14:30:51.343 回答