GC 垃圾回收 和 垃圾回收器

什么是垃圾?

没有任何引用指向的对象就是垃圾

怎么找到一个垃圾?

常用的技术一:引用计数
记录当前的空间有多少个对象在引用,当数值变成一了,就垃圾回收

常用的技术二:根可达算法
哪些对象是根对象?
jvm stack
native
method
pool 等等

如何清除一个垃圾?

一共就三种算法

  • Mark-Sweep 标记清除
  • Copying 拷贝
  • Mark-Compact 标记压缩

Mark-Sweep

在这里插入图片描述
优点:简单
缺点:碎片化,所谓的碎片化就是指的一个空间里清除的区域东一个西一个,千疮百孔,找不到一个连续的空间存储

Copying

在这里插入图片描述
规定空间只能使用一半,将数据存储之后,然后将另外一半 复制过去
缺点:浪费空间

Mark-Compact

在这里插入图片描述
先把要回收的弄到一块区域,集中回收

缺点:效率低

☆☆☆Garbage collectors 垃圾回收器☆☆

新生代 和 老年代?
每经过一个垃圾收集器处理,年龄加1,回收过好几遍都回收不掉的称为老年代
PS + PO
在这里插入图片描述

经常配合使用的是:
parnew 和 cms
serial 和 serial old
PS 和 PO

堆内存逻辑分区

在这里插入图片描述
新产生的对象都会存才Eden区域,但是采用的是复制算法,淘汰的对象很多,只有少部分数据可以进入 survivor区域,survivor区域总有一个是空的。

默认新生代和老年代的占空间大小为1:2,老年代空间要大些,可以自己调节。大小调节不规范就会产生很多问题,比如后面的full gc

在这里插入图片描述

Serial

STW: stop-the-world :立刻停止事件
停止之后进行垃圾回收,停止时间从几秒可以到3天

JVM第一个调优:重启

CMS:承前启后

工作在老年代,mark sweep 碎片化
暂停时间很短

并发执行:垃圾回收线程和工作线程同时执行
冲突:
有些垃圾在某些情况下又不是垃圾了

在这里插入图片描述

内存比较少的时候,serial和serial old配合
内存越来越大,parallel scavenge 和 parallel old 配合
内存更大的时候,parnew 和CMS配合

cms有一个巨大的毛病:用通俗的话来说,可能会产生一个阿姨打扫整个100层楼的酒店情况,会非常的 耗时

jdk 1.8默认的回收机制:PS/PO
jdk 1.8以上默认回收机制:G1

什么是调优

1、。。。。。
2、优化jvm的运行环境
3、解决jvm运行时出现的问题(OOM:内存泄漏)

理解内存泄漏:这空间被占用,无法进行回收
内存溢出:占满了,回收不了,内存崩了

处理cpu内存异常的工具:arthas
在这里插入图片描述

问题:线上运行的程序,cpu突然飙高,你怎么解决这个问题?
在这里插入图片描述
定位线程
我们知道,Java是单进程多线程的,那么,我们接下来看看PID=xxxx的这个Java进程中的各个线程的CPU使用情况,同样是用top命令:
在这里插入图片描述
定位代码
通过top命令,我们目前已经定位到导致CPU使用率较高的具体线程, 那么我么接下来就定位下到底是哪一行代码存在问题。

首先,我们需要把4519这个线程转成16进制:
在这里插入图片描述
在这里插入图片描述

查找出哪些对象回收不了?

jmap -histo 1196 | head 20

可以查找出哪些对象的实占内存最多
在这里插入图片描述

在这里插入图片描述

项目频繁的full gc 你该怎么做?

触发原因有很多种,但归根到底都是因为内存空间不足
Full GC频繁发生,意味着你的内存分配机制存在问题,也许是内存泄露,有大量内存垃圾不断在老年代产生;也许是你的大对象(缓存)过多;也有可能是你的参数设置不好,minor GC清理不掉内存,导致每次minor GC都会触发Full GC;还有可能是你的老年代大小参数设置错误,老年代过小等等原因

1、如果每次gc之后剩余的空间不大,说明有一部分顽固对象一直没法被回收,导致可用内存变少。这种情况下很容易后续出现oom,比如说一次大对象的申请

2、如果每次gc之后剩余的空间比较大,意味着大部分对象都被清理了,但是系统又在频繁的fullgc,说明很快老年代又会涌入大量对象。这个时候就应该检查下jvm的参数配置,很有可能是新生代设置的太小了,导致很多应该在minor gc阶段就清理出去的对象留到了老年代,这种可能性是最大的

新生代可以分为eden、survivor0、survivor1,正常的对象分配都是在eden完成的,如果eden空间不够了,会触发一次minor gc,存活的对象放在s0或s1中。随着每次minor gc,存活的对象会不断的从s0迁到s1,再从s1迁到s0,这个过程经过几次之后,如果对象还是存活的,就会晋升到老年代。

但如果新生代大小设置的太小,就会导致非常频繁的minor gc,s0->s1来回切换的速度加快,导致本身应该在minor gc就清理出去的对象跑到了老年代。

举个例子,正常情况下如果minor gc是1分钟一次,-XX:MaxTenuringThreshold默认配置是15的话,正常的小对象最长可以在新生代待15分钟左右,如果一个对象o的存活时间是5分钟,那它就可以在minor gc的时候被清理出去;但如果新生代设置过小,minor gc的频率降到10秒一次,那么o只能在新生代待150秒左右,然后就会晋升到老年代,这种对象一多,就会导致频繁的fullgc

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

你在狗叫什么、

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

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

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

打赏作者

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

抵扣说明:

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

余额充值