欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

java学习——浅谈Java常量池,

来源: javaer 分享于  点击 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

相关文章

    暂无相关文章
相关栏目:

用户点评