JVM之运行时常量池,不同JDK版本中的变化

文章目录

    • 示例代码
    • JDK6
      • PermGen(永久代)
    • JDK7
    • JDK8
    • 结论

示例代码

/**
 * VM options:-Xms10M -Xmx20M -XX:PermSize=10M -XX:MaxPermSize=10M -XX:-UseGCOverheadLimit
 */
public class JVMTest02 {

	byte[] byteArray = new byte[1 * 1024 * 1024];

	public static void main(String[] args) {
		List<JVMTest02> list = new ArrayList<JVMTest02>();

		int count = 0;
		try {
			while (true) {
				list.add(new JVMTest02());
				count = count + 1;
			}
			
		} catch (Throwable e) {
			System.out.println("********count:" + count);
			e.printStackTrace();
		}
	}
}

在IDE中设置 VM的参数:

-Xms10M -Xmx20M -XX:PermSize=10M -XX:MaxPermSize=10M -XX:-UseGCOverheadLimit

JDK6

JDK6 代码运行及其结果:
JVM之运行时常量池,不同JDK版本中的变化_第1张图片

PermGen(永久代)

http://ifeve.com/java-permgen-removed/

绝大部分 Java 程序员应该都见过 java.lang.OutOfMemoryError: PermGen space 这个异常。
这里的PermGen space 其实指的就是方法区 。不过 方法区PermGen space又有着本质的区别。
方法区 是 JVM 的规范,而 PermGen space 则是 HotSpot 虚拟机基于 JVM 规范对 方法区 的一个落地实现,并且只有 HotSpot 才有 PermGen space
而对于其他类型的虚拟机,如 JRockit(Oracle)、J9(IBM) 并没有 PermGen space

由于方法区 主要存储类的相关信息,所以对于动态生成类的情况比较容易出现永久代的内存溢出。

JDK7

JDK7 代码运行及其结果:
在这里插入图片描述

JDK8

JDK8 代码运行及其结果:JVM之运行时常量池,不同JDK版本中的变化_第2张图片

结论

从运行结果可以得出:

1)、运行时常量池

  • 在 JDK6 ,抛出永久代(PermGen space)异常,说明 运行时常量池 存在于 方法区
  • 在 JDK7、JDK8 抛出堆(Java heap space)异常,说明 运行时常量池 此时在 Java堆 中;

2)、永久代元空间

JDK8 打印ignoring option PermSize=10M; support was removed in 8.0 ... 警告的原因:

  • JDK8时,永久代已被移除,所以不支持 -XX:PermSize=10M -XX:MaxPermSize=10M 永久代的参数设置;
  • JDK8 的方法区是 元空间,其参数设置是 -XX:MetaspaceSize=N -XX:MaxMetaspaceSize=N
  • 反推证出 JDK6 、 JDK7 时,永久代还是存在的,否则打印警告的。

知识扩展:

JDK版本 方法区的实现 运行时常量池所在的位置
JDK6 PermGen space(永久代) PermGen space(永久代)
JDK7 PermGen space(永久代) Heap(堆)
JDK8 Metaspace(元空间) Heap(堆)

JVM 中的方法区、永久代(PermGen space)、元空间(Metaspace)三者的区别:
https://blog.csdn.net/xiaojin21cen/article/details/104267301

你可能感兴趣的:(#,JVM)