java 了解常量池的 javap 输出

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5546280/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 11:37:16  来源:igfitidea点击:

Understanding javap's output for the Constant Pool

javajava-bytecode-asmjavap

提问by Andrew White

When running javap on a very simple HelloWorld application I have some confusion on the output around the constant pool.

在一个非常简单的 HelloWorld 应用程序上运行 javap 时,我对常量池周围的输出有些困惑。

Test Code

测试代码

public class TestClass {
    public static void main(String[] args) {
        System.out.println("hello world");
    }
}

Javap -c -verbose output (snipped)

Javap -c -verbose 输出(剪切)

// Header + consts 1..22 snipped
const #22 = String      #23;    //  hello world
const #23 = Asciz       hello world;

public static void main(java.lang.String[]);
  Signature: ([Ljava/lang/String;)V
  Code:
   Stack=2, Locals=1, Args_size=1
   0:   getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #22; //String hello world
   5:   invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:   return
  // Debug info snipped
}

Ok, so on line 3 we see a pushing of the "hello world" constant onto the stack via #22, but const #23 seems to hold the actual value. I guess I am a little confused with what the #(number) means when it appears on the right-hand-side of the printout.

好的,所以在第 3 行,我们看到通过 #22 将“hello world”常量推入堆栈,但 const #23 似乎保存了实际值。我想我对 #(number) 出现在打印输出的右侧时的含义有些困惑。

Oracle/Sun's man page for javapleaves much to be desired.

Oracle/Sun 的 javap 手册页还有很多不足之处。

回答by Favonius

All your class, interface, fieldnames and stringconstants go into the java constant pool.

您所有的class, interface,field名称和string常量都进入 java常量池

As per VM Spec ( http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html):

根据 VM 规范(http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html):

The constant_pool is a table of structures (§4.4) representing various string constants, class and interface names, field names, and other constants that are referred to within the ClassFile structure and its substructures. The format of each constant_pool table entry is indicated by its first "tag" byte. The constant_pool table is indexed from 1 to constant_pool_count-1.

constant_pool 是一个结构表(第 4.4 节),表示在 ClassFile 结构及其子结构中引用的各种字符串常量、类和接口名称、字段名称和其他常量。每个 constant_pool 表条目的格式由其第一个“标记”字节指示。constant_pool 表的索引从 1 到 constant_pool_count-1。

So in terms of constant pool something like below can be viewed as:

因此,就常量池而言,可以将以下内容视为:

const #22 = String      #23;    //  hello world
const #23 = Asciz       hello world;

The value at #22 (index 22) is of type Stringand its value is null terminated c string (Asciz) hello worldis at index 23.

#22(索引 22)处的String值是类型,其值为空终止 c 字符串(Ascizhello world在索引 23 处。

回答by templatetypedef

The Java constant pool stores two different kinds of entries when storing a string. First, it stores the string literal as UTF-8 encoded data (here, constant #23). Second, it also stores an string entry (#22) indicating that the contents of constant #23 should be used to construct a String. I think the reason for this is that the JVM associates with each class a "runtime constant pool" consisting of a dynamic implementation of the given constants. For strings, this can be a reference to the interned Stringobject holding the given characters. UTF-8 constant data has other uses besides string literals (for example, naming fields and classes), so this extra indirection seems like a reasonable way to separate out the concerns.

Java 常量池在存储字符串时存储两种不同类型的条目。首先,它将字符串文字存储为 UTF-8 编码数据(此处为常量 #23)。其次,它还存储了一个字符串条目(#22),表明应该使用常量#23 的内容来构造一个String. 我认为这样做的原因是 JVM 将每个类与一个“运行时常量池”相关联,该池由给定常量的动态实现组成。对于字符串,这可以是对String包含给定字符的内部对象的引用。UTF-8 常量数据除了字符串文字之外还有其他用途(例如,命名字段和类),因此这种额外的间接寻址似乎是分离关注点的合理方法。

回答by Ernest Friedman-Hill

Pool entry #22 is a java.lang.String object. Entry #23 is the array of characters used to construct that String.

池条目 #22 是一个 java.lang.String 对象。条目#23 是用于构造该字符串的字符数组。

The Java VM Specis the "missing manual" for javap.

Java虚拟机规格是“失踪手册” javap的。