394

I've been reading through a lot of the rookie Java questions on finalize() and find it kind of bewildering that no one has really made it plain that finalize() is an unreliable way to clean up resources. I saw someone comment that they use it to clean up Connections, which is really scary since the only way to come as close to a guarantee that a Connection is closed is to implement try (catch) finally.

I was not schooled in CS, but I have been programming in Java professionally for close to a decade now and I have never seen anyone implement finalize() in a production system ever. This still doesn't mean that it doesn't have its uses, or that people I've worked with have been doing it right.

So my question is, what use cases are there for implementing finalize() that cannot be handled more reliably via another process or syntax within the language?

Please provide specific scenarios or your experience, simply repeating a Java text book, or finalize's intended use is not enough, as is not the intent of this question.

Stuart Marks
  • 127,867
  • 37
  • 205
  • 259
Spencer Kormos
  • 8,381
  • 3
  • 28
  • 45
  • HI finalize () method very well explained here http://howtodoinjava.com/2012/10/31/why-not-to-use-finalize-method-in-java/ – Sameer Kazi Apr 14 '14 at 09:30
  • 5
    Most application and library code will never use `finalize()`. However, _platform library code_, such as `SocketInputStream`, which manages native resources on behalf of the caller, does so to try to minimize the risk of resource leaks (or uses equivalent mechanisms, such as `PhantomReference`, that were added later.) So the ecosystem needs them, even though 99.9999% of developers will never write one. – Brian Goetz Oct 17 '18 at 01:11
  • 4
    **Update:** `finalize` is now deprecated, as of [Java 9](https://en.wikipedia.org/wiki/Java_version_history#Java_SE_9). See the Question, [*Why is the finalize() method deprecated in Java 9?*](https://stackoverflow.com/q/56139760/642706). – Basil Bourque Feb 06 '21 at 04:38

21 Answers21

244

You could use it as a backstop for an object holding an external resource (socket, file, etc). Implement a close() method and document that it needs to be called.

Implement finalize() to do the close() processing if you detect it hasn't been done. Maybe with something dumped to stderr to point out that you're cleaning up after a buggy caller.

It provides extra safety in an exceptional/buggy situation. Not every caller is going to do the correct try {} finally {} stuff every time. Unfortunate, but true in most environments.

I agree that it's rarely needed. And as commenters point out, it comes with GC overhead. Only use if you need that "belt and suspenders" safety in a long-running app.

I see that as of Java 9, Object.finalize() is deprecated! They point us to java.lang.ref.Cleaner and java.lang.ref.PhantomReference as alternatives.

Hearen
  • 7,420
  • 4
  • 53
  • 63
John M
  • 13,053
  • 3
  • 27
  • 26
  • 3
    I guess I generally document well and then yell at people when they don't read the documentation. I guess this would help too. *grin* – Spencer Kormos Oct 01 '08 at 15:36
  • 50
    Just make sure that an exception is never thrown by finalize(), or the garbage collector will not continue cleanup of that object, and you'll get a memory leak. – skaffman Oct 01 '08 at 16:04
  • 17
    Finalize isn't guaranteed to be called, so don't count on it releasing a resource. – flicken Oct 01 '08 at 17:14
  • Remember that finalize also impose performance penalty due to the fact that it takes more than one GC to clean the object! – Shimi Bandiel Oct 05 '08 at 13:38
  • 20
    skaffman - I don't believe that (aside from some buggy JVM implementation). From the Object.finalize() javadoc: If an uncaught exception is thrown by the finalize method, the exception is ignored and finalization of that object terminates. – John M Oct 27 '08 at 17:16
  • 5
    Your proposal can hide peoples bugs (not calling close) for a long time. I wouldn't recommend to do so. – kohlerm Nov 28 '08 at 16:00
  • 2
    Why not just put an assertion within finilize checking that the object is ready for disposal, i.e. "closed" instead of writting to a log? – Vlad Gudim Jan 09 '09 at 13:29
  • 3
    If you need that "belt and suspenders" safety to keep an important system running, I don't want to have an AssertionError thrown. I'd like to maximize the chance that the system keeps running by doing the cleanup, while leaving info in a log so I can realize something's wrong. – John M Jan 12 '09 at 22:41
  • 2
    Finalize hurts GC performance, since the garbage collector has to check twice if the object has been collected. – mdma Apr 29 '10 at 01:43
  • 70
    I have actually used finalize for this exact reason. I inherited the code and it was very buggy and had a tendency to leave database connections open. We modified the connections to contain data about when and where they were created and then implemented finalize to log this information if the connection wasn't closed properly. It turned out to be a great help to track down the non-closed connections. – brainimus May 29 '10 at 21:38
  • 1
    From Java doc about Object.finalize() - "Any exception thrown by the finalize method causes the finalization of this object to be halted, but is otherwise ignored." So exceptions will not cause object to stay in memory – Hayk Nahapetyan Apr 14 '17 at 00:43
  • @brainimus Might even be a debug option in a JDBC connection pool. – Thorbjørn Ravn Andersen May 27 '17 at 10:16
  • Finally deprecated, better use some subject-observer pattern where components of your application can register on a "shutdown hook" and cleanup without involving `finalize()` (see answer of SteveJessop). A bit OT: Do **never ever** invoke `finalize()` by your own! That will have side effects beyond unknown (crashes, segfaults, aborts of JVM). If in doubt, avoid it at all costs. – Roland Aug 22 '18 at 11:41
  • 1
    @Roland `finalize()` is just a method. Calling it yourself has no other effects than execution of the code contained in it. It is semantically wrong and will therefore lead to a maintenance nightmare, but there’s no reason why it should crash the JVM. – Holger Jun 07 '19 at 07:18
  • @VladGudim there’s no sense in putting an assertion instead of a logging statement into `finalize()`, as the only purpose of an `assert` statement, is to cause some kind of logging, just indirectly via an `AssertionError` that will be thrown and hopefully logged. In case of `finalize()`, it won’t, as all thrown exceptions are just ignored. – Holger Jun 07 '19 at 07:22
  • @Holger thank you, I know not to invoke `finalize()` manually as it is done by the garbage collector (as I remember correctly). – Roland Jun 08 '19 at 15:41
  • @Roland well yes, you are not supposed to call it manually, or actually, you are not supposed to finalization it at all. But the side effects of invoking it are not that dramatic. – Holger Jun 08 '19 at 22:44
  • This doesn't work anymore (Java 8+) unless you also work around [premature finalization](https://stackoverflow.com/questions/26642153/finalize-called-on-strongly-reachable-objects-in-java-8/69681735#69681735) everywhere you use your object. (It's a lot more work than calling close()). – Aleksandr Dubinsky Jan 21 '22 at 12:16
186

finalize() is a hint to the JVM that it might be nice to execute your code at an unspecified time. This is good when you want code to mysteriously fail to run.

Doing anything significant in finalizers (basically anything except logging) is also good in three situations:

  • you want to gamble that other finalized objects will still be in a state that the rest of your program considers valid.
  • you want to add lots of checking code to all the methods of all your classes that have a finalizer, to make sure they behave correctly after finalization.
  • you want to accidentally resurrect finalized objects, and spend a lot of time trying to figure out why they don't work, and/or why they don't get finalized when they are eventually released.

If you think you need finalize(), sometimes what you really want is a phantom reference (which in the example given could hold a hard reference to a connection used by its referand, and close it after the phantom reference has been queued). This also has the property that it may mysteriously never run, but at least it can't call methods on or resurrect finalized objects. So it's just right for situations where you don't absolutely need to close that connection cleanly, but you'd quite like to, and the clients of your class can't or won't call close themselves (which is actually fair enough - what's the point of having a garbage collector at all if you design interfaces that require a specific action be taken prior to collection? That just puts us back in the days of malloc/free.)

Other times you need the resource you think you're managing to be more robust. For example, why do you need to close that connection? It must ultimately be based on some kind of I/O provided by the system (socket, file, whatever), so why can't you rely on the system to close it for you when the lowest level of resource is gced? If the server at the other end absolutely requires you to close the connection cleanly rather than just dropping the socket, then what's going to happen when someone trips over the power cable of the machine your code is running on, or the intervening network goes out?

Disclaimer: I've worked on a JVM implementation in the past. I hate finalizers.

Hearen
  • 7,420
  • 4
  • 53
  • 63
Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • 82
    Upvoting for extreme sarcasm justice. – Perception Dec 20 '11 at 17:55
  • 32
    This doesn't answer the question; it just says all the drawbacks of `finalize()` without giving any reasons someone would really want to use it. – Mechanical snail Jun 28 '12 at 04:50
  • Were finalizers and phantom references both part of the original JVM spec? If one had phantom references, and if there were a system-defined phantom-reference notification queue which would notify any objects that were GC'ed on an as-convenient basis, those (along with `WeakReference`) would suffice to do almost everything code *should* be doing with finalize [resurrection may not be possible, but I'm not sure that would be a bad thing]. – supercat May 24 '13 at 16:17
  • 1
    @supercat: phantom references (for that matter all references) were introduced in Java 2 – Steve Jessop May 24 '13 at 16:56
  • @SteveJessop: You mean all the types with `Reference` in the name, I assume. Basic object references are so fundamental I can't imagine them not being in Java from the get-go. I assume finalizers were in Java 1? – supercat May 24 '13 at 17:00
  • 1
    @supercat: sorry yes, by "references" I meant `java.lang.ref.Reference` and its subclasses. Java 1 did have variables :-) And yes, it had finalizers too. – Steve Jessop May 24 '13 at 17:02
  • @SteveJessop: Java brought some good ideas to the mainstream, as well as some bad ones. I mainly deal with .net, but find it interesting to see how it compares with Java. It's too bad neither one provided first-class support for deterministic cleanup, since 99% of object cleanup could easily be handled deterministically, and a significant portion can only be handled deterministically. Further, 99% of the difficulties surrounding "deep" versus "shallow" operations could be resolved if there were a linguistic distinction between references that encapsulate a thing's IDENTITY versus its STATE. – supercat May 24 '13 at 17:08
  • @supercat: Well, C# "using" and Java's "try-with-resources" do provide a form of deterministic cleanup (as does try/finally, of course). They just don't do deterministic cleanup of memory allocations. In both cases that's arguably just an extreme exaggeration of the fact C hides the details of `malloc` -- there's no *guarantee* in C that if you free some memory you can immediately allocate an equal amount of memory. The usability problem with `finalize()` is that it makes GC complicated from the POV of the user, when the complexity "should" be in implementation only. – Steve Jessop May 25 '13 at 15:22
  • @SteveJessop: Non-deterministic reclamation of memory is not a problem, since whether or not a piece of memory is "free" is only relevant if something would have *immediate* use for it. The problem comes with objects that ask other things to alter state on their behalf until further notice (especially when the things grant the objects exclusive access to resources). This is a very common pattern, which `finalize` handles very poorly. The .Net "using" and Java's late-arriving "try-with-resources" are helpful in some scenarios, but there's a common scenario where they really fall flat: – supercat May 30 '13 at 16:44
  • 2
    @SteveJessop: If a base-class constructor asks other entities to alter their state on behalf of the object under construction (a very common pattern), but a derived-class field initializer throws an exception, the partially-constructed object should immediately clean up after itself (i.e. notify those outside entities their services are no longer required), but neither Java nor .NET offers any even-remotely-clean pattern via which that can happen. Indeed, they seem to go out of their way to make it hard for a reference to the thing needing cleanup to reach the cleanup code. – supercat May 30 '13 at 16:49
56

A simple rule: never use finalizers.

The fact alone that an object has a finalizer (regardless what code it executes) is enough to cause considerable overhead for garbage collection.

From an article by Brian Goetz:

Objects with finalizers (those that have a non-trivial finalize() method) have significant overhead compared to objects without finalizers, and should be used sparingly. Finalizeable objects are both slower to allocate and slower to collect. At allocation time, the JVM must register any finalizeable objects with the garbage collector, and (at least in the HotSpot JVM implementation) finalizeable objects must follow a slower allocation path than most other objects. Similarly, finalizeable objects are slower to collect, too. It takes at least two garbage collection cycles (in the best case) before a finalizeable object can be reclaimed, and the garbage collector has to do extra work to invoke the finalizer. The result is more time spent allocating and collecting objects and more pressure on the garbage collector, because the memory used by unreachable finalizeable objects is retained longer. Combine that with the fact that finalizers are not guaranteed to run in any predictable timeframe, or even at all, and you can see that there are relatively few situations for which finalization is the right tool to use.

Hearen
  • 7,420
  • 4
  • 53
  • 63
Tom
  • 55,743
  • 3
  • 27
  • 35
50

The only time I've used finalize in production code was to implement a check that a given object's resources had been cleaned up, and if not, then log a very vocal message. It didn't actually try and do it itself, it just shouted a lot if it wasn't done properly. Turned out to be quite useful.

skaffman
  • 398,947
  • 96
  • 818
  • 769
  • That's the only valid use. You can use [`almson-refcount`](https://github.com/almson/almson-refcount) for this purpose, since implementing it correctly and efficiently is tricky. – Aleksandr Dubinsky Jan 21 '22 at 12:18
39

I've been doing Java professionally since 1998, and I've never implemented finalize(). Not once.

Hearen
  • 7,420
  • 4
  • 53
  • 63
Paul Tomblin
  • 179,021
  • 58
  • 319
  • 408
31

The accepted answer is good, I just wanted to add that there is now a way to have the functionality of finalize without actually using it at all.

Look at the "Reference" classes. Weak reference, Phantom Reference & Soft Reference.

You can use them to keep a reference to all your objects, but this reference ALONE will not stop GC. The neat thing about this is you can have it call a method when it will be deleted, and this method can be guaranteed to be called.

As for finalize: I used finalize once to understand what objects were being freed. You can play some neat games with statics, reference counting and such--but it was only for analysis, but watch out for code like this (not just in finalize, but that's where you are most likely to see it):

public void finalize() {
  ref1 = null;
  ref2 = null;
  othercrap = null;
}

It is a sign that somebody didn't know what they were doing. "Cleaning up" like this is virtually never needed. When the class is GC'd, this is done automatically.

If you find code like that in a finalize it's guaranteed that the person who wrote it was confused.

If it's elsewhere, it could be that the code is a valid patch to a bad model (a class stays around for a long time and for some reason things it referenced had to be manually freed before the object is GC'd). Generally it's because someone forgot to remove a listener or something and can't figure out why their object isn't being GC'd so they just delete things it refers to and shrug their shoulders and walk away.

It should never be used to clean things up "Quicker".

Bill K
  • 62,186
  • 18
  • 105
  • 157
  • 3
    Phantom references are a better way to keep track of which objects are being freed, I think. – Bill Michell Nov 07 '08 at 14:27
  • 2
    upvoting for providing the best explanation of "weak reference" I've ever heard. – sscarduzio Nov 03 '13 at 08:14
  • I'm sorry that this took me so many years to read this, but it really is a nice addition to the answers. – Spencer Kormos Apr 15 '14 at 16:18
  • This pattern is now implemented as [`Cleaner`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/ref/Cleaner.html) in the JDK. It's more efficient, but not really different from finalization. – Aleksandr Dubinsky Jan 21 '22 at 12:19
28

I'm not sure what you can make of this, but...

itsadok@laptop ~/jdk1.6.0_02/src/
$ find . -name "*.java" | xargs grep "void finalize()" | wc -l
41

So I guess the Sun found some cases where (they think) it should be used.

Hearen
  • 7,420
  • 4
  • 53
  • 63
itsadok
  • 28,822
  • 30
  • 126
  • 171
20
class MyObject {
    Test main;

    public MyObject(Test t) {    
        main = t; 
    }

    protected void finalize() {
        main.ref = this; // let instance become reachable again
        System.out.println("This is finalize"); //test finalize run only once
    }
}

class Test {
    MyObject ref;

    public static void main(String[] args) {
        Test test = new Test();
        test.ref = new MyObject(test);
        test.ref = null; //MyObject become unreachable,finalize will be invoked
        System.gc(); 
        if (test.ref != null) System.out.println("MyObject still alive!");  
    }
}

====================================

result:

This is finalize

MyObject still alive!

=====================================

So you may make an unreachable instance reachable in finalize method.

Hearen
  • 7,420
  • 4
  • 53
  • 63
Kiki
  • 209
  • 2
  • 3
  • 21
    For some reason, this code makes me think of zombie movies. You GC your object and then it stands up again... – steveha Oct 23 '12 at 23:45
  • above is good codes. I was wondering how to make the object re-reachable again just now. – Jackie Jun 03 '13 at 15:00
  • 17
    no, above is bad codes. it's an example of why finalize is bad. – Tony Jan 29 '14 at 20:18
  • 1
    Remember that invoking `System.gc();` is not a guarantee that the garbage collector will actually run. It is the GC's full discretion to cleanup heap (maybe still enough free heap around, maybe not fragmented to much, ...). So it is only a humble request by the programmer "please, could you hear me out and run?" and not a command "do run now as I say!". Sorry for using lingual words but it says it exactly how the JVM's GC works. – Roland Aug 22 '18 at 11:34
11

finalize() can be useful to catch resource leaks. If the resource should be closed but is not write the fact that it wasn't closed to a log file and close it. That way you remove the resource leak and give yourself a way to know that it has happened so you can fix it.

I have been programming in Java since 1.0 alpha 3 (1995) and I have yet to override finalize for anything...

Hearen
  • 7,420
  • 4
  • 53
  • 63
TofuBeer
  • 60,850
  • 18
  • 118
  • 163
6

You shouldn't depend on finalize() to clean up your resources for you. finalize() won't run until the class is garbage collected, if then. It's much better to explicitly free resources when you're done using them.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
5

Be careful about what you do in a finalize(). Especially if you are using it for things like calling close() to ensure that resources are cleaned up. We ran into several situations where we had JNI libraries linked in to the running java code, and in any circumstances where we used finalize() to invoke JNI methods, we would get very bad java heap corruption. The corruption was not caused by the underlying JNI code itself, all of the memory traces were fine in the native libraries. It was just the fact that we were calling JNI methods from the finalize() at all.

This was with a JDK 1.5 which is still in widespread use.

We wouldn't find out that something went wrong until much later, but in the end the culprit was always the finalize() method making use of JNI calls.

Hearen
  • 7,420
  • 4
  • 53
  • 63
Steven M. Cherry
  • 1,355
  • 1
  • 11
  • 14
5

To highlight a point in the above answers: finalizers will be executed on the lone GC thread. I have heard of a major Sun demo where the developers added a small sleep to some finalizers and intentionally brought an otherwise fancy 3D demo to its knees.

Best to avoid, with possible exception of test-env diagnostics.

Eckel's Thinking in Java has a good section on this.

Michael Easter
  • 23,733
  • 7
  • 76
  • 107
4

Hmmm, I once used it to clean up objects that weren't being returned to an existing pool.

They were passed around a lot, so it was impossible to tell when they could safely be returned to the pool. The problem was that it introduced a huge penalty during garbage collection that was far greater than any savings from pooling the objects. It was in production for about a month before I ripped out the whole pool, made everything dynamic and was done with it.

Hearen
  • 7,420
  • 4
  • 53
  • 63
3

When writing code that will be used by other developers that requires some sort of "cleanup" method to be called to free up resources. Sometimes those other developers forget to call your cleanup (or close, or destroy, or whatever) method. To avoid possible resource leaks you can check in the finalize method to ensure that the method was called and if it wasn't you can call it yourself.

Many database drivers do this in their Statement and Connection implementations to provide a little safety against developers who forget to call close on them.

John Meagher
  • 22,808
  • 14
  • 54
  • 57
2

Edit: Okay, it really doesn't work. I implemented it and thought if it fails sometimes that's ok for me but it did not even call the finalize method a single time.

I am not a professional programmer but in my program I have a case that I think to be an example of a good case of using finalize(), that is a cache that writes its content to disk before it is destroyed. Because it is not necessary that it is executed every time on destruction, it does only speed up my program, I hope that it i didn't do it wrong.

@Override
public void finalize()
{
    try {saveCache();} catch (Exception e)  {e.printStackTrace();}
}

public void saveCache() throws FileNotFoundException, IOException
{
    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("temp/cache.tmp"));
    out.writeObject(cache);
}
user265243
  • 21
  • 2
  • I think a cache (of the type you would flush to disk) is a good example. And even if finalize is not called, no sweat. – foo Oct 19 '11 at 19:15
2

It can be handy to remove things that have been added to a global/static place (out of need), and need to be removed when the object is removed. For instance:

    private void addGlobalClickListener() {
        weakAwtEventListener = new WeakAWTEventListener(this);

        Toolkit.getDefaultToolkit().addAWTEventListener(weakAwtEventListener, AWTEvent.MOUSE_EVENT_MASK);
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();

        if(weakAwtEventListener != null) {
            Toolkit.getDefaultToolkit().removeAWTEventListener(weakAwtEventListener);
        }
    }
Alexander Malfait
  • 2,691
  • 1
  • 23
  • 23
  • This needs additional efforts, as when the listener has a strong reference to the `this` instance passed to it in the constructor, that instance will never become unreachable, hence the `finalize()` will never clean up anyway. If, on the other hand, the listener hold a weak reference to that object, as the name suggests, this construct risks getting cleaned up at times when it shouldn’t. Object life cycles are not the right tool for implementing application semantics. – Holger Jun 07 '19 at 07:37
1

The accepted answer lists that closing a resource during finalize can be done.

However this answer shows that at least in java8 with the JIT compiler, you run into unexpected issues where sometimes the finalizer is called even before you finish reading from a stream maintained by your object.

So even in that situation calling finalize would not be recommended.

Hearen
  • 7,420
  • 4
  • 53
  • 63
Joeblade
  • 1,735
  • 14
  • 22
  • It would work, if the operation is made thread safe, which is a must, as finalizers may be called by arbitrary threads. Since correctly implemented thread safety implies that not only the close operation, but also the operations using the resource must synchronize on the same object or lock, there will be a happens-before relationship between the use and the close operation, which also prevents too early finalization. But, of course, at a high price for the entire usage… – Holger Jan 28 '16 at 12:29
0

iirc - you can use finalize method as a means of implementing a pooling mechanism for expensive resources - so they don't get GC's too.

JGFMK
  • 8,425
  • 4
  • 58
  • 92
0

Personally, I almost never used finalize() except in one rare circumstance: I made a custom generic-type collection, and I wrote a custom finalize() method that does the following:

public void finalize() throws Throwable {
    super.finalize();
    if (destructiveFinalize) {
        T item;
        for (int i = 0, l = length(); i < l; i++) {
            item = get(i);
            if (item == null) {
                continue;
            }
            if (item instanceof Window) {
                ((Window) get(i)).dispose();
            }
            if (item instanceof CompleteObject) {
                ((CompleteObject) get(i)).finalize();
            }
            set(i, null);
        }
    }
}

(CompleteObject is an interface I made that lets you specify that you've implemented rarely-implemented Object methods like #finalize(), #hashCode(), and #clone())

So, using a sister #setDestructivelyFinalizes(boolean) method, the program using my collection can (help) guarantee that destroying a reference to this collection also destroys references to its contents and disposes any windows that might keep the JVM alive unintentionally. I considered also stopping any threads, but that opened a whole new can of worms.

Hearen
  • 7,420
  • 4
  • 53
  • 63
Ky -
  • 30,724
  • 51
  • 192
  • 308
  • 4
    Calling `finalize()` on your `CompleteObject` instances like you do in the above code implies that it might get called twice, as the JVM still might invoke `finalize()` once these objects actually became unreachable, which, due to the logic of finalization, might be *before* the `finalize()` method of your special collection gets called or even concurrently at the same time. Since I don’t see any measures to ensure thread safety in your method, you seem to be unaware of this… – Holger Jan 28 '16 at 12:24
0

The resources (File, Socket, Stream etc.) need to be closed once we are done with them. They generally have close() method which we generally call in finally section of try-catch statements. Sometimes finalize() can also be used by few developers but IMO that is not a suitable way as there is no guarantee that finalize will be called always.

In Java 7 we have got try-with-resources statement which can be used like:

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
  // Processing and other logic here.
} catch (Exception e) {
  // log exception
} finally {
  // Just in case we need to do some stuff here.
}

In the above example try-with-resource will automatically close the resource BufferedReader by invoking close() method. If we want we can also implement Closeable in our own classes and use it in similar way. IMO it seems more neat and simple to understand.

Hearen
  • 7,420
  • 4
  • 53
  • 63
akhil_mittal
  • 23,309
  • 7
  • 96
  • 95
0

As a side note:

An object that overrides finalize() is treated specially by the garbage collector. Usually, an object is immediately destroyed during the collection cycle after the object is no longer in scope. However, finalizable objects are instead moved to a queue, where separate finalization threads will drain the queue and run the finalize() method on each object. Once the finalize() method terminates, the object will at last be ready for garbage collection in the next cycle.

Source: finalize() deprecated on java-9

Hearen
  • 7,420
  • 4
  • 53
  • 63
Sudip Bhandari
  • 2,165
  • 1
  • 27
  • 26