4 Java 如何判定是否存活或者死亡

在堆中存放着几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事就是要确定这些对象之中哪些还活着,哪些对象已经死去.

判断对象是否已经死亡有以下几种算法:

  1. 引用计数法算法

定义 : 给对象中添加一个引用计数器,当有一个地方引用时,计数器加1,引用失效时,就减1,当对象的引用计数器为0时,对象就是不可再被使用的.

特点 : JAVA虚拟机中很少使用这种算法,主要原因是它很难解决对象之间的循环引用问题

  1. 可达性分析算法

定义 : 通过一系列的称为 GC Roots 的对象作为起点,从这些节点开始向下搜索,搜索把走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连(就是从GC Roots 到这个对象不可达)时,则证明此对象是不可用的.如下图

上图中的 5,6,7 对象就是不可达的,就是不可用的.

1) 哪些对象可以作为 GC Roots 对象呢?

1 虚拟机栈(栈帧中的本地变量表)中引用的对象

2 方法区中类静态属性引用的对象

3 方法区中常量引用的对象

4 本地方法栈中JNI引用的对象

2) 再谈引用:(从上到下依次减弱)

1 强引用 : 只要强引用还存在,垃圾收集器永远不回收被引用的对象

2 软引用 : 在内存溢出异常之前,回收对象

3 弱引用 : 在下一次 GC 时,无论当前内存是否足够,都会回收被引用的对象

4 虚引用 : 没用,唯一的用处是在对象回收时,会收到一个系统通知

3) 对象的 finalize() 方法作用

生存还是死亡?

即使在可达性分析算法中不可达的对象,也并非是"非死不可"的,这时候它们暂时处于"缓刑"阶段,要真正宣告一个对象死亡,至少要经历2次标记:

1 如果对象在进行可达性分析后发现对象不可达,那它将会被第一次标记并进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法.当对象没有覆盖finalize()方法,或者finalize()方法已经执行过,虚拟机将这种情况视为没有必要执行

2 如果对象被判定为有必要执行finalize()方法,那么这个对象将会放置在一个叫做F-Queue的队列之中,并在稍后由一个由虚拟机自动建立的,低优先级的Finalizer线程去执行它.这里所谓的招行是指虚拟机会触发这个方法,但并不承诺等待它运行结束,这样做的原因是,如果一个对象在finalize()方法中做耗时的操作,将很可能会导致 F-Queue队列中的其它对象永久处于等待,甚至导致整个内存回收系统线程崩溃, finalize()方法是对象逃脱死亡命运的最后一次机会,稍后GC将对F-Queue中的对象进行第二次标记,如果对象要在finalize()中成功拯救自己,即只要对象重新和引用链上的任何一个对象发生关联即可,即将自己(this关键字)赋值给某个类变量或者对象的成员变量,那么在第二次标记时它将被移出"即将回收"的集合,如果对象这时候还没有逃脱,那么基本上它真的要被回收了

注:尽量不要用finalize()方法,忘了这个方法

时间: 2024-08-10 19:07:32

4 Java 如何判定是否存活或者死亡的相关文章

Java 如何判定当前时间是否在某个范围

由于一些特别的原因  需要判定当前时间是否在某个特定的范围 以下是一个根据数据库里面规定的日期选择是否打折,以及打几折的一个DEMO 1 /* 2 Navicat Premium Data Transfer 3 4 Source Server : localhost_3306 5 Source Server Type : MySQL 6 Source Server Version : 80017 7 Source Host : localhost:3306 8 Source Schema : s

Java中高级判定

String str; str = user.getName() == null ? "" : user.getName(); //表示user.getName是否为空, 如果为空则用空字符串 ""表示, 否则为user.getName. 原文地址:https://www.cnblogs.com/mengqimoli/p/8941991.html

JVM之垃圾收集

众所周知,Java语言的一个重要特性就是自动内存管理与垃圾回收机制.垃圾收集也被称作GC(Garbage Collection),在讲到GC的时候,我根据<深入理解Java虚拟机>中提到的内容,打算从三个方面讲述: 哪些内存需要回收? 什么时候进行回收? 怎样回收? 首先从理论上讲述这三个问题,然后再以HotSpot为例讲述这三点的具体实现. 一.哪些内存需要回收 1.1.哪些内存区域需要考虑GC 前面对于JVM的内存划分中讲到,JVM将其管理的内存分为程序计数器.虚拟机栈.本地方法栈.堆以及

Java基础面试题集(一)

Java基础面试题 一.面向对象编程(OOP) 7 二.常见的Java问题 7 2.1.什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? 7 2.2.JDK和JRE的区别是什么? 8 2.4.是否可以在static环境中访问非static变量? 8 2.5.Java支持的数据类型有哪些?什么是自动拆装箱? 8 2.6.Java中的方法覆盖(Overriding)和方法重载(Overloading)是什么意思? 8 2.7.Java中,什么是构造函数?什么是构造函数重载?什么是

Java基础(面试题)

1:面向对象编程有很多重要的特性: 封装,继承,多态和抽象. 2:什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? (1)Java虚拟机是一个可以执行Java字节码的虚拟机进程.Java源文件被编译成能被Java虚拟机执行的字节码文件. (2)Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译. Java虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性. 3:JDK和JRE的区别是什么? Java运行时环境(JR

Java虚拟机(五)——垃圾收集机制

垃圾回收介绍 ?? Java虚拟机内存划分讲到了Java 内存运行时区域的各个部分,其中程序计数器,虚拟机栈,本地方法栈三个区域随线程而生,随线程而灭,栈中的栈帧随着方法的进入和退出有条不紊地执行着出栈和入栈操作.每一个栈帧中分配多少内存基本上是在类结构确定下来是就已知了.因此这几个区域的内存分配和回收都具有确定性,在这几个区域就需要过多考虑回收的问题,因为方法结束或者线程结束时,内存自然就跟随着回收了.而Java 堆和方法区则不一样,一个接口中的多个实现类需要的内存可能不一样,一个方法中的多个

JVM学习与问题总结——java内存区域与内存溢出异常

java虚拟机将内存分为哪些区域? 根据Java SE7版本的Java虚拟机规范,虚拟机管理的内存包括5个运行时数据区域: 程序计数器 虚拟机栈 本地方法栈 方法区 堆 运行时数据区各部分的作用? 程序计数器 一个线程所执行的字节码的行号指示器. 字节码解释器会通过改变计数器的值来选取下一条将要执行的指令,那么分支.循环.跳转.异常处理.线程恢复都需要依赖计数器来完成.而Java虚拟机当中的多线程是通过争取CPU时间片来切换线程执行任务,当一个线程重新获取CPU时间片的时候就需要恢复上一次任务执

Java对象&quot;后事处理&quot;那点事儿——垃圾回收(一)

1.Dead Or Alive 我们都知道对象死亡的时候需要进行垃圾回收来回收这些对象从而释放空间,那么什么样的对象算是死亡呢,有哪些方法可以找出内存中的死亡对象呢?一般来说,我们可以这样认为:如果内存中不存在对当前对象的引用,则此对象一定是死亡状态:但是死亡状态的对象并不一定没有其他对象进行引用(可能存在死亡对象循环引用的情况).这里需要说明一下,死亡的对象并不一定会被回收释放占用的空间,这种情况就是常称的"内存泄漏".判定对象存活的算法一般是以下两种. 1.1 引用计数法 引用计数

JAVA面试题和答案(二)

本文我们将要讨论Java面试中的各种不同类型的面试题,它们可以让雇主测试应聘者的Java和通用的面向对象编程的能力.下面的章节分为上下两篇,第一篇将要讨论面向对象编程和它的特点,关于Java和它的功能的常见问题,Java的集合类,垃圾收集器,第二篇主要讨论异常处理,Java小应用程序,Swing,JDBC,远程方法调用(RMI),Servlet和JSP. 开始! 目录 面向对象编程(OOP) 常见的Java问题 Java线程 Java集合类 垃圾收集器 面向对象编程(OOP) Java是一个支持