所有分类
  • 所有分类
  • 未分类

JVM原理–元空间(MetaSpace)与永久代(PermGen)的区别

简介

说明

本文介绍JVM中元空间(MetaSpace)与永久代(PermGen)的区别。

永久代和元空间与方法区的关系

JVM一共分为五个部分:堆,方法区,虚拟机栈,本地方法栈,程序计数器。

永久代和元空间都属于方法区,都是方法区的实现。

JDK8的的变化

从JDK7 开始,JDK开发者们就开始消灭永久代了,JDK8完全完成:

  1. 永久代的字面量 (interned strings)     转移到 Java heap;    (JDK7完成)
  2. 永久代的静态变量(class statics)        转移到Java heap ;   (JDK7完成)
  3. 永久代的符号引用(Symbols)              转移到 Native heap ;(JDK7完成)
  4. 永久代中的 class metadata                    转移到 Meta Space; (JDK8完成)
    1. 永久代参数 (PermSize MaxPermSize) 改为 元空间参数(MetaspaceSize MaxMetaspaceSize)

元空间与永久代的区别

元空间

使用本地内存(native mermory)。

它不属于JVM内存,不受JVM垃圾回收的控制。最大大小取决于系统内存,而不是堆大小。

永久代

使用JVM的内存。

为什么要使用元空间?

原因1:避免OOM异常

使用永久代时

使用永久代时,通常使用 -XX:PermSize 和 -XX:MaxPermSize设置永久代的初始大小和设置永久代的最大值,但是不是总能知道应该设置为多大合适(太小,容易导致永久代溢出;太大,容易导致老年代溢出),如果使用默认值很容易遇到OOM(OutOfMemory)错误。

使用元空间时

JDK8 的方法区是元空间,元空间可以加载多少类的元数据由系统的实际可用空间来控制。

元空间使用本地内存(Native memory)。元空间使用本地内存也就意味着只要本地内存足够,就不会出现OOM的错误。默认情况下元空间大小是无限的。

原因2:将虚拟机进行合并

Oracle想合并HotSpot和JRockit的代码。

元空间里是什么数据?

Metaspace 是用来存放 class metadata 的,class metadata 用于记录一个 Java 类在 JVM 中的信息,包括但不限于 JVM class file format 的运行时数据:

  1. Klass 结构
    1. 这个非常重要,可以理解为一个 Java 类在虚拟机内部的表示;
  2. method metadata
    1. 包括方法的字节码、局部变量表、异常表、参数信息等;
  3. 注解;
  4. 方法计数器,记录方法被执行的次数,用来辅助 JIT 决策

虽然每个 Java 类都关联了一个 java.lang.Class 的实例,而且它是一个贮存在堆中的 Java 对象。但是类的 class metadata 不是一个 Java 对象,它不在堆中,而是在 Metaspace 中。

元空间的分配、回收、配置

什么时候分配 Metaspace 空间?

当一个类被加载时,它的类加载器在 Metaspace 中分配空间用于存放这个类的元数据

什么时候回收 Metaspace 空间?

分配给一个类的空间,是归属于这个类的类加载器的,只有当这个类加载器卸载的时候,这个空间才会被释放。

所以,只有当这个类加载器加载的所有类都没有存活的对象,并且没有到达这些类和类加载器的引用时,相应的 Metaspace 空间才会被 GC 释放。

配置 Metaspace 空间

  • -XX:MetaspaceSize=N              设置原始元空间大小;
  • -XX:MaxMetaspaceSize=N       设置最大元空间大小,默认是没有限制的。
  • -XX:CompressedClassSpaceSize:Metaspace 中 Compressed Class Space 的最大允许内存,默认值是 1G,这部分会在 JVM 启动的时候向操作系统申请 1G 的虚拟地址映射,但不是真的就用了操作系统的 1G 内存。

0

评论0

请先

显示验证码
没有账号?注册  忘记密码?

社交账号快速登录