21

We don't have any destructor in Java as we have in C++.

Q1. How should we clean up any Object in java.

Q2. Is there any alternative to a finally block.

Q3. Sometimes we have to call explicitely initialization/termination of a third party code from our class e.g.

public classs MyClass{
    public MyClass(){
        ThirdPartyInitialize();
    }

    protected void finalize(){
        ThirdPartyTerminate();
    }
}

Is this the correct way?

pankajt
  • 7,642
  • 12
  • 39
  • 60

8 Answers8

21

You generally cannot "clean up" Java objects yourself. The garbage collector decides when to clean objects up. You can indicate when you are done with an object reference by setting it to null, but generally just letting it go out of scope is good enough. Either way, you still have no control over when it gets garbage collected.

The finally block is intended for performing actions whether an exception is thrown from a try block or not, and is the best place to perform clean up. Generally you only would clean up non-object resources like open streams.

finalize() is not guaranteed to be called because the garbage collector is not guaranteed to be called before your program exits. It is not really like a C++ destructor because C++ destructors are always called and you can rely on them being called. You cannot rely on finalize() being called.

So 1) use finally blocks to release non-object resources 2) let the garbage collector clean up object-resources 3) you can hint to the garbage collector that you are done with an object by setting it to null if it is used in a long-running method.

SingleShot
  • 18,821
  • 13
  • 71
  • 101
6

You could also add a shutdown hook to your program, if your program is shutting down too:

//add shutdown hook
Runtime.getRuntime().addShutdownHook(new Thread() {
    public void run() {
        ThirdPartyTerminate();
    }
});
dave4351
  • 2,208
  • 2
  • 18
  • 17
3

Two syntax sugar options:

1) There is a @Cleanup annotation in Lombok that mostly resembles C++ destructors (more):

@Cleanup
ResourceClass resource = new ResourceClass();

2) There is also try-with-resources statement. For example:

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
  System.out.println(br.readLine());
}
Community
  • 1
  • 1
Alexey
  • 9,197
  • 5
  • 64
  • 76
2

The best way to clean up after objects is to just drop the object.

Finally blocks can be abstracted using the Execute Around idiom.

Finalisers should be avoided. They probably wont get called immediately. The clean up should happen anyway. They are relatively slow. You might want to add one as a safety-net if you are writing a low-level resource wrapper (for, say, a file handle) if performance is not critical.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
  • I'm not sure what you mean. If you don't release the resource immediately then you have potential issues (and not just performance). If you aren't throwing an exception, then on any reasonably exception implement it makes little difference whether there is a try block or not (this is different from most C++ implementations). If the contents of the finally block are slow, then it may be worth returning to a pool (even if the "pool" just releases the resource in a separate thread). – Tom Hawtin - tackline Sep 04 '09 at 20:19
1

You can clean up objects by removing references to it, when you no longer need it. You dont have to do it explicitly. An explicit cleanup would require setting the reference to null, thereby providing a hint to the garbage collector that the object can be collected. This hint works because of internal reference counts for each object, that are maintained internally. For instance


C a = new C(); //create an object of class C and assign it to 'a'
a = new C(); //create another object of class C and assign it to 'a'. The older object is no longer referred to. It is now eligible for GC.

There are better alternatives to finalize() depending on how much finalize() is helping your situation.

Often, the best practice is to provide a method like close() or disposeResources() in the API which will allow the caller to help the API clean up itself. For instance, the java.sql.Connection class does this. This is better than the finalize() method, since the JVM will call the finalize() method. Often the finalize() method will be run by a low priority thread in the JVM, leading to certain strange errors.

In the case of the Connection class, waiting for the JVM to perform finalization does prove costly in a lot of applications, since a database can accept only so many connections at a time. Therefore, most programmers will call close() explicitly on a Connection object.

In your case, it should translate into something similar (and in this context, the finally block is guaranteed to run always)


try
{
 ThirdPartyInitialize();
 // use third party component in this try block
}
finally
{
 ThirdPartyTerminate();
}

This is similar to the how the Connection class is also used in most situations.

Vineet Reynolds
  • 76,006
  • 17
  • 150
  • 174
1

You can use java.lang.ref.Cleaner in Java 9,

Glavo
  • 448
  • 3
  • 13
0

The finalize is used similar to a destructor, but, if you use the try...finally block for resources then you can open a resource and in the finally block you close the resource.

The finally block is always called, when the block is exited, either normally or through an exception being thrown.

Finalize is risky for resource management, as you don't know when it will be called, and if it closes an object that also has finalize then it can take a while.

The finally block is the better approach.

James Black
  • 41,583
  • 10
  • 86
  • 166
  • I would *not* say that finalize() is similar to a destructor. The rest of your text is fine, but it largely contradicts that first statement. You never know when finalize() will be called. So it's unlike a C++ destructor, which is called when an object leaves scope or is deleted. – John M Sep 04 '09 at 19:04
  • When an object is garbage collected the finalizer will be called, but no idea when it will be garbage collected, so the finalizer may not be called in a timely fashion. – James Black Sep 04 '09 at 20:22
-1

Your objects in Java really never need to be "Cleaned Up", GC Just works. Nearly every time I've seen someObject=null in code, it's been someone who didn't know what they were doing. There IS a theoretical case for this, but it's really an edge case and generally better handled in other ways like the recently added try with resource.

If you have an external resource that needs to be cleaned up when an object is no longer used, that is another matter.

There are "Reference" classes that will hold a special type of Reference to your class--it will not stop garbage collection, but can notify you when the class is garbage collected (Through a callback if you like). Look up WeakReference, PhantomReference, etc.

These are reliable and work in a much more deterministic way than a actual "finalize" method would because the callback is outside your class, so you don't end up executing a method in some pre-deleted or half-deleted state and the problems that could cause.

Bill K
  • 62,186
  • 18
  • 105
  • 157
  • This isn't an answer to the question above as you're essentially telling them not to clean up their objects. There are plenty of instances (especially when using an Event Bus and Thread Variables) where objects need to be cleaned up and unregistered for these types of systems. If you are using very simple pojos, then yes you don't need to do much. However, any remotely complex task needs to be evaluated for leaky objects as its the leading cause of issues in the community as it stands today. – dsutherland Jan 29 '16 at 17:18
  • Actually, a great deal of java objects require you to call a cleanup method on them. `Obj.open(...); Obj.close();` – iPherian Apr 25 '17 at 20:01