Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
finalize()在java中如何工作?_Java_Multithreading_Memory Management_Garbage Collection_Finalize - Fatal编程技术网

finalize()在java中如何工作?

finalize()在java中如何工作?,java,multithreading,memory-management,garbage-collection,finalize,Java,Multithreading,Memory Management,Garbage Collection,Finalize,因此,我最近在Java中发现了finalize方法(不确定为什么我以前错过了它,但它就在这里)。这个似乎可以解决我正在处理的许多问题,但我想先获得更多的信息 在网上,我发现这张图表演示了垃圾收集和最终确定的过程: 有几个问题: 这是在一个单独的线程中发生的,对吗 如果我在finalize期间实例化一个新对象会发生什么?允许吗 如果我从finalize调用静态方法会发生什么 如果从finalize中建立对对象的新引用,会发生什么 我想我应该解释一下我为什么感兴趣。我经常使用LWJGL,如果我可

因此,我最近在Java中发现了finalize方法(不确定为什么我以前错过了它,但它就在这里)。这个似乎可以解决我正在处理的许多问题,但我想先获得更多的信息

在网上,我发现这张图表演示了垃圾收集和最终确定的过程:

有几个问题:

  • 这是在一个单独的线程中发生的,对吗
  • 如果我在finalize期间实例化一个新对象会发生什么?允许吗
  • 如果我从finalize调用静态方法会发生什么
  • 如果从finalize中建立对对象的新引用,会发生什么

  • 我想我应该解释一下我为什么感兴趣。我经常使用LWJGL,如果我可以使用finalize使Java对象自动清理OpenGL资源,那么我可以在API方面做一些非常好的事情。

    finalize()在Java垃圾收集器检测到不存在对该特定对象的引用时被调用。finalize()由所有Java对象通过对象类继承

    据我所知,从finalize()方法I进行静态方法调用不会有任何困难,您可以从finalize()建立对它的新引用-但是我认为这是糟糕的编程实践

    您不应该依赖finalize()进行清理,最好是边清理边清理。我更喜欢使用try、catch、finally进行清理,而不是使用finalize()。特别是,通过使用finalize(),您将使JVM保留可终结对象引用的所有其他对象,以防它调用它们。这意味着您可能不需要使用内存。更重要的是,这也意味着您可以使JVM永远不会处理对象,因为如果另一个对象finalize方法需要,它们必须保留对象,例如竞争条件

    也可以考虑,GC是不可能被调用的。因此,您实际上不能保证将调用finalize()


    我的建议是,在使用完资源后立即清理资源,不要依赖finalize()来完成此操作。

    首先,请记住,不能保证所有对象都会运行finalize。您可以使用它来释放在与对象关联的本机代码中分配的内存,但对于纯Java代码,大多数用例只是执行清理资源的“备份”机制。这意味着在大多数情况下,您应该手动释放资源,如果您忘记按标准方式进行清理,终结器只能充当一种帮助器来进行清理。但是,不能将它们用作清理的唯一或主要机制。更一般地说,您不应该编写任何正确性取决于正在运行的终结器的代码

    公元1年。据我所知,对于线程调用的
    finalize()
    ,没有任何保证,尽管实际上这可能是一个GC线程

    公元2年。允许实例化新对象。但是,在终结器中处理对象引用存在许多缺陷。特别是,如果在某个活动对象中存储对正在最终确定的对象的硬引用,则可以防止清理即将被垃圾收集的对象。这种物体复活如果失去控制可能会耗尽你的资源。另外,请注意
    finalize()
    中的异常-它们可能会停止终结,但您的程序无法自动了解它们。您需要将代码包装在try-catch块中,并自己传播信息。此外,终结器的长执行时间可能会导致对象队列的建立并消耗大量内存。中描述了一些其他值得注意的问题和限制

    公元3年。从终结器调用静态方法不应该有任何问题

    公元4年。如第2点所述,在终结期间,通过在另一个活动对象中放置对对象的引用,可以防止对象被垃圾收集(以使其复活)。然而,这是一种棘手的行为,可能不是好的做法


    总之,您不能依赖终结器来清理资源。您需要手动处理该问题,在您的情况下,终结器充其量也可以用作备份机制,以掩盖在某种程度上的草率编码。不幸的是,这意味着,您通过使用终结器清理OpenGL资源来改进API的想法可能行不通。

    我不认为有任何关于将使用哪个线程的保证。可以实例化新对象并调用静态方法。建立对对象的新引用将防止对其进行垃圾收集,但不会再次调用
    finalize
    方法——您不想这样做

    清理资源正是
    finalize
    方法的目的,因此您应该在这方面做得很好。不过,有几个警告:

    不能保证调用该方法。如果您占用了程序停止时不会自动释放的资源,请不要依赖于
    finalize

    调用该方法的时间不能保证。由于内存紧张,这将更快。有了大量的空闲内存,它将是以后的事,如果有的话。这可能很适合你:有了大量的内存,你可能不太关心如何释放资源。(尽管挂在它们上面可能会干扰同时运行的其他软件,在这种情况下,您可能会担心。)

    我通常的解决办法是采用某种处理方法来进行清理。如果可以的话,我会在某个时候明确地称之为,而且会尽快。然后我添加了一个finalize方法,它只调用dispose方法。(请注意,当多次调用dispose方法时,该方法必须表现良好!Ind