编程语言
首页 > 编程语言> > jvm堆中的分区以及对应使用的GC算法

jvm堆中的分区以及对应使用的GC算法

作者:互联网

jvm堆中的分区以及对应使用的GC算法

记录第一篇博客

jvm堆的解释

我们在jvm中的分类有许多,其中包括有两个子系统(类装载器,执行引擎)和两个组件(运行时数据区、本地方法接口)。
而堆属于运行时数据区中的其中一个组件。堆在jvm中的重要性不言而喻。它几乎存储了所有的引用对象的实际值,也就是引用对象的地址。
他也是java虚拟机中内存最大的一块,所有的对象的内存分配都在这里进行。而且堆是被所有的线程共享。这个特性直接和主内存挂钩。

堆中的分区

在虚拟机堆中的分区从大类上来说可以分为三类,分别为新生区、老年区、以及永久区,而新生代又可以分为伊甸园区、幸存者0区、以及幸存者1区。在jdk1.6之前,永久区叫做永久代,常量池在方法区中,在jdk1.7这个版本,逐渐实现去永久代。常量池在堆中。在jdk1.8之后,没有永久代的说法,更多的是叫做元空间。实质是一样的。

值得注意的是元空间属于逻辑上存在、但是物理上不存在的。我们可以在运行程序的时候给堆内存进行参数的调试。打印出对应的区的大小。可以看到新生区加老年区的大小正好是我们给堆定义的内存大小。在物理角度上元空间是不存在的。

在永久区中都是用来存放jdk自身携带的class对象。interface元数据,
存储java运行时的一些环境或者类信息。这个区域不存在垃圾回收。关闭虚拟机就会释放这个区域内存。

值得注意的是永久区不会出现OOM的错误。仅在以下几种情况可能出现
1、一个启动类加载了大量的第三方jar包,tomcat部署太多应用、大量动态生成的反射类。
2、不断的被加载。直到内存满就会出现OOM。(永久区中的内存满。)
所以jvm调优都是在新生区以及老年区中进行。

几乎所有的GC都是在新生区以及老年区中进行。

新生区中使用的GC算法-复制算法

在堆中使用不同的GC算法的时候,我们应该选择最适合该区的算法。不同的区有不同的GC算法。
复制算法:
好处:没有内存碎片。
坏处:浪费了内存空间,多了一半空间永远是空的。(唯一缺点)
复制算法最佳使用场景:对象存活度较低的时候,而对象存活度较低的时候正好符合新生区。

老年区中使用的GC算法-标记清除+标记压缩混合使用

老年区中的对象基本都是在新生区中的幸存者区中在进行垃圾回收之后仍然没有被回收的对象,此时这个对象将进入老年区。一般来说这个对象的存活时间较长。如果使用复制算法的话,那么复制的成本将会大大的增加。所以争对老年区应该使用标记清除以及标记压缩进行GC。
1、标记清除算法:
缺点:两次扫描,严重浪费时间。并且会产生内存碎片。
优点:不需要额外的内存空间。

扫描两次
第一次将使用的对象进行标记,没有使用的对象不进行标记
第二次将没有标记的对象进行回收。而标记的对象随之进入对应的区域。

2、标记压缩:压缩,向一端移动存活的对象。相对于标记清除可以防止内存碎片的产生。
当标记清除之后内存碎片如果很多,在进行一次标记清除之后就应该进行标记压缩,但是如果进行少数次的标记清除过后产生的内存碎片如果不多,那么可以在多次标记清除过后在进行标记压缩。避免内存碎片过多导致jvm的性能下降以及分配内存时导致hash值不够迅速。

三种GC算法的效率对比

内存效率:复制 >标记清除 >标记压缩

内存整齐度:复制> 标记压缩 >标记清除

内存利用率:标记压缩=标记清除>复制



标签:区中,标记,算法,GC,内存,jvm,堆中
来源: https://blog.csdn.net/m0_46415190/article/details/115251088