iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >java中如何判断对象是否是垃圾
  • 540
分享到

java中如何判断对象是否是垃圾

java判断垃圾java判断对象垃圾 2023-05-18 05:05:58 540人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

目录判断对象是否为“垃圾”引用计数算法可达性分析算法垃圾的回收Finalize方法方法区回收Java会自动进行内存管理,JVM会进行垃圾回收,哪它是怎么判定哪

Java会自动进行内存管理,JVM会进行垃圾回收,哪它是怎么判定哪些是“垃圾”并决定“垃圾”的生死呢?

判断对象是否为“垃圾”

Java有两种算法判断对象是否是垃圾:引用计数算法和可达性分析算法。

引用计数算法

引用计数(Reference Counting)算法就是给对象加一个引用计数器,当对象被引用,计数器加一;当引用失效时,计数器减一;当对象的引用计数器为0,对象就会被视为垃圾。

优点:

简单、判定垃圾效率高。

缺点:

  • 需要额外的空间存储引用计数器
  • 每当一个引用被赋值给另一个引用时,引用计数器就要进行调整,增加了赋值语句时间
  • 会出现循环引用。比如,对象a引用了对象b,同时对象b也引用了对象a,这就导致两个对象之间循环引用。对象a和对象b的引用都不为0,即使这两个对象已经没有其他引用,由于它们的引用计数都大于0,所以它们就没有办法被回收。如果要解决这个问题就要引入额外机制,这样效率又进一步降低了。

循环引用

引用计数算法在当前主流的JVM中已经没有再被使用了。

简单的例子测试一下

public class ReferenceCountingTest {

    public Object instance = null;

    // 10M 占用内存,便于分析
    private byte[] bytes = new byte[10*1024*1024];

    public static void main(String[] args) {
        ReferenceCountingTest objectA = new ReferenceCountingTest();
        ReferenceCountingTest objectB = new ReferenceCountingTest();

        //互相引用
        objectA.instance = objectB;
        objectB.instance = objectA;

        //切断可达
        objectA = null;
        objectB = null;
        
        //强制进行垃圾回收
        System.GC();
    }
}

ReferenceCountingTest类中有一个10M的byte数组, 让objectA.instance = objectBobjectB.instance = objectA导致objectAobjectB互相引用,如果采用引用计数法的话,这两个对象是没法办法进行回收的,并且每个对象占用不少于10M的内存空间。

在VM options 设置参数 -XX:+PrintGC打印GC情况,来看下运行结果是怎样的:

[GC (System.gc())  24381K->1106K(249344K), 0.0009894 secs]
[Full GC (System.gc())  1106K->957K(249344K), 0.0054511 secs]

从结果24381K->1106K可以看到内存从24381K回收到1106K,回收的空间差不多就是objectAobjectB两个对象占用的空间。这也从侧面说明JVM不是采用引用计数算法判定对象是否存活的。

可达性分析算法

可达性分析算法思路是使用一系列根对象(GC Roots)作为起点,从根节点开始向下进行搜索,搜索过的路径称为引用链(Reference Chain),如果某个对象到根节点没有任何引用链相连或者说从根节点到这个对象不可达,则这个对象就被视为“垃圾”。

如上图所示,白色椭圆形Object4、Object5、Object6之间虽然有关联,但是由于没有和GC Roots关联,所以它们被判定为可回收对象。

在Java中有以下7种GC Roots:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象。比如:方法入参、局部变量等
  • 方法区中常量引用的对象
  • 方法区中类静态属性引用的对象:Java类的引用类型静态变量
  • 通过JNI调用本地代码(nactive code)产生的JNI引用。包括JNI的局部变量或者全局变量
  • 被系统类加载器加载的类,这些类不会被回收。它们可以以静态字段的方式去持有对象。
  • 所有被同步(synchronized 关键)持有的对象
  • 被JVM保留用于特殊目的的对象。哪些对象被保留取决于虚拟机的实现,可能的有:系统类加载器、一些重要的异常类、做为异常类处理的被预分配对象或者一些自定义的类加载器。

以上8种GC Roots中前4个比较重要,在面试中也会经常被问到,后3个了解一下即可。

可达性分析算法是目前在动态语言中使用最广泛的算法,目前JVM判断对象是否是垃圾用的都是这种算法。

垃圾的回收

Finalize方法

对象通过可达性分析算法被判定为可回收对象,也不是说对象一定要被回收,对象可以通过重写finalize()方法获得一次“免死”机会。当发生GC的时候,JVM会判断可回收的对象是否调用过finalize()方法,如果调用过finalize()方法,对象将会被回收;反之,如果没有调用过 finalize()方法,会将要调用finalize()方法的对象 F-Queue的队列之中等待调用,在调用时如果对象重写了finalize()方法,可以在finalize()方法中“托关系想办法”让自己和GC Roots搭上关系进行一次自我拯救,比如把自己(this关键字) 赋值给某个类变量或者对象的成员变量,对象就会从即将回收的列表中移除,这样对象就完成了一次自我拯救。在执行完finalize()方法后,还会再判断一次对象是否可达,如果不可达,自我拯救失败,最后还是要被回收的。

要注意的一点是:对象finalize()方法只会调用一次,如果对象自我拯救成功一次,当第二次再发生GC的时候会忽略调用对象的finalize()方法,最后都要被回收。这就是JVM世界的法则,只给对象一次不成为垃圾的机会,如果再次成为垃圾,不好意思那只能被回收了。所以机会只有一次,要好好抓住。

下面通过例子测试一下对象的自我拯救:

public class FinalizeGC {
    private static Object instance;

    public static void main(String[] args) throws InterruptedException {
        instance = new FinalizeGC();

        instance = null;
        //进行第一次垃圾回收
        System.gc();
        //休眠1s
        Thread.sleep(1000);
        if (instance != null) {
            System.out.println("I'm still alive.");
        }else {
            System.out.println("I'm dead.");
        }

        
        instance = null;
        //进行第二次垃圾回收
        System.gc();
        //休眠1s
        Thread.sleep(1000);
        if (instance != null) {
            System.out.println("I'm still alive.");
        }else {
            System.out.println("I'm dead.");
        }
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("Override finalize method execute");
        instance = this;
    }    
}

运行结果:

Override finalize method execute
I'm still alive.
I'm dead.

从运行结果可以看到对象只被自我拯救一次,第二次自我拯救失败。

线程休眠Thread.sleep(1000)1s是因为F-Queue的队列中的finalize()方法,会由一条由虚拟机自动建立的、低调度优先级的Finalizer线程去执行它们,休眠是为了等待Finalizer线程去执行finalize()方法。

Thread.sleep(1000)注释掉连续执行多次,你可能会看到如下情况:

Override finalize method execute
I'm dead.
I'm dead.

或者

I'm dead.
Override finalize method execute
I'm dead.

出现上面的原因是finalize()方法执行缓慢,对象还没有自我拯救就会回收了。所以finalize()方法最好不要使用,太不可靠了,也不要想着用finalize()方法进行自我拯救,finalize()能做的所有工作,使用try-finally或者其他方式都可以做得更好、更及时。

方法区回收

方法区的垃圾收集主要回收两部分内容:废弃的常量和不再使用的类型。回收废弃常量与回收Java堆中的对象非常类似。举个常量池中字面量回收的例子,假如一个字符串“suncodernote”曾经进入常量池中,但是当前系统又没有任何一个字符串对象的值是“suncodernote”,换句话说,已经没有任何字符串对象引用常量池中的“suncodernote”常量,且虚拟机中也没有其他地方引用这个字面量。如果在这时发生内存回收,而且垃圾收集器判断确有必要的话,这个“suncodernote”常量就将会被系统清理出常量池。常量池中其他类(接口)、方法、字段的符号引用也与此类似。

判定一个常量是否“废弃”还是相对简单,而要判定一个类型是否属于“不再被使用的类”的条件就比较苛刻了,必须同时满足以下的条件(仅仅是可以,不代表必然,因为还有一些参数可以进行控制):

  1. 该类所有的实例都已经被回收,也就是堆中不存在该类的任何实例。
  2. 加载该类的 ClassLoader 已经被回收。
  3. 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法.
  4. 参数控制:-Xnoclassgc参数可以禁用类的垃圾收集(GC),这可以节省一些GC时间,从而缩短应用程序运行期间的中断

到此这篇关于java中如何判断对象是否是垃圾的文章就介绍到这了,更多相关java判断垃圾内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: java中如何判断对象是否是垃圾

本文链接: https://www.lsjlt.com/news/211640.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • java中如何判断对象是否是垃圾
    目录判断对象是否为“垃圾”引用计数算法可达性分析算法垃圾的回收Finalize方法方法区回收Java会自动进行内存管理,JVM会进行垃圾回收,哪它是怎么判定哪...
    99+
    2023-05-18
    java 判断垃圾 java判断对象垃圾
  • java判断对象是否是数组
    从构造函数入手,obj instanceof Arraytypeof 和 instanceof 都可以用来判断变量,typeof方法返回一个字符串,来表示数据的类型; 但是typeof来判断数据类型其实并不准确。比如数组、正则、日期、对象的...
    99+
    2017-01-10
    java基础 java 判断 对象 数组
  • java对象如何判断是否为空
    在实际书写代码的时候,经常会因为对象为空,而抛出空指针异常java.lang.NullPointerException。下面我们来看一下java中判断对象是否为空的方法:(推荐:java视频教程)首先来看一下工具StringUtils的判断...
    99+
    2017-05-08
    java 对象
  • 如何判断java对象是否为空
    首先来看一下工具StringUtils的判断方法:一种是org.apache.commons.lang3包下的;另一种是org.springframework.util包下的。这两种StringUtils工具类判断对象是否为空是有差距的:S...
    99+
    2017-08-03
    java入门 判断 java 对象
  • java如何判断对象是否相等
    equals的作用及与==的区别equals被用来判断两个对象是否相等。equals通常用来比较两个对象的内容是否相等,==用来比较两个对象的地址是否相等。equals方法默认等同于“==”。Object类中的equals方法定义为判断两个...
    99+
    2021-10-21
    java基础 java 判断 对象 相等
  • java如何判断对象是否为空
    在Java中,可以使用以下方法来判断一个对象是否为空:1. 使用`==`运算符来判断对象是否为null。如果对象等于null,则表示...
    99+
    2023-08-17
    java
  • java判断对象是否为空
    对 Java 语言来说,一切皆是对象。把现实世界中的对象抽象地体现在编程世界中,一个对象代表了某个具体的操作。一个个对象最终组成了完整的程序设计,这些对象可以是独立存在的,也可以是从别的对象继承过来的。对象之间通过相互作用传递信息,实现程序...
    99+
    2018-09-04
    java
  • java判断对象是否是string类型
    instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。 用法:result = object instanceof clas...
    99+
    2019-10-13
    java
  • java如何判断一个对象是否为空对象
    最近项目中遇到一个问题,在用户没填数据的时候,我们需要接收从前端传过来的对象为null,但是前端说他们一个一个判断特别麻烦,只能传个空对象过来,我第一个想法就是可以通过反射来判断对象...
    99+
    2022-11-13
  • java怎么判断对象是否null
    判断Java对象是否为null可以有两层含义: (推荐学习:java课程)第一层: 直接使用 object == null 去判断,对象为null的时候返回true,不为null的时候返回false。第二层:在object...
    99+
    2017-08-19
    java基础 java
  • java判断对象是否为数组
    数组对于每一门编程语言来说都是重要的数据结构之一,当然不同语言对数组的实现及处理也不尽相同。用法: (推荐学习:java课程)Array.isArray(object)参数object:要检测的内容返回值返回值是布尔类型...
    99+
    2017-12-03
    java基础 java
  • Java中如何判断一个对象是否为空
    在Java中,可以使用以下几种方法来判断一个对象是否为空:1. 使用 `==` 运算符判断是否为 `null`:通过将对象与 `nu...
    99+
    2023-09-25
    Java
  • java判断对象是否是null的方法
    Java 语言支持两种数据类型,分别是基本数据类型和引用数据类型,而 null 是一种特殊的引用数据类型。判断一个对象是否为 null,可以用if (obj == null) { }来判断。代码如下:// 判断对象是否为null if (s...
    99+
    2014-08-30
    java 对象
  • Python判断对象是否是functio
    在Python中,判断一个对象是否是方法有如下三种方法。 1. 根据“__call__”属性判断 有时候用python就有这么一种感悟,各种钩子函数就是通过内置的“__”属性实现,python学得好不好,就是对“__”属性理解得透...
    99+
    2023-01-31
    对象 Python functio
  • java中怎么判断对象是否为空
    java中判断对象是否为空的方法:首先来看一下工具StringUtils的判断方法:一种是org.apache.commons.lang3包下的;另一种是org.springframework.util包下的。这两种StringUtils工...
    99+
    2016-03-01
    java
  • java判断集合对象是否为空
    Java 集合类中的 List.isEmpty() 方法用于判断集合对象是否为空,如果为空,则返回 true,否则返回 false。语法:isEmpty()应用:本示例使用 List 接口的实现类 ArrayList 初始化一个列表对象 l...
    99+
    2014-08-18
    java基础 java 判断 集合对象 为空
  • java判断对象是否为字符串
    java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。用法:result = object instanceo...
    99+
    2020-01-27
    java基础 java
  • java判断一个对象是否数组
    判断对象是否为数组:public static void main(String[] args) { String[] a = ["1","2"]; if(a instanceof String[]){ ...
    99+
    2019-07-20
    java基础 java 数组
  • Javascript中如何判断对象是否存在
    本篇文章给大家分享的是有关Javascript中如何判断对象是否存在,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。Javascript 语言的...
    99+
    2022-10-19
  • es6中如何判断对象是否为null
    这篇文章主要介绍“es6中如何判断对象是否为null”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“es6中如何判断对象是否为null”文章能帮助大家解决问题。 ...
    99+
    2022-10-19
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作