`

JAVA8 JVM的变化: 元空间(Metaspace)

 
阅读更多
本文将会分享至今为至我收集的关于永久代(Permanent Generation )的替代者:元空间(Metaspace)的信息。我也会比较在执行JAVA 程序时HotSpot 1.7 和 HotSpot 1.8 (b75)的运行行为。



关于元空间(Metaspace)最后的规范、调整参数和文档将在Java 8 正式发布之后公开。



元空间(Metaspace):一个新的内存空间的诞生.与 Oracle JRockit 和 IBM JVM类似,JDK 8.HotSpot JVM开始使用本地化的内存存放类的元数据,这个空间叫做元空间(Metaspace)。



一个好的消息是意味着java.lang.OutOfMemoryError: PermGen的空间问题将不复存在,并且不再需要调整和监控这个内存空间,虽然还没有那么快。当这个变化被默认执行的时候,我们会发现你任然需要担心类的元数据的内存占用率的问题,所以请记住这个新的特性并不会奇迹般的消除类和类加载器的内存泄漏。而是你需要使用一些不同的方式和学习新名词来追查这些问题。



总结:永久区这个内存空间被完全的移除 ,JVM参数PermSize 和 MaxPermSize会被忽略,当前在启动时会有警告信息



元空间(Metaspace)内存分配模型。现在大多数的类元数据分配在本地化内存中。我们用来描述类的元数据的klasses已经被移除。



元空间的容量 默认情况下,类元数据分配受到可用的本机内存容量的限制(容量依然取决于你使用32位JVM还是64位操作系统的虚拟内存的可用性)。



一个新的参数 (MaxMetaspaceSize)可以使用。允许你来限制用于类元数据的本地内存。如果没有特别指定,元空间将会根据应用程序在运行时的需求动态设置大小。



元空间的垃圾回收



如果类元数据的空间占用达到参数“MaxMetaspaceSize”设置的值,将会触发对死亡对象和类加载器的垃圾回收。



为了限制垃圾回收的频率和延迟,适当的监控和调优元空间是非常有必要的。元空间过多的垃圾收集可能表示类,类加载器内存泄漏或对你的应用程序来说空间太小了。



java堆空间的影响 一些各种各样的数据已经转移到Java堆空间。这意味着JDK8升级后,您可能会发现Java堆空间的不断增加。



元空间监控 元空间的使用从HotSpot 1.8开始有详细的GC日志输出。在我们基于B75测试的时候Jstat 和JVisualVM还没有升级, 目前还是引用到老的永久代空间。现在有足够的理论,我们可以通过我们的Java程序泄漏的行为来观察我们的这个新的内存空间...



永久代和元空间运行时对照:为了更好的理解新的元空间运行时的行为特征,我们创建一个类元数据泄露的java程序,你可以在这里下载源代码:



我们测试下面的场景:

使用JDK 1.7运行java程序,并且为了监控和耗尽永久代内存空间,将其设置为128MB

使用JDK1.8(B75)运行java程序,并且监控新的元空间内存的冬天增长和垃圾回收。

使用JDK1.8(B75)运行java程序,通过设置MaxMetaspaceSize 为128MB来同样耗尽元空间 .



JDK 1.7 @64-bit – PermGen depletion

java程序设置50k次的迭代

java的堆空间为1024MB

java的永久代空间为128MB  (-XX:MaxPermSize=128m)



正如你看到的JVisualVM的报告,当加载30K+ 的类的时候,永久代被耗尽。我们也可以从程序和GC的输出文件中发现耗尽。类元数据泄漏模拟器的作者Pierre-Hugues Charbonneau在博客: http://javaeesupportpatterns.blogspot.com中描述了错误: ERROR: java.lang.OutOfMemoryError: PermGen space 。现在我们使用 HotSpot JDK 1.8 JRE.来运行程序。



JDK 1.8 @64-bit – Metaspace dynamic re-size

Java 程序设置50k次的迭代

Java 堆空间为1024MB

Java 元空间为无限(默认值) 



正如你看到的详细的GC输出,为了满足我们的Java程序不断增加的类元数据的内存占用,JVM元空间扩大从20 MB动态占用本机内存高达328 MB。我们也可以观察垃圾收集,JVM在试图摧毁任何死类或类加载器对象。自从我们的Java程序泄漏,JVM不得不扩张元空间的内存空间。



该方案可以迭代50K次,并且没有OOM事件和加载50K+类。

接下去我们来看最后的测试场景:

JDK 1.8 @64-bit – Metaspace depletion

Java 程序设置50k次的迭代

Java 堆空间为1024MB

Java 元空间为128 MB (-XX:MaxMetaspaceSize=128m)



正如你看到的JVisualVM的报告,当加载30K+ 的类的时候,元空间被耗尽,和在JDK1.7的表现非常相近。我们也可以在程序和GC的输出日志中找到。另一个有趣的现象是,本机内存保留的占用空间是指定的最大大小的两倍之多。如果可能的话,为了避免本机内存浪费。这可能表明需要优化元空间扩张尺寸的策略,。

现在我们可以从java程序的输出日志中找到下面的异常:

ERROR: java.lang.OutOfMemoryError: Metadata space



正如预期的那样,设置元空间最大尺寸为128 MB,就像我们在JDK1.7中一样没有让我们完成我们的50K迭代的计划。JVM抛出一个新的OOM错误。上述OOM事件是由JVM从元空间在捕获一个一个内存分配失败后抛出。



metaspace.cpp 结束语

我希望你能欣赏这个对新的Java8元空间的早期的分析和实验 。目前观测表明,为了远离类似在我们最后测试场景中出现的频繁的元空间GC和OOM的问题,适当的监控和调优是必须的。以后的文章中可能包括性能比较,以确定这一新功能相关的潜在性能改进。请随时提供任何意见。

分享到:
评论

相关推荐

    JDK8的JVM内存结构,元空间替代永久代成为方法区及常量池的变化1

    在JDK8中,JVM内存结构发生了显著变化,尤其是元空间(MetaSpace)替代了永久代(Permanent Generation)作为方法区的一部分。这种方法区的调整是由于永久代存在的一些问题,比如大小设定困难,容易引发溢出,以及给...

    JVM内存空间分配笔记

    JVM(Java虚拟机)内存模型主要由以下几个部分组成:程序计数器、Java虚拟机栈、本地方法栈、Java堆以及方法区(在JDK 8之后称为元空间)。下面将对这几个部分进行详细介绍。 #### 二、程序计数器 程序计数器是一...

    java面试题_jvm(21题)

    15. **方法区的元空间(Metaspace)**:Java 8中取代了永久代,与操作系统内存直接交互,了解其溢出情况及配置。 16. **JIT编译器**:JVM如何使用即时编译技术提高程序运行效率,了解如何开启与优化。 17. **...

    java jvm初步了解;打卡狂神

    Java8 虚拟机采用了 Metaspace,取代了之前的 PermGen 空间,解决了之前的内存溢出问题。同时,Java8 虚拟机还引入了新的垃圾回收算法,like G1 垃圾回收器,提高了垃圾回收的效率。 3. OOM 和 StackOverFlowError ...

    杭州-蚂蚁金服-Java高级 java并发编程、JVM等

    - **更好的扩展性**:元空间大小不再受JVM堆内存限制,可以根据需要动态调整。 ### 5. 自主设计中间件的考量 #### 关键特性 - **远程过程调用(RPC)**:实现跨进程、跨语言的服务调用。 - **面向消息**:利用消息...

    最新 java se8 虚拟机 详解

    8. **MetaSpace替代PermGen**:Java 8中,永久代(Permanent Generation)被MetaSpace取代,这解决了 PermGen 空间溢出的问题,并允许JVM动态调整元空间大小。 9. ** invokedynamic指令**:Java 8进一步利用了...

    Jvm内存面试问题总结(2020).docx

    Java 8之后,永久代被元空间(Metaspace)取代。 - **年轻代**:进一步细分为Eden区和两个Survivor区(S0和S1),通常Eden区较大,而Survivor区较小。年轻代主要存储新创建的对象。 - **年老代**:存储经历过多次...

    JVM中[方法区]的所有内容-pdf

    而从JDK8开始,HotSpot JVM用元空间(Metaspace)取代了永久代,元空间不再局限于JVM设置的内存,而是利用本地内存,通过-XX:MetaspaceSize和-XX:MaxMetaspaceSize进行配置。元空间的大小更灵活,可以随应用需求动态...

    JVM-内存管理 2012-12.pdf

    在JDK 8及之后的版本中,方法区的实现被移除了,取而代之的是元空间(Metaspace),它使用本地内存而不是JVM堆内存。 Java堆是JVM内存管理中最大的一块区域,它负责存储对象实例及数组值。在虚拟机启动时创建,并且...

    JVM技术培训讲座

    如果PermGen空间(Java 8之前的版本)或Metaspace(Java 8及之后版本)过小,可能会导致频繁的GC活动,甚至出现OutOfMemoryError异常。 5. **常用的GC回收算法有哪些?** 常用的GC回收算法包括但不限于:串行收集...

    jvm调优示例

    GC是JVM自动回收不再使用的对象的过程,有新生代(Young Generation)、老年代(Tenured Generation)和持久代(Perm Generation,Java 8后被元空间Metaspace取代)三个部分。通过调整新生代和老年代的比例,如 `-XX...

    jvm的总结,主要是通过一些例子验证相关理论

    在JDK 8中,方法区被替换为元空间,使用本地内存而非JVM堆内存。 - **代码缓存(Code Cache)**:用于存储JIT编译后的本地代码。 - **压缩类空间(Compressed Class Space)**:用于存储指向类元数据的指针。 #### 三...

    【JVM】灵性一问——为什么用元空间替换永久代?

    然而,自Java 8开始,HotSpot JVM将永久代替换为了元空间(Metaspace)。这一转变源于对JVM性能优化和内存管理策略的改进需求。本文将深入探讨这一变化背后的原因以及元空间的特点。 首先,理解方法区的概念至关...

    JVM优化与OOM分析PPT

    在JDK8之后,永久代被元空间(Metaspace)所替代。 - **栈里对象存放**:通常情况下,栈中存放的是对象的引用而非对象本身。对象实例主要存放在堆中。 - **直接内存**:JDK1.4中新加入的概念,它允许Java程序直接...

    JVM面试1

    5. `-XX:MetaspaceSize`:设置元空间的初始大小,元空间替代了之前的永久代,存储类元数据。 6. `-XX:+PrintGCDetails`:开启详细GC日志输出,帮助分析垃圾回收性能。 7. `-XX:SurvivorRatio`:设置新生代中Eden区与...

    JVM内存溢出

    2. **OutOfMemoryError: PermGen space**:这个问题出现在永久代(在Java 8之前,之后称为Metaspace),这是存储类元数据的地方。如果类的数量过多或者加载了大量的动态库,可能导致永久代空间不足。可以通过`-XX:...

    tomcat-jvm调优

    - 在JDK 9及以后版本中,永久代被元空间(Metaspace)所替代,相关参数也发生了变化: - `XX:MetaspaceSize` 和 `-XX:MaxMetaspaceSize` 分别控制元空间的初始大小和最大大小。 #### 三、具体参数详解 接下来,...

    JVM基础知识及性能调优

    Java虚拟机(JVM)作为Java程序运行的基础环境,其内部结构复杂且高效。理解JVM的基础知识对于优化Java应用程序至关重要。JVM主要由以下几个关键部分组成: 1. **类加载器系统**:负责读取Java类文件(.class),并将其...

    JVM性能调优-JVM内存整理及GC回收.pdf

    从Java 8开始,永久代被元空间(Metaspace)取代。 #### 总结 综上所述,JVM性能调优涉及多个方面,包括理解参数传递机制、掌握不同类型的引用以及深入了解垃圾回收算法和分区处理方式等。通过合理配置和调整这些...

    JVM优化3(Tomcat参数调优,JVM参数调优,jvm字节码,代码优化).zip

    - **类加载和Metaspace大小**:`-XX:MaxMetaspaceSize`和`-XX:ClassCacheSize`限制元空间大小,防止内存溢出。 **3. JVM字节码理解与优化** JVM通过字节码执行Java程序,理解字节码有助于深入优化。关键概念有: -...

Global site tag (gtag.js) - Google Analytics