转载请注明出处: Java对象的生命周期 与 垃圾回收 - ITeye博客 - 老Man


创建对象的方式

  • 用new语句创建对象。
  • 使用反射,调用java.lang.Class或java.lang.reflect.Constructor的newInstance()实例方法。
  • 调用对象的clone()方法
  • 使用反序列化手段,调用java.io.ObjectInputStream对象的readObject()方法。

还有其他一些隐式创建对象的方法:

  • 对于java命令中的每个命令行参数,Java虚拟机都会创建相应的String对象,并把它们组织到一个String数组中,再把该数组作为参数传递给程序入口main(String args[])方法。
  • String类型的直接量对应一个String对象。
  • 字符串操作符”+”的运算结果为一个新的String对象。
  • 当JVM加载一个类时,会隐含地创建描述这个类的Class实例。

不管采取哪种方式创建对象,JVM创建一个对象都包含以下步骤:

(1) 给对象分配内存。

(2) 将对象的实例变量自动初始化为其类型的默认值。

(3) 初始化对象,给实例变量赋予正确的初始值。

对于以上第三个步骤,JVM可采用3种方式来初始化对象,到底采用何种初始化方式取决于创建对象的方式。

  • 如果对象是通过clone()方法创建的,那么JVM把原来被克隆对象的实例变量的值拷贝到新对象中。
  • 如果对象通过ObjectInputStream类的readObject()方法创建的,那么JVM通过输入流中读入的序列化数据来初始化那些非暂时性的实例变量。
  • 在其他情况下,如果实例变量在声明时被显示初始化,那么就把初始化值赋给实例变量,接着再执行构造方法。这是最简单初始化对象的方式。

垃圾回收

Java语言中,内存回收任务由JVM来担当。

在程序的运行环境中,JVM提供了一个系统级的垃圾回收器线程,它负责自动回收那些无用对象所占用的内存。这种内存回收的过程被称为垃圾回收。

垃圾回收具有以下优点:

  • 程序员从复杂的内存追踪,监测和释放等工作解放出来,减轻程序员进行内存管理的负担。
  • 防止系统内存被非法释放,从而使系统更加健壮和稳定。
  • 只有当对象不再被程序中的任何引用变量引用时,它的内存才可能被回收。
  • 程序无法迫使垃圾回收器立即执行垃圾回收操作。
  • 当垃圾回收器将要回收无用对象的内存时,先调用该对象的finalize()方法,该方法有可能使对象使对象复活,导致垃圾回收器取消回收该对象的内存。

对象的可触及性

在JVM的垃圾回收器来看。堆区中的每个对象都肯能处于以下三个状态之一:

  • 可触及状态:当一个对象被创建后,只要程序中还有引用变量引用该对象,那么它就始终处于可触及状态。
  • 可复活状态:当程序不再有任何引用变量引用对象时,它就进入可复活状态。该状态的对象,垃圾回收器会准备释放它占用的内存,在释放前,会调用它的finalize()方法,这些finalize()方法有可能使对象重新转到可触及状态。
  • 不可触及状态:当JVM执行完所有的可复活状态的finalize()方法后,假如这些方法都没有使对象转到可触及状态。那么该对象就进入不可触及状态。只有当对象处于不可触及状态时,垃圾回收器才会真正回收它占用的内存。

垃圾回收的时间

当一个对象处于可复活状态时,垃圾回收线程执行它的finalize()方法,任何使它转到不可触及状态,任何回收它占用的内存,这对于程序来说都是透明的。程序只能决定一个对象任何不再被任何引用变量引用,使得它成为可以被回收的垃圾。

类比:居民把无用物品放在指定的地方,清洁工人会把它收拾走。但垃圾被收走的时间,居民是不知道的,也无需了解。

垃圾回收器作为低优先级线程独立运行。在任何时候,程序都无法迫使垃圾回收器立即执行垃圾回收操作。

程序中可调用System.gc()或Runtime.gc()方法提示垃圾回收器尽快执行垃圾回收操作,但是不能保证调用后垃圾回收器会立即执行垃圾回收。

类比:小区垃圾成堆时,居民打电话给环保局,催促清洁工尽快来处理垃圾。但是清洁工不一定立即就来了,也有可能很长时间后再来。

对象的finalize()方法简介

finalize()定义在Object类中:

protected void finalize() throws Throwable

因为该方法为protected,所以任何Java类都可以覆盖finalize()方法,该方法中进行释放对象所占的相关资源的操作。

注意:

JVM的垃圾回收操作对程序来说都是透明的。因此程序无法预料某个无用对象的finalize()方法何时被调用。

finalize()方法的特点:

  • 垃圾回收器是否会执行该方法及何时执行该方法,都是不确定的。
  • finalize()方法有可能使对象复活,使它恢复到可触及状态。
  • 垃圾回收器在执行finalize()方法时,如果出现异常,垃圾回收器不会报告异常,程序继续正常运行。

对象的强,软,弱,虚引用

强引用

如果一个对象具有强引用,垃圾回收器绝不会回收它。当内存空间不足,JVM宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会考随意回收具有强引用的对象来解决内存不足的问题。

软引用

如果一个对象具有软引用。如果内存空间足够。垃圾回收器不会回收它。如果内存不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。

软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。

软引用可用来实现内存敏感的高速缓存。

弱引用

如果一个对象具有弱引用。当垃圾回收器发现只具有弱引用对象,不管当前内存空间足够与否,都会回收它的内存。

不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现只具有弱引用的对象。

虚引用

虚引用不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用主要用来跟踪对象被垃圾回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃 圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是 否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。程序如果发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

下面这个实验代码很好的探究了四种引用级别对垃圾回收的影响

import java.lang.ref.PhantomReference; //虚引用
import java.lang.ref.ReferenceQueue; //引用队列
import java.lang.ref.SoftReference; //软引用
import java.lang.ref.WeakReference; //弱引用class Obj
{private final String name;public Obj(String name){this.name = name;}@Overrideprotected void finalize() throws Throwable{System.out.println("执行finalize方法"+name);super.finalize();}
}public class Test
{public static void main (String[] args){
//      hardTest();
//      softTest();
//      weakTest();phanTest();}public static void hardTest(){Obj hard = new Obj("hard");
//      hard = null;System.gc();System.out.println(hard);}public static void softTest(){SoftReference <Obj> soft = new SoftReference<Obj>(new Obj("soft"));System.gc();System.out.println(soft.get());}public static void weakTest(){WeakReference <Obj> weak = new WeakReference<Obj>(new Obj("weak"));System.gc();System.out.println(weak.get());}public static void phanTest(){ReferenceQueue<Obj> rq = new ReferenceQueue<Obj>();PhantomReference<Obj> phan = new PhantomReference<Obj>(new Obj("phan"), rq);System.out.println(phan.get());}
}

分别执行四个函数, 并控制强/软引用中的obj是否为null, 共6次实验, 我们可以总结出:

1. 显式的把(强引用)对象置为null,会大大加大 垃圾回收执行频率。几乎只要我们给出建议,jvm就会回收。

2. 对于软引用,如果不显式的置为null的话,和强引用差不多,垃圾回收不会执行。和强引用的区别是:只会等到内存不足的时候才会执行。

3. 对于弱引用,就算你不显式的把他置为null,垃圾回收也会立即执行。

4. 虚引用,相当于null。如果一个对象的虚引用加入了引用队列, 那么这个对象行将就木了

Java对象的生命周期与垃圾回收以及四种引用相关推荐

  1. java对象什么时候回收_Java对象的生命周期与垃圾回收以及四种引用

    创建对象的方式用new语句创建对象. 使用反射,调用java.lang.Class或java.lang.reflect.Constructor的newInstance()实例方法. 调用对象的clon ...

  2. Android 内存溢出、垃圾回收、四种引用

    内存溢出 内存溢出(OutofMemory):系统会给每个APP分配内存也就是HeapSize值.当APP占用的内存加上我们申请的内存资源超过了Dalvik虚拟机的最大内存时就会抛出的OutOfMem ...

  3. java对象的生命周期及回收

    在网上看到一篇不错的文章,记录下来备忘. 要理解java对象的生命周期,我们需要要明白两个问题, 1.java是怎么分配内存的 ,2.java是怎么回收内存的. 喜欢java的人,往往因为它的内存自动 ...

  4. Java 对象的生命周期

    Java对象的生命周期 在Java中,对象的生命周期包括以下几个阶段: 创建阶段(Created) 应用阶段(In Use) 不可见阶段(Invisible) 不可达阶段(Unreachable) 收 ...

  5. Java对象的生命周期与作用域的讨论(转)

    导读: Java对象的生命周期大致包括三个阶段:对象的创建,对象的使用,对象的清除.因此,对象的生命周期长度可用如下的表达式表示:T = T1 + T2 +T3.其中T1表示对象的创建时间,T2表示对 ...

  6. 谈谈Java对象的生命周期

    经过前面的分析 ,我们现在来看一下创建的对象到底是什么东西,并且完整的总结一下一个对象从创建到回收到底经过了哪些阶段. 1 对象的创建 对象创建的主要流程:  1.类加载检查 虚拟机遇到一条new指令 ...

  7. 垃圾回收之如何判断对象可以回收、四种引用以及实际案例操作

    垃圾回收 JVM内存结构中的堆存在垃圾回收机制,我们接下来就来详细地学习一下垃圾回收的相关知识. 1. 如何判断对象可以回收 1.1 引用计数法 只要一个对象被其他变量所引用,那就让这个对象的计数+1 ...

  8. java对象从新生代晋升到老年代的四种方式

    晋升的四种方式 担保机制 大对象直接进入老年代 长期存活的对象 动态年龄判断 1.担保机制 1.1什么是担保机制 我们都用过花呗借呗.或者信用卡吧? 就是你身上的前不够用的时候,你可以去借信用卡.借花 ...

  9. JVM(三)GC垃圾回收以及四种GC算法

    JVM(三) 学习视频链接,以示尊重:https://www.bilibili.com/video/BV1iJ411d7jS?p=4 图片来源:https://blog.csdn.net/weixin ...

最新文章

  1. 小米输掉官司,倒打一耙不如坦然认错
  2. So many interfaces!
  3. git或者ssh出错 fatal:open /dev/null or dup failed: No such file or directory、弹出mitty.dump文件
  4. python创建学生类和教师类_创建StudentServices类
  5. STM32F407+CubeMX-使用TIM计算编码器的脉冲总数,并计算脉冲方向
  6. ubuntu1604安装tensorflow
  7. 兴利调节matlab编程,水利计算之兴利调节计算.ppt
  8. java面向对象程序设计编程题,已拿到offer
  9. php中文分词类 关键词提取,php如何使用PHPAnalysis提取关键字中文分词
  10. java 读取wav采样数据_读取wav文件中的音频数据操作
  11. 七段式svpwm和5段式的区别_SVPWM实现概述
  12. 我的爬虫入门书 —— 《Python3网络爬虫开发实战(第二版)》
  13. 前后端分离的优势是什么?
  14. php软件怎么使用方法,ps软件的日常使用方法有哪些?
  15. 第一行代码-第二版(郭霖著)笔记十一(Material Design)
  16. 关于蓝墨云班课,视频不能拖动,但想快速搞完的解决方法
  17. 如何在 LaTeX 中输入角度、角分、角秒?
  18. warnings 忽视警告
  19. 浅谈对程序员的认识_8年编程生涯回顾:谈谈我对程序员的理解
  20. DTM使用途中的bug记录

热门文章

  1. thinkphp如何调试,打印错误信息sql等
  2. android平板 跑分软件,安卓平板拿啥比?M1 iPad Pro跑分公布:差距实在太大
  3. 电子计算机怎么按不了数字,计算器失灵按不出数字
  4. facade 门面模式和mediator 调停者
  5. 系统安全 - windowns系统镜像下载
  6. 禁止搜索引擎收录的方法
  7. 2020最新各大厂面试遇到的100道软件测试面试题+答案纯干货!! 金九银十到了 快点看!!!
  8. mysql中分层查询_在mysql中连接任意数量的字符串行(分层查询)
  9. php ci CodeIgniter框架图片缩略图处理类优化 缩放到固定大小
  10. MCU 8080规格LCD屏斜线问题——Tear功能