方法区和运行时常量池溢出
来源:互联网 发布:分销商城系统源码下载 编辑:程序博客网 时间:2024/06/01 10:49
本文来自《深入理解Java虚拟机》
由于运行时常量池是方法区的一部分,因此这两个区域的溢出测试就放在一起进行。前面提到JDK1.7开始逐步“去永久代”的事情,在此就以测试代码观察一下这件事对程序的实际影响。
String.intern()是一个Native方法,它的作用是:如果字符串常量池中已经包含一个等于此String对象的字符串,则返回代表池中这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。在JDK1.6及之前的版本中,由于常量池分配在永久代内,我们可以通过-XX:PermSize和-XX:MaxPermSize限制方法区大小,从而间接限制其中常量池的容量,如代码:
/***VM Args:-XX:PermSize=10M -XX:MaxPermSize=10Mpublic class RuntimeConstantPoolOOM{public void main(String[] args){ //使用List保持着常量池引用,避免Full GC回收常量池行为 List<String> list = new ArrayList<String>(); //10M的PermSize在integer范围内足够产生OOM了 int i = 0; while(true){ list.add(String.valueOf(i++).intern()); } }}
运行结果:
从运行结果中可以看出,在OutOfMemoryError后面跟随的提示信息是“PermGen space”,说明运行时常量池属于方法区(HotSpot虚拟机中的永久代)的一部分。而使用JDK1.7运行这段程序就不会得到相同的结果,while循环将一直进行下去。关于这个字符串常量池的实现问题,还可以引申出一个更有意思的影响,如:
public class RuntimeConstantPoolOOM{ public void main(String[] args){ String str1 = new StringBuild("计算机").append("软件").toString(); System.out.println(str1.intern() == str1); String str2 = new StringBuild("ja").append("va").toString(); System.out.println(str2.intern() == str2); }}这段代码在JDK 1.6中运行,会得到两个f al se,而在JDK 1.7中运行,会得到一个t ru e和一个f al se。产生差异的原因是:在JDK 1.6中,in t ern ()方法会把首次遇到的字符串实例复制到永久代中,返回的也是永久代中这个字符串实例的引用,而由St rin g Bu i lder创建的字符串实例在Java堆上,所以必然不是同一个引用,将返回f al se。而JDK 1.7(以及部分其他虚拟机,例如JRock i t)的in t ern ()实现不会再复制实例,只是在常量池中记录首次出现的实例引用,因此in t ern ()返回的引用和由St rin g Bu i lder创建的那个字符串实例是同一个。对st r2比较返回f al se是因为“java”这个字符串在执行St rin g Bu i lder.t oSt rin g ()之前已经出现过,字符串常量池中已经有它的引用了,不符合“首次出现”的原则,而“计算机软件”这个字符串则是首次出现的,因此返回t ru e。
0 0
- 方法区和运行时常量池溢出
- 方法区和运行时常量池溢出
- 方法区和运行时常量池溢出
- 方法区和运行时常量池溢出
- 方法区和运行时常量池溢出
- Java方法区和运行时常量池溢出问题分析
- 运行时常量池溢出
- 运行时常量池溢出
- Java虚拟机-----方法区和运行时常量池
- Java虚拟机-----方法区和运行时常量池
- Java虚拟机-----方法区和运行时常量池
- Java虚拟机-----方法区和运行时常量池
- jvm_内存溢出_运行时常量池溢出
- 编译时常量和运行时常量
- 运行时常量池
- 运行时常量池
- java常量池和运行时常量池
- Java虚拟机OOM之运行时常量池溢出(5)
- 【javaEE】mybatis下编译出错
- Bootstrap源码解读(第十一弹:模态弹出框)
- Windows TrayIcon (Shell_NotifyIcon)
- magento的prototype表单验证
- linux命令
- 方法区和运行时常量池溢出
- smarty学习4
- 关于开漏极(open drain)输出与推挽(push/pull)输出
- JS来回切换路径
- 数据库事务隔离级别
- RESTful API 设计指南
- Zabbix分布式监控(zabbix-proxy)的配置关键点
- Java进阶 ---- 内存管理与垃圾回收
- 微信公众号开发系列之发送红包-java版本