栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

jvm垃圾回收

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

jvm垃圾回收

如何判断对象可以回收
1、引用计数法
	给对象添加一个引用计数器,当对象被别的对象引用时,计数加1,当计数为0时则可以被回收
	缺点:无法解决循环引用问题
2、可达性分析
	通过GC ROOTS对象的引用链,当一个对象,没有任何引用链可以到达GC ROOTS对象时,则说明GC ROOTS对象到这个对象是不可达的,可以被回收。
	可以作为GC ROOTS对象包括:
		a、虚拟机栈中引用的对象
		b、方法区中类静态属性引用的对象
		c、方法区中常量引用的对象
		d、本地方法栈中Native方法引用的对象
		 a和d都是指的方法的本地变量表,c主要是指声明为final的常量值。
四种引用
1、强引用
	只有GC ROOTS通过可达性分析不能到达时才会被回收
2、软引用
	仅有软引用引用该对象时,如果jvm内存不足,则会回收软引用对象,如果内存足够,则不会回收,可以配合引用队列来释放软引用自身。
	应用:网页缓存,图片缓存等
3、无论内存是否充足,只要发生GC都会被回收
	应用:mybatis中的缓存
4、虚引用
	必须配合引用队列使用。当GC时,就会加入引用队列,由 Reference Handler 线程调用虚引用相关方法释放直接内存
	应用:配合unsafe.freememory()操作释放直接内存
5、终结器引用
	重写终结方法finallize方法。当没有强引用引用对象时,可以被回收。也是对象放入引用队列,再由 Finalizer 线程通过终结器引用找到被引用对象并调用它的 finalize方法,第二次 GC 时才能回收被引用对象
	处理引用队列的优先级低,工作效率低,可能内存迟迟不被释放,太复杂。一般不推荐使用
回收算法
1、标记清除
	先标记需要回收的对象,再清除。
	缺点:效率较低,遍历两次。产生内存碎片
2、复制算法
	将内存分为等大的两块。将存活的对象放到另一块。剩余的那块清理。
	优点:没有内存碎片
	缺点:每次只是用内存的一半,内存利用率较低;每次都复制长生存对象,效率也有所降低
3、标记整理
	将不用的对象标记。清除后将存活的对象向空闲处移动保证内存的连续。
	优点:没有内存碎片,不用花费更多内存
	缺点:内存地址的复制移动成本更高
4、分代垃圾回收
	a、对象首先分配在伊甸园区域
	b、新生代内存不足时,触发minorGC,伊甸园和幸存区from中存活的对象复制到新生代中幸存区to中。对象的年龄+1,	然后交换from和to
	c、minorGC会引发stw
	d、当幸存区from中年龄超过阈值时,晋升至老年代。最大寿命为2的4次方-1=15
	e、当老年代空间不足时,先触发minorGC,当内存仍不足时,触发fullGC,stw时间更长。	
垃圾回收器
1、串行
	-XX:+UseSerialGC = Serial + SerialOld
	堆内存较小,适合个人电脑,单线程
2、吞吐量优先(parallelGC)
	多线程
	堆内存较大,多核 cpu
	让单位时间内,STW 的时间最短 0.2 0.2 = 0.4,垃圾回收时间占比最低,这样就称吞吐量高
	a、开启
		-XX:+UseParallelGC 手动开启Parallel回收器.jkd8默认开启.
		-XX:+UseParallelOldGC 手动开启Parallel Old回收器.jkd8默认开启.
		上面这两个参数关联,开启一个,默认开启另一个
	b、parallel old 使用的是标记整理回收算法,所以会产生stw,所以该回收器适合做后天工资支付,批量处理,订单处理的应用程序.
3、响应时间优先(cms)
	多线程
	堆内存较大,多核 cpu
	尽可能让单次 STW 的时间最短 0.1 0.1 0.1 0.1 0.1 = 0.5
	a、主打低延迟,可以让用户线程和垃圾回收线程同时运行
	b、运行过程:
		初始标记:需要stw,时间较短(标记根对象)
		并发标记:并发标记线程和用户线程同时运行(标记垃圾)
		重新标记:标记在并发阶段产生的新垃圾
		清除:采用标记清除算法,会产生垃圾碎片,无法采用标记-整理算法是因为,在整理的时候,会有用户线程使用内存,因此无法标记整理。
4、G1
	a、在jdk1.9中默认的垃圾回收器
	b、将堆内存分为很多个不同的region区域
	c、g1根据region垃圾回收价值大小,维护一个优先列表,价值高的优先回收
	d、特殊区域,Humongous,占用的空间超过类内存的50%以上的巨型对象。默认直接分配在老年代。
	e、整体采用标记+整理算法,两个区域之间是 复制 算法
	f、三个阶段
		youngGC:伊甸园中的垃圾回收。存活的对象复制到幸存区,幸存区中对象达到阈值后晋升到老年代
		youngGC+CM:在youngGC时进行GC Root的初始标记;老年代占用堆空间达到阈值(45%)时,进行并发标记。
		Mixed GC:对伊甸园,幸存区,老年代的对象进行全面垃圾回收;最终标记(会stw),拷贝存活。
		根据最大暂停时间,根据优先列表,有选择的选择回收价值最高的对象进行回收。
5、fullGC
	新生代内存不足发生的垃圾回收,minor GC
	老年代内存不足发生的垃圾回收,full GC
5、young collection跨代引用
	a、老年代存在卡表的概念,一个老年代分为很多个卡表区域
	b、新生代存在remember set,记录老年代对新生代的引用。
	c、通过post-write-barrier写屏障+dirty card queue来标记脏卡。每次由特定线程更新remember set
	d、主要作用是减少遍历查找GC Roots的时间,加速新生代的垃圾回收
7、jdk 8u20字符串去重(该特性只在G1中体现,默认不开启)
	String s1 = new String("hello"); // char[]{'h','e','l','l','o'}
	String s2 = new String("hello"); // char[]{'h','e','l','l','o'}
	两个对象引用同一个地址
	优点:节省了内存
	缺点:多占用了cpu计算
	注意:与String.intern()方法不同
		String.intern() 关注的是字符串对象
		而字符串去重关注的是 char[]
		在 JVM 内部,使用了不同的字符串表
8、 JDK 8u40 并发标记类卸载
	所有对象都经过并发标记后,就能知道哪些类不再被使用,当一个类加载器的所有类都不再使用,则卸=载它所加载的所有类
9、JDK 8u60 回收巨型对象
	一个对象大于 region 的一半时,称之为巨型对象
	G1 不会对巨型对象进行拷贝
	回收时被优先考虑
	G1 会跟踪老年代所有 incoming 引用,这样老年代 incoming 引用为0 的巨型对象就可以在新生代垃圾回收时处理掉
垃圾回收调优
1、调优领域
	内存
	锁竞争
	cpu占用
	io
2、确定目标
	低延迟】还是【高吞吐量】,选择合适的回收器
	CMS,G1,ZGC
	ParallelGC
	Zing
3、最快的 GC
	不发生GC
4、新生代调优
	新生代的特点:
		所有的 new 操作的内存分配非常廉价
		TLAB thread-local allocation buffer
		死亡对象的回收代价是零
		大部分对象用过即死
		Minor GC 的时间远远低于 Full GC
	越大越好吗?
		新生代能容纳所有【并发量 * (请求-响应)】的数据
		幸存区大到能保留【当前活跃对象+需要晋升对象】
		晋升阈值配置得当,让长时间存活对象尽快晋升
5、老年代调优
	以 CMS 为例
		CMS 的老年代内存越大越好
		先尝试不做调优,如果没有 Full GC 那么已经...,否则先尝试调优新生代
		观察发生 Full GC 时老年代内存占用,将老年代内存预设调大 1/4 ~ 1/3
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/754696.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号