20210608 由永久代到元空间

Posted 陈如水

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20210608 由永久代到元空间相关的知识,希望对你有一定的参考价值。

永久代(perm)

永久代是Hotspot虚拟机特有的概念,是方法区的一种实现。在Java 8中,永久代被彻底移除,取而代之的是另一块与堆不相连的本地内存——元空间

永久代或者“Perm Gen”包含了JVM需要的应用元数据,这些元数据描述了在应用里使用的类和方法。注意,永久代不是Java堆内存的一部分。永久代存放JVM运行时使用的类。永久代同样包含了Java SE库的类和方法。永久代的对象在full GC时进行垃圾收集。

在Java8中,元空间(Metaspace)登上舞台,方法区存在于元空间(Metaspace)。同时,元空间不再与堆连续,而且是存在于本地内存(Native memory)。

本地内存(Native memory),也称为C-Heap,是供JVM自身进程使用的。当Java Heap空间不足时会触发GC,但Native memory空间不够却不会触发GC。

元空间存在于本地内存,意味着只要本地内存足够,它不会出现像永久代中“java.lang.OutOfMemoryError: PermGen space”这种错误。看上图中的方法区,是不是“膨胀”了。

默认情况下元空间是可以无限使用本地内存的,但为了不让它如此膨胀,JVM同样提供了参数来限制它使用的使用。

 

java 8 内存结构

 

Full GC

Major GC/Full GC 是老年代GC,指的是发生在老年代的GC,出现Major GC一般经常会伴有Minor GC,Major GC的速度比Minor GC慢的多。

Full GC 是发生在老年代的垃圾收集动作,所采用的是标记-清除算法。

Full GC 发生的次数不会有 Minor GC 那么频繁,并且做一次 Full GC 要比进行一次 Minor GC 的时间更长。 另外,标记-清除算法收集垃圾的时候会产生许多的内存碎片 ( 即不连续的内存空间 ),此后需要为较大的对象分配内存空间时,若无法找到足够的连续的内存空间,就会提前触发一次 GC 的收集动作。

触发FullGC的条件

1)老年代空间不足

     如果创建一个大对象,Eden区域当中放不下这个大对象,会直接保存在老年代当中,如果老年代空间也不足,就会触发Full GC。为了避免这种情况,最好就是不要创建太大的对象。

2)持久代空间不足

    如果有持久代空间的话,系统当中需要加载的类,调用的方法很多,同时持久代当中没有足够的空间,就出触发一次Full GC。Perm永久代空间不足会触发Full GC,可以让CMS清理永久代的空间。设置CMSClassUnloadingEnabled即可。

3)YGC出现promotion failure

    promotion failure发生在Young GC, 如果Survivor区当中存活对象的年龄达到了设定值,会就将Survivor区当中的对象拷贝到老年代,如果老年代的空间不足,就会发生promotion failure, 接下去就会发生Full GC.

4)统计YGC发生时晋升到老年代的平均总大小大于老年代的空闲空间

      在发生YGC是会判断,是否安全,这里的安全指的是,当前老年代空间可以容纳YGC晋升的对象的平均大小,如果不安全,就不会执行YGC,转而执行Full GC。

5)显示调用System.gc。System.gc()引起的Full GC,可以设置DisableExplicitGC来禁止调用System.gc引发Full GC

 

对象年龄计算器

虚拟机给每个对象定义了一个对象年龄(Age)计数器。如果对象在 Eden 出生并经过第一次 Minor GC 后仍然存活,并且能被 Survivor 容纳的话,将被移动到 Survivor 空间中,并将对象年龄设为 1。对象在 Survivor 区中每熬过一次 Minor GC,年龄就增加 1 岁,当它的年龄增加到一定程度(默认为 15 岁)时,就会被晋升到老年代中。对象晋升老年代的年龄阈值,可以通过参数 -XX:MaxTenuringThreshold (阈值)来设置。

以上是关于20210608 由永久代到元空间的主要内容,如果未能解决你的问题,请参考以下文章

面试官,Java8 JVM内存结构变了,永久代到元空间

面试官,Java8中JVM内存结构变了,永久代到元空间

永久代退出舞台,元空间腾空出世

永久代退出舞台,元空间腾空出世

java 8中撤销永久代,引入元空间

方法区永久代元空间