HotSpot虚拟机在java 1.8中的新实现

HotSpot

Java HotSpot 虚拟机是 Java SE 平台的一个核心组件。它实现 Java 虚拟机规范,并作为 Java 运行时环境中的一个共享库来提供。作为 Java 字节码执行引擎,它在多种操作系统和架构上提供 Java 运行时设施,如线程和对象同步。它包括自适应将 Java 字节码编译成优化机器指令的动态编译器,并使用为降低暂停时间和吞吐量而优化的垃圾收集器来高效管理 Java 堆。它为分析、监视和调试工具及应用程序提供数据和信息。

最近在研究它在1.8中的新特性:

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

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

1. 永久代

在说java8内存模型之前先说一下永久代的概念。

在Java虚拟机(JVM)内部,class文件中包括类的版本、字段、方法、接口等描述信息,还有运行时常量池,用于存放编译器生成的各种字面量和符号引用。

在过去类大多是”static”的,很少被卸载或收集,因此被称为“永久的(Permanent)”。

同时,由于类class是JVM实现的一部分,并不是由应用创建的,所以又被认为是“非堆(non-heap)”内存。

在JDK8之前的HotSpot JVM,存放这些”永久的”的区域叫做“永久代(permanent generation)”。

永久代是一片连续的堆空间,在JVM启动之前通过在命令行设置参数-XX:MaxPermSize来设定永久代最大可分配的内存空间,默认大小是64M(64位JVM由于指针膨胀,默认是85M)。

永久代的垃圾收集是和老年代(old generation)捆绑在一起的,因此无论谁满了,都会触发永久代和老年代的垃圾收集。

不过,一个明显的问题是,当JVM加载的类信息容量超过了参数-XX:MaxPermSize设定的值时,应用将会报OOM的错误

2. Metaspace(元空间)

jdk1.8中则把永久代给完全删除了,取而代之的是 MetaSpace


heap in JAVA 8

2.1 metaspace的组成

metaspace其实由两大部分组成

  • Klass Metaspace
  • NoKlass Metaspace

Klass Metaspace就是用来存klass的,klass是我们熟知的class文件在jvm里的运行时数据结构,不过有点要提的是我们看到的类似A.class其实是存在heap里的,是java.lang.Class的一个对象实例。

这块内存是紧接着Heap的,和我们之前的perm一样,这块内存大小可通过-XX:CompressedClassSpaceSize参数来控制,这个参数前面提到了默认是1G,但是这块内存也可以没有,假如没有开启压缩指针就不会有这块内存,这种情况下klass都会存在NoKlass Metaspace里,另外如果我们把-Xmx设置大于32G的话,其实也是没有这块内存的,因为这么大内存会关闭压缩指针开关。

还有就是这块内存最多只会存在一块。

NoKlass Metaspace专门来存klass相关的其他的内容,比如method,constantPool(常量池)等,这块内存是由多块内存组合起来的,所以可以认为是不连续的内存块组成的。

这块内存是必须的,虽然叫做NoKlass Metaspace,但是也其实可以存klass的内容,上面已经提到了对应场景。

Klass Metaspace和NoKlass Mestaspace都是所有classloader共享的,所以类加载器们要分配内存,但是每个类加载器都有一个SpaceManager,来管理属于这个类加载的内存小块。

如果Klass Metaspace用完了,那就会OOM了,不过一般情况下不会,NoKlass Mestaspace是由一块块内存慢慢组合起来的,在没有达到限制条件的情况下,会不断加长这条链,让它可以持续工作。

2.2 Metaspace的内存分配与管理

Metaspace VM利用内存管理技术来管理Metaspace。

这使得由不同的垃圾收集器来处理类元数据的工作,现在仅仅由Metaspace VM在Metaspace中通过C++来进行管理。

Metaspace背后的一个思想是,类和它的元数据的生命周期是和它的类加载器的生命周期一致的。

也就是说,只要类的类加载器是存活的,在Metaspace中的类元数据也是存活的,不能被释放。

每个类加载器存储区叫做“a metaspace”。

这些metaspaces一起总体称为”the Metaspace”。

仅仅当类加载器不再存活,被垃圾收集器声明死亡后,该类加载器对应的metaspace空间才可以回收。

Metaspace空间没有迁移和压缩。

但是元数据会被扫描是否存在Java引用。

Metaspace VM使用一个块分配器(chunking allocator)来管理Metaspace空间的内存分配。

块的大小依赖于类加载器的类型。

其中有一个全局的可使用的块列表(a global free list of chunks)。

当类加载器需要一个块的时候,类加载器从全局块列表中取出一个块,添加到它自己维护的块列表中。

当类加载器死亡,它的块将会被释放,归还给全局的块列表。

块(chunk)会进一步被划分成blocks,每个block存储一个元数据单元(a unit of metadata)。

Chunk中Blocks的分配线性的(pointer bump)。

这些chunks被分配在内存映射空间(memory mapped(mmapped) spaces)之外。

在一个全局的虚拟内存映射空间(global virtual mmapped spaces)的链表,当任何虚拟空间变为空时,就将该虚拟空间归还回操作系统。


Metaspace的内存分配与管理

2.3 Metaspace VM内存碎片问题

先前提到的,Metaspace VM使用块分配器(chunking allocator)。

chunk的大小取决于类加载器的类型。

由于类class并没有一个固定的尺寸,这就存在这样一种可能:

可分配的chunk的尺寸和需要的chunk的尺寸不相等,这就会导致内存碎片。

内存碎片的产生

Metaspace VM还没有使用压缩技术,所以内存碎片是现在的一个主要关注的问题。

2.4 Metaspace 总结

元空间的本质和永久代类似,都是对JVM规范中方法区的实现。

不过元空间与永久代之间最大的区别在于:

元空间并不在虚拟机中,而是使用本地内存。

因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过参数来指定元空间的大小。


java8内存模型图

2.5 MetaSpace应该掌握的知识

  1. 在 JDK 1.7 和 1.8 中将字符串常量池由永久代转移到堆中
  2. 存放类相关信息的地方也不在heap(堆)中。在元空间里。
  3. 在jdk1.8中没有永久代的概念
  4. metaspace其实由两大部分组成
  • Klass Metaspace
    存放klass的,klass是我们熟知的class文件在jvm里的运行时数据结构,这个空间的默认大小是1G
  • NoKlass Metaspace
    专门来存klass相关的其他的内容,比如method,constantPool(常量池)等,这块内存是由多块内存组合起来的,所以可以认为是不连续的内存块组成的。这块内存是必须的

Klass Metaspace和NoKlass Mestaspace都是所有classloader共享的,所以类加载器们要分配内存,但是每个类加载器都有一个SpaceManager,来管理属于这个类加载的内存小块。

如果Klass Metaspace用完了,那就会OOM了,不过一般情况下不会,NoKlass Mestaspace是由一块块内存慢慢组合起来的,在没有达到限制条件的情况下,会不断加长这条链,让它可以持续工作。

5.metaspace主要相关参数

-XX:MetaspaceSize,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:

  • 如果释放了大量的空间,就适当降低该值;
  • 如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。

-XX:MaxMetaspaceSize,最大空间,默认是没有限制的。

-XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集

-XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集

  1. Metaspace的内存分配与管理 都应该清楚
  2. 为什么要将永久代替换成Metaspace?
  • 字符串存在永久代中,容易出现性能问题和内存溢出。
  • 类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。
  • 永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。
  • Oracle 可能会将HotSpot 与 JRockit 合二为一。

参见:
Java 8新特性探究(九)跟OOM:Permgen说再见吧:http://www.importnew.com/14933.html
JVM(二)Java8内存划分:https://blog.csdn.net/yjp198713/article/details/78759933
JVM源码分析之Metaspace解密:http://www.cnblogs.com/paddix/p/5309550.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容