文章目录

  • 3.2.1 引用计数算法
  • 3.2.2 可达性分析算法(重点)
  • 3.2.3 再谈引用
    • 强引用
    • 软引用
    • 弱引用
    • 虚引用
  • 3.2.4 生存还是死亡
  • 3.2.5 回收方法区

判断对象是否为垃圾(是否存活)的算法

1.引用计数算法 (基本上废掉了)
2.可达性分析算法


3.2.1 引用计数算法

https://blog.csdn.net/linsongbin1/article/details/51448714

在对象中添加一个引用计数器,当有引用指向这个对象时,引用计数器+1,当指向该对象的引用失效时,引用计数器-1。

任何时刻计数器为0 的对象就是不可能再被使用的;

Person p = new Person();则引用计数器+1
p = null;引用p失效,则引用计数器-1

优点
1.实时性,无需等到内存不够的时候,才开始回收,运行时根据对象的计数器是否为0,就可以直接回收。
2.区域性 ,更新对象的计数器时,只是影响到该对象,不会扫描全部对象

缺点
1.浪费资源,每次对象被引用时,即使内存足够,都需要去更新计数器;
2.无法解决循环引用问题(现在主流的JVM很少使用引用计数算法的原因),因为如果存在对象间相互引用,如果这个指向对象的引用为null,则这几块对象内存会被gc认为是垃圾

循环引用

class TestA{public TestB b;}
class TestB{public TestA a;
}
public class Main{public static void main(String[] args){A a = new A();B b = new B();a.b=b;b.a=a;a = null;b = null;//假设在这行发生GC,objA和objB不能被回收System.gc();}
}

3.2.2 可达性分析算法(重点)

在主流的商用程序语言中(Java和C#),都是使用可达性分析算法判断对象是否存活的。

通过一系列名为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的;

    上图的对象object5,object6,object7虽然有互相引用,但它们到GC Roots是不可达的,所以它们将会判定为是可回收对象。

作为GC Roots的对象有:

1 虚拟机栈(栈桢中的 局部变量表中的 本地变量表)中的引用的对象
2 方法区中的 类的静态属性 引用的对象(static)
3 方法区中的常量引用的对象(final修饰的变量)
4 本地方法栈中JNI(Native方法)的引用的对象


3.2.3 再谈引用

强引用

就是在程序代码之中普遍存在的,类似Object obj = new Object() 这类的引用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象;

当JVM的内存空间不足时,宁愿抛出OutOfMemoryError使得程序异常终止也不愿意回收具有强引用的存活着的对象!

软引用

用来描述一些还有用但并非必须的元素。当内存空间足够的时候,垃圾回收器不会回收它,只有当JVM认定内存空间不足时才会去回收软引用指向的对象;

    JVM会确保在抛出OOM前清理软引用指向的对象,而且会尽可能优先回收长时间闲置不用的软引用指向的对象,对那些刚构建的或刚使用过的软引用指向的对象尽可能的保留软引用是通过SoftReference类实现的.get()方法获取对象。

    软引用一般用来实现内存敏感的缓存,如果有空闲内存就可以保留缓存,当内存不足时就清理掉,这样就保证使用缓存的同时不会耗尽内存。例如图片缓存框架中缓存图片就是通过软引用的

//mObject 对 MyObject 的强引用
MyObject mObject = new MyObject();
//来自 SoftReference对象 的软引用
SoftReference mSoftReference = new SoftReference(mObject);//结束 mObject 对MyObject的强引用这时候MyObject为软引用,如果这时候执行GC,MyObject对象可能会被回。
mObject = null;//获取MyObject对象,如果这之前执行GC,MyObject对象就可能会被回收,如果被回收,则get()返回null。
mSoftReference.get();

以下的了解
    使用ReferenceQueue清除已经失去了软引用对象的SoftReference:
    如果有很多软引用的对象被回收之后,就会存在大量的SoftReference对象(比如上面的mSoftReference),这些对象的遗留没有任何用处,却可能会带来内存泄露。所以,软引用通常可以和一个引用队列(ReferenceQueue)联合使用;如果软引用所引用的对象被垃圾回收,java虚拟机就会把这个软引用加入到与之关联的引用队列(ReferenceQueue)中。
    所以在创建软引用的对象时:

MyObject mObject = new MyObject();
ReferenceQueue queue = new ReferenceQueue();
SoftReference ref = new SoftReference(mObject,queue);
mObject = null;

弱引用

用来描述非必须对象的,但是它的强度比软引用更弱一些,无论当前内存是否足够都会回收掉只被弱引用关联的对象

    垃圾回收器会扫描它所管辖的内存区域的过程中,只要发现弱引用的对象,不管内存空间是否有空闲,都会立刻回收它。
    弱引用是通过WeakReference类实现的,也是通过get()方法获取对象。

Object obj = new Object();
WeakReference<Object> wf = new WeakReference<Object>(obj);
obj = null;wf.get();//返回是否被垃圾回收器标记为即将回收的垃圾
wf.isEnQueued();

虚引用

虚引用的唯一目的在于跟踪垃圾回收过程,在对象被收集器回收时收到一个系统通知

    所以可以利用虚引用来进行销毁前的一些操作,比如说资源释放等。

Object obj = new Object();
PhantomReference<Object> pf = new PhantomReference<Object>(obj);
obj=null;//永远返回null,没有意义,了解
pf.get();//返回是否从内存中已经删除,唯一作用
pf.isEnQueued();

3.2.4 生存还是死亡

在可达性算法中,一个不可达的对象也并非非死不可

若要被真正的回收需要经历两次标记:

  • 第一次标记:
        如果对象在可达性分析中没有与GC Roots相连接的引用链,那么此时就会被第一次标记并且进行一次筛选;

    筛选的条件是是否++有必要执行finalize()方法++。当对象没有覆盖finalize()方法或者该方法已经被虚拟机调用过,那么就认为是没必要执行finalize()方法。

  • 第二次标记:
        如果该对象++有必要执行finalize()方法++,那么这个对象将会放在一个称为F-Queue的队列中;稍后GC对处于F-Queue中的对象进行第二次被标记,如果对象在finalize()中重新与引用链上任何一个对象建立关联即可(如把当前对象的引用this赋值给某对象的类变量/成员变量,重新建立可达的引用),否则,该对象将被移除“即将回收”集合,等待回收。

  • 关于finalize()方法
        finalize()只会在对象内存回收前被调用一次;
        finalize()方法现在并没有什么用,finalize()是Java刚诞生时为了使C/C++程序员更容易接受它所做出的一个妥协。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G2YYxz86-1602329911723)(DBA57715FA6A4F088544215129F22127)]

上面的总结如下:
如何自我救赎:
1.对象覆写了finalize()方法(这样在被判死后才会调用此方法,才有机会做最后的救赎);
2.在finalize()方法中重新引用到"GC Roots"链上(如把当前对象的引用this赋值给某对象的类变量/成员变量,重新建立可达的引用).


3.2.5 回收方法区

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

  • 假如一个字符串“abc”已经进入了常量池中,如果当前系统没有任何Stirng对象引用常量池的“abc”常量,这个时候发生内存回收并且有必要的话,这个常量就会被清理出常量池。

  • 常量池中的其他类(接口)、方法、字段的符号引用也与此类似。

判断类是无用的类,必须同时满足以下3个要求:
1.这个类的所有对象都被回收了,就是,堆中没有这个类的实例;
2.加载这个类的classloader已经被回收;
3.这个类的java.lang.class没有被任何地方引用,无法再任何地方通过反射访问该类的方法。

方法区、元空间和永久代的概念

  1. 方法区也被称为永久代是因为HotSpot设计团队希望将GC分带手机扩展到方法区;

  2. HotSpot虚拟机在1.8之后已经取消了永久代,改为元空间;

可以把元空间,永久代都理解成方法区;


java引用计数法、可达性分析法、强软虚弱、强引用、软引用、弱引用、虚引用、回收方法区、finalize()方法相关推荐

  1. 对象是否要被回收(引用计数和可达性分析算法)

    java堆和方法区主要存放各种类型的对象(方法区中也存储一些静态变量和全局常量等信息),那么我们在使用GC对其进行回收的时候首先要考虑的就是如何判断一个对象是否应该被回收.也就是要判断一个对象是否还有 ...

  2. 【JVM】引用计数和可达性分析算法详解

    前言 JVM堆中几乎存放了所有对象的实例,那么垃圾收集器怎么确定哪些对象还"存活"着,哪些已经"死去"呢?本文主要介绍判断对象是否存活算法引用计数算法和可达性分 ...

  3. JVM—引用计数和可达性分析算法(存活性判断)

    1 引用计数算法 1.1 算法思想   给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1:   当引用失效时,计数器值就减1:   任何时候计数器为0时的对象就是不能再被使用. 1. ...

  4. java中四种引用类型(对象的强、软、弱和虚引用)

    2019独角兽企业重金招聘Python工程师标准>>> 对象的强.软.弱和虚引用在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有 ...

  5. 软件测试 通用技术03 测试用例 黑盒测试用例设计方法 等价类划分法 边界值分析法 判定表法 场景法 功能图法 其他用例设计方法 用例设计方法综合选择

    文章目录 1 测试用例 1.1 测试用例的定义 1.2 测试用例模板 1.3 测试用例模板的内容 测试用例编号 测试项 依赖用例 测试步骤 测试数据 预期结果 测试结果 测试人 备注 2 测试用例编写 ...

  6. 语法分析:自上而下分析(递归下降分析法+预测分析法)

    语法分析:自上而下分析 目录 语法分析:自上而下分析 知识背景 递归下降分析法 内容一:根据文法生成子程序 内容二:调用文法开始符号所对应的子程序 预测分析法 内容一:构造预测分析表 内容二:预测分析 ...

  7. Java:对象的强、软、弱和虚引用

    见:http://zhangjunhd.blog.51cto.com/113473/53092 maven/Java/web/bootstrap/dataTable/app开发QQ群:56686262 ...

  8. java-基础-强、软、弱、虚引用

    Java的四种引用,强弱软虚,用到的场景. JDK1.2之前只有强引用,其他几种引用都是在JDK1.2之后引入的. 强引用(Strong Reference) 最常用的引用类型,如Object obj ...

  9. 对象的强、软、弱和虚引用

    本文介绍对象的强.软.弱和虚引用的概念.应用及其在UML中的表示. 1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有 ...

  10. 软引用和弱引用的区别_强、软、弱、虚引用的区别和使用

    原文阅读: 强.软.弱.虚引用的区别和使用​mp.weixin.qq.com Java提供了四种级别的应用类型:强引用.软引用.弱引用及虚引用.那么这四种引用类型有什么区别呢? 首先我们通过一张图来看 ...

最新文章

  1. xslt 标签取集合第一条数据_XSLT函数集合:数值函数、字符串函、节点集函数和布尔函数...
  2. sql调用web服务
  3. 装载:CodePen项目网站简介(以备不时之需)
  4. leetCode刷题-第二题两数之和
  5. k8s service服务发现详解:ipvs代理模式、服务类型
  6. java 数据保存内存_java中的各种数据类型在内存中存储的方式 一
  7. python设置本机IP地址、子网掩码、DNS,获取本机IP地址、子网掩码、DNS、MAC
  8. 网信办:从严整治激情打赏、高额打赏、诱导打赏
  9. web安全之XSS攻击
  10. 编程的一些经历和感想
  11. Nginx开启访问日志记录
  12. springboot MVC拓展配置
  13. QPSK调制与解调(matlab,详细介绍仿真方案的设计、结果及结论、完整代码及注释)
  14. 工程模式写入imei_开发初期IMEI号的写入
  15. 六一小学生计算机创新活动总结,2020小学生六一儿童节活动总结
  16. 2021-08-26小白笔记2
  17. 十三个提高远程办公效率的工具
  18. Java 使用Axis实现WebService实例
  19. c语言0x前缀的作用,有趣的问题,C语言程序中,为什么十六进制数字以前缀0x开头呢?...
  20. Android6.0 MountService和vold详解(三) vold SD卡、otg

热门文章

  1. 基于android p的miui,小米8青春版终于迎来基于AndroidP的MIUI10系统,米粉欢呼
  2. java int integer_浅谈java中int和Integer的区别
  3. java架构实践_Java架构实践-关于IO流
  4. 上验证cudnn是否安装成功_ubuntu18.04 安装cuda、cudnn、tensorflow和pytorch其实很简单...
  5. ORB feature to FAST,定向快速旋转简报
  6. Mysql数据恢复有哪几种_MYSQL 数据恢复有哪些
  7. JAVA日常优化---Guava缓存玩耍异步刷新
  8. springmvc使用rest风格的404错误
  9. 【Nowcoder - 5666 H Minimum-cost Flow】2020牛客暑期多校训练营(第一场)【最小费用流变形】
  10. 每日一题/003/微积分/极限问题转化为定积分的定义