JDK1.6-1.8方法区的变化

方法区

方法区的定义

  • jvm中存储对象类型信息的地方,是jvm重要的组成部分之一。

方法区的存储内容

  • 1.类型信息(域信息,方法信息)
  • 2.运行时常量池
  • 3.静态变量
  • 4.JIT代码缓存

版本更迭变化对比

版本 内容
JDK1.6及以前 方法区的具体实现为永久代,永久代和堆相互隔离,为虚拟机内的一块内存。大小在启动JVM时可以设置一个固定值,不可变;
JDK1.7 依然存在永久代,但是已经开始去除永久代,将字符创常量池以及静态变量存储在堆中
JDK1.8及以后 方法区的具体实现变为元空间,元空间使用的是本地内存,存储类型信息,常量,方法,字段。字符串常量池和静态变量依然在堆中

为什么将永久代替换为元空间

  • 1.为永久代设置空间大小比较困难
    不好判断要为永久代设置多大的空间,如果动态加载的类比较多,容易产生OOM,设置的比较小又会频繁发生FULL GC导致STW时间变长,设置的过大又比较浪费。
    元空间使用的是本地内存,maxMetaspaceSize默认值为-1,随便用。

  • 2.对永久代调优是很困难的
    永久代的垃圾回收主要回收的是常量以及不再使用的类型信息
    常量没人用了就回收,但是类型信息则不然,其需要满足比较多的条件才能被回收

    • 1.该类所有的实例均被回收

    • 2.加载该类的类加载器被回收

    • 3.该类对应的 CLASS对象没有任何地方被引用

为什么将字符串常量池从永久代移到堆空间中

  • 因为字符串常量池在开发过程中是经常会被使用到的,像之前被放置在永久代中被回收的概率就比较低,导致永久代空间不够用,放在堆中,能够及时回收。