深入JVM 方法区和常量池溢出

Java虚拟机运行数据区中,常量池属于方法区内部,主要存放类加载的元信息、常量、静态变量、即时编译的代码,还有编译后生成的字面值 符号引用

而最经典的String.intern()方法是一个native本地方法,它的作用:如果字符串常量池中已经等于此String的对象字符串,则返回常量池中的这个String对象;否则,将此String对象放入常量池,并返回String对象的引用

案例演示:  

设定常量池上限,由于HotSpot常量池属于永生代  设置PermSize

VM Args:-XX:PermSize=10M -XX:MaxPermSize=10M

通过不断的String.intern()看能否到达常量区上限

注意通过链表保持对常量池对象的引用,否则可能被GC回收,导致无法观察到异常

深入JVM 方法区和常量池溢出

结果程序并没有出现OutOfMemoryError错误异常,而是不断运行

原来在JDK1.7之后,常量池已经不再属于永生代

 

再看一段程序

 

 

 

深入JVM 方法区和常量池溢出

在JDK1.7之前 这个结果返回false  而在JDK1.7之后(本机为JDK1.8) 结果如图为true

StringBuilder构造的String先在堆中创建,而后调用String.intern()将引用存放到常量池中  所以2者均指向堆中同一对象 

 

方法区溢出是一种常见的内存溢出错误异常,一个类要被垃圾收集器回收,判定条件苛刻,在动态生成大量Class应用中,容易发生方法区内存溢出。如 大量JSP文件的应用,由于JSP第一次运行时需要编译为Java类,可能出现大量类加载涌入方法区,而造成OutOfMemoryError异常

 

 

 

 

 

 

 

 

 

来源:一只老风铃

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2019年1月17日
下一篇 2019年1月18日

相关推荐