gc java root_聊聊Java的GC机制

原标题:聊聊Java的GC机制

近日,MIUI在小米全球社区发布公告,表示MIUI将在全球市场销售的手机中预装谷歌拨号及谷歌消息应用程序(中国、印度、印度尼西亚等市场除外)。小米表示,小米9T Pro之后的设备在全球范围内都将会预装上述两款应用程序,不再预装MIUI自带的拨号、消息等APP,该调整是为了遵守当地的隐私政策和法律法规。

大家周一早上好,距离过年的日子已经越来越近,新的一周继续加油哦!

本篇文章转载自某人Valar的博客,分享了他对Java的GC机制的相关理解,相信会对大家有所帮助!

https://juejin.im/post/5df2ec71f265da33d7442433

/ 什么是GC /

GC:垃圾回收(Garbage Collection),在计算机领域就是指当一个计算机上的动态存储器(内存空间)不再需要时,就应该予以释放,以让出存储器,便于他用。这种存储器的资源管理,称为垃圾回收。

有一些语言是没有垃圾回收机制的,像C、C++,如果需要释放无用变量内存空间就由自己来处理。而其他的一些语言如Java、C#都支持垃圾回收器,Java虚拟机(JVM)或.NET CLR发现内存资源紧张的时候,就会自动地去清理无用对象(没有被引用到的对象)所占用的内存空间。而我们今天主要讲Java中的GC。

上面说到JVM会自动清理无用的对象,那么我们就有了疑问:

JVM清理的是哪一块的对象?

哪些对象会被清理,为什么清理A而不清理B?

JVM又是如何清理的?

这三个问题将分别对应接下来的3节一一解答。

/ JVM内存结构简单介绍 /

我们都知道,Java代码是要运行在虚拟机上的,而虚拟机在执行Java程序的过程中会把所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途。

在《Java虚拟机规范(Java SE 8)》

https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5.4

中描述了JVM运行时内存区域结构如下:

以上是Java虚拟机规范,不同的虚拟机实现可能会各有不同,但是一般会遵守规范。

方法区:存储已被虚拟机加载的类信息、常量、静态变量等

堆:堆是Java 虚拟机所管理的内存中最大的一块。唯一目的就是存放对象实例。在虚拟机栈中存放的只是引用,而引用指向的是堆中的对象。GC主要作用的区域。

虚拟机栈:局部变量表、操作数栈等。虚拟机栈描述的是Java 方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法返回地址等信息。

本地方法栈:与虚拟机栈类似,是为native方法提供服务的。

程序计数器:记录当前线程执行的方法执行到了第几行。如果线程正在执行的是一个Java 方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址。如果正在执行的是Natvie 方法,这个计数器值则为空(Undefined)。

/ 可达性分析与GC Roots /

可达性分析

Java中通过可达性分析法来确定某个对象是不是“垃圾”。

该方法的基本思想是通过一系列的“GC Roots”对象作为起点进行搜索,如果在“GC Roots”和一个对象之间没有可达路径,则称该对象是不可达的,不过要注意的是被判定为不可达的对象不一定就会成为可回收对象。

被判定为不可达的对象要成为可回收对象必须至少经历两次标记过程,如果在这两次标记过程中仍然没有逃脱成为可回收对象的可能性,则基本上就真的成为可回收对象了。

注意其本质是通过找出所有活对象来把其余空间认定为“无用”,而不是找出所有死掉的对象并回收它们占用的空间。如下图,当object5、6、7不存在到GC Roots的引用时,即不可到达GC Roots,则判定他们是不可达的。

GC Roots

对于哪些对象可以被当成GC Roots网上有很多种说法,有的不够权威、有的不够全面。

最终找到了一份eclipse的官方文档,里面有如下的介绍:

Garbage Collection Roots

https://help.eclipse.org/2019-09/index.jsp?topic=%2Forg.eclipse.mat.ui.help%2Fconcepts%2Fgcroots.html&resultof=%22%67%61%72%62%61%67%65%22%20%22%67%61%72%62%61%67%22%20

(自己翻译了一下,如有不准确的地方,请指出)

A garbage collection root is an object that is accessible from outside the heap. The following reasons make an object a GC root:

System Class (被boostrap 或者系统类加载器加载的系统类)

Class loaded by bootstrap/system class loader. For example, everything from the rt.jar like java.util.* .

JNI Local( 一些用户定义jni 代码或者jvm的内部代码局部变量)

Local variable in native code, such as user defined JNI code or JVM internal code.

JNI Global( jni 代码中的全局变量)

Global variable in native code, such as user defined JNI code or JVM internal code.

Thread Block(被阻塞的线程引用的对象)

Object referred to from a currently active thread block.

Thread (正在运行的线程)

A started, but not stopped, thread.

Busy Monitor(正在等待的线程)

Everything that has called wait or notify or that is synchronized.For example, by calling synchronized(Object) or by entering a synchronized method. Static method means class, non-static method means object.

Java Local(仍然在线程的栈中的方法的传入参数或方法内部创建的对象)

Local variable.For example, input parameters or locally created objects of methods that are still in the stack of a thread.

Native Stack(本地方法栈中输入或输出参数,例如,用于文件/网络I/O的方法或反射的参数。)

In or out parameters in native code, such as user defined JNI code or JVM internal code. This is often the case as many methods have native parts and the objects handled as method parameters become GC roots.For example, parameters used for file/network I/O methods or reflection.

Finalizable(在回收队列中的对象)

An object which is in a queue awaiting its finalizer to be run.

Unfinalized(覆盖了finalize方法但是还没有被放入回收队列中的对象)

An object which has a finalize method, but has not been finalized and is not yet on the finalizer queue.

Unreachable(一个从任何其他根无法访问的对象,但由Memory Analyzer Tool 标记为根,以便该对象可以包含在分析中)

An object which is unreachable from any other root, but has been marked as a root by MAT to retain objects which otherwise would not be included in the analysis.

Java Stack Frame

A Java stack frame, holding local variables.Only generated when the dump is parsed with the preference set to treat Java stack frames as objects.

Unknown

An object of unknown root type. Some dumps, such as IBM Portable Heap Dump files, do not have root information. For these dumps the MAT parser marks objects which are have no inbound references or are unreachable from any other root as roots of this type. This ensures that MAT retains all the objects in the dump.

复制代码简单总结下就是:

由系统类加载器(system class loader)加载的对象

活着的线程,包含处于等待或阻塞的线程

当前被调用的方法(Java方法、native方法)的一些参数/局部变量

方法区中静态变量、常量引用的对象

Held by JVM - JVM由于特殊目的为GC保留的对象,但实际上这个与JVM的实现是有关的。可能已知的一些类型是:系统类加载器、一些JVM知道的重要的异常类、一些用于处理异常的预分配对象以及一些自定义的类加载器等。

/ 常见的垃圾回收算法 /

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

这是最基础的垃圾回收算法,之所以说它是最基础的是因为它最容易实现,思想也是最简单的。标记-清除算法分为两个阶段:标记阶段和清除阶段。标记阶段的任务是标记出所有需要被回收的对象,清除阶段就是回收被标记的对象所占用的空间。具体过程如下图所示:

优缺点:

从图中可以很容易看出标记-清除算法实现起来比较容易

但是有一个比较严重的问题就是容易产生内存碎片,碎片太多可能会导致后续过程中需要为大对象分配空间时无法找到足够的空间而提前触发新的一次垃圾收集动作。

Copying(复制)算法

为了解决Mark-Sweep算法的缺陷,Copying算法就被提了出来。它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用的内存空间一次清理掉,这样一来就不容易出现内存碎片的问题。具体过程如下图所示:

优缺点:

这种算法实现简单,运行高效且不容易产生内存碎片

但是却对内存空间的使用做出了高昂的代价,因为能够使用的内存缩减到原来的一半。

Mark-Compact(标记-整理)算法

该算法标记阶段和Mark-Sweep一样,但是在完成标记之后,它不是直接清理可回收对象,而是将存活对象都向一端移动,然后清理掉端边界以外的内存。具体过程如下图所示:

优缺点:

标记-整理算法是在标记-清除算法的基础上,又进行了对象的移动,因此成本更高

但是却解决了内存碎片的问题。

Generational Collection(分代收集)算法

分代收集算法是目前大部分JVM的垃圾收集器采用的算法。它的核心思想是根据对象存活的生命周期将内存划分为若干个不同的区域。一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),在HotSpot中,设计者将方法区纳入也纳入了GC分代收集,并为其起了一个名字,永久代(PerGen space)。

老年代:特点是每次垃圾收集时只有少量对象需要被回收,一般使用的是标记-整理(Mark-Compact)、标记-清除(Mark-Sweep)算法。

新生代:特点是每次垃圾回收时都有大量的对象需要被回收,对于新生代都采取复制(Copying)算法。

因为新生代中每次垃圾回收都要回收大部分对象,也就是说需要复制的操作次数较少,但是实际中并不是按照1:1的比例来划分新生代的空间的,一般来说是将新生代划分为一块较大的Eden空间(伊甸园,亚当和夏娃偷吃禁果生娃娃的地方,用来表示内存首次分配的区域,再贴切不过)和两块较小的Survivor空间,每次使用Eden空间和其中的一块Survivor空间,当进行回收时,将Eden和Survivor中还存活的对象复制到另一块Survivor空间中,然后清理掉Eden和刚才使用过的Survivor空间。一般来说分配比例为eden 80%、survivor1 10%、survivor2 10%。

永久代:方法区和永久代的关系很像Java中接口和类的关系,类实现了接口,而永久代就是HotSpot虚拟机对虚拟机规范中方法区的一种实现方式。

在方法区进行垃圾回收一般”性价比”较低, 因为在方法区主要回收两部分内容: 废弃常量和无用的类。回收废弃常量与回收其他年代中的对象类似, 但要判断一个类是否无用需要以下条件:

该类所有的实例都已经被回收, Java堆中不存在该类的任何实例;

该类对应的Class对象没有在任何地方被引用(也就是在任何地方都无法通过反射访问该类的方法);

加载该类的ClassLoader已经被回收。

但即使满足以上条件也未必一定会回收,Hotspot VM还提供了-Xnoclassgc参数控制(关闭CLASS的垃圾回收功能)。

参考:

https://cloud.tencent.com/developer/article/1390547

附:HotSpot虚拟机在1.8之后已经取消了永久代,改为元空间,类的元信息被存储在元空间中,元空间这里不过多介绍,有兴趣的同学可以自己了解下。

/ 结语 /

到此关于Java GC的基本概念、JVM的内存结构、GC回收基本机制都已经介绍的差不多了。有疑问或者发现文章中有错误的可以在下方留言交流。像Java垃圾收集器、元空间这里并没有详细的说明,之后有时间的话会单独拿出来聊聊。返回搜狐,查看更多

责任编辑:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/244584.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c语言课程设计 第2版,c语言课程设计报告模版(电子版)2.pdf

c语言课程设计报告模版(电子版)2大连交通大学 软件学院 C语言课程设计报告SOFTWARE INSTITUTEOF DALIAN JIAOTONG UNIVERSITY EXPERIMENT DESIGNINGC语言课程设计报告Course Design reporter课程名称 : C语言课程设计英文名称 : Course Design of C Programming专 业…

jmeter跨线程组传多个值_Jmeter 跨线程组传递参数 之两种方法(转)

终于搞定了Jmeter跨线程组之间传递参数,这样就不用每次发送请求B之前,都需要同时发送一下登录接口(因为同一个线程组下的请求是同时发送的),只需要发送一次登录请求,请求B直接用登录请求的参数即可,直到登录接口的参数…

wallpaper代码_70 行 python 代码实现壁纸批量下载!

好久没有写文章了,因为最近都在适应新的岗位,以及利用闲暇时间学习python。这篇文章是最近的一个python学习阶段性总结,开发了一个爬虫批量下载某壁纸网站的高清壁纸。注意:本文所属项目仅用于python学习,严禁作为其他…

c语言调用go函数,C中调用go中的回调函数

在用go包装某些c库时(如glut),需要将go函数当作回调函数传递给c库(如glutDisplayFunc(&draw)中的draw函数,我想将go写的函数传过去),应该怎么做?我写了一个示例,但一直不成功,不知道为什么?…

100g流量在电脑上可以用多久_三大运营商5G体验方案出炉!100G一个月够不够?...

前段时间,工信部向中国移动、中国联通、中国电信、中国广电发放5G商用牌照,这也意味着,我国5G网络正式开始被商用。并且目前三大运营商都已完成了5G网络下的终端组网测试,计划于今年第三季度开始进行试商用。而就在近期&#xff0…

easyui一行显示多行_easyui datagrid以及oracle中的多行合并一行

页面显示:前端代码:toolbar"#toolbar" rownumbers"true" singleSelect"true" fitColumns"true">大箱码关联的箱码(不同箱码用分号分开,相同箱码用逗号分开)关联数量data-options"total: 0,pageSize:15,pageList: […

leetcode跳跃游戏C语言,LeetCode:跳跃游戏

给定一个非负整数数组,你最初位于数组的第一个位置。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个位置。示例 1:输入: [2,3,1,1,4]输出: true解释: 我们可以先跳 1 步,从位置 0 到达 位置 1, 然后再从位置 1 跳 3 步到…

java 获取注释_Java面试题Java语言有哪些注释的方式?

点击上方“千锋Java学院”,选择“置顶公众号”每天一道面试模拟真题及解析课前导读●回复"每日一练"获取以前的题目,持续更新!●我希望大家积极参与!有什么不懂可以加小千微信进行讨论★把面试准备工作,拆分…

度秘语音引擎app_语音机器人哪家强 度秘/小冰/Siri/小娜横向评测

关于智能语音机器人,想必大家都不陌生,它们在某种程度上给我们带来了极大的便利。近日,百度推出了基于百度人工智能的手机助理产品——度秘。笔者也进行了体验,感觉不错,就顺带连着微软小冰、小娜和苹果Siri一起来个横…

c语言数字储存于变量,用C语言写中文数字字符串转数值变量

用C语言写中文数字字符串转数值变量C语言写中文数字字符转数值变量最近突发奇想:程序中要是输入一串中文数字,如“十万”就能自动识别转换成数值100000储存到变量里该多好。也许你会说,那很简单啊,先将中文字符分开,再…

微服务微应用的安全测试_提高微服务安全性的11个方法

1.通过设计确保安全设计安全,意味着从一开始就应该将安全性纳入软件设计中。关于安全,其中最常见的一个威胁就是恶意字符。我问我的朋友罗伯温奇(Rob Winch)他对删除恶意字符的想法。Rob是Spring Security项目的负责人,被广泛认为是安全专家。…

密度图的密度估计_箱形图、小提琴图、直方图……统统可以卡通化!

全文共11345字,预计学习时长23分钟或更长对于数据科学家来说,可视化工具比比皆是,因此,退一步去钻研每种可视化的类型及其适用的最佳案例就变得十分重要。为了发挥工具的最佳效用,有时可以考虑将其拟人化,甚…

android 屏幕分辨率 屏幕密度,Android屏幕适配——多分辨率多屏幕密度

为什么要适配,适配的好处等等这里就不说了,直接说我们要怎么适配,请看下面的内容。1.重要概念px:pixel,像素Android原生API,UI设计计量单位,如获取屏幕宽高。屏幕分辨率:指在纵向和横…

操作系统锁的实现方法有哪几种_「从入门到放弃-Java」并发编程-锁-synchronized...

简介上篇【从入门到放弃-Java】并发编程-线程安全中,我们了解到,可以通过加锁机制来保护共享对象,来实现线程安全。synchronized是java提供的一种内置的锁机制。通过synchronized关键字同步代码块。线程在进入同步代码块之前会自动获得锁&…

cocos2dx标准容器_cocos2dx[3.2](24)——内存管理机制

【唠叨】整合参考文档。【参考】【内存管理机制】在3.x版本,Cocos2d-x采用全新的根类 Ref,实现Cocos2d-x 类对象的引用计数记录。引擎中的所有类都派生自Ref。1、引用计数Cocos2d-x 提供引用计数管理内存。> 调用 retain() 方法 &#xf…

android长按加入购物车,《Android APP可能有的东西》之UI篇:加入购物车动画

很多电商app的加入购物车的动作会要求加上动画效果:飞进购物车,想来也合理,在listview界面时商品快速加入购物车,一直toast用户加入成功好像不太正常,所以添加一个动画,用户自然就懂了,而且也挺…

python里的shell是什么_python中的shell操作

http://blog.csdn.net/meng_tianshi/article/details/6682317 首先介绍一个函数: os.system(command) 这个函数可以调用shell运行命令行command并且返回它的返回值。试一下在python的解释器里输入os.system(”ls-l”),就可以看到”ls”列出了当前目录下的…

基于android 定位系统,基于Android平台定位系统设计和实现

2 0 1 3牟第 1 2期文章编号: 1 0 0 9— 2 5 5 2 ( 2 0 1 3 ) 1 2— 0 1 8 7— 0 4 中图分类号: T P 3 1 6 . 8 9 文献标识码: A基于 A n d r o i d平台定位系统设计和实现李瑞宣,王山东,徐志远,王伶俐(河海…

集合竞价如何买入_集合竞价买入法 如何在集合竞价中买入股票?

集合竞价买入法、 如何在集合竞价中买入股票?要想集合竞价买入涨停板,要做到如下3点:快、准、狠!文章将为你盘点这几个方法的具体做法,希望对股民有所帮助。快:就是利用9:15-9:25这1…

python 公众号爬虫_python_爬虫_微信公众号抓取

importrequests,pymysqlimportjson,jsonpath,random,re,time,datetime,os,imghdrfrom lxml importetreefrom selenium importwebdriverfrom urllib importrequestimportssl ssl._create_default_https_contextssl._create_unverified_context注意点:如果同一时间内刷…