zoukankan      html  css  js  c++  java
  • java面试一日一题:如何判断一个对象是否为垃圾对象

    问题:请讲下在java中如何判断一个对象是否为垃圾

    分析:该问题主要考察对java中的垃圾回收,用什么方式去识别一个对象是垃圾;

    回答要点:

    主要从以下几点去考虑,

    1、GC回收的是什么,回收发生在内存的那部分?

    2、怎么判断一个对象是否可以被回收?

    3、垃圾回收的算法有哪些?

    都说C/C++语言难学,难的点其实不是语言本身,而是在内存管理方面,因为在C/C++中需要开发者自己管理内存,包括申请内存和释放内存,不恰当的释放内存经常导致程序崩溃,而在java中开发者却不需要关心何时释放内存。很多人认为java没有内存管理的概念,其实不是这样的,只不过java虚拟机帮我们做了,那就是垃圾回收,简称GC。

    所谓GC就是要回收java程序允许过程中产生的垃圾,也可以理解为不再使用的内存,一个程序的内存是有限的,随着程序的运行,肯定存在申请内存的情况,如果使用完内存迟迟得不到释放,那么程序最终会因为没有内存而停止,所以内存的释放很重要。在面向对象程序中内存的释放意味着对象的销毁,只有对象销毁了内存才有可能得以释放,内存才至于枯竭。

    上面明白了为什么要有GC,GC的目的就是为了释放内存,使程序可以持续运行。在java中程序运行时的内存区域可分为堆、虚拟机栈、本地方法栈、程序计数器、方法区。GC回收的区域是堆和方法区,为什么回收这两个区域那,因为他们是线程共享的,即java程序中所有的线程都可以访问,在这两部分中回收的重点在堆,方法区一般回收起来很困难,下面的介绍均是指堆方法区的垃圾回收。为什么虚拟机栈、本地方法栈、程序计数器没有GC,因为他们是线程私有的,随着线程的消亡而消亡。

    从网上找了一张运行时内存区域的图,

    该图很形象的说明了java运行时数据区的每个部分,当然是逻辑划分而不是物理划分。

    现在,弄清楚了GC要回收的内存区域是堆,堆中存放的是对象,在java的世界中万事万物都是对象,归根结底要回收的是堆中的对象。那如何确定什么对象是可回收的什么对象是不可回收的。java提供了两种算法,引用计数法和可达性分析法。java中使用的是可达性分析法

    引用计数法

    所谓引用计数法,每个对象额外保存一个计数属性,如果有一个对象引用了它,那么该属性会加1,例,

    A a=new A();
    A a2=a;

    上面这段代码会在堆中生成一个A的对象实例,且a、a2都指向了该对象,那么该对象的计数属性便是2,又如,

    A a=new A();
    A a2=a;
    a=null;
    a2=null;

    这时a、a2均指向了null,那么A的对象实例的计数属性则为0,按照引用计数法的定义这时该实例可以被回收。

    看上去该算法很完美,但是java中为什么没用,有个问题如果出现循环引用怎么办,

    A a=new A();
    B b=new B();
    
    a.b=b;
    b.a=a;
    
    a=null;
    b=null;

    上面的代码在堆中会有一个A的实例一个B的实例,且计数属性均为1,执行了第3、4两行代码后,两个实例的引用计数均为2,执行了5、6两行代码后两个实例的计数属性均为1,这时a、b均指向了null,但是堆中的两个实例的计数属性的值却不为0,那么这两个实例无法回收,存在内存泄漏的风险;

    可达性分析法

    所谓可达性分析法,就是从一些称为引用链(GC ROOTS)的对象作为起点,从这些节点向下搜索,搜索走过的路径称为引用链(reference chain),当一个对象到GC ROOTS没有引用链的时则该对象不可达,该对象可以被回收。哪些对象是引用链那,虚拟机栈是java程序中方法执行的区域,每个方法的执行对应着一个栈帧的入栈和出栈,方法执行完了其申请的内存便可以释放,所以栈帧中的对象可作为引用链对象,同时本地方法栈的情况也是类似的;在方法区中存在常量和类静态变量,这两种变量也可以作为引用链对象,总结下来有下面几种,

    1、虚拟机栈中的局部变量表中的对象;

    2、方法区中常量引用的对象;

    3、方法区中类的静态变量引用的对象;

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

    使用可达性分析方法判断为可回收的对象,还有一次逃过回收的机会,那就是在Object类中有finalize()方法,如果在该方法中没有与上述的引用链建立链接,那么该对象则确定要被回收。

    知道了要回收的内存区域,以及如何判定哪些对象可以被回收,确定了回收对象,接下来就是如何回收,且听下次分解。

    参考:https://www.cnblogs.com/czwbig/p/11127124.html

    一个爱写文章的程序员,欢迎关注我的公众号“北漂程序员”。我有故事,你有酒吗
  • 相关阅读:
    映射和分析
    文档操作
    向 Nginx 主进程发送 USR1 信号
    ES集群7.3.0设置快照,存储库进行索引备份和恢复等
    ES7.3.0配置邮件告警
    Elasticsearch 史上最全最常用工具清单
    Grok在线调试网址
    Linux 小知识翻译
    Linux 小知识翻译
    Linux 小知识翻译
  • 原文地址:https://www.cnblogs.com/teach/p/14761465.html
Copyright © 2011-2022 走看看