JAVA面试基础

JVM垃圾回收算法

2018-11-20  本文已影响72人  ssttIsme

1标记-清除

标记存活对象,清理其他垃圾对象。
优点:效率高(只需要把其他位置擦掉)。缺点:产生碎片(碎片导致分配大对象时要整理成连续的)。




2标记-整理

标记之后,把其他垃圾对象清除,整理对象成连续存放。减少磁盘碎片。




优点:
没有碎片。
缺点:
效率低(对象在空间里频繁复制)。


3复制(要有对等内存空间保持为空)

需要两块相等的内存空间,一块内存保存为空。



标记存活对象后,直接复制到右边空的内存空间,清空全部左边空间




优点:效率高

缺点:浪费内存

垃圾对象

1从根对象出发,所有被引用的对象都是存活对象。
2其他对象,都是垃圾。
根对象:
1栈中的引用变量所引用的对象
2方法区的静态变量所引用的对象


栈存的是方法里面的局部变量或if代码块的局部变量

根对象是栈中的引用变量所引用的对象

根对象还是方法区的静态变量所引用的对象


蓝色是存活对象 粉色是垃圾对象

JVM的内存分区

1新生代
2老年代
3永久代(方法区)

1新生代(分三块)


-伊甸园
-生存区
--1 from
--2 to

1新建对象,在伊甸园分配内存
2伊甸园存满,复制到from
3from存满,复制到to,并交换角色
4对象在from,to之间复制15次,次数可指定参数配置(一般不需配置)
5晋升到老年代

老年代


使用标记-整理和标记-清除
间隔一段时间,会执行一次小范围的垃圾回收
当老年代空间占用到一定比例(一般是85%),会执行一次full-gc(完整垃圾回收-效率不高)

老年代使用的垃圾回收器

1 CMS(并发的标记-清除)
2 G1

CMS-并发的标记-清除
@运行效率高,STW(Stop The World-如果执行垃圾回收过程,STW可能会把虚拟机锁定,只允许垃圾回收器执行。你的代码会短暂地中断)暂停时间非常短暂。
CMS执行过程
1初始标记

只标记根对象(根对象数量有限-速度非常快,初始标记过程会引起STW)
2并发标记
垃圾回收器,与其他java程序并行执行。(你的程序还在执行)
3对象漏标记时,重新标记
只对并发标记没有标记的对象,重新标记,会引起两次STW时间
4并发清除
与其他java程序并行执行,把其他垃圾对象擦除,你的程序正常执行

jdk1.7后默认使用CMS。
CMS配置参数过多,可以详细配置新生代,老年代,永久带内存空间大小。但是使用过于复杂。

如果要详细配置内存区:
要让老年代内存空间内存要大。


老年代很多对象,长时间生存,这种长时间生存的对象,没有必要频繁扫描这段内存空间,它已经存活很长时间了。在未来更长时间内,很可能都不变成垃圾,这样预测的话,就不必对老年代对象频繁扫描。而在伊甸园新建的对象,刚刚创建的对象非常不稳定,可能很快就会变成垃圾,所以对新生代伊甸园的对象要频繁地扫描,伊甸园只要填满就扫描找垃圾,回收。所以这块空间要比较小,而且它有空白空间会浪费内存。而且它执行垃圾回收频繁地复制,空间太大,复制的内存块太大就会比较大

生存区要比伊甸园小。配置生存区更大好一些。让from放更多的对象以减少老年代的压力。

在伊甸园新建对象,分配内存
伊甸园被占满,标记存活对象
把存活对象放在from 并且伊甸园清空。用的是标记复制。 在伊甸园继续创建新对象,等伊甸园再满了,标记存活对象,把存活对象复制到from,伊甸园直接清空
from空间沾满
继续标记from当中的存活对象
复制到to
from中的对象清空
from和to颠倒
继续在伊甸园创建对象

伊甸园满了往from复制,存活对象被复制到from
标记其中的存活对象
继续向to复制
清空from 再交换角色

from-to来回复制,每次复制对象年龄加1,复制15次,晋升到老年代。


G1-GarbageFirst垃圾第一

内存被划分为几千个内存块,也有分代的划分。有的是伊甸园,有的是生存区,有的是老年代。这样划分,如果创建对象还是在伊甸园,伊甸园创建满了向生存区复制,生存区满了,在多个生存区之间来回复制,复制多次之后还可向老年代复制,老年代满了还可向另外一个老年代复制。所以现在执行的垃圾回收算法都是复制,没有清除整理,也不会产生碎片。(复制本身效率比较高)



所有的垃圾回收算法都是复制。

G1垃圾回收器会找到垃圾最多的内存快,优先回收。

G1的配置参数非常简单,只需要配置目标停顿时间(stw时间),G1会自动调整其他参数,来达到预期的停顿时间(一般不超过200ms)

现在虚拟机默认不是G1,如果你想用G1来代替CMS,那么你需要配置来使用。

G1的出现就是为了代替CMS,但是还有bug。

上一篇下一篇

猜你喜欢

热点阅读