何时何地在Java源代码中初始化/存储String?

这是我的源代码:

public class Koray { public static void main(String [] args) { System.out.println("This is a sample program."); } } 

当我编译它时,我得到字节码。 当我用hex查看器查看字节码时,我看到部分:

 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 

我拆开这个课我看到:

 Compiled from "Koray.java" public class Koray { public Koray(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."":()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 指令 ? 它从运行时常量池中加载常量。 这就是你的字符串存储的地方。 要打印常量池,请在javap调用中添加-verbose 选项 。

 ldc #3; //String This is a sample program. 

该行使用opcode ldc ,它将常量加载到操作数堆栈上。 此时,我们将加载常量池表的索引#3的任何常量。

常量池表是存储大多数文字常量值的位置。 ( ref )命令javap -c -verbose 提供常量池表的输出。

输出示例:

 const #22 = String #23; // This is a sample program const #23 = Asciz This is a sample program; 

有关VM Spec( http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html )的更多信息:

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

ldc #3加载存储在常量池中的字符串常量,该常量池是一个单独的表,用于存储常量,如String文字和类名。

请参阅JVM规范中的http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4 :

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

您可以使用javap -verbose ClassName查看字符串表。

示例输出将类似于:

 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. ...