In C++ we acquiring a resource in a constructor and release it in a destructor.
So when an exception rises in a middle of a function there will be no resource leak or locked mutexes or whatever.
AFAIK java classes don't have destructors. So how does one do the resource management in Java.
For example:
public int foo() {
Resource f = new Resource();
DoSomething(f);
f.Release();
}
How can one release resource if DoSomething throws an exception? We can't put try\catch blocks all over the code, can we?
Yes you can and should put try/catch/finally block around your code. In C# there is a shorthand "using" statement, but in Java you are stuck with:
public int foo() {
Resource f = new Resource();
try {
DoSomething(f);
}
finally {
f.Release();
}
}
This question dates to 2008 and therefore pertains to Java 6. Since then Java 7 has been released, which contains a new feature for Automatic Resource Management. For a more recent question that is relevant to Java 7 see this question:
java techniques for automatic resource release? "prompt cleanup"?
It is possible to factor out try/finally (and exception and algorithms) using the Execute around idiom. However the syntax is highly verbose.
public int foo() {
withResource(new WithResource() { public void run(Resource resource) {
doSomething(resource);
}});
}
...
public interface WithResource {
void run(Resource resource);
}
public static void withResource(WithResource handler) {
Resource resource = new Resource();
try {
handler.run(resource);
} finally {
resource.release();
}
}
This sort of thing makes more sense if you are abstracting more than try/finally. For instance, with JDBC you can execute a statement, loop through the results, close resources and wrap the exception.
If you want the using block get involved in the java closure debate :S
Sorry to disappoint you but in Java we do use try\catch\finally blocks a lot. And with "a lot", I mean A LOT. I do sometimes wish that Java has the C# using block. Most of the time you won't need to free up resources as Java's garbage collector will take care of that.
However exceptions do have their uses in making error handling a lot cleaner. You can write your own exceptions and catch them for whatever you are doing. No more returning arbitrary error codes to the user!
Related
I was asked this question in an interview.
There is a class, lets call it A. It has a default constructor and it initializes 2 different connections in its constructor.
Methods initDB & initSocket creates a DB connection and a socket connection and saves them in an instance field. They are just an example. They could also be file open or anything else.
Lets say a client instantiates an instance of this class. Now initDB executed successfully, but initSocket threw exception. So the object creation was aborted. But the DB connection was not closed prior to the exception. This resulted in a resource leak. How would I tackle this kind of resource leak?
E.g.
class A {
public A(){
this.dbConnection = initDB();
this.socketConnection = initSocket(); // throws exception
}
}
My initial answer was that I would not initialize these in constructor but in a separate init(). He countered by suggesting that this could be a legacy class, and I have been asked to maintain this. In which case I need to somehow clear the resource leak. How would I approach this problem?
I got stumped because instance creation threw an exception I lost any kind of reference to those connection fields. So I cannot call close() on them. But they will still be present in the OS level (this is my guess).
Note 1
As stated by Interviewer, I cannot change the behavior of the already written constructor. I can extend or do something around it, but cannot change the code.
Note 2
I think interviewer was not looking for explicitly any code that would handle this scenario. Would any JMX stuff help? I took a jibe at it & then we moved on. For those who think this is a very good question, I think interviewer knew this is not a general practice and probably would not be able to answer.
We have a few options here...
Box the thing off somewhere else. It's clearly problematic legacy code. Perhaps this "blob" which has access control issues can be moved into something some other process that can communicate with the rest of the system via RPC. You are better off doing this if the system is horribly broken. You can extend it other ways, such as composition; but if it's so sealed off you can't get it it, then you're boned
Use byte code modification. You could do this and you could get enough leverage to get what you need. ByteBuddy would come in handy for this. I wouldn't do this personally but hey, sometimes desperate measures call for desperate solutions...
If you can influence initDB, then you can decorate the return value with something else. For example, let's supposed it was some from some base class we did control or some other method we controlled, then we could perhaps do something like this
Connection initDb() {
try {
this.wrappedProvider.initDb();
} catch(Exception e) {
// .. destroy the connection...
}
}
... and then since you can influence this, you can change the effective semantics of it.
Can you influence the "Connection" of "A"? How does it get "A"? If it gets it from some DI container or something you can influence, then you can sub out the implementation for that class for something that "times out" if not talked to or initialized in some given time. Hacky, sure but without more info that's the best we're going to get...
Solution 1:
Provided that:
You can extend class A, and then use instances of class B instead,
method initSocket is overridable (not final nor private)
field dbConnection is accessible from class B (not private)
You can override method initSocket to close the dbConnection in case of an exception:
#Override
protected Socket initSocket() {
boolean ok = false;
try {
Socket result = super.initSocket();
ok = true;
return result;
} finally {
if (!ok) {
dbConnection.close();
}
}
}
Solution 2:
Provided that:
You can extend class A
method initDb is overridable (not final nor private)
You can wrap your A object in another class, and save the connection so that it can be closed in case of an exception:
class B {
private static ThreadLocal<Connection> CONNECTION = new ThreadLocal<>();
private final A delegate;
public B() {
boolean ok = false;
try {
delegate = new A() {
#Override
protected Connection initDb() {
Connection result = super.initDb();
CONNECTION.set(result);
return result;
}
};
ok = true;
} finally {
if (!ok) {
Connection cnt = CONNECTION.get();
if (cnt != null) {
cnt.close();
}
}
CONNECTION.set(null);
}
}
}
Q1 : (removed)
Q2 : try-with-resource to create own resource implement AutoCloseable interface and override close() method.
From javadoc
Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.
So, here I created a simple program MyAuto.java
class Demo implements AutoCloseable {
public void show() {
System.out.println("show");
}
public void close() {
System.out.println("close from demo");
}
}
class MyAuto {
public static void main(String[] args) {
try(Demo d = new Demo()) {
int x = 10/0;
d.show();
}catch(ArithmeticException e) {
System.out.println(e);
}
}
}
This program runs fine. :) and giving output
close from demo : as expected, no matters exception occurs, d will be closed.
But my question is I didn't write any code that close this resource, I simply put a print statement. What here actually closing a resource mean ? Assigning null to reference variable of resource or anything else ?
Or JVM runs any other method after running close() behind the scene.
And finally the most important question..
Q3 : In the above scenario if I add my own interface AutoCloseable
interface AutoCloseable {
void close() throws Exception;
}
It gives compile time error on compiling MyAuto.java
error: incompatible types: try-with-resources not applicable to variable type
try(Demo d = new Demo()) {
^
(Demo cannot be converted to AutoCloseable).
So, please give me answer why it's happening. Why can't we create and use our own Interfaces instead of provided by java. What is difference between my interface and the one predefined, although both are same.
What is difference between my interface and the one predefined, although both are same.
They're not the same. Not by a long shot.
The AutoCloseable required for try-with-resources is java.lang.AutoCloseable. Your custom AutoCloseable doesn't come from that package, so Java isn't going to respect it.
Above all, introducing that would not be the best approach, since it'll only lead to confusing semantics and a bad experience later down the road, even if you elected to have your interface extend java.lang.AutoCloseable for whatever reason.
In the same vein...
...I didn't write any code that close this resource, I simply put a print statement. What here actually closing a resource mean ? Assigning null to reference variable of resource or anything else ? Or JVM runs any other method after running close() behind the scene.
The interface can't enforce anything like that. All it can do is provide a mechanism that, if well-implemented, will behave as you expect.
Up front: I'm a C# guy doing Java right now. Some of these frustrations come from my lack of knowledge of Java.
First, is there a way to have a "safe" AutoCloseable implementation that does not require the Exception to be checked? If I'm implmementing my own class that won't throw from its close method, I don't see why I have to check it.
Second, is there a way to simplify the expression in the try statement where I don't care what's returned? For instance in C# I can do this:
using (new Disposable())
{
// yay!
}
and Java seems to force me to assign it to a temporary variable:
try (AutoCloseable iDontCare = getAutoCloseable()) {
// dont you dare use iDontCare
}
I wish I could simplify the Java to
try (getAutoCloseable()) {
// yay!
}
C# isn't quite Java; this is one of those gotchas you'll have to deal with going forward.
First, is there a way to have a "safe" AutoCloseable implementation that does not require the Exception to be checked? If I'm implmementing my own class that won't throw from its close method, I don't see why I have to check it.
You have to because it's mandated by the interface. Not just that, but it throws a checked exception, which does have to be handled at some level.
If you know for a fact that your code will never throw any kind of exception, you could still place the throwing of the exception in some kind of guaranteed-not-to-be-executed-block inside of your implemented close method. Or, implement your own interface which extends AutoCloseable and overrides close to not throw an exception.
Your first question:
Yes. You can implement AutoCloseable.close without the throws Exception part if your implementation doesn't throw checked exceptions.
Your second question:
No. The try with resources statement requires that variable. You can rename it to something like ignored or unused to make that clear.
final class Test implements AutoCloseable {
#Override
public void close() {
System.out.println("Closing");
}
public static void main(String[] args) {
try (Test ignored = new Test()) {
System.out.println("Not using ignored");
}
}
}
Makoto's answer does a nice job of addressing the first part of your question, so I'll attempt to address the second.
I think what you want is a try (without resources). For example:
try {
//yay!
} finally {
// always executed
}
The finally block will execute regardless of whether an exception is thrown or not.
Edit:
If you don't need anything to execute, you could just declare a new block
{
//yay!
}
How can I detect when an Exception has been thrown anywhere in my application?
I'm try to auto-magically send myself an email whenever an exception is thrown anywhere in my Java Desktop Application. I figure this way I can be more proactive.
I know I could just explicitly log and notify myself whenever an exception occurs, but I'd have to do it everywhere and I might(more likely will) miss a couple.
Any suggestions?
You probobly don't want to mail on any exception. There are lots of code in the JDK that actaully depend on exceptions to work normally. What I presume you are more inerested in are uncaught exceptions. If you are catching the exceptions you should handle notifications there.
In a desktop app there are two places to worry about this, in the event-dispatch-thread (EDT) and outside of the EDT. Globaly you can register a class implementing java.util.Thread.UncaughtExceptionHandler and register it via java.util.Thread.setDefaultUncaughtExceptionHandler. This will get called if an exception winds down to the bottom of the stack and the thread hasn't had a handler set on the current thread instance on the thread or the ThreadGroup.
The EDT has a different hook for handling exceptions. A system property 'sun.awt.exception.handler' needs to be registerd with the Fully Qualified Class Name of a class with a zero argument constructor. This class needs an instance method handle(Throwable) that does your work. The return type doesn't matter, and since a new instance is created every time, don't count on keeping state.
So if you don't care what thread the exception occurred in a sample may look like this:
class ExceptionHandler implements Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e) {
handle(e);
}
public void handle(Throwable throwable) {
try {
// insert your e-mail code here
} catch (Throwable t) {
// don't let the exception get thrown out, will cause infinite looping!
}
}
public static void registerExceptionHandler() {
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());
System.setProperty("sun.awt.exception.handler", ExceptionHandler.class.getName());
}
}
Add this class into some random package, and then call the registerExceptionHandler method and you should be ready to go.
The new debugging hooks in Java 1.5 let you do this. It enables e.g. "break on any exception" in debuggers.
Here's the specific Javadoc you need.
Check out Thread.UncaughtExceptionHandler. You can set it per thread or a default one for the entire VM.
This would at least help you catch the ones you miss.
If you're using a web framework such as Spring then you can delegate in your web.xml to a page and then use the controller to send the email. For example:
In web.xml:
<error-page>
<error-code>500</error-code>
<location>/error/500.htm</location>
</error-page>
Then define /error/500.htm as a controller. You can access the exception from the parameter javax.servlet.error.exception:
Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception");
If you're just running a regular Java program, then I would imagine you're stuck with public static void main(String[] args) { try { ... } catch (Exception e) {} }
If you are using java 1.3/1.4, Thread.UncaughtExceptionHandler is not available.
In this case you can use a solution based on AOP to trigger some code when an exception is thrown. Spring and/or aspectJ might be helpful.
In my current project I faced the similar requirement regarding the errors detection. For this purpose I have applied the following approach: I use log4j for logging across my app, and everywhere, where the exception is caught I do the standard thing: log.error("Error's description goes here", e);, where e is the Exception being thrown (see log4j documentation for details regarding the initialization of the "log").
In order to detect the error, I use my own Appender, which extends the log4j AppenderSkeleton class:
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;
public class ErrorsDetectingAppender extends AppenderSkeleton {
private static boolean errorsOccured = false;
public static boolean errorsOccured() {
return errorsOccured;
}
public ErrorsDetectingAppender() {
super();
}
#Override
public void close() {
// TODO Auto-generated method stub
}
#Override
public boolean requiresLayout() {
return false;
}
#Override
protected void append(LoggingEvent event) {
if (event.getLevel().toString().toLowerCase().equals("error")) {
System.out.println("-----------------Errors detected");
this.errorsOccured = true;
}
}
}
The log4j configuration file has to just contain a definition of the new appender and its attachement to the selected logger (root in my case):
log4j.rootLogger = OTHER_APPENDERS, ED
log4j.appender.ED=com.your.package.ErrorsDetectingAppender
You can either call the errorsOccured() method of the ErrorsDetectingAppender at some significant point in your programs's execution flow or react immidiately by adding functionality to the if block in the append() method. This approach is consistent with the semantics: things that you consider errors and log them as such, are detected. If you will later consider selected errors not so important, you just change the logging level to log.warn() and report will not be sent.
In this case I think your best bet might be to write a custom classloader to handle all classloading in your application, and whenever an exception class is requested you return a class that wraps the requested exception class. This wrapper calls through to the wrapped exception but also logs the exception event.
I assume you don't mean any Exception but rather any uncaught Exception.
If this is the case this article on the Sun Website has some ideas. You need to wrap your top level method in a try-catch block and also do some extra work to handle other Threads.
Sending an email may not be possible if you are getting a runtime exception like OutOfMemoryError or StackOverflow. Most likely you will have to spawn another process and catch any exceptions thrown by it (with the various techniques mentioned above).
There is simply no good reason to be informed of every thrown exception. I guess you are assuming that a thrown exception indicates a "problem" that your "need" to know about. But this is wrong. If an exception is thrown, caught and handled, all is well. The only thing you need to be worried about is an exception that is thrown but not handled (not caught). But you can do that in a try...catch clause yourself.
Update: As #PaulGroke points out below, things have changed with Java 7: there now is AutoCloseable. Which isn't tied to streams and supported by the new try-with-resources construct.
AutoCloseable is the direct Java equivalent for .NET's IDisposable interface.
The Closeable interface introduced in Java 1.5 is tightly tied to streams, and even has an exception specifier for IOException. This suggests that it should only be used for streams or other IO related activities, rather than general purpose cleanup logic.
Certainly the description for the close() method would make absolutely no sense outside of a stream/IO context:
void close() throws IOException
Closes this stream and releases any system resources associated with it.
Should I therefore declare my own interface, Disposable, with a Dispose() method on it, and use that as an analogue to .NET's IDisposable interface? Or should I re-use Closeable even though it may not be a perfect fit?
I'm sure most people are aware of it, but since this question is still among the top results when searching for "IDisposable Java" (#2 result for me just now), and it's still not mentioned here...
Things have changed with Java 7: there now is AutoCloseable. Which isn't tied to streams and supported by the new try-with-resources construct.
Especially given that close() throws an IOException you then have to write exception handling code for, I would advise you write your own interface. This interface can then throw any checked exceptions that are appropriate to the use you want to put the interface to.
Interfaces tend to signify intent in the mind of the reader, so having a class implement an IO-associated Closeable interface will make the reader assume the class is also IO-based.
Obviously, if the objects you do want to close are all IO-related, you should use Closeable. But otherwise go for
/** Interface for objects that require cleanup post-use. Call dispose() in finally block! */
public interface Disposable {
public void dispose();
}
When implementing Closeable (or AutoClosable for that matter) in a class it's also possible to just omit the throws declaration:
class X implements Closeable {
#Override public void close() /* I don't throw */ {
}
}
So when someone is using a typed object they can call close() without having to catch anything:
void f() { // notice no need for throws because close() doesn't throw
X x = new X();
try {
// do something
} finally {
x.close();
}
}
It is also compatible with anything expecting a Closeable: if this object is passed into somewhere that handles Closeable, they already anticipate an exception and handle it correctly, albeit futilely in this case.
This includes libraries like Guava Closeables and Java 7 try-with-resources as Paul Groke suggests:
try (X x = new X()) {
// do something
}
There's a rare caveat though: you can't reintroduce the exception in child-classes once it's stripped:
class Y extends X {
/* compile error */
#Override public void close() throws IOException {
// Y.close clashes with X.close: overridden method does not throw IOException
}
}