JVM中对象的销毁
1、可达性分析算法:
可达性分析算法用来寻找将要销毁的对象,它的基本思路是:通过一系列的称为“GC ROOTs”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径成为引用链,当一个对象到GC ROOTs没有任何引用链想连时,则证明此对象是不可用的。如下图所示:

对象 object5/object6/object7 虽然相互关联,但它们到GC Roots 是不可达的,所以它们会被判定为可回收的对象。
在 Java 语言中,可作为GC Roots的对象包括下面几种:
·虚拟机栈(栈帧中的本地变量表)中引用的对象
·本地方法栈中 Native方法 引用的对象
·方法区中类静态属性引用的对象
·方法区中常量引用的对象
2、宣判对象死亡的过程:
此过程以流程图的形式表示更为直观:

F-Queue 队列的执行,是由一个虚拟机自动建立的、低优先级的 Finalizer 线程执行的。这里的执行是指虚拟机会触发这个方法,但不保证会等待方法执行结束,这样是为了防止 Finalizer 执行缓慢或发生死循环,进而引起 F-Queue 队列中其他对象永久等待,甚至整个内存回收系统崩溃。
下面给出一段 finalize() 被执行但对象仍然存活的示例:
/**
* 此代码演示了两点:
* 1.对象可以在被GC时自我拯救
* 2.这种自救的机会只有一次。因为一个对象的 finalize()方法最多只会被系统自动调用一次
* @author yangtf
*
*/
public class FinalizeEscapeGC {
public static FinalizeEscapeGC SAVE_HOOK = null; public void isAlive(){
System.out.println("Yes,I am still alive");
} @Override
protected void finalize() throws Throwable{
super.finalize();
System.out.println("finalize method executed!");
FinalizeEscapeGC.SAVE_HOOK = this; // 将自己赋值给 SAVE_HOOK
} public static void main(String[] args) throws InterruptedException {
SAVE_HOOK = new FinalizeEscapeGC(); // 对象第一次成功拯救自己
SAVE_HOOK = null;
System.gc(); // finalize方法优先级很低,所以暂停0.5秒以等待它
Thread.sleep(500);
if (SAVE_HOOK != null) {
SAVE_HOOK.isAlive();
} else {
System.out.println("No, I am dead");
} // 下面这段代码与上面完全相同,但这次自救失败了
SAVE_HOOK = null;
System.gc(); Thread.sleep(500);
if (SAVE_HOOK != null) {
SAVE_HOOK.isAlive();
} else {
System.out.println("No, I am dead");
}
}
}
执行结果:
finalize method executed!
Yes,I am still alive
No, I am dead
从结果可以看出,SAVE_HOOK 对象的 finalize() 方法确实被GC收集器触发过,并且在被收集前成功逃脱了。
执行第二次失败,因为任何一个对象的 finalize() 方法都只会被系统自动调用一次,如果对象面临下一次回收,它的 finalize() 方法不会被再次执行,因此第二段代码的自救失败。
3、对象的引用
JDK1.2后,Java 将对象引用概念进行扩张,将其分为:强引用、软引用、弱引用、虚引用,四种引用强度依次减弱。
1)强引用:代码中普遍存在,类似“Object obj = new Object()”。只要强引用还存在,垃圾收集器永远不会对其引用的对象进行回收。
2)软引用:用来描述还有用,但并非必须的对象。对软引用关联的对象第一次不回收,若第一次回收之后内存仍不够,则将其回收;即进行第二次回收。
3)弱引用:比软引用更弱的引用。第一次垃圾回收就会将其回收。
4)虚引用:也称为幽灵引用或幻影引用。一个对象是否有虚引用存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用的唯一目的,就是能在这个对象被收集器回收时收到一个系统通知。
JVM中对象的销毁的更多相关文章
- JVM中对象的回收过程
当我们的程序开启运行之后就,就会在我们的java堆中不断的产生新的对象,而这是需要占用我们的存储空间的,因为创建一个新的对象需要分配对应的内存空间,显然我的内存空间是固定有限的,所以我们需要对没有 ...
- JVM中对象的创建过程
JVM中对象的创建过程如以下流程图中所示: 对其主要步骤进行详细阐述: 为新生对象分配内存: 内存的分配方式: 指针碰撞:假设Java堆中内存是绝对规整的,所有用过的内存放在一边,空闲的内存在另一边, ...
- Java虚拟机笔记(五):JVM中对象的分代
为什么要分代 为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪些对象没用, ...
- 学习一下 JVM (二) -- 学习一下 JVM 中对象、String 相关知识
一.JDK 8 版本下 JVM 对象的分配.布局.访问(简单了解下) 1.对象的创建过程 (1)前言 Java 是一门面向对象的编程语言,程序运行过程中在任意时刻都可能有对象被创建.开发中常用 new ...
- JVM中对象访问定位两种方式
1.通过句柄方式访问, 在Java堆中分出一块内存进行存储句柄池,这样的话,在栈中存储的是句柄的地址 优点: 当对象移动的时候(垃圾回收的时候移动很普遍),这样值需要改变句柄中的指针,但是栈中的指针不 ...
- @JVM中对象的引用类型
JVM中有四种引用类型:强引用.软引用.弱引用.虚引用 强引用(Stong Reference):是指在程序代码中普遍存在的,类似:Object obj = new Object()这类的引用,只 ...
- JVM中对象的内存布局与访问定位
一.对象的内存布局 已主流的HotSpot虚拟机来说, 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header).实例数据(Instance Data)和对齐填 ...
- JVM中对象是否已死
- 《深入Java虚拟机学习笔记》- 第7章 类型的生命周期/对象在JVM中的生命周期
一.类型生命周期的开始 如图所示 初始化时机 所有Java虚拟机实现必须在每个类或接口首次主动使用时初始化: 以下几种情形符合主动使用的要求: 当创建某个类的新实例时(或者通过在字节码中执行new指令 ...
随机推荐
- JS截取,删除,替换字符串常用方法详细
删除和替换是一样的,开始用的是,如果是删除就直接替换为空 arr="abc001abc002abc003" arr.replace('abc','123') 结果发现只能替换第一个 ...
- WPF 画心2.0版之元旦快乐
2017年元旦已经到了,想做一个祝福语的窗口,就把上一篇画心的程序改了改,变成了如下界面. 说下改动的地方,首先窗口没有标题栏了. MainWindow.xaml AllowsTransparency ...
- C++开始前篇,深入编译链接(补充2)
在开始链接之前,我们先了解几个概念: 一>符号的概念. 我们知道,链接的最重要的是"对符号的重定位",而且上面提到了符号表,那什么是符号呢,在链接中,我们将函数和变量统称为符 ...
- ios 输入框bar设置
_textView = [[class alloc] init]; _textView.translatesAutoresizingMaskIntoConstraints = NO; ...
- 关于QImage提取单色通道方法(vector)
转载请标明处: 作者:微微苏荷 本文地址:关于QImage提取单色通道方法(vector) 近日,用QT和mxnet结合做一个图像识别的demo.遇到需要把图片从QImage转为vector单色分离的 ...
- sorl入门
本教程是从别人的基础上借鉴整理的 Solr是一个独立的企业级搜索应用服务器,它对外提供API接口.用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引(solr生成倒排索引,数 ...
- 64位主机64位oracle下装32位客户端ODAC(NFPACS版)
64位主机64位oracle下装32位客户端ODAC(NFPACS版) by dd 1.下载Oracle Data Access Components(ODAC) Xcopy的两个版本: x86:(我 ...
- 学习CSS3动画(animation)
CSS3就是出了不少高大上的功能,3D效果.动画.多列等等.今天写篇文章记录怎么一下怎么用CSS3写一个动画. 丑话还得说前头,IE9以及以下版本不支持CSS3动画(如真要实现可以考虑用js,不过估计 ...
- mysql开启远程访问权限
1. //登录数据库 mysql -u root -pvmwaremysql>use mysql; //%为所有ip都可以远程访问 mysql>update user set host = ...
- android事件处理之基于监听
Android提供了了两种事件处理方式:基于回调和基于监听. 基于监听: 监听涉及事件源,事件,事件监听器.用注册监听器的方法将某个监听器注册到事件源上,就可以对发生在事件源上的时间进行监听. 最简单 ...