首页 > 编程 > Java > 正文

理解Java_GC:时机、对象、行为、算法

2019-11-06 07:00:59
字体:
来源:转载
供稿:网友

1.GC执行的时机

GC将堆里的对象分为新生代,老年代,持久代。新生代有一个Eden区,两个survivor区。新生成的对象直接放在Eden区,Eden区满了就放进survivor1,当survivor1满了就会出发一次Minor GC:将存活的对象放入survivor2,然后清空Eden和survivor1,再将survivor区的交换,保证survivor2为空。当survivor2不足以存放Eden和survivor1的存活对象时,就会放入老年区。较大的对象和长期存活的对象直接进入老年区。当即将进入老年区的对象超过老年区剩余大小时,触发一次full GC。 频率上说,Minor GC较频繁,full GC不频繁。 持久代会存放一些静态值和方法。

2.对象

其实就是对什么对象进行回收。比较标准的回答是:从root搜索不到,而且经过第一次标记、清理后,仍然没有复活的对象。 gc roots: 1. 虚拟机栈中的引用的对象 2. 方法区中静态属性引用的对象,常量引用的对象 3. 本地方法栈中JNI(即一般说的Native方法)引用的对象。

3.行为

新生代:复制清理。 老年代:标记-清除、标记-压缩

4.算法

1° 引用计数(早期策略)

堆中每个对象都有一个计数变量,每当有引用指向该对象时,变量加1,每当一个引用超出生命周期或指向其他对象时,变量减一。当为0时,会被认为是垃圾。 - 优点:简单,效率高 - 缺点:无法识别互相引用但不能从外部访问的对象。

2°标记-清除

从root开始扫描,对存活的对象进行标记,再扫描整个空间的对象,对没有标记的对象进行回收. - 缺点:会造成内存碎片。

3°标记-压缩

在标记-清除后,将所有对象向空闲区移动,并更新指针。成本更高了。 - 优点:解决了内存碎片 - 缺点:增加句柄,成本高

4°复制清理

将内存空间分为对象面和空闲面。当对象面满了,就将存活的对象复制到空闲面。然后清除对象面。如果按照1:1的比例分配空间,那太浪费了。如果对象生存期都非常短,那可以减少空闲区空间,可以节省空间。如主流的虚拟机上新生代Eden:Survivor1:Survivor2=8:1:1。 - 优点:解决了内存碎片和增加句柄的问题。 - 缺点:对于生存期长的对象,浪费空间。

这是我看了网上一些大神的博客和一些学长的理解后,自己整理的我自己关于java gc的大致认识。希望可以解决你的一些小困惑。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表