Java为什么修改永久代_Java从永久代PermGen到MetaSpace元空间的迁移

Java8永久代被移除

OutOfMemoryError,这是由于您的HotSpotVM的PermGen空间耗尽造成的。这个问题很常见,通常是由于应用程序的动态重新部署(例如,从应用程序服务器加载和卸载Java EE应用程序)通常会触发类元数据泄漏;最终导致固定PermGen空间完全耗尽。

然而,oraclejrockit和ibmjre一开始并没有使用PermGen空间。它们使用C堆(本机内存)来存储类元数据。

当前的oraclejvm策略是将HotSpot和JRockit产品线合并到一个JVM项目中,该项目将包含每个VM的最佳特性。

没有永久代的未来对你意味着什么?

没有PermGen空间意味着不再通过–XX:PermSize&-XX:MaxPermSize配置和调整此内存空间,因为类元数据将移动到本机内存(C-Heap)和OldGen空间,不再可配置。

但是,我建议您提高对本机内存空间(例如C-Heap)的警觉性和监视级别。与Java堆一样,您可能仍然面临本机内存空间的容量或泄漏问题,因此请确保在JVM容量规划练习中包含此分析。

永久空间移除了吗?

还不完全。正如在Oracle博客中提到的,PermGen的删除需要一段时间,所以在java7的更多版本发布之前不要期望完全删除。

最后,我使用Java 7示例程序运行了一个简单的测试详细:gc已打开如您所见,PermGen内存空间仍然存在于这个热点版本(构建21.0-b17)中。

d587718a76e86dc10d19b6fe5d321f3f.png

0988e01c324884c614965e46565d628b.png

Java8中的metaspace元空间

在这篇文章中,我们将看到一个JVM更新,即删除永久代生成。在这里,我们将看到为什么需要删除永久代和它的替代元空间。

这就是Java6中堆结构的样子

f2919d5f34e6c19ecd5e3d65a89cfd72.png

永久代Permgen

包含虚拟机本身的所有反射数据的池,例如类和方法对象。对于使用类数据共享的javavm,这一代分为只读和读写两部分。

永久生成包含JVM描述应用程序中使用的类和方法所需的元数据。永久生成由JVM在运行时根据应用程序使用的类填充。此外,javase库类和方法可以存储在这里。

如果JVM发现不再需要类,并且其他类可能需要空间,则可以收集(卸载)这些类。永久生成包含在完整的垃圾收集中

用于JVM类元数据的Java堆区域。

Hotspot对Java类的内部表示。

类层次结构信息、字段、名称

方法编译信息和字节码

变量

常数池与符号分解

PermGen永久代大小

限制为MaxPermSize–默认值为64M-85M

与Java堆相邻:使用非连续堆-card table(一种记录一代中oop发生变化的记忆集)来识别旧gen和permgen的年轻引用将更加昂贵和复杂。

一旦耗尽抛出内存错误“永久空间”。

应用程序可以清除导致类卸载的引用。

使用更大的MaxPermSize重新启动。

所需的大小取决于类的数量、方法的大小、常量池的大小。

为什么PermGen被淘汰了?

启动时大小固定-难以调整。

-XX: MaxPermSize=?

内部热点类型是Java对象:可以用完整的GC移动,不透明,不强类型,很难调试,需要元数据。

简化完整集合:每个收集器的元数据的特殊迭代器

想同时释放类数据,而不是在GC暂停期间

实现PermGen限制的未来改进。

JVM元数据现在去了哪里?

d181af0337ee79c6e7e4eb7e2caf73e9.png

metaspace元空间

永久生成(PermGen)空间已经被完全移除,并被一个称为元空间的新空间所取代。

删除PermGen的结果是,显然PermSize和MaxPermSize JVM参数被忽略,您永远不会得到java.lang.OutOfMemoryError:PermGen错误。

jdk8热点JVM现在使用本机内存来表示类元数据,称为Metaspace。

利用Java语言规范属性:类和关联的元数据生存期与类装入器的生存期匹配。

每个装载机存储区域–元空间

仅线性分配

不单独回收(除了重定义类和类加载失败)

无GC扫描或压缩

无需重新定位元空间对象

类加载器被GC发现死机时集体回收

java8metaspace内存溢出的排查思路可参考这篇文章:https://javakk.com/160.html

元空间内存分配模型

类元数据的大多数分配现在都是从本机内存中分配的。

用于描述类元数据的类已被删除。

为元数据分配了多个映射的虚拟内存空间。

按类装入器块列表分配

块大小取决于类装入器的类型。

sun/reflect/Delegating类加载器的较小块。

将区块返回到空闲区块列表。

清空时返回虚拟内存空间。

减少分裂的策略。

我们将看到如何为元数据分配虚拟内存空间,以及它如何使用此图片加载每类加载程序

bb71de640ca524bd56d155225a6d876d.png

您可以看到如何分配虚拟内存空间(vs1、vs2、vs3)以及如何分配每个类装入器块。CL-类加载器

理解“_mark标记”和“_klass指针”

要理解下一个图表,您需要了解这些指针。

在JVM中,每个对象都有一个指向其类的指针,但只指向其具体类,而不指向其接口或抽象类。

对于32位JVM:

_标记:4字节常量

_klass:指向类的4字节指针

内存中对象布局中的第二个字段(对于32位JVM,偏移量为4,对于64位JVM,偏移量为8,从内存中对象的地址开始偏移量为8)指向内存中对象的类定义。

对于64位JVM:

_标记:8字节常量

_klass:指向类的8字节指针

对于具有压缩OOP的64位JVM:

_标记:8字节常量

_klass:指向类的4字节指针

Java对象内存布局

c927b0db9571de51f857ea6cad909c13.png

带有压缩指针的Java对象内存布局

697ab1a6ee7b66057fc6c8ca1af8c759.png

64位平台的默认值。

压缩对象指针-XX:+UseCompressedOops

“oops”是“普通”对象指针。

对象指针在Java堆中的对象中被压缩到32位。

使用堆基(如果Java堆在较低的26G内存中,则为零)。

压缩类指针-XX:+UseCompressedClassPointers。

对象有一个指向VM元数据类(第二个字)的指针,该类压缩为32位。

使用压缩类指针空间的基。

元空间与压缩类指针空间的区别

压缩的类指针空间只包含类元数据。

InstanceKlass,arraylass

仅当UseCompressedClassPointers为true时。

出于性能考虑,其中包括Java虚拟表。

我们仍在缩小此元数据类型。

Metaspace包含所有其他可能很大的类元数据。

方法,字节码,ConstantPool。。。

元空间调整

可以使用-XX:MaxMetaspaceSize标志设置最大元空间大小,默认值为无限,这意味着只有系统内存是限制。-XX:MetaspaceSize调优标志定义了元空间的初始大小,如果不指定此标志,则元空间将根据运行时的应用程序需求动态重新调整大小。

调整标志-MaxMetaspaceSize

-XX: MaxMetaspaceSize={unmited}

元空间受计算机上内存量的限制。

在发生过度交换和本地分配失败之前,限制类元数据使用的内存。

如果怀疑类装入器内存泄漏,请使用。

如果地址空间可能耗尽,请在32位上使用。

初始MetaspaceSize 21 mb–GC初始高水位标记,用于完成完整的GC收集类。

GC的目的是检测死区类装入器和卸载类。

如果启动时执行太多GC,则设置为更高的限制。

可能使用PermSize设置的相同值来延迟初始GC。

高水痕随着后续收集的增加而增加,在下一次元空间GC之前,合理数量的主室。

请参见MinMetaspaceFreeRatio和MaxMetaspaceFreeRatio

与类似GC自由比参数类似的解释

调整标志-CompressedClassSpaceSize

仅当-XX:+UseCompressedClassPointers(默认值为64位)时有效。

-XX:CompressedClassSpaceSize=1G。

由于这个空间目前在启动时是固定的,所以一开始就要保留大量空间。

使用前不提交。

未来的工作是使这片空间变得可扩展。

不需要是连续的,只能从基地址访问。

而是将更多的类元数据转移到元空间。

将来可能会根据PredictedLoadedClassCount(现在是实验标志)进行人体工程学设置。

设置其他内部JVM数据结构的大小,如加载类的字典。

元空间工具

jmap-permstat选项重命名为jmap-clstats

打印Java堆的类装入器统计信息。对于每个类装入器,将打印其名称、活动性、地址、父类装入器以及它已加载的类的数量和大小。此外,还打印了内插字符串的数量和大小。

jstat-gc选项显示Metaspace而不是PermGen。

jcmdGC.class_stats统计.

提供类元数据大小的详细柱状图。

使用-XX:+UnlockDiagnosticVMOptions启动java

改进的GC性能

如果您很好地理解了元空间的概念,就很容易看到垃圾收集方面的改进

在完全收集期间,不扫描指向元数据指针的元数据。

删除了许多用于元数据扫描的复杂代码(尤其是CMS)。

Metaspace包含一些指向Java堆的指针。

指向类元数据中java/lang/Class实例的指针

指向数组类元数据中组件java/lang/Class的指针

没有压缩元数据的成本。

减少根扫描(不扫描已加载类的VM字典和其他内部哈希表)。

缩短完整收集时间。

并行标记循环后G1中的类卸载工作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值