网站首页 > 精选教程 正文
一晃又是过元旦,
二零一九快过完,
回想一年成绩单,
满脸苦笑心里烦。
---------------------------------打油诗分割线---------------------------------------
面向对象编程,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
- 上一篇: 如何识别Java中的内存泄漏
- 下一篇: Java面试必考问题:有哪几种常用的垃圾回收算法
猜你喜欢
- 2024-12-11 Java面试必考问题:有哪几种常用的垃圾回收算法
- 2024-12-11 如何识别Java中的内存泄漏
- 2024-12-11 Java JVM垃圾回收算法浅记
- 2024-12-11 Java中的垃圾回收算法与垃圾回收器
- 2024-12-11 Java 高级篇:JVM 垃圾回收机制
- 2024-12-11 Java面试必背——垃圾回收机制及如何手动触发垃圾回收,附代码
- 2024-12-11 硬核图解!新手也能看懂的Java 垃圾回收!
- 2024-12-11 Java 程序员必会的「垃圾回收」算法
- 2024-12-11 详解Java的垃圾回收机制(GC)
- 2024-12-11 面试讲解JAVA GC(垃圾回收机制)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)