深入了解Java GC

什么是GC

前🧂:以下GC均代表Java中的GC

我们学习了解的第一步就是明白它能干什么,为什么要用它,它的工作原理是什么。 GC(垃圾回收),能在对象不再使用后会自动被回收。开发者无需过问内存管理,可以专注于解决实际问题。众所周知Java是一门面向对象的语言,Java的内存管理实际上就是对象的管理。通常GC采用有向图的方式记录堆中的对象,在Java中采用的是可达性分析算法,通过GCRoot找出所有活着的对象(GCRoot可达的对象就是存活的对象)。

怎么判断哪些是垃圾对象

1_引用计数法:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。
这种算法不能解决对象之间相互引用的情况,所以在Java中这种方法不靠谱,故不考虑!(python使用的就是引用计数法判断是否是垃圾对象)

2_可达性分析算法(java使用):这个算法的基本思想是通过一系列称为“GCRoots”的对象作为起始点,从这些节点向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链(即GCRoots到对象不可达)时,则证明此对象是不可用的。 在Java语言中,可以作为GCRoots的对象包括

  1. 栈中引用的对象。
  2. 方法区中的类静态属性引用的对象。
  3. 方法区中常量引用的对象。
  4. 本地方法栈中JNI(Native方法)引用的对象。

垃圾收集算法

标记清除(Mark-Sweep)算法

这是最基础的算法,标记-清除算法就如同它的名字样,分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,标记完成后统一回收所有被标记的对象。这种算法的不足主要体现在效率和空间,从效率的角度讲,标记和清除两个过程的效率都不高;从空间的角度讲,标记清除后会产生大量不连续的内存碎片, 内存碎片太多可能会导致以后程序运行过程中在需要分配较大对象时,无法找到足够的连续内存而不得不提前触发一次垃圾收集动作。

复制(Copying)算法

复制算法是为了解决效率问题而出现的,它将可用的内存分为两块,每次只用其中一块,当这一块内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已经使用过的内存空间一次性清理掉。这样每次只需要对整个半区进行内存回收,内存分配时也不需要考虑内存碎片等复杂情况,只需要移动指针,按照顺序分配即可。

标记整理(Mark-Compact)算法

复制算法在对象存活率较高的场景下要进行大量的复制操作,效率很低。万一对象100%存活,那么需要有额外的空间进行分配担保。老年代都是不易被回收的对象,对象存活率高,因此一般不能直接选用复制算法。根据老年代的特点,有人提出了另外一种标记-整理算法,过程与标记-清除算法一样,不过不是直接对可回收对象进行清理,而是让所有存活对象都向一端移动,然后直接清理掉边界以外的内存。

堆内存区域划分

在这里插入图片描述

GC流程

程序new出来的对象会首先会进入年轻代的伊甸园区中(如果对象太大可能直接进入老年代)。在GC之前对象是存在伊甸园区中的,当伊甸园区的内存满了之后执行Young GC,进行Young GC的时候伊甸园区的对象被拷贝到幸存者空间(survive(幸存者)空间:包括from和to,他们的空间大小是一样的,又叫s1和s2)中(有一个拷贝算法),From中的对象(算法会考虑经过GC幸存的次数)到一定次数(阈值(如果说每次GC之后这个对象依旧在幸存者中存在,Young GC一次他的Age就会加1,默认15就会放到老年代。
当老年代存满之后,会执行Full GC,此时除gc线程外的所有用户线程处于暂停状态,也就是不会有响应了,会给用户卡顿时间较长。所以GC调优就是让虚拟机尽可能少的执行Full GC。(System.GC调用的是Full GC方法)

Minor gc、Full gc、Major gc的区别

Minor GC是清理年轻代
Major GC 是清理老年代
Full GC 是清理整个堆空间—包括年轻代和老年代。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值