Java 8彻底将永久代移除出了HotSpot JVM,将其原有的数据迁移至Java Heap或Metaspace。这一篇文章我们来总结一下Metaspace(元空间)的特性。如有错误,敬请指出,谢谢~

一、引言:永久代为什么被移出HotSpot JVM了?

详见:JEP 122: Remove the Permanent Generation
原因主要有两个:

1、由于Permanent Generation内存经常不够用或发生内存泄露,引发恼人的java.lang.OutOfMemoryError: PermGen (在Java Web开发中非常常见)。
2、移除Permanent Generation可以促进HotSpot JVM与 JRockit VM的融合,因为JRockit没有永久代。
This is part of the JRockit and Hotspot convergence effort. JRockit customers do not need to configure the permanent generation (since JRockit does not have a permanent generation) and are accustomed to not configuring the permanent generation.
根据上面的各种原因,永久代最终被移除,方法区移至Metaspace,字符串常量移至Java Heap。

二、探秘元空间

由于Metaspace的资料比较少,这里主要是依据Oracle官方的Java虚拟机规范及Oracle Blog里的几篇文章来总结的。
首先,Metaspace(元空间)是哪一块区域?官方的解释是:

In JDK 8, classes metadata is now stored in the native heap and this space is called Metaspace.
也就是说,JDK 8开始把类的元数据放到本地化的堆内存(native heap)中,这一块区域就叫Metaspace,中文名叫元空间。

1、优点

使用本地化的内存有什么好处呢?最直接的表现就是java.lang.OutOfMemoryError: PermGen 空间问题将不复存在,因为默认的类的元数据分配只受本地内存大小的限制,也就是说本地内存剩余多少,理论上Metaspace就可以有多大(貌似容量还与操作系统的虚拟内存有关?这里不太清楚),这解决了空间不足的问题。不过,让Metaspace变得无限大显然是不现实的,因此我们也要限制Metaspace的大小:使用-XX:MaxMetaspaceSize参数来指定Metaspace区域的大小。JVM默认在运行时根据需要动态地设置MaxMetaspaceSize的大小。
除此之外,它还有以下优点(没有完全理解,先贴出来吧,来自StackOverflow):

Take advantage of Java Language Specification property : Classes and associated metadata lifetimes match class loader’s
Linear allocation only
No individual reclamation (except for RedefineClasses and class loading failure)
No GC scan or compaction
No relocation for metaspace objects
2、垃圾回收

如果Metaspace的空间占用达到了设定的最大值,那么就会触发GC来收集死亡对象和类的加载器。根据JDK 8的特性,G1和CMS都会很好地收集Metaspace区(一般都伴随着Full GC)。
为了减少垃圾回收的频率及时间,控制吞吐量,对Metaspace进行适当的监控和调优是非常有必要的。如果在Metaspace区发生了频繁的Full GC,那么可能表示存在内存泄露或Metaspace区的空间太小了。

3、新增参数

-XX:MetaspaceSize是分配给类元数据空间(以字节计)的初始大小(Oracle逻辑存储上的初始高水位,the initial high-water-mark ),此值为估计值。MetaspaceSize的值设置的过大会延长垃圾回收时间。垃圾回收过后,引起下一次垃圾回收的类元数据空间的大小可能会变大。
-XX:MaxMetaspaceSize是分配给类元数据空间的最大值,超过此值就会触发Full GC,此值默认没有限制,但应取决于系统内存的大小。JVM会动态地改变此值。
-XX:MinMetaspaceFreeRatio表示一次GC以后,为了避免增加元数据空间的大小,空闲的类元数据的容量的最小比例,不够就会导致垃圾回收。
-XX:MaxMetaspaceFreeRatio表示一次GC以后,为了避免增加元数据空间的大小,空闲的类元数据的容量的最大比例,不够就会导致垃圾回收。
4、监控与调优(待补充)

VisualVM,jstat,jstack可以监测元空间的动态,后续将更新这里。

深入探究JVM(2) - 探秘Metaspace的更多相关文章

  1. JVM总结(一):概述--JVM对象探秘

    这一节我们来讨论一下JVM对象建立过程. JVM对象探秘 对象的建立 对象的内存布局 对象的访问定位 JVM对象探秘 对象的建立 对象的建立过程   图一:对象建立过程 1.类加载检查. 当JVM检测 ...

  2. 深入探究JVM(1) - Java的内存区域解析

    http://blog.csdn.net/sczyh22/article/details/46652901<br>Java 虚拟机在执行Java程序的时候会把它管理的内存区域划为几部分,这 ...

  3. 探究JVM——垃圾回收

    垃圾回收主要考虑三件事情:哪些内存需要回收?什么时候回收?如何回收? 一.哪些内存需要回收? 堆内存:对于JVM 来说,垃圾回收主要是针对堆内存中的对象实例. 方法区:垃圾收集行为在方法区是比较少出现 ...

  4. 探究JVM和GC

    1.Java堆中各代分布: 图1:Java堆中各代分布 Young:主要是用来存放新生的对象. Old:主要存放应用程序中生命周期长的内存对象. Permanent:是指内存的永久保存区域,主要存放C ...

  5. 深入探究jvm之类装载器

    一.class装载验证流程 1.加载 1).取得类的二进制流. 2).转为方法区数据结构. 3).在Java堆中生成对应的java.lang.Class对象. 2.链接--验证(目的:保证Class流 ...

  6. 深入探究jvm之GC的算法及种类

    一.GC基本概念 GC(Garbage Collection)垃圾收集,1960年最早在List中使用.在Java中GC回收的对象是堆空间和永久区,可以有效避免程序员人为造成内存泄漏问题.将堆空间和永 ...

  7. 深入探究jvm之GC的参数调优

    在上一篇博客记录了GC的算法及种类,这篇博客主要记录一下GC的参数如何调整以提高jvm的性能. 一.堆的回顾: 堆的内存空间总体分为新生代和老年代,老年代存放的老年对象,新构造的对象分配在eden区中 ...

  8. 深入探究JVM之内存结构及字符串常量池

    前言 Java作为一种平台无关性的语言,其主要依靠于Java虚拟机--JVM,我们写好的代码会被编译成class文件,再由JVM进行加载.解析.执行,而JVM有统一的规范,所以我们不需要像C++那样需 ...

  9. 深入探究JVM之对象创建及分配策略

    @ 目录 前言 正文 一.对象的创建方式 二.对象的创建过程 对象在哪里创建 分配内存 对象的内存布局 三.对象的访问定位 四.判断对象的存活 对象生死 回收方法区 引用 对象的自我拯救 五.对象的分 ...

随机推荐

  1. Python 内置函数super

    super()函数是用于调用父类/超类的一个方法 super是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没有问题,但是如果使用多继承,会涉及到查找顺序(MRO),重复调用(钻石继 ...

  2. JS跨域--window.name

    JS跨域--window.name:https://www.jianshu.com/p/43ff69d076e3

  3. Java 线程池 8 大拒绝策略,面试必问!

    前言 谈到java的线程池最熟悉的莫过于ExecutorService接口了,jdk1.5新增的java.util.concurrent包下的这个api,大大的简化了多线程代码的开发.而不论你用Fix ...

  4. [Bzoj1911][Apio2010]特别行动队(斜率优化)

    题目链接 斜率优化的经典模型,将序列分成若干段,每段有一个权值计算方法,求权值和最大/小 暴力的dp $O(n^{2})$ dp[i]为1-i的序列的最优解.sum[i]为前缀和,$D(i)=ax^{ ...

  5. ubuntu14 文件夹添加/删除书签

    1. 打开文件管理,进入你要添加书签的目录 2. 把鼠标移到顶部选择“Bookmarks" 3. 这是文件管理左侧可以看到 4. 右键可以选择删除

  6. c++多线程并发学习笔记(1)

    共享数据带来的问题:条件竞争 避免恶性条件竞争的方法: 1. 对数据结构采用某种保护机制,确保只有进行修改的线程才能看到修改时的中间状态.从其他访问线程的角度来看,修改不是已经完成了,就是还没开始. ...

  7. Python 入门之流程控制语句

    Python 入门之流程控制语句 1.if判断 (1) 单 if if –-如果 if 条件: 缩进 结果 (官方推荐4个空格,或者一个tab 不能空格和tab混合使用) money = 10 pri ...

  8. Windows下spark1.6.0本地环境搭建

    由于spark是用scala编写的,且需要jdk的环境支撑,所以本地spark环境的搭建需要四个步骤:JDK的安装,scala的安装,hadoop的配置,spark的配置. 一.jdk的安装与环境变量 ...

  9. python3 pycurl 出现 TypeError: string argument expected, got 'bytes' 解决方案

    用pycurl请求指定链接并返回结果时出现 TypeError: string argument expected, got 'bytes'  错误 经过排查问题出现在使用StringIO的write ...

  10. c#中DataTable和DataSet区别

    你可以把DataTable和DataSet看做是数据容器,比如你查询数据库后得到一些结果,可以放到这种容器里,那你可能要问:我不用这种容器,自己读到变量或数组里也一样可以存起来啊,为什么用容器? 原因 ...