详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt266

正如大家所知,JDK 8 Early Access版已经提供下载。这使开发者可以体验Java8的新特性。其中之一,是Oracle从JDK7发布以来就一直宣称的要完全移除永久代空间。例如,字符串内部池,已经在JDK7中从永久代中移除。JDK8的发布将宣告它的终结。这篇文章将会分享到目前为止对 PermGen 继任者:Metaspace的了解。我们将通过运行一个存在类元数据对象“泄漏”的程序,来对比HotSpot1.7与HotSpot1.8(b75,译者注:翻译文章时已经到b118)的运行时行为。待Java 8 正式发布之后,才会提供最终的规范,优化参数和相关文档。

元空间(Metaspace):

一种新的内存空间的诞生

JDK8 HotSpot JVM 使用本地内存来存储类元数据信息并称之为:元空间(Metaspace);这与Oracle JRockit 和IBM JVM’s很相似。这将是一个好消息:意味着不会再有java.lang.OutOfMemoryError: PermGen问题,也不再需要你进行调优及监控内存空间的使用……但请等等,这么说还为时过早。在默认情况下,这些改变是透明的,接下来我们的展示将使你知道仍然要关注类元数据内存的占用。请一定要牢记,这个新特性也不能神奇地消除类和类加载器导致的内存泄漏。你需求使用不同的方法以及遵守新的命名约定来追踪这些问题。我推荐大家阅读有关PermGen移除总结和Jon对此的评论。

总结如下:

PermGen 空间的状况

  • 这部分内存空间将全部移除。

  • JVM的参数:PermSize 和 MaxPermSize 会被忽略并给出警告(如果在启用时设置了这两个参数)。

Metaspace 内存分配模型

  • 大部分类元数据都在本地内存中分配。

  • 用于描述类元数据的“klasses”已经被移除。

Metaspace 容量

  • 默认情况下,类元数据只受可用的本地内存限制(容量取决于是32位或是64位操作系统的可用虚拟内存大小)。

  • 新参数(MaxMetaspaceSize)用于限制本地内存分配给类元数据的大小。如果没有指定这个参数,元空间会在运行时根据需要动态调整。

Metaspace 垃圾回收

  • 对于僵死的类及类加载器的垃圾回收将在元数据使用达到“MaxMetaspaceSize”参数的设定值时进行。

  • 适时地监控和调整元空间对于减小垃圾回收频率和减少延时是很有必要的。持续的元空间垃圾回收说明,可能存在类、类加载器导致的内存泄漏或是大小设置不合适。

Java 堆内存的影响

  • 一些杂项数据已经移到Java堆空间中。升级到JDK8之后,会发现Java堆 空间有所增长。

Metaspace 监控

  • 元空间的使用情况可以从HotSpot1.8的详细GC日志输出中得到。

  • Jstat 和 JVisualVM两个工具,在我们使用b75版本进行测试时,已经更新了,但是还是能看到老的PermGen空间的出现。

前面已经从理论上充分说明,下面让我们通过“泄漏”程序进行新内存空间的观察……

PermGen vs. Metaspace 运行时比较

为了更好地理解Metaspace内存空间的运行时行为,我们建立了一个类元数据泄漏程序。可以从此处下载源代码。

将进行以下几种场景的测试:

  • 使用JDK1.7运行Java程序,监控并耗尽设定的128MB大小的PermGen内存空间。

  • 使用JDK1.8 (b75)运行Java程序,监控新Metaspace内存空间的动态增长和垃圾回收过程。

  • 使用JDK1.8 (b75)运行Java程序,模拟耗尽通过“MaxMetaspaceSize”参数设定的128MB大小的Metaspace内存空间。

JDK 1.7 @64-bit – PermGen 耗尽测试

  • Java程序中包括5万次可配置迭代过程

  • Java堆大小为1024 MB

  • Java的PermGen空间为128 MB(-XX:MaxPermSize=128m)

可以从上面的JVisualVM的截图看出:当加载超过3万个类之后,PermGen被耗尽。我们也能通过程序和GC的输出观察耗尽的过程。

copy

  1. Class metadata leak simulator

  2. Author: Pierre-Hugues Charbonneau

  3. http://javaeesupportpatterns.blogspot.com

  4. ERROR: java.lang.OutOfMemoryError: PermGen space

下面我们使用HotSpot JDK 1.8 JRE来执行程序。

JDK 1.8 @64-bit – Metaspace大小动态调整测试

  • Java程序中包括5万次可配置迭代过程

  • Java堆大小为1024 MB

  • Java的Metaspace空间:不受限制 (默认)

从上面的截图可以看到详细的GC输出日志,JVM Metaspace进行了动态扩展,本地内存的使用由20MB增长到328MB,以满足程序中不断增长的类数据内存占用需求。我们也能观察到JVM的垃圾回收事件—试图销毁僵死的类或类加载器对象。但是,由于我们程序的泄漏,JVM别无选择只能动态扩展Metaspace内存空间。程序能够运行5万次迭代,加载超过5万个类,而没有出现OOM事件。下面继续进行最后的一个测试场景:

JDK 1.8 @64-bit – Metaspace depletion

  • Java程序中包括5万次可配置迭代过程

  • Java堆大小为1024 MB

  • Java的Metaspace空间:128MB(-XX:MaxMetaspaceSize=128m)

可以从上面的JVisualVM的截图看出:当加载超过3万个类之后,Metaspace被耗尽;与JDK1.7运行时非常相似。我们也能通过程序和GC的输出观察耗尽的过程。另一个有趣的现象是,保留的原生内存占用量是设定的最大大小两倍之多。这可能表明,如果可能的话,可微调元空间容量大小策略,来避免本地内存的浪费。

从Java程序的输出中看到如下异常。

[html] view plaincopy

  1. Class metadata leak simulator

  2. Author: Pierre-Hugues Charbonneau

  3. http://javaeesupportpatterns.blogspot.com

  4. ERROR: java.lang.OutOfMemoryError: Metadata space

完成!

正如预期的那样,像运行JDK1.7基线时一样,限定128 MB大小元空间时,并不能让程序完成50万次迭代。一种新的OOM错误被JVM抛出。上述OOM事件,是由于元空间内存分配失败由JVM抛出的。

#metaspace.cpp

结束语

我希望您能喜欢这篇较早的对Java8元空间的分析和实验文章。目前的观察有力地表明,适当的监控和调优是必须的,以此来避免诸如,过度的在元空间中的GC,或像我们测试场景下触发OOM的条件。后面的文章中可能包括,性能上的比较,以确定这一新特性是否有潜在的性能上的提升。

    参考:Java 8: From PermGen to Metaspace from ourJCG partner Pierre-Hugues Charbonneau at theJava EE Support Patterns & Java Tutorialblog.

java8 去掉 perm 用 Metaspace 来替代的更多相关文章

  1. Metaspace 之一--java8 去掉 perm 用 Metaspace 来替代

    正如大家所知,JDK 8 Early Access版已经提供下载.这使开发者可以体验Java8的新特性.其中之一,是Oracle从JDK7发布以来就一直宣称的要完全移除永久代空间.例如,字符串内部池, ...

  2. Java8 Lambda使用指南

    Java8 Lambda 的使用指南 原文地址:https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#s ...

  3. metaspace之三--Metaspace解密

    概述 metaspace,顾名思义,元数据空间,专门用来存元数据的,它是jdk8里特有的数据结构用来替代perm,这块空间很有自己的特点,前段时间公司这块的问题太多了,主要是因为升级了中间件所致,看到 ...

  4. Java.lang.OutOfMemoryError:Metaspace

    Understand the OutOfMemoryError Exceptionhttps://docs.oracle.com/javase/8/docs/technotes/guides/trou ...

  5. JVM(完成度95%,不断更新)

    一.HotSpot HotSpot是最新的虚拟机,替代了JIT,提高Java的运行性能.Java原先是将源代码编译为字节码在虚拟机运行,HotSpot将常用的部分代码编译为本地代码. 对象创建过程 类 ...

  6. 【垃圾回收】Java内存回收实践经验 防止内存报警

    jdk6和7服务器端(-server) 默认的新生代的垃圾回收器为:PS Scavenge,老年代默认的垃圾回收器为:PS MarkSweep 目前项目使用了jdk7,tomcat7,经常出现内存堆使 ...

  7. jdk8 永久代变更

    java8 去掉了永久代permgen(又称非堆,其实也是堆的一部分),类的方法代码,常亮,方法名,静态变量等存放在永久代中 改为使用元空间 Metaspace , Metaspace 不在是堆的一部 ...

  8. HotSpot Java虚拟机中的“方法区”“持久代”“元数据区”的关系?

    Sun/Oracle JDK的HotSpot VM中,直到JDK7都有“持久代”(Permanent Generation,简称PermGen).也称为方法区.Oracle JDK8的HotSpot ...

  9. 深入理解JVM虚拟机11:Java内存异常原理与实践

    本文转自互联网,侵删 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutori ...

随机推荐

  1. 【viewport】移动设备的兼容性问题

    前段时间用微信开发者工具重构一个菜单项目的时候发现iphoneSE显示不全以及布局错乱的问题,找到了一个简单粗暴的解决方法.     移动设备上的viewport分为layout viewport  ...

  2. Password

    Description Rivest是密码学专家.近日他正在研究一种数列E = {E[1],E[2],--,E[n]}, 且E[1] = E[2] = p(p为一个质数),E[i] = E[i-2]* ...

  3. struts2相关简单介绍

    一 Struts2环境配置 1.准备jar包,核心jar包有: 2.创建Struts2项目并导入jar包 3.在Struts2项目中src下创建Struts.xml配置文件 4.在Web.xml文件中 ...

  4. Ubuntu虚拟机可以上网,可以ping网络,但是无法update和install,报连接不上服务器的错误解决方案:

    http://askubuntu.com/questions/711889/err-apt-get-update-on-ubuntu-14-04即使给Ubuntu配置了代理,terminal能ping ...

  5. asp.net 动态压缩、切割图片,并做缓存处理机制

    在asp.net中,新建一个handler,把需要切割的网内图片,通过调用此URL来切割并缓存.http://localhost:53829/CacheImage/ResizeImage.ashx?s ...

  6. C互质个数

    C互质个数 Time Limit:1000MS  Memory Limit:65536K Total Submit:55 Accepted:27 Description 贝贝.妞妞和康康都长大了,如今 ...

  7. 【NO.12-2】jmeter-执行脚本

    //拿jmeter举例 //要进入到jmeter工具的bin目录 //当使用其它的开源测试工具的时候,也可以参考上面这一点,即:进入到bin目录 //如果工具本身不包含bin文件,那么在工具的1级目录 ...

  8. let const 下篇

    1.不存在变量提升 在之前的js代码中,声明一个变量或者是函数,会存在变量提升的现象,也就是说变量可以在声明之前使用,值为undefined: es5: console.log(a); //undef ...

  9. 王佩丰第一讲 认识excel笔记

    改变工作表表浅颜色 批量插入工作表 选择多张工作表然后插入 找到表格边界区域快捷键(找到表格的最后一行):快速到达最上下左右端 点击边框上下左右双击 从指定的位置开始冻结窗格 输入今天的日期 快捷键c ...

  10. 云计算之openstack mitaka 配置详解(将疑难点都进行划分)

    在配置openstack项目时很多人认为到处是坑,特别是新手,一旦进坑没有人指导,身体将会感觉一次次被掏空,作为菜鸟的我也感同身受,因为已经被掏空n次了. 以下也是我将整个openstack配置过程进 ...