博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JVM-垃圾回收相关概念的补充与回顾
阅读量:2047 次
发布时间:2019-04-28

本文共 3230 字,大约阅读时间需要 10 分钟。

文章目录

一、System.GC的理解

在默认情况下,通过System.gc()或者Runtime.getRuntime().gc()的调用,会显式触发Full GC,同时对老年代和新生代进行回收,但是这个执行情况确实不一定执行的,也就是说我调用了System.GC方法尝试主动进行垃圾回收,这个行为是不一定执行的。

举例说明:

public class SystemGC {
public static void main(String[] args) {
new SystemGC(); System.gc();//显示执行gc,但是不一定执行 //System.runFinalization();//强制调用finalize()方法 } @Override protected void finalize() throws Throwable {
super.finalize(); System.out.println("SystemGC重写了finalize()"); }}

二、内存溢出与内存泄漏

1、内存泄漏

定义:

严格意义上只有对象不会再被程序使用了,并且GC又不能对其进行回收了,才叫内存泄漏。
宽泛意义上的内存泄漏也可以指某些对象生命周期过长甚至导致OOM。比如说我们定义一个变量本来可以定义在方法内作为局部变量出现,随着方法的入栈而存活,方法的出栈而死亡,但是我们把他定义成了成员变量,或者通过static修饰把它变成了静态变量,随着类加载而加载,类消亡而消亡,如果这类对象大量出现加上一些没办法被回收的数据的存在从而导致OOM。
图解内存泄漏:在这里插入图片描述
简单总结就是GC Roots 中通过可达性分析对象可达,但是这个对象已经不再使用了,我们没有把它所在的引用链断开,从而导致内存泄漏。
举例说明:
1、 数据库链接, 线程池开启后这些资源链接使用之后没有手动关闭。
2、 单例模式下的内存泄漏,由于单例模式下的静态属性使得它的生命周期与应用程序一样长,如果一个对象已经不再使用,而单例对象持有该对象的引用,从而导致内存泄漏。

2、内存溢出

定义:

javadoc文档对于内存溢出(OOM)的定义是没有空闲内存,并且垃圾收集器进行垃圾回收后仍然无法提供所需要的内存。
两大罪魁祸首:
1、java虚拟机堆内存设置的大小不合理,通过-Xms,-Xmx来调整
2、代码中创建了大量对象,因为被引用的问题而导致无法被GC,从而额导致内存溢出。
补充:
一般情况下,在抛出OOM异常之前,都会进行一次GC操作对垃圾进行回收,但是也有可能存在我们分配了一个占用了内存很大的数组,老年代也放不下该数组对象,则直接抛出OOM异常。


三、STW概念理解

定义:

指的是GC事件发生的过程中,应用程序停顿,停顿的过程中整个应用程序线程都被暂停。例如在可达性分析的时候对对象进行标记的时候,如果不暂停线程,那么在应用程序执行的过程中,对象的引用关系可能存在变化,从而导致可达性分析并不准确。
作用:
确保一致性
补充:
1、STW是JVM在后台自动发起和完成的
2、STW无论采取那款垃圾回收器GC都会存在,目前来说。


四、并行和并发

1、程序中的并发和并行:

定义:

1、并发:指的是多个事情,在同一时间段内同时发生了。
2、并行:指的是多个事情,在同一时间点上同时发生了。
主要区别
1、 并发的多个任务之间是互相抢占资源的。
2、 并行的多个任务之间是不互相抢占资源的。
补充说明:
只有在多CPU或者一个CPU多核的情况中,才会发生并行。否则,看似同时发生的事情,其实都是并发执行的。

2、垃圾回收中的并发和并行:

并行(Parallel)

指多条垃圾收集线程并行工作,但此时用户线程仍处于等待状态。如ParNew、 Parallel Scavenge、 Parallel 0ld;
串行(Serial):

1、相较于并行的概念,单线程执行。

2、如果内存不够,则程序暂停,启动JVM垃圾回收器进行垃圾回收。回收完,再启动程序的线程。
在这里插入图片描述
并发(Concurrent)
1、指用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交替执行),垃圾回收线程在执行时不会停顿用户程序的运行。
2、用户程序在继续运行,而垃圾收集程序线程运行于另一个CPU上;
如: CMS、G1
在这里插入图片描述


五、安全点与安全区域

1、安全点

#引言:

通过上面的学习,我们知道当GC发生的时候,是会触发STW暂停用户线程以方便垃圾回收的,那么我们是可以在程序执行时的所有地方都可以停下来进行GC吗?答案是否定的,程序执行只有在特定的位置才可以停下来进行GC,这个点我们就称之为安全点。
#安全点的选择:
安全点的选择很重要,如果安全点太少,那么就可能会导致GC时间过长,如果安全点太多,又会导致运行性能下降,那么我们的安全点应该选在哪呢?----选择一些执行时间较长的指令作为安全点,例如方法调用,循环跳转等。
那么问题又来了,如何在GC的时候,确保所有线程都进入了安全点呢?这里就提供了两种实现机制:
#抢先式中断(目前虚拟机以不再使用):
首先中断所有线程,如果还有线程不在安全点,则恢复线程,让线程跑到安全点。
#主动式中断:
设置一个中断标志,各个线程跑到安全点的时候,主动轮询这个标志,如果中断标志为真,则将当前线程挂起以等待GC。

2、安全区

我们知道安全点中的主动式中断,他需要线程运行到安全点之后通过轮询的方式判断这个中断标志,那么问题又来了,那如果这个线程休眠了,或者说这个线程阻塞了,线程就“走”不到安全点去响应中断请求,这个时候怎么办呢? 这里我们就引入了安全区的概念:

#定义:
安全区是指在一段代码片段中,对象的引用关系不会发生变化,在这个区域中的任何位置开始GC都是安全的,可以理解安全区是扩展了的安全点。
#补充:
当线程运行到安全区时,标识为Safe Region,此时GC如果执行,会忽略被标记为Safe Region的线程。当线程尝试离开安全区的时候,JVM会检查GC是否执行完毕,如果执行完毕则放行。


6、相关引用

通过前面的学习,我相信大家对JVM已经有了一些基本的了解,我们在前些篇章的描述中,说道:当内存空间还足够的时候,则直接将对象保存在内存中;如果内存空间不足,会在此之前进行一次GC,如果再不够则抛出OOM异常,通过本章的学习之后我们会对此过程有个比较全新的了解,如果内存空间不足的话在垃圾回收后还是很紧张,是可以抛弃这些对象不报异常的。


一、强引用(可触及的)

#简单总结:不回收

1、只要强引用关系存在,无论内存空间是不是不够了报OOM异常了也不回收。我们日常开发中用的绝大部分都是强引用,诸如 Object obj = new Object();
2、内存泄漏的主要原因


二、软引用(可触及的)

#简单总结:内粗你不足即回收

1、第二次回收中,内存不够了才回收。(第一次主要是回收那些没被标记的,不可触及的对象),如果第二次回收内存还不够,则报OOM异常。
2、软引用常用来实现内存敏感的缓存。比如:高速缓存就有用到软引用。


三、弱引用(可触及的)

#简单总结:发现即回收

1、用来保存可有可无的缓存
2、只能存活到下一次GC之前
3、因为GC回收线程优先级比较低,不一定很快的发现持有弱引用的对象,因此可以存活较长的时间

四、虚引用(可触及的)


#简单总结:对象回收跟踪

1、就像其名字一样,是很虚空的存在。一个对象是否有虚引用的存在,对其生存时间没有任何影响,也无法通过虚引用来获得一个对象的实例。它唯一的目的就是能在这个对象被回收的时候收到一个系统通知。
2、虚引用必须配合引用队列一起使用。
在这里插入图片描述


转载地址:http://edqof.baihongyu.com/

你可能感兴趣的文章
【Loadrunner】Error -26601: Decompression function 错误解决、27728报错解决方案
查看>>
【其他】csv文件打开是乱码,怎么办?
查看>>
【Python】web.py初识学习
查看>>
【Python】【Web.py】python调用html【问题:echart图标调用html上未显示】
查看>>
【雅思】金山词霸-单词学习(1-40)
查看>>
【F12】谷歌浏览器F12前端调试工具 Console
查看>>
【服务器】如何在服务器发布网站?Sasa讲解
查看>>
【F12】九个Console命令,让js调试更简单
查看>>
【数据库】left join(左关联)、right join(右关联)、inner join(自关联)的区别...
查看>>
【雅思】【写作】【大作文】Advantage VS. Disadvantage
查看>>
【雅思】金山词霸-单词学习(41-80)
查看>>
【雅思】【写作】【大作文】Report
查看>>
【雅思】【作文】顾家北100句翻译
查看>>
【雅思】【写作】【大作文】Discuss both views and give your own opinion
查看>>
【托业】【金山词霸】21-42
查看>>
【托业】【金山词霸】单词1-20
查看>>
【Python】脚本运行报错:IndentationError: unindent does not match any outer indentation level...
查看>>
【JMeter】前置处理器
查看>>
【Linux】top命令详解
查看>>
【黑盒测试】测试用例的常用方法
查看>>