Java 源代码中的字符串 initialised/stored 何时何地?
When and Where is the String initialised/stored in Java source code?
这是我的源代码:
public class Koray {
public static void main(String [] args) {
System.out.println("This is a sample program.");
}
}
当我编译它时,我得到了字节码。当我用十六进制查看器查看字节码时,我看到了部分:
19 54 68 69 73 20 69 73 20 61 20 73 61 6D 70 6C 65 20 70 72 6F 67 72 61 6D 2E
可以读作
This is a sample program.
如果字节被解释为字符。
当我这样做时
javap -c Koray.class
拆开这个 class 我明白了:
Compiled from "Koray.java"
public class Koray {
public Koray();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String This is a sample program.
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: bipush 10
10: istore_1
11: return
}
我的问题是,在反汇编的文本中哪里可以看到这个字符串?我只在评论中看到它。
ldc #3; //String This is a sample program.
这一行使用了opcode
ldc
,它将一个常量加载到操作数栈中。此时,我们将加载常量池 table.
的索引 #3
中的任何常量
常量池table是存储大多数文字常量值的地方。 (ref)命令javap -c -verbose <classfile>
为常量池table提供输出。
示例输出:
const #22 = String #23; // This is a sample program
const #23 = Asciz This is a sample program;
更多信息来自 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.
ldc #3
加载存储在常量池中的字符串常量,常量池是一个单独的table,存储String
字面量和class名称等常量。
请参阅 JVM 规范中的 http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4:
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.
您可以使用 javap -verbose ClassName
查看字符串 table。
示例输出类似于:
Compiled from "Test.java"
public class tests.Test extends java.lang.Object
SourceFile: "Test.java"
minor version: 0
major version: 50
Constant pool:
const #1 = class #2; // tests/Test
const #2 = Asciz tests/Test;
const #3 = String #4; // This is a sample program.
...
看到 ldc
instruction 了吗?它从运行时常量池中加载一个常量。那就是你的字符串存储的地方。
要同时打印常量池,请将 -verbose
option 添加到 javap 调用。
这是我的源代码:
public class Koray {
public static void main(String [] args) {
System.out.println("This is a sample program.");
}
}
当我编译它时,我得到了字节码。当我用十六进制查看器查看字节码时,我看到了部分:
19 54 68 69 73 20 69 73 20 61 20 73 61 6D 70 6C 65 20 70 72 6F 67 72 61 6D 2E
可以读作
This is a sample program.
如果字节被解释为字符。
当我这样做时
javap -c Koray.class
拆开这个 class 我明白了:
Compiled from "Koray.java"
public class Koray {
public Koray();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String This is a sample program.
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: bipush 10
10: istore_1
11: return
}
我的问题是,在反汇编的文本中哪里可以看到这个字符串?我只在评论中看到它。
ldc #3; //String This is a sample program.
这一行使用了opcode
ldc
,它将一个常量加载到操作数栈中。此时,我们将加载常量池 table.
#3
中的任何常量
常量池table是存储大多数文字常量值的地方。 (ref)命令javap -c -verbose <classfile>
为常量池table提供输出。
示例输出:
const #22 = String #23; // This is a sample program
const #23 = Asciz This is a sample program;
更多信息来自 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.
ldc #3
加载存储在常量池中的字符串常量,常量池是一个单独的table,存储String
字面量和class名称等常量。
请参阅 JVM 规范中的 http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4:
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.
您可以使用 javap -verbose ClassName
查看字符串 table。
示例输出类似于:
Compiled from "Test.java"
public class tests.Test extends java.lang.Object
SourceFile: "Test.java"
minor version: 0
major version: 50
Constant pool:
const #1 = class #2; // tests/Test
const #2 = Asciz tests/Test;
const #3 = String #4; // This is a sample program.
...
看到 ldc
instruction 了吗?它从运行时常量池中加载一个常量。那就是你的字符串存储的地方。
要同时打印常量池,请将 -verbose
option 添加到 javap 调用。