`

JAVA 8 :从永久区(PermGen)到元空间(Metaspace)

    博客分类:
  • JVM
阅读更多
本文系翻译:原文地址
你注意到了吗?JDK 8早期可访问版本已经提供下载了,java 开发人员可以使用java 8 提供的新的语言和运行特性来做一些实验。其中一个特性就是完全的移除永久代(Permanent Generation (PermGen)),这从JDK 7开始Oracle就开始行动了,比如:本地化的String从JDK 7开始就被移除了永久代(Permanent Generation )。JDK 8让它最终退役了。

本文将会分享至今为至我收集的关于永久代(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的空间问题将不复存在,并且不再需要调整和监控这个内存空间,虽然还没有那么快。当这个变化被默认执行的时候,我们会发现你任然需要担心类的元数据的内存占用率的问题,所以请记住这个新的特性并不会奇迹般的消除类和类加载器的内存泄漏。而是你需要使用一些不同的方式和学习新名词来追查这些问题。

我建议你阅​​读永久带移除的总结和Jon对这个问题的意见

 总结:

永久区的情况:

  • 这个内存空间被完全的移除 
  • 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程序的输出日志中找到下面的异常:
1.Class metadata leak simulator
2.Author: Pierre-Hugues Charbonneau
4.ERROR: java.lang.OutOfMemoryError: Metadata space
5.Done!
正如预期的那样,设置元空间最大尺寸为128 MB,就像我们在JDK1.7中一样没有让我们完成我们的50K迭代的计划。JVM抛出一个新的OOM错误。上述OOM事件是由JVM从元空间在捕获一个一个内存分配失败后抛出。
 #metaspace.cpp 结束语
 我希望你能欣赏这个对新的Java8元空间的早期的分析和实验 。目前观测表明,为了远离类似在我们最后测试场景中出现的频繁的元空间GC和OOM的问题,适当的监控和调优是必须的。以后的文章中可能包括性能比较,以确定这一新功能相关的潜在性能改进。请随时提供任何意见。 
 
分享到:
评论
1 楼 yizishou 2017-06-06  

相关推荐

    java.lang.OutOfMemoryError: PermGen space及其解决方法

    - 从Java 8开始,PermGen space被Metaspace所替代。Metaspace不在堆上分配,而是使用本机内存。这样可以在一定程度上解决PermGen space不足的问题。 - 示例命令行参数:`-XX:MaxMetaspaceSize=256m` 4. **清理...

    java.lang.OutOfMemoryError: PermGen space

    然而,自Java 8开始, PermGen 空间已经被移除,取而代之的是Metaspace。Metaspace的出现是为了避免先前PermGen空间的限制,它不再有固定的大小上限,而是根据需要自动增长。但这并不意味着我们可以忽视内存管理,...

    解决OutOfMemoryError: PermGen space

    - Java 8引入了一个新的内存区域称为Metaspace,代替了PermGen space。Metaspace位于本地内存中,其大小不受JVM堆内存的限制。这在一定程度上缓解了PermGen space溢出的问题。 #### 四、总结 解决...

    OutOfMemoryError-PermGen-space-的解决方案亲测有效

    - 从Java 8开始,PermGen空间被Metaspace所取代,Metaspace的大小不再受固定限制,而是随着可用物理内存而变化。这有助于缓解PermGen空间不足的问题。 #### 五、案例分析 本案例发生在一个使用MyEclipse 8.5和...

    Java内存不足PermGen space错误探究.pdf

    1. 增大PermGen空间大小:通过调整JVM启动参数,如`-XX:MaxPermSize`(Java 8之前)或`-XX:MaxMetaspaceSize`(Java 8及以后版本)来增加永久代或元空间的容量。 2. 优化类加载:减少不必要的类加载,如使用类的懒...

    解决Eclipse Tomcat OutOfMemoryError:PermGen space的问题

    此外,升级到Java 8及以上版本也是一个有效的解决方案,因为这些版本的JVM已经用Metaspace取代了PermGen,Metaspace具有更灵活的内存管理机制,可以自动扩展以适应应用需求,从而减少了此类内存溢出问题的发生。

    java虚拟机参数配置

    从Java 9开始,永久代已经被元空间(Metaspace)所取代。但在本例中,我们依然使用了针对永久代的配置参数,这些参数在Java 8及更早版本中非常常见。 - **-XX:PermSize=512m**:此参数指定了PermGen Space的初始...

    tomcat 出现 OutOfMemoryError 的解决方法

    - 从 JDK 8 开始,PermGen space 已被永久代 (metaspace) 替换。Metaspace 使用本地内存而非堆内存,因此可以更灵活地调整其大小。 #### 五、Java heap space 溢出的原因及解决方法 除了 PermGen space 溢出之外,...

    JAVA8虚拟机(jvm)规范_Chinese version.rar

    6. **元空间(Metaspace)**:Java8替代了永久代(PermGen),使用元空间来存储类元数据。元空间位于 native memory 中,避免了永久代因类数量过多导致的 OutOfMemoryError。 7. **并行与并发**:JVM支持多线程执行...

    tomcat内存溢出问题.doc

    在早期的Java版本中,方法区被划分为永久代(Permanent Generation, PermGen),用于存储类的元数据,如类名、方法信息、字段信息等。随着Java的更新,这个区域被移除并替换为MetaSpace(在Java 8及以后的版本)。 ...

    Java面试题--java8

    在Java 8中,元空间(MetaSpace)取代了永久代(PermGen Space)。永久代是JVM中存储类元数据的区域,但在Java 8中,元数据被存储在本机内存的MetaSpace中,不再占用堆内存,从而避免了内存溢出的问题。元空间的大小...

    java内存机制及异常处理

    常见的内存错误包括`java.lang.OutOfMemoryError: Heap space`(堆空间不足)、`java.lang.OutOfMemoryError: PermGen space`(方法区空间不足)和`java.lang.StackOverflowError`(栈溢出)。这些错误通常由于物理...

    Javaheapspace与PermGenspace.docx

    Java虚拟机(JVM)在运行Java程序时,会分配不同的内存区域,包括堆空间(Heap Space)和永久代空间(PermGen Space)。这两个区域的设置不当可能导致内存溢出错误,影响程序的稳定性和效率。 1. **Java Heap Space...

    最新 java se8 虚拟机 详解

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

    优化Java堆大小的5个技巧

    - **综合考虑多方面因素**:不仅要关注Java Heap的大小调整,还要考虑到Native Heap和PermGen/Metaspace的需求。 #### 二、数据和应用程序为王:回顾静态占用需求 ##### **2.1 应用程序与数据的影响** 应用程序的...

    java内存泄漏解决

    3. **使用Metaspace**:升级到JDK 8及以上版本,利用Metaspace代替永久代,自动管理元数据的内存。 #### 七、总结 解决Java内存泄漏问题需要从多方面入手,包括合理设置JVM参数、优化代码逻辑、使用合适的工具进行...

    OutOfMemoryError_8种典型案例分享

    随着Java的发展,类元信息的存储方式从永久代转移到了使用本地内存的元空间(Metaspace)。当元空间内存放的类元信息超出限制时,会抛出OutOfMemoryError: Metaspace错误。增加-XX:MaxMetaspaceSize参数可以设置元...

    jboss内存溢出原因

    1. **PermGen Space(永久代)内存溢出**:当JVM的永久代空间不足时,会抛出`java.lang.OutOfMemoryError: PermGen space`异常。 2. **Heap Space(堆空间)内存溢出**:当JVM的堆空间不足时,会抛出`java.lang....

Global site tag (gtag.js) - Google Analytics