JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

jvm基础之垃圾(堆)回收

wys521 2024-12-11 12:11:41 精选教程 20 ℃ 0 评论

一晃又是过元旦,

二零一九快过完,

回想一年成绩单,

满脸苦笑心里烦。

---------------------------------打油诗分割线---------------------------------------

面向对象编程,C++与java都是,但是两者之间存在一个重大的差别,就是内存管理与垃圾回收机制,正因为有了java的垃圾回收机制,小伙伴们写代码才能近乎无节制的索取“对象”,而不用考虑善后。

这一次,一起学习下java的垃圾回收,主要分以下几部分:

1.确定对象存活与否

2.垃圾回收算法

3.垃圾收集器

4.内存分配与回收

5.GC日志查看

一,确定对象存活与否:

1.1 引用计数算法

简单点说,就是就是引用这个对象,那么+1,引用失效,那么-1,然后对引用计数为0的对象进行回收。但这个算法有其缺陷,就是无法解决循环引用的问题,导致在java主流虚拟机中使用不多。

循环引用例子如下:

Object obj1=new Object();

Object obj2=new Object();

obj1.instance=obj2;

obj2.instance=obj1;

obj1=null;

obj2=null;

System.gc();//如果在此处发生GC,则使用引用计数算法无法回收,因为两个对象的计算都为1

1.2可达性分析算法:

用一系列"GC Roots"的对象作为起点,走过所有的引用路径,如果该对象没有任何路径可以连接到,则是不可达的对象,可以被判断为可回收的对象,判断为可回收对象后,至少还要经过两次标记,才能真正回收。

作为"GC Roots"的对象,一般是虚拟机栈中的局部变量引用的对象,方法区中静态引用的对象,常量对象及Native对象。

如下图所示,instance1和instance2为活跃对象,instance3和instance4为可回收对象。


1.3java中的四种引用

java在jdk1.2之后,对引用的概念进行了扩充,分为强引用,软引用,弱引用,虚引用。

强引用(Strong Reference):类似于“Object obj=new Object()”这样的句式,只要引用存在就不会被回收。

软引用(Soft Reference):有用但非必须的引用,在OOM发生前,JVM会将这些引用回收,如果还没有足够内存,才会OOM。所以一些图片,展示的内容,可以考虑使用软引用。

弱引用(Weak Reference):也是非必须的引用,但生存周期更短,会在下一次GC中被回收。

虚引用(Phantom Reference):基本无法在程序中使用的引用,垃圾回收时会直接回收不考虑该引用类型。

二,垃圾回收算法

2.1标记-清除算法(Mark-Sweep)

像它的名字说的,分为标记,清除两个步骤。标记就是之前使用的判断是否需要回收的标记,清除就是直接清理标记的内存。如下图所示,该方法比较容易让内存不连续,从而影响大内存空间申请。



2.2 复制算法

复制算法同样简单粗暴,分成两块内存,把一块内还在使用的对象直接复制到另一块,然后整块内存清理。如下图所示:



Hotspot目前就有使用此种算法,根据Eden和Survivor区8:1的比例,将Eden和其中一块Survivor区还活跃的对象,复制到另一块Survivor区,然后将这两块全部清理。

2.3 标记-整理算法

结合了以上两种算法,出现的标记-整理算法,过程与之前的差不多,只是标记之后将内存向一端移动,将边界之外的内存清理。

效果看起来有点像。。汗


2.4 分代收集算法

根据对象活跃周期的不同,分新生代和老生代,新生代中因对象生存周期短,一般使用“复制”算法,而在老生代中,则使用“标记-清理”或“标记-整理”算法。

三,垃圾收集器

3.1Serial收集器

古老的收集器,需要暂停所有工作线程的收集器,目前在JVM的client模式下依然有使用。

3.2 ParNew收集器

Serial收集器的多线程版本

3.3 Parallel Scavenge收集器

更关注CPU吞吐量的收集器。

3.4 Serial Old收集器

Serial收集器的老年代版本。

3.5 CMS收集器

一种以最短回收停顿时间为目标的收集器,通过标记-清除算法实现。

3.6 G1收集器

Garbage-First,当前比较先进的收集器,具有并发,分代,空间整理,可预测停顿时间等优点。

以上收集器没有哪个是全能的,只能说根据合适的场景使用合适的收集器。

四,内存分配与回收的几条规则

4.1 对象优先在Eden区分配

4.2 大对象(占大量连续空间的对象)直接进入老生代

4.3 长期存活的对象进入老生代

在Suervivor区中熬过多次Minor GC的话,就会被移入老生代,阈值由MaxTenuringThreshold控制。

五,如何看懂GC日志

如下例子所示:
2019-11-18T16:02:17.606: 611.633: [GC 611.633: [DefNew: 843458K->2K(948864K), 0.0059180 secs] 2186589K->1343132K(3057292K), 0.0059490 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

其含义大概如下:

611.633(时间戳):

[GC: 表示是非FULL GC,没有STOP-THE-WORLD

[DefNew: GC发生的区域为Serial收集器的新生代中,DefNew是"Default New Generation"的缩写。Serial收集器的老年代和永久代分别表示为"Tenured"、"Perm",名字与手机器关系很大,也可以是ParNew、PSYoungGen等。

843458K(垃圾回收前的已使用容量)->2K(回收后的已使用容量)(948864K(总容量)),

0.0059180 secs(本次回收的时间,单位为秒)

再后面是本次垃圾回收cpu所用时间。


GC相关的JVM参数请参考以下文章:

https://www.cnblogs.com/redcreen/archive/2011/05/04/2037057.html

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表