方法区和运行时常量池溢出

由于运行时常量池是方法区的一部分,因此这两个区域的溢出测试就放在一起进行。

如果要向运行时常量池中添加内容,最简单的做法就是使用String.intern()这个Native方法。该方法的作用是:如果字

符串常量池中已经包含一个等于此String对象的字符串,则返回代表池中这个字符串的String对象;否则,将此String

对象包含的字符串添加到常量池中,并且返回此String对象的引用。在JDK 1.6及之前的版本中,由于常量池分配在永

久代区内,我们可以通过-XX:PermSize和-XX:MaxPermSize限制方法区的大小,从而间接限制其中常量池的容量,

如代码清单2-6所示。


代码清单2-6 运行时常量池导致的内存溢出异常

<span style="font-size:18px;">package com.npf.test;

import java.util.ArrayList;
import java.util.List;

/**
 * 
 * VM Args:-XX:PermSize=10M -XX:MaxPermSize=10M
 * 
 * @author Jack
 */
public class RuntimeConstantPoolOOM {

	public static void main(String[] args) {
		// 使用List保持着常量池引用,避免Full GC回收常量池行为
		List<String> list = new ArrayList<String>();
		
		// 10MB的PermSize在integer范围内足够产生OOM了
		int i = 0;
		while (true) {
			list.add(String.valueOf(i++).intern());
		}
	}

}
</span>

运行结果(JDK 1.6):

<span style="font-size:18px;">Exception in thread "main" java.lang.
OutOfMemoryError: PermGen space  
at java.lang.String.intern(Native Method)  
at org.fenixsoft.oom.RuntimeConstantPoolOOM.
main(RuntimeConstantPoolOOM.java:18)</span>


从运行结果中可以看到,运行时常量池溢出,在OutOfMemoryError后面跟随的提示信息是“PermGen space”,说明

运行时常量池属于方法区(HotSpot虚拟机中的永久代)的一部分。

而使用JDK 1.7 运行这段程序就不会得到相同的结果,While循环将一直进行下去。



----------------------------------华丽的分割线----------------------------------------------------------------------------

关于这个字符串常量池的实现问题,还可以引申一个更有意思的影响。



参考文献:

1. 第2章 Java内存区域与内存溢出异常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值