首页 > 其他分享 >JVM 判断是否应该回收对象

JVM 判断是否应该回收对象

时间:2023-12-30 10:37:23浏览次数:20  
标签:对象 虚拟机 回收 引用 JVM 方法 内存


JVM内存 中程序计数器、虚拟机栈、本地方法栈 3 个区域随线程而生,随线程而灭。这几个区域不用考虑回收问题,因为方法结束后 或者 线程结束后,内存就跟着回收了。而Java堆方法区不一样,一个接口的多个实现类需要的内存不一样,一个方法的多个分支需要的内存也可能不一样,我们只有在程序运行的时候才知道会创建那些对象,这部分内存的分配和回收都是动态的,垃圾收集主要所关注的就是Java堆方法区。

1. 可达性分析算法

可达性分析算法,这个算法的思想,通过一系列的称为 GC Roots 的起始点,当一个对象到 GC Roots 没有任何的引用链相连,则证明这个对象是不可用的,这个对象是可回收的,如下图中的object5、object6,object7是可回收的(该图选自:深入理解Java虚拟机:JVM高级特性与最佳实践 / 周志明老师著)。

JVM 判断是否应该回收对象_方法区

GCRootS 对象包括如下几种。

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象。
  • 方法区中类静态属性引用的对象。
  • 方法区中常量引用的对象。
  • 本地方法栈中 JNI (即一般说的Native方法)引用的对象。

我们知道,每个方法执行的时候,JVM 都会创建一个相应的栈帧(栈帧中包括操作数栈、局部变量表、运行时常量池的引用),栈帧中包含这在方法内部使用的所有对象的引用(当然还有其他的基本类型数据),当方法执行完后,该栈帧会从虚拟机栈中弹出,这样一来,临时创建的对象的引用(虚拟机栈中)也就不存在了,或者说没有任何 GCRootS 指向这些临时对象(堆中),这些对象在下一次GC时便会被回收掉。

静态属性是该类型(class)的属性,不单独属于任何实例,因此该属性自然会作为GCRootS 。只要这个class存在,该引用指向的对象也会一直存在。Class 也是会被回收的,请看第四小节。

2 引用

引用的定义:如果 reference 类型的数据(栈帧中的本地变量表)中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表着一个引用。一个对象如果只有两种状态:引用和未被引用,如下情况无法去实现,以类对象,内存空间还足够的时候,可以保存这类对象,内存空间不够的话,则抛弃(回收)这些对象。

Java的引用类型分为:强引用,软引用,弱引用,虚引用。

强引用:Object object = new Object(); 这类引用,只要强引用存在,就不会回收被引用的对象(堆中)。

软引用:用来描述一些还有用,但并非必须的对象,在内存将要溢出的时候,会对于软应用的对象进行回收,如果这次回收之后内存还是不够,才会报出异常。使用 SoftReference 类来创建软引用。

弱引用:弱引用都只能活到下次垃圾回收之前,无论内存是否足够,都会进行回收。使用 WeakReference 类来创建弱引用。

虚引用:最弱的一种引用关系,一个对象是否有虚引用的存在完全不会对其生存时间构成影响,也无法通过虚引用来获取实例,为一个对象设置虚引用就是这个对象被垃圾收集器回收时受到一个系统通知。使用 PhantomReference 来创建虚引用。

3. 生存还是死亡

可达性分析方法中不可达的对象也不是“非死不可”的,这时候它们处于“缓刑”阶段,要真正宣告一个对象死亡还需要两次标记过程。

第一次标记:如果对象进行可达性分析后,发现没有与GC Roots 相连接的引用链,那么他会被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行 finalize 方法,当对象没有覆盖 finalize 方法 或者 finalize 方法已经被虚拟机调用过,虚拟机将这两种情况都是为“没必要执行”。

如果有必要执行,则将他们添加到队列F-Queue的队列之中,并在稍后由一个虚拟机自动建立、低优先级的 Finalizer 线程去执行它,这里所谓的“执行”是指虚拟机会触发这个方法,但并不承诺会等他运行结束,这样做的原因,如果一个对象在 finalize() 方法中执行缓慢,或者发生了死循环,导致其他对象一直等待, finalize() 方法是逃脱被回收的最后一次机会。

第二次标记:GC会再次对 F-Queue中的对象进行第二次小规模的标记,如果对象要在finalize()中拯救自己,只要重新与引用链上的任何一个对象建立关联即可,例如:把自己赋值给某个类变量或者对象的成员变量,那在第二次标记时他将被移除“即将回收”的集合;如果对象这时候还没有逃脱,那基本上它就真的被回收了。

4. 回收方法区 

很多人认为方法区(或者HotSpot虚拟机的永久代)是没有垃圾收集的,Java 虚拟机规范中确实说过可以不要求虚拟机在方法区实现垃圾收集,而且在方法区中进行垃圾收集的“性价比”较低;在堆中,尤其是在新生代,常规应用进行一次垃圾收集一般可以回收 70%~95% 的空间,而永久代的垃圾收集效率远低于此。

永久代的垃圾收集主要回收两部分内容:废弃常量和无用的类

回收废弃常量与回收 Java 堆中的对象非常相似。例如:有一个常量字符串 “abc”,如果没有String 对象使用它,就回收这个常量字符串。

判断类是否为废弃类,需要满足三个条件。

  • 该类的所有实例都被回收,也就是Java堆中不存在该类的任何实例。
  • 加载该类的 ClassLoader 已经被回收。
  • 该类对应的 Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

在大量使用反射、动态代理、CGLib 等框架中、动态生成 JSP 以及 OSGI 这类频繁自定义 ClassLoader 的场景都需要虚拟机具备卸载的功能,以保证永久代不会溢出。

参考文献

  • 深入理解Java虚拟机:JVM高级特性与最佳实践 / 周志明著. —— 2 版 . —— 北京:机械工业出版社,2013.6 

标签:对象,虚拟机,回收,引用,JVM,方法,内存
From: https://blog.51cto.com/xuxiangyang/9038448

相关文章

  • JVM 的垃圾收集器
    JVM的垃圾收集器:Serial、ParNew、 ParallelScavenge、SerialOld、ParallelOld、CMS、G1。 1. 概述下图中垃圾收集器只要连线则表明垃圾收集器可以搭配使用。没有万能的收集器,具体应用选择合适的垃圾收集器。2. Serial垃圾收集器单线程收集器,用于新生代,这里的单线程指的......
  • 在 Flask 中使用数据库 允许我们使用面向对象的方式来操作数据库 Flask 中使用表单的
    在Flask中使用数据库,你可以使用ORM(对象关系映射)技术,它允许我们使用面向对象的方式来操作数据库,而不需要直接编写SQL语句¹。以下是一些基本步骤:安装依赖:首先,我们需要安装Flask和ORM库的依赖。Flask提供了多个ORM库的选择,例如SQLAlchemy、Peewee和SQLObject等。在这......
  • PLSQL打开数据库对象乱码
    1.问题描述   PLSQL打开远程数据库对象后,发现其中的中文内容为问号乱码.    2.处理方式   这种情况一般是我们初次安装PLSQL后,未在本地配置与数据库一致的NLS_LANG环境变量,导致远端获取的对象字符集在本地解析时无法识别。2.1远程数据库配置情况   使用......
  • java-面向对象编程
    面向对象编程是一种编程范式,它将程序设计组织为对象的集合,这些对象通过相互之间的交互来完成任务。下面是面向对象编程的一些重要概念和Java的相关实现:类(Class)和对象(Object):在Java中,类是定义对象的模板。它描述了对象的属性(成员变量)和行为(方法)。对象是类的实例化结果,可以创建多......
  • 金蝶云星空权限对象表结构
    一、BOS平台【权限对象】 二、MSSQL脚本--权限对象主表SELECT*FROMT_SEC_PermissionObjectWHEREFITEMID='64f6de86387210'--权限对象多语言表SELECT*FROMdbo.T_SEC_PERMISSIONOBJECT_LWHEREFITEMID='64f6de86387210'--FNAME='售后单'--权限对象下的权限项......
  • Dapper 查询多个表,映身到对象的实例对象
    publicasyncTask<IEnumerable<SplitMergeOrderSourcePlanOrderView>>GetSplitMergeOrderSourcePlanOrderViewAsync(longsplitMergeOrderId){stringsql="selecta.*,b.*fromPlanOrderViewajoinSplitMergeOrderSourcebona.Id=b.PlanOr......
  • JVM-实战篇-GC调优
    1GC调优GC调优指的是对垃圾回收进行调优。GC调优的主要目标是避免由垃圾回收引起的程序性能下降。GC调优的核心分为三部分:通过JVM参数的设置;特定垃圾回收器的JVM参数的设置;解决由频繁的FULLGC引起的程序性能问题。GC调优没有唯一的标准答案,重点学习调优的工具和方法。......
  • 如何在 Ubuntu 16.04 上使用 Minio 设置对象存储服务器
    前些天发现了一个人工智能学习网站,通俗易懂,风趣幽默,最重要的屌图甚多,忍不住分享一下给大家。点击跳转到网站。介绍从基于云的备份解决方案到高可用性内容交付网络(CDN),对象存储已成为现代技术领域不可或缺的一部分。而且,凭借其占用空间小、界面简单以及与多种云存储服务的兼容性......
  • 云上攻防--云服务&&对象存储(域名接管)&&弹性计算(元数据泄露)
    云上攻防--云服务&&对象存储(域名接管)&&弹性计算(元数据泄露)对象存储各个厂商对于对象存储的叫法不同,但是除了叫法基本没有其他区别。对象存储各大云名词:阿里云:OSS腾讯云:COS华为云:OBS谷歌云:GCS微软云:Blob亚马逊云:S3对于对象存储的漏洞或者说错误配置点如下权限配置......
  • JAVA面向对象程序设计
    第2章:类与对象定义类:在Java中,一个类是创建对象的蓝图或原型。类定义了一组属性(变量)和方法(函数)。-创建类:演示一个简单的Java类的声明,包括类名、属性和方法。```javapublicclassPhone{//属性(Variables)Stringbrand;Stringmodel;intprice;//方法(Methods)voidcall(S......