英文原稿:http://vdisk.weibo.com/s/vxGdGZEZTEjk

中文整理稿:http://it.deepinmind.com/gc/2014/05/14/metaspace-in-java-8.html

其实上面的整理稿,是针对这篇英文文稿的翻译兼整理,但是感觉有点乱,有点强迫症,所以干脆自己来翻译。关于vm相关性能数据的监控部分略掉了,此稿件主要是介绍perm gen的设计与移除,以及移除perm gen之后新的内存模型,所以后面关于内存的调优还有性能的监测都过于简单,如果想了解,可以去看周志明先生的《深入理解Java虚拟机》,里面对jstat等工具有更多的介绍。

翻译:

Oracle HotSpot JVM中的perm gen保存了HotSpot用于描述Java对象(Java objects)的元数据(metadata)。perm gen在Full GC中会和Java堆(Java Heap)一起经历垃圾回收。perm gen在JDK8中的HotSpot中,已经被移除了。本节简单的描述了perm gen及移除它的动机。还讨论了移除perm gen可能对Java程序的执行造成的多方面的影响。

议题

  • 什么是perm gen
  • 现在的元数据在哪儿
  • 压缩的类指针
  • 新的调节参数
  • Memory Pool MXBeans

什么是perm gen

  • 全名permanent generation
  • 是Java Heap中用于存储虚拟机类的元数据的区域
  • Java类在HotSpot中的内在表现
    • 类的结构信息,字段,名字
    • 方法的汇编信息和字节码
    • Vtables(虚函数表)
    • 常量池和符号解析

含有perm gen的vm内存分布示意图:

PermGen 大小

  • 1.受限于参数MaxPermSize(默认是64M-85M)
  • 2.需要Java Heap中连续的存储空间:如果分配的堆空间不连续,那么从old gen和perm gen定位指向新对象的引用,代价就会更大,而且也会更复杂。(card table   remembered set)
  • 3.一旦耗尽,就会抛异常
    • 清除引用来触发类卸载
    • 配置更大的MaxPermSize
  • 4.perm gen的大小依赖于类的数量,方法的大小,以及常量池的大小

为什么要移除PermGen

  • 启动的时候就要指定大小,难以调优:MaxPermSize要设多大?
  • HotpSpot内部类型是Java对象,可能会在Full GC中移动,对应用程序来说,不透明,并且非强类型,很难调试,需要用于存储元数据的空间
  • 简化Full GC
    • 为每个收集器的元数据指定迭代器
  • 希望能并发的回收类型数据空间,而不是在GC停顿期间
  • 使受限于permgen的未来的改进成为可能

元数据去哪儿了?

得益于Java语言特性:类及相关元数据的生命周期和累加载器相匹配

每一个加载器的存储空间

  • 仅线性分配
  • 没有单独的回收(除非RedefineClasses和类加载失败)
  • 没有GC扫描和整理
  • 不需要重新安置元数据空间对象
  • 当GC发现类加载器死亡,则整个空间一起回收

这些存储空间的集体称为Metaspace

Metaspace 分配

  • 为元数据分配多个映射虚拟内存空间
  • 为每个类加载器分配块状空间列表
    • 块的大小依赖于类加载器的大小
    • 为sun/reflect/DelegatingClassLoader, JSR292匿名类的加载器分配较小的块
  • 归还内存块,以释放块状列表
  • 当被清空的时候,归还虚拟内存空间
  • 设计诸多策略来减少碎片

如下图:

(图中CL为类加载器,Boot CL为启动类加载器,vs1,vs2,vs3为虚拟内存空间,黄色的块为元数据块)

Java对象内存分配

堆上对象有指向Metaspace中自己类信息的指针—>_klass

在64位平台上,为了压缩JVM对象中的类指针,引入了“压缩类指针空间”(对象中的_klass变为4字节,指向压缩类空间中的数据,该数据再指向Metaspace中的类信息)

压缩指针(压缩类指针,压缩对象指针)

  • 默认是为了64位平台
  • 使用-XX:+UseCompressedOops 来压缩对象指针
    • oops是指普通对象指针
    • Java堆中对象的对象指针被压缩到32bit
    • 使用堆基地址(如果在低26G内存空间中,为0)即,指针的偏移量针对于堆的基地址
  • 使用-XX:+UseCompressedClassPointers 压缩类指针
    • 对象的类指针(_klass)被压缩至32bit
    • 使用类指针压缩空间的基地址

Metaspace与类压缩空间的对比

  • 类压缩空间只包含像接口指针(InstanceKlass),数组指针(ArrayKlass)等元数据

    • 仅当UseCompressedClassPointers为true的时候会这样
    • 为了性能问题,这里还保存了Java 虚方法表
    • 我们仍然在减少这个元数据类型
  • 而Metaspace包含了元数据的其他所有的数据,这可能比较大,如方法,字节码,常量池

GC性能的提升

  • 在Full GC,元数据到元数据的指针不需要扫描

    • 一大堆元数据扫描的复杂代码(尤其在CMS)都被删除了
  • 元数据空间包含较少的指向Java Heap的指针
    • 指向java/lang/Class对象的指针存储在类元数据中
    • 数据类元数据中,有指向其成员类Class对象的指针
    • 我们要移除这些
  • 元数据不再有整理消耗
  • 减少了根扫描(不扫描VM已加载类的字典和其他内部的哈希表)
  • Full GC的时间将会缩短(不同情况下可能会有所不同)
  • 在G1中可以在并发标记之后进行类卸载
  • 可以调优

调优标志

MaxMetaspaceSize

  • -XX:MaxMetaspaceSize={unlimited}
  • Metaspace受机器内存的限制
  • 在虚拟内存切换频繁和本地内存分配失败之前,限制类元数据使用的内存
    • 如果类加载器内存可能泄漏
    • 如果在32位平台上,地址空间可能耗尽
  • MaxMetaspaceSize是指Metaspace和压缩类指针空间的总和

MetaspaceSize

  • 初始大小为21mb,超过这个值,将进行Full GC来回收类

    • GC的相关操作用于检测已死的类加载器,和未加载的类
  • 如果在启动阶段发生了过多的GC,则需要设置一个高点的限制
  • 可以使用与PermSize相同的值,来延缓初始GC
  • 在下次Metaspace GC之前,High water mark会随着接下来合理数量的头空间的收集而增高

CompressedClassSpaceSize

  • 当使用了-XX:+UseCompressedClassPointers 才有效
  • -XX:CompressedClassSpaceSize=1G
  • 因为这个空间只能在启动的时候设置,所以一开始就设置大一点
  • 不使用的时候,不会分配
  • 未来的工作,是要使这块空间可增长
    • 不需要连续,只需要从基地址可达
    • 更倾向于将更多的类元数据移到Metaspace中
  • 未来可能会以性能为主导
    • PredictedLoadedClassCount (该标志目前处于试验性):用于设置其他JVM内部数据结构的大小,像已加载类的字典
  • 开发者可能会发现对于CompressedClassSpaceSize和UseCompressedClassPointers的不同命名。但在JDK-8015107中已经设定,对metaspace的概念,需要使用统一的命名方式

可以通过-XX:+PrintGCDetails and -XX:+PrintHeapAtGC来查看metaspace的使用情况

PermGen内存池以前在内存管理中属于Heap内存池的列表中,现在移除了

总结:

  • HotSpot 元数据现在存在元空间中

    • 压缩类指针空间仍然需要被设定,但是要大一些
  • 有调优标志,虽然并不是必须要使用的
  • 这种改变使得其他优化与特性成为可能
    • 共享类数据
    • 新生代优化,G1进行类卸载
    • 元数据减少

译者有话说:

表示有些地方,我没看懂,不过总的还是有收获的。而且,我感觉是指导性文档,抠字眼就没必要了。最近一直在看JVM的相关内容,总结一句话,发展时间太久,各种词汇乱用,导致哪哪儿都模棱两可。

比如,现在从一些较官方的文档来看,Java Heap和我们常说的java堆是不同的,我们常说的java堆只包含新生代和老年代,是用来存储对象实例数据的,但是Java Heap是包括perm gen在内的GC作用的整个堆空间。有人说,这有神马影响吗?没影响的时候没影响,有影响的时候,真是搞脑子。

简单点概括

过去类的元数据存储在perm gen,作为Java Heap的一部分,使用instanceKlass,instanceKlassKlass,klassKlass(详见R大关于perm gen数据的追踪博客),接受GC传统意义上的扫描。弊端:内存受限,容易溢出;空间回收性能低等。现在的元数据存在元空间中。元空间由多个虚拟内存空间构成,每个虚拟内存空间又被划分为不同大小的块。以类加载器为源头,随着类的不断加载,不断从虚拟内存空间中分配块空间,从而使每个类加载器对应了一个块列表。当GC检测到某个类加载器已死,就整体释放整个列表,回收内存。

至于压缩类空间,出于多个原因考虑,主要有两个。第一,在64位平台,指针膨胀导致内存浪费,使用压缩类指针,压缩类指针空间基地址的概念,继续使用32位指针寻址;第二,这样一个空间还可以存储部分元数据,以提高相应性能。

Permanent Generation Removal Overview(译文)的更多相关文章

  1. JVM年轻代(young generation)老年代(old generation tenured)持久代(permanent generation)GC

    关于jvm内存代,看到这篇文章,转发下 链接地址 ---多谢 虚拟机中的共划分为三个代:年轻代(Young Generation).老年代(Old Generation)和持久代(Permanent ...

  2. Permanent Space 和 Heap Space

      JVM堆内存 JVM堆内存分为2块:Permanent Space 和 Heap Space. Permanent 即 持久代(Permanent Generation),主要存放的是Java类定 ...

  3. 牛客网Java刷题知识点之垃圾回收算法过程、哪些内存需要回收、被标记需要清除对象的自我救赎、对象将根据存活的时间被分为:年轻代、年老代(Old Generation)、永久代、垃圾回收器的分类

    不多说,直接上干货! 首先,大家要搞清楚,java里的内存是怎么分配的.详细见 牛客网Java刷题知识点之内存的划分(寄存器.本地方法区.方法区.栈内存和堆内存) 哪些内存需要回收 其实,一般是对堆内 ...

  4. 使用MAT(Memory Analyzer Tool)工具分析dump文件--转

    原文地址:http://gao-xianglong.iteye.com/blog/2173140?utm_source=tuicool&utm_medium=referral 前言 生产环境中 ...

  5. The The Garbage-First (G1) collector since Oracle JDK 7 update 4 and later releases

    Refer to http://www.oracle.com/technetwork/tutorials/tutorials-1876574.html for detail. 一些内容复制到这儿 Th ...

  6. 成为JavaGC专家(1)—深入浅出Java垃圾回收机制

    转载自:http://www.importnew.com/1993.html 对于Java开发人员来说,了解垃圾回收机制(GC)有哪些好处呢?首先可以满足作为一名软件工程师的求知欲,其次,深入了解GC ...

  7. Myeclipse常用快捷键

    转自:http://zjxbw.blog.51cto.com/2808787/543792 Ctrl+Shift+L    显示所有快捷键 Ctrl+K      参照选中的词(Word)快速定位到下 ...

  8. Java内存分配

    概述 对从事C和C++的程序员来说,在内存管理方面,他们既是拥有最高权利的人,也是从事最基础工作的“劳动人民”. 而对于Java程序员来说,JVM自动进行内存管理,程序员不再需要为每一个new操作去写 ...

  9. Java 7 jstat – JVM Statistics Monitoring Tool【翻译】

    原文地址:Java 7 jstat 本文内容 语法 参数 描述 虚拟机标识符 选项 一般选项 输出选项 示例 先发出来,然后慢慢翻译~ 语法 jstat [ generalOption | outpu ...

随机推荐

  1. 让EFCore更疯狂些的扩展类库(一):通过json文件配置sql语句

    前言 EF通过linq和各种扩展方法,再加上实体模型,编写数据库的访问代码确实是优美.舒服,但是生成的sql不尽如意.性能低下,尤其是复杂些的逻辑关系,最终大家还是会回归自然,选择能够友好执行sql语 ...

  2. Unable to find setter method for attribute: 属性名

    tld文件里面的名称和标签内的属性名要一致.

  3. 如何在项目中引入MetaQ消息收发机制

    当需要异步发送和接收大量消息时,需要在Crystal项目中引入MetaQ消息收发机制. 关于MetaQ使用的官方例子可参考:https://github.com/killme2008/Metamorp ...

  4. linux系统时间同步

    1.linux系统时间同步[root@xuegod62 ~]# /usr/sbin/ntpdate ntp1.aliyun.com2.linux系统定时同步[root@xuegod62 ~]# ech ...

  5. Hadoop学习笔记-008-CentOS_6.5_64_yum安装mysql

    ******************************卸载mysql***************************** 第一步,查看centos上是否已经安装了mysql数据库 # rp ...

  6. C#进阶系列——使用Advanced Installer制作IIS安装包(二:配置安装包依赖项和自定义dll)

    前言:上篇C#进阶系列——使用Advanced Installer制作IIS安装包(一:配置IIS和Web.config)介绍了下使用Advanced Installer配置IIS和Web.confi ...

  7. 如何用CSS进行网页布局---学习总结

    页面布局:对页面的文字.图形或表格进行格式设置.包括字体.字号.颜色纸张大小和方向以及页边距等 页面布局分为4种: 一栏布局 两栏布局 三栏布局 混合布局 灵活利用float.position对页面进 ...

  8. 很傻很二很简单的一个问题,json键值为变量如何取值

    js里的json的键值是变量的话,那么传统的做法似乎不管用了. 例如: var json={'a':'123','b':'999'}    json.a得到123,如果a用变量表示呢,有笨法for循环 ...

  9. [译] AR SDK的种类比你想得要多!这里介绍七个棒棒哒

    作者:Eddie Offermann 原文:There are dozens more Augmented Reality SDKs than you think! Here are seven gr ...

  10. WKWebView的使用与JS交互详细解读

    前言: WKWebView 这是在iOS8.0之后增加的一个比UIWebView更加完善和强大的控件!看网上关于它的博客也是有许多的了,从各个方面总结一下这个WKWebView看网上说它主要是为了和J ...