String常量池在内存中的位置
- JDK 6及之前:位于方法区。方法区是Java虚拟机规范中定义的一块内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
- JDK 7:移至堆内存中。堆是Java虚拟机所管理的内存中最大的一块,是被所有线程共享的一块内存区域,在虚拟机启动时创建,用于存放对象实例。
- JDK 8及之后:仍然在堆内存中。此时方法区被元空间取代,元空间并不在虚拟机内存中,而是使用本地内存。
String常量池在内存管理方面的主要特点
- 共享机制:当创建一个新的字符串常量时,JVM会首先检查常量池中是否已经存在相同内容的字符串。如果存在,则直接返回常量池中该字符串的引用,而不是在堆中创建一个新的对象。这样可以减少内存的开销,提高内存利用率。例如:
String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2); // 输出true,因为s1和s2引用的是常量池中的同一个字符串对象
- 动态性:常量池并非在编译期就完全确定,某些字符串常量可能在运行时才被加入到常量池中。例如,通过
intern()
方法可以将运行时创建的字符串对象添加到常量池中。
String s3 = new String("world");
String s4 = s3.intern();
String s5 = "world";
System.out.println(s4 == s5); // 输出true,s3.intern()将s3对应的字符串加入常量池并返回其引用,与s5引用相同
- 生命周期:常量池中的字符串对象生命周期与应用程序的生命周期相关。只要应用程序在运行,并且常量池中的字符串被引用,这些对象就不会被垃圾回收。当应用程序结束或者常量池中的字符串不再被任何地方引用时,它们所占用的内存才有可能被垃圾回收机制回收。