Java8新特性 - metaspace
原创2020/9/4...大约 2 分钟
Java8移除了永久代,新增了metaspace。
Java7中的永久代
在JVM规范第7版中,把内存分为以下5个区域:
- 方法区 Method Area
- 堆 Heap
- 虚拟机栈 VM Stack
- 本地方法栈 Native Method Stack
- 程序计数器 Program Counter Register
方法区是线程共享的内存区域,用于存储类信息、常量、静态变量等。
各个虚拟机对内存管理的实现方式可能略有不同,以最常见的HotSpot虚拟机为例,把虚拟机栈和本地方法栈合二为一了,并使用了永久代(Permanent Generation) 来实现方法区。
提示
原本常量池是放在永久代的,但在JDK1.7的HotSpot中已经把字符串常量池移到了堆中
涉及永久代的参数:
-XX:PermSize=256M
-XX:MaxPermSize=256M
永久代的缺陷
HotSpot使用永久代来实现方法区,本意是想让垃圾收集器像管理Java堆一样管理方法区,而避免为方法区再写一个垃圾收集器。
然而这样做带来了其他问题:
- 容易造成永久代内存溢出
- 由于方法区主要存储类信息,因此对方法区的垃圾回收主要是回收已卸载的类型,而类的回收条件非常苛刻,通常回收效果并不理想
提示
其他虚拟机,例如Oracle JRockit、IBM J9没有永久代概念。
Metaspace
在java8中,准确说是在HotSpot虚拟机中移除了永久代,而使用元空间(Metaspace) 来存储类元数据信息。元空间使用的是本地内存,可以使用-XX:MetaspaceSize和-XX:MaxMetaspaceSize调整元空间的大小,默认初始大小约21M,最大值不限制。
Metaspace会为每个类加载器及其加载过的类单独分配内存,通过以下几个命令可以查看Metaspace的空间占用情况。
- jmap -heap <pid>
- jmap -clstats <pid>
- jstat -gc <pid>