Java中的finalize()方法什么时候被调用?

发布于 2024-08-26 12:07:27 字数 249 浏览 6 评论 0原文

我需要知道 何时Finalize() 方法在 JVM 中调用。我创建了一个测试类,当通过覆盖调用 finalize() 方法时,该测试类会写入文件。它没有被执行。谁能告诉我它不执行的原因吗?

I need to know when the finalize() method is called in the JVM. I created a test class which writes into a file when the finalize() method is called by overriding it. It is not executed. Can anybody tell me the reason why it is not executing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(18

儭儭莪哋寶赑 2024-09-02 12:07:27

当对象即将被垃圾回收时,将调用 finalize 方法。这可以是在它有资格进行垃圾收集之后的任何时间。

请注意,对象完全有可能永远不会被垃圾回收(因此永远不会调用finalize)。当对象永远不符合 gc 条件时(因为它在 JVM 的整个生命周期中都是可访问的),或者在对象变得符合条件的时间和 JVM 停止运行的时间之间实际上没有运行垃圾收集时,就会发生这种情况(这种情况通常发生在简单的情况下)测试程序)。

有多种方法可以告诉 JVM 在尚未调用的对象上运行 Finalize,但使用它们也不是一个好主意(该方法的保证也不是很强) )。

如果您依靠 finalize 来使应用程序正确运行,那么您就做错了。 finalize 应该用于清理(通常是非Java)资源。正是如此,因为 JVM 不保证在任何对象上调用 Finalize。

The finalize method is called when an object is about to get garbage collected. That can be at any time after it has become eligible for garbage collection.

Note that it's entirely possible that an object never gets garbage collected (and thus finalize is never called). This can happen when the object never becomes eligible for gc (because it's reachable through the entire lifetime of the JVM) or when no garbage collection actually runs between the time the object become eligible and the time the JVM stops running (this often occurs with simple test programs).

There are ways to tell the JVM to run finalize on objects that it wasn't called on yet, but using them isn't a good idea either (the guarantees of that method aren't very strong either).

If you rely on finalize for the correct operation of your application, then you're doing something wrong. finalize should only be used for cleanup of (usually non-Java) resources. And that's exactly because the JVM doesn't guarantee that finalize is ever called on any object.

随心而道 2024-09-02 12:07:27

一般来说,最好不要依赖 finalize() 进行任何清理等。

根据 Javadoc (值得一读),它是:

当垃圾收集确定不再有对该对象的引用时,由对象上的垃圾收集器调用。

正如 Joachim 指出的,如果对象始终可访问,那么在程序的生命周期中这可能永远不会发生。

此外,不保证垃圾收集器在任何特定时间运行。一般来说,我想说的是 finalize() 可能不是一般情况下使用的最佳方法,除非有特定的需要它。

In general it's best not to rely on finalize() to do any cleaning up etc.

According to the Javadoc (which it would be worth reading), it is:

Called by the garbage collector on an object when garbage collection determines that there are no more references to the object.

As Joachim pointed out, this may never happen in the life of a program if the object is always accessible.

Also, the garbage collector is not guaranteed to run at any specific time. In general, what I'm trying to say is finalize() is probably not the best method to use in general unless there's something specific you need it for.

絕版丫頭 2024-09-02 12:07:27
protected void Finalize() throws Throwable {}
  • 每个类都继承了 finalize() 方法
    java.lang.Object
  • 垃圾收集器在确定时调用该方法
    不再引用该对象
    存在
  • 对象的finalize方法不执行任何操作,但它可以被覆盖
    任何类别
  • 通常应该重写它来清理非 Java 资源,即关闭
    一个文件
  • 如果重写finalize(),那么使用
    try-catch-finally 语句并
    始终调用 super.finalize()。这
    是确保您这样做的安全措施
    不要无意中错过关闭
    对象调用所使用的资源

    protected void Finalize() throws Throwable {
         尝试 {
             关闭(); // 关闭打开的文件
         } 最后 {
             super.finalize();
         }
     }
    
  • 垃圾回收期间 finalize() 抛出的任何异常都会停止
    最终确定但被忽略

  • finalize() 绝不会在任何对象上运行多次

finalize() 永远不会在引用自以下内容的 :http://www.janeg.ca/scjp/gc/finalize.html

您还可以查看这篇文章:

protected void finalize() throws Throwable {}
  • every class inherits the finalize() method from
    java.lang.Object
  • the method is called by the garbage collector when it determines
    no more references to the object
    exist
  • the Object finalize method performs no actions but it may be overridden by
    any class
  • normally it should be overridden to clean-up non-Java resources ie closing
    a file
  • if overridding finalize() it is good programming practice to use a
    try-catch-finally statement and to
    always call super.finalize(). This
    is a safety measure to ensure you do
    not inadvertently miss closing a
    resource used by the objects calling
    class

    protected void finalize() throws Throwable {
         try {
             close();        // close open files
         } finally {
             super.finalize();
         }
     }
    
  • any exception thrown by finalize() during garbage collection halts the
    finalization but is otherwise ignored

  • finalize() is never run more than once on any object

quoted from: http://www.janeg.ca/scjp/gc/finalize.html

You could also check this article:

十年不长 2024-09-02 12:07:27

Java finalize() 方法不是析构函数,不应该用于处理应用程序所依赖的逻辑。 Java 规范规定,不保证在应用程序的生命周期内调用 Finalize 方法。

您可能想要的是finally 和清理方法的组合,如下所示:

MyClass myObj;

try {
    myObj = new MyClass();

    // ...
} finally {
    if (null != myObj) {
        myObj.cleanup();
    }
}

这将正确处理MyClass() 构造函数抛出异常时的情况。

The Java finalize() method is not a destructor and should not be used to handle logic that your application depends on. The Java spec states there is no guarantee that the finalize method is called at all during the livetime of the application.

What you problably want is a combination of finally and a cleanup method, as in:

MyClass myObj;

try {
    myObj = new MyClass();

    // ...
} finally {
    if (null != myObj) {
        myObj.cleanup();
    }
}

This will correctly handle the situation when the MyClass() constructor throws an exception.

话少心凉 2024-09-02 12:07:27

查看《Effective Java》第二版第 27 页。
第 7 项:避免终结器

终结器是不可预测的,通常是危险的,而且通常是不必要的。永远不要在终结器中做任何对时间要求严格的事情。绝不
依赖终结器来更新关键持久状态。

要终止资源,请使用 try-finally 代替:

// try-finally 块保证终止方法的执行
Foo foo = new Foo(...);
尝试 {
    // 做 foo 必须做的事情
    ...
} 最后 {
    foo.terminate(); // 显式终止方法
}

Check out Effective Java, 2nd edition page 27.
Item 7: Avoid finalizers

Finalizers are unpredictable, often dangerous, and generally unnecessary. never do anything time-critical in a finalizer. never
depend on a finalizer to update critical persistent state.

To terminate a resource, use try-finally instead:

// try-finally block guarantees execution of termination method
Foo foo = new Foo(...);
try {
    // Do what must be done with foo
    ...
} finally {
    foo.terminate(); // Explicit termination method
}
合约呢 2024-09-02 12:07:27

Java中什么时候调用finalize()方法?

Finalize方法将在GC检测到对象不再可达之后、实际回收对象使用的内存之前被调用。

  • 如果一个对象永远不会变得无法访问,则永远不会对其调用 finalize()

  • 如果 GC 不运行,则可能永远不会调用 finalize()。 (通常,GC 仅在 JVM 认为可能有足够的垃圾值得执行时才运行。)

  • 在 GC 确定某个特定对象无法访问之前,可能需要多个 GC 周期。 (Java GC 通常是“分代”收集器...)

  • 一旦 GC 检测到某个对象无法访问且可终结,它就会被放入终结队列中。终结通常与普通 GC 异步发生。

(JVM 规范实际上允许 JVM 从不运行终结器...前提是它不回收对象使用的空间。以这种方式实现会被削弱/无用,但如果这种行为是“允许的”。)

结果是依赖最终确定来完成必须在确定的时间范围内完成的事情是不明智的。根本不使用它们是“最佳实践”。应该有一种更好(即更可靠)的方法来完成您在 Finalize() 方法中尝试执行的任何操作。

终结的唯一合法用途是清理与应用程序代码丢失的对象关联的资源。即使如此,您也应该尝试编写应用程序代码,以便一开始就不会丢失对象。 (例如,使用 Java 7+ try-with-resources 确保始终调用 close() ...)


我创建了一个测试类,当通过覆盖调用 Finalize() 方法时,该测试类会写入文件。它没有被执行。谁能告诉我它不执行的原因吗?

这很难说,但有几种可能性:

  • 该对象没有被垃圾回收,因为它仍然是可访问的。
  • 该对象不会被垃圾回收,因为 GC 在测试完成之前不会运行。
  • GC 找到该对象并将其放入终结队列中,但在测试完成之前终结尚未完成。

When is the finalize() method called in Java?

The finalize method will be called after the GC detects that the object is no longer reachable, and before it actually reclaims the memory used by the object.

  • If an object never becomes unreachable, finalize() will never be called on it.

  • If the GC doesn't run then finalize() may never be called. (Normally, the GC only runs when the JVM decides that there is likely to enough garbage to make it worthwhile.)

  • It may take more than one GC cycle before the GC determines that a specific object is unreachable. (Java GCs are typically "generational" collectors ...)

  • Once the GC detects an object is unreachable and finalizable, it is places on a finalization queue. Finalization typically occurs asynchronously with the normal GC.

(The JVM spec actually allows a JVM to never run finalizers ... provided that it doesn't reclaim the space used by the objects. A JVM that was implemented this way would be crippled / useless, but it this behavior is "allowed".)

The upshot is that it is unwise to rely on finalization to do things that have to be done in a definite time-frame. It is "best practice" not to use them at all. There should be a better (i.e. more reliable) way to do whatever it is you are trying to do in the finalize() method.

The only legitimate use for finalization is to clean up resources associated with objects that have been lost by application code. Even then, you should try to write the application code so that it doesn't lose the objects in the first place. (For example, use Java 7+ try-with-resources to ensure that close() is always called ...)


I created a test class which writes into a file when the finalize() method is called by overriding it. It is not executed. Can anybody tell me the reason why it is not executing?

It is hard to say, but there are a few possibilities:

  • The object is not garbage collected because it is still reachable.
  • The object is not garbage collected because the GC doesn't run before your test finishes.
  • The object is found by the GC and placed in the finalization queue by the GC, but finalization isn't completed before your test finishes.
蹲在坟头点根烟 2024-09-02 12:07:27

由于 JVM 调用 Finalize() 方法存在不确定性(不确定被重写的 Finalize() 是否会被执行),出于研究目的,观察调用 Finalize() 时发生的情况的更好方法是通过命令 System.gc() 强制 JVM 调用垃圾回收。

具体来说,当对象不再使用时调用 Finalize()。但是当我们尝试通过创建新对象来调用它时,它的调用并不确定。因此,为了确定性,我们创建了一个 null 对象 c,它显然没有未来的用途,因此我们看到了对象 c 的 Finalize 调用。

示例

class Car {

    int maxspeed;

    Car() {
        maxspeed = 70;
    }

    protected void finalize() {

    // Originally finalize method does nothing, but here we override finalize() saying it to print some stmt
    // Calling of finalize is uncertain. Difficult to observe so we force JVM to call it by System.gc(); GarbageCollection

        System.out.println("Called finalize method in class Car...");
    }
}

class Bike {

    int maxspeed;

    Bike() {
        maxspeed = 50;
    }

    protected void finalize() {
        System.out.println("Called finalize method in class Bike...");
    }
}

class Example {

    public static void main(String args[]) {
        Car c = new Car();
        c = null;    // if c weren`t null JVM wouldn't be certain it's cleared or not, null means has no future use or no longer in use hence clears it
        Bike b = new Bike();
        System.gc();    // should clear c, but not b
        for (b.maxspeed = 1; b.maxspeed <= 70; b.maxspeed++) {
            System.out.print("\t" + b.maxspeed);
            if (b.maxspeed > 50) {
                System.out.println("Over Speed. Pls slow down.");
            }
        }
    }
}

输出

    Called finalize method in class Car...
            1       2       3       4       5       6       7       8       9
    10      11      12      13      14      15      16      17      18      19
    20      21      22      23      24      25      26      27      28      29
    30      31      32      33      34      35      36      37      38      39
    40      41      42      43      44      45      46      47      48      49
    50      51Over Speed. Pls slow down.
            52Over Speed. Pls slow down.
            53Over Speed. Pls slow down.
            54Over Speed. Pls slow down.
            55Over Speed. Pls slow down.
            56Over Speed. Pls slow down.
            57Over Speed. Pls slow down.
            58Over Speed. Pls slow down. 
            59Over Speed. Pls slow down.
            60Over Speed. Pls slow down.
            61Over Speed. Pls slow down.
            62Over Speed. Pls slow down.
            63Over Speed. Pls slow down.
            64Over Speed. Pls slow down.
            65Over Speed. Pls slow down.
            66Over Speed. Pls slow down.
            67Over Speed. Pls slow down.
            68Over Speed. Pls slow down.
            69Over Speed. Pls slow down.
            70Over Speed. Pls slow down.

注意 - 即使在打印了 70 个之后并且此后对象 b 不再在程序中使用,也不确定 b 是否被清除或不由 JVM 执行,因为不会打印“Called Finalize method in class Bike...”。

Since there is an uncertainity in calling of finalize() method by JVM (not sure whether finalize() which is overridden would be executed or not), for study purposes the better way to observe what happens when finalize() is called, is to force the JVM to call garbage collection by command System.gc().

Specifically, finalize() is called when an object is no longer in use. But when we try to call it by creating new objects there is no certainty of its call. So for certainty we create a null object c which obviously has no future use, hence we see the object c's finalize call.

Example

class Car {

    int maxspeed;

    Car() {
        maxspeed = 70;
    }

    protected void finalize() {

    // Originally finalize method does nothing, but here we override finalize() saying it to print some stmt
    // Calling of finalize is uncertain. Difficult to observe so we force JVM to call it by System.gc(); GarbageCollection

        System.out.println("Called finalize method in class Car...");
    }
}

class Bike {

    int maxspeed;

    Bike() {
        maxspeed = 50;
    }

    protected void finalize() {
        System.out.println("Called finalize method in class Bike...");
    }
}

class Example {

    public static void main(String args[]) {
        Car c = new Car();
        c = null;    // if c weren`t null JVM wouldn't be certain it's cleared or not, null means has no future use or no longer in use hence clears it
        Bike b = new Bike();
        System.gc();    // should clear c, but not b
        for (b.maxspeed = 1; b.maxspeed <= 70; b.maxspeed++) {
            System.out.print("\t" + b.maxspeed);
            if (b.maxspeed > 50) {
                System.out.println("Over Speed. Pls slow down.");
            }
        }
    }
}

Output

    Called finalize method in class Car...
            1       2       3       4       5       6       7       8       9
    10      11      12      13      14      15      16      17      18      19
    20      21      22      23      24      25      26      27      28      29
    30      31      32      33      34      35      36      37      38      39
    40      41      42      43      44      45      46      47      48      49
    50      51Over Speed. Pls slow down.
            52Over Speed. Pls slow down.
            53Over Speed. Pls slow down.
            54Over Speed. Pls slow down.
            55Over Speed. Pls slow down.
            56Over Speed. Pls slow down.
            57Over Speed. Pls slow down.
            58Over Speed. Pls slow down. 
            59Over Speed. Pls slow down.
            60Over Speed. Pls slow down.
            61Over Speed. Pls slow down.
            62Over Speed. Pls slow down.
            63Over Speed. Pls slow down.
            64Over Speed. Pls slow down.
            65Over Speed. Pls slow down.
            66Over Speed. Pls slow down.
            67Over Speed. Pls slow down.
            68Over Speed. Pls slow down.
            69Over Speed. Pls slow down.
            70Over Speed. Pls slow down.

Note - Even after printing upto 70 and after which object b is not being used in the program, there is uncertainty that b is cleared or not by JVM since "Called finalize method in class Bike..." is not printed.

任谁 2024-09-02 12:07:27

Finalize 将打印出类创建的计数。

protected void finalize() throws Throwable {
    System.out.println("Run F" );
    if ( checkedOut)
        System.out.println("Error: Checked out");
        System.out.println("Class Create Count: " + classCreate);
}

while ( true) {
    Book novel=new Book(true);
    //System.out.println(novel.checkedOut);
    //Runtime.getRuntime().runFinalization();
    novel.checkIn();
    new Book(true);
    //System.runFinalization();
    System.gc();

你所见。以下输出显示当类计数为 36 时第一次执行 gc。

C:\javaCode\firstClass>java TerminationCondition
Run F
Error: Checked out
Class Create Count: 36
Run F
Error: Checked out
Class Create Count: 48
Run F

finalize will print out the count for class creation.

protected void finalize() throws Throwable {
    System.out.println("Run F" );
    if ( checkedOut)
        System.out.println("Error: Checked out");
        System.out.println("Class Create Count: " + classCreate);
}

main

while ( true) {
    Book novel=new Book(true);
    //System.out.println(novel.checkedOut);
    //Runtime.getRuntime().runFinalization();
    novel.checkIn();
    new Book(true);
    //System.runFinalization();
    System.gc();

As you can see. The following out put show the gc got executed first time when the class count is 36.

C:\javaCode\firstClass>java TerminationCondition
Run F
Error: Checked out
Class Create Count: 36
Run F
Error: Checked out
Class Create Count: 48
Run F
情泪▽动烟 2024-09-02 12:07:27

最近在与终结器方法进行斗争(为了在测试期间处理连接池),我不得不说终结器缺少很多东西。使用 VisualVM 观察并使用弱引用跟踪实际交互,我发现在 Java 8 环境(Oracle JDK、Ubuntu 15)中存在以下情况:

  • Finalize 不会立即调用 Finalizer(GC 部分)单独拥有引用难以捉摸的是
  • ,默认的垃圾收集器池无法访问的对象
  • Finalize 被批量调用,指向垃圾收集器在某个阶段释放资源的实现细节。
  • 调用 System.gc() 通常不会导致对象更频繁地被终结,它只会导致终结器更快地意识到无法访问的对象
  • 。堆转储或其他一些内部机制
  • 最终化接缝受内存要求(释放更多内存)或被标记为最终化增长的特定内部限制的对象列表的约束。因此,如果有很多对象被终结,那么与只有少数对象相比,终结阶段将被更频繁、更早地触发。 在
  • 某些情况下,System.gc() 会直接触发终结,但前提是引用是本地且短暂的。这可能与世代有关。

最终想法

Finalize 方法不可靠,但只能用于一件事。您可以确保对象在垃圾收集之前已关闭或处置,从而如果正确处理涉及生命周期结束操作的更复杂生命周期的对象,则可以实现故障安全。这是我能想到的一个值得超越它的原因。

Having wrestled with finalizer methods lately (in order to dispose connection pools during testing), I have to say that finalizer lacks many things. Using VisualVM to observe as well as using weak references to track the actual interaction I found that following things are true in a Java 8 environment (Oracle JDK, Ubuntu 15):

  • Finalize is not called immediately the Finalizer (GC part) individually owns the reference elusively
  • The default Garbage Collector pools unreachable objects
  • Finalize is called in bulk pointing to an implementation detail that there is a certain phase the garbage collector frees the resources.
  • Calling System.gc() often does not result in objects being finalized more often, it just results in the Finalizer getting aware of an unreachable object more rapidly
  • Creating a thread dump almost always result in triggering the finalizer due to high heap overhead during performing the heap dump or some other internal mechanism
  • Finalization seams to be bound by either memory requirements (free up more memory) or by the list of objects being marked for finalization growing of a certain internal limit. So if you have a lot of objects getting finalized the finalization phase will be triggered more often and earlier when compared with only a few
  • There were circumstances a System.gc() triggered a finalize directly but only if the reference was a local and short living. This might be generation related.

Final Thought

Finalize method is unreliable but can be used for one thing only. You can ensure that an object was closed or disposed before it was garbage collected making it possible to implement a fail safe if objects with a more complex life-cylce involving a end-of-life action are handled correctly. That is the one reason I can think of that makes it worth in order to override it.

无妨# 2024-09-02 12:07:27

如果一个对象无法从任何活动线程或任何静态引用访问,那么它就符合垃圾收集或 GC 的条件,换句话说,如果一个对象的所有引用都为空,那么您可以说该对象有资格进行垃圾收集。循环依赖不计为引用,因此如果对象 A 具有对象 B 的引用,并且对象 B 具有对象 A 的引用,并且它们没有任何其他实时引用,则对象 A 和 B 都将有资格进行垃圾收集。
通常,在以下情况下,对象在 Java 中适合垃圾回收:

  1. 该对象的所有引用显式设置为 null,例如 object = null
  2. 对象在块内创建,一旦控制退出该块,引用就会超出范围。
  3. 父对象设置为 null,如果一个对象持有另一个对象的引用,并且当您将容器对象的引用设置为 null 时,子对象或包含的对象将自动符合垃圾回收的条件。
  4. 如果一个对象仅通过 WeakHashMap 具有实时引用,则它将有资格进行垃圾回收。

An Object becomes eligible for Garbage collection or GC if its not reachable from any live threads or any static refrences in other words you can say that an object becomes eligible for garbage collection if its all references are null. Cyclic dependencies are not counted as reference so if Object A has reference of object B and object B has reference of Object A and they don't have any other live reference then both Objects A and B will be eligible for Garbage collection.
Generally an object becomes eligible for garbage collection in Java on following cases:

  1. All references of that object explicitly set to null e.g. object = null
  2. Object is created inside a block and reference goes out scope once control exit that block.
  3. Parent object set to null, if an object holds reference of another object and when you set container object's reference null, child or contained object automatically becomes eligible for garbage collection.
  4. If an object has only live references via WeakHashMap it will be eligible for garbage collection.
梅窗月明清似水 2024-09-02 12:07:27

finalize 方法不受保证。当对象符合 GC 条件时,将调用此方法。在许多情况下,对象可能不会被垃圾收集。

finalize method is not guaranteed.This method is called when the object becomes eligible for GC. There are many situations where the objects may not be garbage collected.

帅的被狗咬 2024-09-02 12:07:27

有时,当一个对象被破坏时,它必须做出一个动作。例如,如果一个对象具有文件句柄或字体等非 java 资源,则可以在销毁对象之前验证这些资源是否已释放。为了管理这种情况,java 提供了一种称为“finalizing”的机制。通过完成它,您可以定义当对象即将从垃圾收集器中删除时发生的特定操作。
要将终结器添加到类中,只需定义 finalize() 方法即可。 Java 执行时每当要删除该类的对象时都会调用此方法。在 Finalize 方法()中,您可以指定在销毁对象之前要执行的操作。
垃圾收集器会定期搜索不再引用任何运行状态的对象或间接搜索任何其他具有引用的对象。在释放资产之前,Java 运行时会调用对象的 Finalize() 方法。 finalize() 方法具有以下一般形式:

protected void finalize(){
    // This is where the finalization code is entered
}

使用 protected 关键字,可以防止类外部的代码访问 finalize()
重要的是要理解 finalize() 在垃圾回收之前被调用。例如,当对象离开作用域时,不会调用它。这意味着您无法知道 Finalize() 何时或是否会被执行。因此,程序必须提供其他方法来释放系统资源或对象使用的其他资源。 您不应该依赖finalize()来保证程序的正常运行。

Sometimes when it is destroyed, an object must make an action. For example, if an object has a non-java resource such as a file handle or a font, you can verify that these resources are released before destroying an object. To manage such situations, java offers a mechanism called "finalizing". By finalizing it, you can define specific actions that occur when an object is about to be removed from the garbage collector.
To add a finalizer to a class simply define the finalize() method. Java execution time calls this method whenever it is about to delete an object of that class. Within the finalize method() you specify actions to be performed before destroying an object.
The garbage collector is periodically searched for objects that no longer refer to any running state or indirectly any other object with reference. Before an asset is released, the Java runtime calls the finalize() method on the object. The finalize() method has the following general form:

protected void finalize(){
    // This is where the finalization code is entered
}

With the protected keyword, access to finalize() by code outside its class is prevented.
It is important to understand that finalize() is called just just before the garbage collection. It is not called when an object leaves the scope, for example. It means you can not know when, or if, finalize() will be executed. As a result, the program must provide other means to free system resources or other resources used by the object. You should not rely on finalize() for normal running of the program.

初吻给了烟 2024-09-02 12:07:27

JDK 18 的最新消息

根据 JEPS 421 在 openjdk 18 上交付了最终版本,因此提供了以下功能: finalize() 方法将被标记为 deprecated(forRemoval=true) ,这意味着在 jdk 18 之后的某个更高版本中将永久删除。

从 jdk 18 开始,一个新命令 -行选项 --finalization=disabled 禁用所有地方的终结机制,即使对于 jdk 本身内部的声明也是如此。

这也与这里的问题相关,因为计划删除它的原因是它包含一些主要缺陷。这些缺陷之一是,从对象变得无法访问到调用其终结器之间可能需要很长的时间。 GC 确实不保证任何终结器都会被调用。

Recent news from JDK 18

According to JEPS 421 delivered on openjdk 18 the finalization and therefore the functionality of finalize() method will be marked as deprecated(forRemoval=true) meaning the permanent removal would follow in some later version after jdk 18.

As from jdk 18 a new command-line option --finalization=disabled disables finalization mechanism everywhere even for declarations inside the jdk itself.

This is also relevant to this question here as the reason it is planned for removal, is some major flaws it contains. One of those flaws is that a very long time may pass between the moment an object becomes unreachable and the moment its finalizer is called. It is also true that the GC provides no guarantee that any finalizer will ever be called.

世界如花海般美丽 2024-09-02 12:07:27

我们重写finalize方法的类

public class TestClass {    
    public TestClass() {
        System.out.println("constructor");
    }

    public void display() {
        System.out.println("display");
    }
    @Override
    public void finalize() {
        System.out.println("destructor");
    }
}

finalize方法被调用的机会,

public class TestGarbageCollection {
    public static void main(String[] args) {
        while (true) {
            TestClass s = new TestClass();
            s.display();
            System.gc();
        }
    }
}

当内存因转储对象而超载时,

gc将调用finalize方法,运行并查看控制台,当内存超载时,您不会发现finalize方法被频繁调用然后finalize方法将被调用。

Class where we override finalize method

public class TestClass {    
    public TestClass() {
        System.out.println("constructor");
    }

    public void display() {
        System.out.println("display");
    }
    @Override
    public void finalize() {
        System.out.println("destructor");
    }
}

The chances of finalize method being called

public class TestGarbageCollection {
    public static void main(String[] args) {
        while (true) {
            TestClass s = new TestClass();
            s.display();
            System.gc();
        }
    }
}

when the memory is overloaded with dump objects the gc will call finalize method

run and see the console, where you dont find the finalize method being called frequently, when the memory is getting overloaded then the finalize method will be called.

羁拥 2024-09-02 12:07:27

finalize() 在垃圾回收之前调用。当对象超出范围时不会调用它。这意味着您无法知道finalize()何时或是否会被执行。

示例:

如果您的程序在垃圾收集器发生之前结束,则 finalize() 将不会执行。因此,它应该用作备份过程,以确保正确处理其他资源,或用于特殊用途的应用程序,而不是作为程序在正常操作中使用的手段。

finalize() is called just before garbage collection. It is not called when an object goes out of scope. This means that you cannot know when or even if finalize() will be executed.

Example:

If your program end before garbage collector occur, then finalize() will not execute. Therefore, it should be used as backup procedure to ensure the proper handling of other resources, or for special use applications, not as the means that your program uses in its normal operation.

思慕 2024-09-02 12:07:27

Java 允许对象实现一个名为 Finalize() 的方法
这可能会被调用。

如果垃圾收集器尝试执行操作,finalize() 方法就会被调用
收集物体。

如果垃圾收集器不运行,则不会调用该方法。

如果垃圾收集器未能收集对象并尝试运行
再说一次,该方法不会在第二次被调用。

实际上,您不太可能在实际项目中使用它。

请记住,它可能不会被调用,但它肯定会被调用
不会被叫两次。 Finalize() 方法可以运行零个或一个
时间。

在下面的代码中,当我们执行finalize()方法时,finalize()方法不会产生任何输出
运行它,因为程序在需要运行之前退出
垃圾收集器。

来源

Java allows objects to implement a method called finalize()
that might get called.

finalize() method gets called if the garbage collector tries to
collect the object.

If the garbage collector doesn't run, the method doesn't get called.

If the garbage collector fails to collect the object and tries to run
it again, the method doesn't get called in the second time.

In practice, you are highly unlikely to use it in real projects.

Just keep in mind that it might not get called and that it definitely
won't be called twice. The finalize() method could run zero or one
time.

In the following code, finalize() method produces no output when we
run it since the program exits before there is any need to run the
garbage collector.

Source

绿光 2024-09-02 12:07:27

正如 https:/ 中指出的/wiki.sei.cmu.edu/confluence/display/java/MET12-J.+Do+not+use+finalizers,

终结器的执行时间没有固定的限制,因为执行时间取决于 Java 虚拟机 (JVM)。唯一的保证是,任何执行的终结器方法都会在关联对象变得不可访问之后(在垃圾收集的第一个周期中检测到)和垃圾收集器回收关联对象的存储之前的某个时候(在垃圾收集器的第二个周期期间)执行。 。在对象变得不可访问后,对象终结器的执行可能会延迟任意长的时间。因此,调用时间关键的功能(例如在对象的 Finalize() 方法中关闭文件句柄)是有问题的。

As pointed out in https://wiki.sei.cmu.edu/confluence/display/java/MET12-J.+Do+not+use+finalizers,

There is no fixed time at which finalizers must be executed because time of execution depends on the Java Virtual Machine (JVM). The only guarantee is that any finalizer method that executes will do so sometime after the associated object has become unreachable (detected during the first cycle of garbage collection) and sometime before the garbage collector reclaims the associated object's storage (during the garbage collector's second cycle). Execution of an object's finalizer may be delayed for an arbitrarily long time after the object becomes unreachable. Consequently, invoking time-critical functionality such as closing file handles in an object's finalize() method is problematic.

黒涩兲箜 2024-09-02 12:07:27

尝试运行该程序以更好地理解

public class FinalizeTest 
{       
    static {
        System.out.println(Runtime.getRuntime().freeMemory());
    }

    public void run() {
        System.out.println("run");
        System.out.println(Runtime.getRuntime().freeMemory());
    }

     protected void finalize() throws Throwable { 
         System.out.println("finalize");
         while(true)
             break;          
     }

     public static void main(String[] args) {
            for (int i = 0 ; i < 500000 ; i++ ) {
                    new FinalizeTest().run();
            }
     }
}

Try runiing this Program for better understanding

public class FinalizeTest 
{       
    static {
        System.out.println(Runtime.getRuntime().freeMemory());
    }

    public void run() {
        System.out.println("run");
        System.out.println(Runtime.getRuntime().freeMemory());
    }

     protected void finalize() throws Throwable { 
         System.out.println("finalize");
         while(true)
             break;          
     }

     public static void main(String[] args) {
            for (int i = 0 ; i < 500000 ; i++ ) {
                    new FinalizeTest().run();
            }
     }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文