java学习——浅谈Java常量池,
分享于 点击 30855 次 点评:246
java学习——浅谈Java常量池,
一、概述
- 常量池:编译期被确定,*.class文件中的一部分,包含字面量(Literal)和符号引用(Symbolic Reference)。
- 字面量:文本字符串、声明为final的常量值(int/long/double...)等。
- 符号引用:类和接口的完全限定名(Fully Qualified Name)、字段的名称和描述符(Descriptor)、方法的名称和描述符。
- 运行时常量池:方法区的一部分,jvm在完成类装载操作后,将class文件中的常量池载入内存并保存在方法区中。
- JDK1.6之前字符串常量池位于方法区。
JDK1.7字符串常量池已经被移至堆。
JDK1.8字符串常量池位移至元空间。
二、字符串常量池
字符串常量池属于运行时常量池的一部分
String s1 = "Hello";
String s2 = "Hello";
String s3 = "Hel" + "lo";
String s4 = "Hel" + new String("lo");
String s5 = new String("Hello");
String s6 = s5.intern();
String s7 = "H";
String s8 = "ello";
String s9 = s7 + s8;
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // true
System.out.println(s1 == s4); // false
System.out.println(s1 == s9); // false
System.out.println(s4 == s5); // false
System.out.println(s1 == s6); // true
java中==比较的是内存地址
- 以上所讲仅涉及字符串常量池,实际上还有整型常量池、浮点型常量池等等,但都大同小异
- 数值类型的常量池不可以手动添加常量,程序启动时常量池中的常量就已经确定了,比如整型常量池中的常量范围:-128~127,只有这个范围的数字可以用到常量池。
三个非常重要的结论:
三、常量池溢出
/**
* jdk1.6 -XX:MaxPermSize=5M OutOfMemoryError: PermGen space
* jdk1.7 -Xmx5M OutOfMemoryError: Java heap space
* jdk1.8 -Xmx5M OutOfMemoryError: GC overhead limit exceeded
* jdk1.8 -XX:MaxMetaspaceSize=2M OutOfMemoryError: Metaspace
*/
public class ConstantPoolOOM {
public static void main(String[] args) throws InterruptedException {
List<String> list = new ArrayList<String>();
int index = 0;
while (true) {
list.add(String.valueOf(index++).intern());
}
}
}
- jdk1.6运行时常量池在方法区中,设置-XX:MaxPermSize=5M,导致OutOfMemoryError: PermGen space
- jdk1.7运行时常量池在堆中,仅仅保存常量的引用,常量对象在堆中,设置-Xmx5M,导致OutOfMemoryError: Java heap space
- jdk1.8运行时常量池在元空间中,仅仅保存常量的引用,常量对象在堆中,
设置-XX:MaxMetaspaceSize=2M,导致OutOfMemoryError: Metaspace
设置-Xmx5M,导致OutOfMemoryError: GC overhead limit exceeded
四、jdk1.6和1.7+常量池的差异
/**
* jdk1.6 false false
* jdk1.7+ true false
*/
public class ConstantPoolTest {
public static void main(String[] args) {
String str1=new StringBuilder("计算机").append("软件").toString();
System.out.println(str1.intern()==str1);
String str2=new StringBuilder("ja").append("va").toString();
System.out.println(str2.intern()==str2);
}
}
参考资料:
http://www.cnblogs.com/iyangyuan/p/4631696.html
https://segmentfault.com/a/1190000010412582
相关文章
- 暂无相关文章
用户点评