GC垃圾回收

JVM垃圾回收机制

GC:垃圾回收;把不用的内存帮我们自动释放
STW问题:有时候内存垃圾已经很多;而这是还触发一次GC操作;开销可能非常大;会吃掉部分资源。回收垃圾时有可能会涉及锁操作;导致业务代码卡顿;没法正常速度执行。
Scanner、DataSource需要手动释放;因为这个释放的不是内存;是文件资源的那些;这个还得手动释放

如何回收

回收以对象为单位进行回收;而不是以字节为单位。我们可以三类情况
1:正在使用内存(还有一些一部分在使用;一部分不使用;比如一个对象属性一部分后面要使用;一部分后面不用了)
2:不使用;还没回收内存(回收的是这种)
3:未被分配的内存

回收过程:
1:找到垃圾、判定什么是垃圾;看看哪个对象后面一定不用的;哪个对象后面还可能使用(java只有一种方式;通过引用来使用对象;如果一个对象没有引用指向就不会再被使用)
2:进行对象释放

如何判断什么是垃圾?
1:引用计数;给每个对象分配一个计数器;每创建一个引用指向该对象;计数器就+1;每次该引用被销毁;计数器就-1(不是java做法;Python、PHP的做法)
为什么java没有使用这种方法?
问题1:内存空间浪费多;如果每一个对象都要分配一个计数器(假设按4字节算);;对象多的话就会占用额外的空间特别多。如果对象体积大那问题不是很大;如果一个对象体积是4字节;那足足体积扩大1倍;影响就会很大。
问题2:存在循环引用问题;
在这里插入图片描述
然后a、b这两个引用销毁了;但是对象还没法消失。相当于这两个对象都没用了;没人能访问到这两个东西;就是垃圾;但是计数器不为0;就没法释放。所以Python和PHP是使用其它机制结合使用避免循环引用。
2:可达性分析(java做法)把可达的找到;把不可达的删掉
就是它帮我们串起来的;jvm;串成这个树;多叉树就比较快一点;只知道下面对象的地址;不需要知道上面对象的地址;用他们的地址在这里链表/树串起来。这样子他就可以通过一个根节点遍历到使用的节点;找到可达很不可达;看看这些对象指向是否为null

类似:
找到可达就标记一下;后续如果再遍历到这个(还有后面对象引用指向这个对象;假设这里e换成a;a就直接通过了)可达直接就通过了
在这里插入图片描述
可达性分析起点:GCroots;一个代码有很多这样的起点;把每个起点遍历一遍就相当于完成一次扫描
1:栈上局部变量
2:常量池中对象
3:静态成员变量

如何清理垃圾

这里垃圾回收;回收的是堆上的不再使用的对象
三种清除方法:
1:标记清除;一块内存;哪里是垃圾哪里就释放。会出现内存碎片化问题:释放的空间是零散的;不是连续的。相当于内存已经被分割了;会导致系统无法分配大块内存空间;因为中间占着一些小块的内存;就没法分配连续的内存空间。
比如:计算机总内存空闲空间10k;现在被上述操作分成1k一个;如果此时你要申请2k内存就会申请失败
在这里插入图片描述
2:复制算法(能解决内存碎片化问题);把整个内存分两半;一半是不使用。把不是垃圾的复制到另一半;然后再把前面的空间整个删掉。每次触发都是向另一半进行复制。会出现空间利用率底;如果垃圾少;有效对象多;复制成本就比较大

3:标记整理(能解决内存碎片化和复制算法一部分问题)
类似于顺序表删除中间元素;会有元素搬运操作

上述各有优点:不同场景适用;分代回收是利用上面的三种方法的复合策略;大部分情况有效;有例外的是不适合的。
java 的对象要么就是生命周期特别短,要么就是特别长;所以可以根据生命周期长短;分别使用不同算法
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瞭望~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值