String abc = "dog";
String变量名称(即abc)是否存储堆中的位置,而它本身存储在堆栈中,就像数组一样?或者字符串的工作方式不同?
答案 0 :(得分:4)
abc
:如果该代码位于某个方法中,则名称 abc
不会存储在任何位置。它只是索引引用的堆栈变量。
如果该代码在类级别,它定义了一个实例变量,因此它的名称存储在字节码中。
您可以使用javap -c ClassName
查看类的字节码,当然,您可以通过您喜欢的二进制文件查看器查看.class
文件的内容(或者如果您喜欢它-school,hexdump -C filename
)。
字符串的值(如所有对象的值)存储在堆中(概念上,请参阅*以获取更多信息)。 String literals 和其他字符串编译时常量(例如代码中的"dog"
)存储在the constant pool中,用于类(这是.class
的一部分格式)。加载类时,这些字符串常量为interned到当前运行的JVM的字符串实习池中。字符串实习池位于堆上。
如果该代码在方法中,则字符串池中字符串的引用将存储在堆栈中。
如果该代码在类级别,则引用存储在实例变量的存储中,该存储是实例变量所属对象的一部分。该对象在概念上是在堆上。*
Oracle的JVM非常聪明。在一个方法中,本地创建的对象可以很好地分配在堆栈而不是堆上,作为性能优化,因为在离开方法时重置堆栈指针比释放堆内存要简单得多。但是,如果对方法的引用在方法终止后仍然存在,则将对象从堆栈复制到堆中,因为当然,堆栈将作为退出方法的过程的一部分弹出。 JVM关于是否这样做的决定是基于各种因素,尤其是所讨论的方法是否在代码中的“热点”值得优化。
但这是JVM中的性能优化。从概念上讲,对象是在堆上分配的。