元空间和永久代

  • 一份总结,概念性的东西比较多,甚至还有点凌乱.
  • 可以理解是LeetCode刷题刷烦了,来看看博客整理整理概念放松一下 ( º﹃º )
  • 突然感觉我也没必要非要一次性写完深入了解Java虚拟机的读后总结了,可以把Java的内存区域单独先回忆总结.
  • 本文从众多博文以及谷歌中总结,并没有权威性.

永久代(PermGen)

  • 永久代(PermGen)是根据HotSpot VM中的GC分代策略在JVM管理的堆内存区域(区分于Java堆)中划分出来的一块内存区域.是分代GC中的概念。
  • 方法区在永久代中(也有说永久代是实现方法区的一种方式),相当于说永久代和方法区一样保存了已加载的类信息,元数据,运行时常量池,静态变量,即时编译后的代码等.
  • 永久代的内存区域在JVM内部。

永久代的垃圾收集

  • 永久代中的数据并不是真的会永久保存,只是这块区域的GC频率低且效率也不高.
  • 永久代的GC主要包括无用类的卸载和常量池中废弃常量的回收,且一般采用的都是标记-清除算法.
  • 在永久代中,无用类的判定较为苛刻(深入了解Java虚拟机原文):
    1. 该类的所有实例对象已经回收。
    2. 加载该类的ClassLoader已经被回收
    3. 该类型的java.lang.Class没有在任何地方被引用,该类型不能在任何地方以反射的方式实例化一个对象

永久代存在的问题

  • 从上面也能大概的看出永久代中存在以下的问题:
    1. 动态的字符串常量池保存在永久代中,很容易出现OOM和性能问题.
    2. 永久代的大小不好确定,保存的数据也很复杂,PermSize指定太小就容易造成OutOfMemoryError "PermGen space"异常
    3. 永久代在堆空间中,它的存在同时也增加了GC的复杂性,每个垃圾收集器都需要一份代码处理无用类的回收.

永久代到元空间

  • JDK7开始,HotSpot就开始着手移除了PermGen.
    • JDK7中,将永久代中的静态变量以及字符串常量池的字面量部分被转移到堆(Heap)中,常量池的符号引用部分则被转移到本地内存(Native Memory)中.
    • JDK8中,直接移除了永久代,将类的元数据也转移到本地内存(Native Memory)中 ,这部分区域就被称为元数据空间(Metaspace).

元空间(Metaspace)

  • 首先要强调的是元空间是位于本地内存(Native Memory)也就是堆外内存中,并不在JVM的内存区域内(有说法因为元空间和堆的物理内存空间是共享的,所以逻辑上可认为在Heap中).
  • 元空间的最大可分配空间不再受JVM内存制约,而是所在系统的可用内存空间,如果没有设置元空间的大小,JVM也会自动根据元数据大小动态的增加其容量.

元空间的内存管理

元空间的内存分配

  • 元空间的内存管理是由元空间虚拟机(Metaspace VM)来完成的没本事自己画,理解也不到家只能盗图维持生活这样子
  • 元空间虚拟机采用的是组块形式的内存分配规则,组块大小因类加载器的类型而异,在虚拟机内部会维护这一个全局的空闲组块列表,而类加载器会在必要时间申请这部分列表.
  • 严格来说,每一个类加载器的存储区域都可以称作元空间,也会根据自身单元结构在获得组块列表中再次细分,而组合在一起就是总的元空间.
  • 为类加载器单独划分空间的的好处是,统一了类和其元数据的与类加载器的生命周期,也就是说,只要类的类加载器是存活的,在Metaspace中的类元数据也必须是存活的,不能被释放,
  • 组块大小取决于类加载器的类型,但由于类加载器并没有固定的尺寸所以也就存在分配的空间大于类加载器所需空间的情况,这就会导致内存碎片的产生,而且Metaspce VM也并没有内存压缩技术。

元空间的垃圾收集

  • 元空间出现之前,GC最麻烦的点就是永久代,元数据的清理就需要各类垃圾收集器有专门的处理代码。
  • 独立到元空间并借由元空间虚拟机管理内存空间之后,就不必那么麻烦,仅由元空间虚拟机中的垃圾收集代码就可以完成,而且由于元空间的分配具有和Java Heap相同的地址空间,共享同一片物理内存,因此MetaspaceJava Htap甚至可以完成无缝管理,大大降低了Full GC的复杂度.

元空间新增的JVM参数

  • -XX:MetaspaceSize 是分配给类元数据空间的初始大小,默认为21MB,如果达到这个大小,就会触发Full GC,之后会根据GC后释放的元空间大小重新调整,如果初始设置的过低会导致Full GC的频繁调用,所以建议MetaspaceSize设置为一个相对较高的值。
  • -XX:MaxMetaspaceSize 是分配给类元数据空间的最大值`,默认没有限制,JVM会在运行时动态调整元空间大小,
  • -XX:MinMetaspaceFreeRatio / XX:MaxMetaspaceFreeRatio 用来设置元空间空闲比例的最大值和最小值

相关博客以及文章

Java 永久代去哪儿了

Java PermGen 去哪里了?(和上一个是不同翻译)

JAVA 方法区与堆--java7前,java7,java8各不相同

Metaspace 之一

results matching ""

    No results matching ""