These "resource leak" warnings I'm getting in Eclipse for AutoCloseables seem to be a life-saver.
However, how do I get them to work for factory created instances?
For example (a works, but b doesn't):
public static void main(String[] args) {
// a) This emits a warning
new AutoCloseable() {
#Override
public void close() throws Exception {}
};
// b) But this doesn't!
newResource();
}
public static AutoCloseable newResource() {
return new AutoCloseable() {
#Override
public void close() throws Exception {}
};
}
Is there an annotation I can stick on newResource() or something I can do to let the compiler (or is it Eclipse?) know of the ownership change?
The Neon Eclipse documentation on "resource leak" detection explains what is going on; see "avoiding resource leaks". It states:
Ownership / responsibility
The above diagnostics basically assume that a method that creates an
instance of a resource type is also responsible for closing this
resource. However, some resources will be shared among several
methods. Here the analysis makes the following assumptions:
If a method returns a resource to its caller, it is not responsible for closing; no problem is reported.
If a resource is stored in a field, no single method is considered as responsible for closing; no problem is reported.
If a method obtains a resource via a method call rather than by a new expression, it may or may not be responsible; any problems are
only flagged as potential resource leaks.
If a resource is passed as an argument in a method call or constructor call, the current method may or may not be responsible;
any problems are only flagged as potential resource leaks.
Point #1 explains why there is no "resource leak" warning for the return statement in the newResource method.
Point #3 explains why there is no "resource leak" warning for the newResource() call. At best, it would be a "potential resource leak" warning. Either you have those warnings disabled, or the previous warning is inhibiting it.
Q: Is there an annotation to tell Eclipse about transfer of resource ownership?
A: The Neon Eclipse documentation doesn't mention any such annotation. (And it does go into detail about the annotations for null checking!)
Related
When using Spring Retry #Recover method (which works ok) IntelliJ always marking method as unused and suggest to safe delete
#Recover
public void recover(RetryableException e, String param1) {
//recover
}
#Retryable(include = RetryableException.class, maxAttempts = 2)
public void retryable(String param1) {
//execute
throw new RetryableException();
}
Method 'recover(com.gth.common.exceptions.RetryableException, java.lang.String)' is never used
How can it be avoided? how can IntelliJ be aware of the recover method usage?
I don't want IntelliJ to stop warn about Unused declaration, only the false positive warnings
Method declarations looks ok but as you haven't shared any further details, it is mostly because you are not throwing RetryableException from your retryable method.
To invoke recovery after retries, your retry must throw type of exception which you have defined as recover method's argument. Please check about that , if that is not case, please share some more details.
Edit:
Spring's recovery method gets called internally after retry & hence after scanning code, intellij didn't find any reference where your recover is getting called.
This is just warning from intellij & don't pose any issue. You can disable this behaviour from Preferences > Editor > Inspections > Unused Declaration >Java > Unused declaration .
Other option is to use #SuppressWarnings("unused") above your recover.
logEvent.getContextData().size() == 0 and logEvent.getContextStack().size() == 0 but otherwise the attributes of the LogEvent are fine in:
public class MyAppender extends AbstractAppender {
.........
#override
public void append(LogEvent ev) {
ev.getDataContext().size(); // <=== how can this equals 0?
ev.getStackContext().size(); // <=== how can this equals 0?
....
}
}
I cannot figure-out why this is the case. Do I need to create an AbstractConverter? AbstractFilter? Is my log4j2.xml or maybe the plugin config wrong?
Based on our discussion in the comments, it looks like what you're actually after is the location information. In a custom appender, this can be obtained by walking the stack trace provided by LogEvent.getSource(). You should be aware that obtaining this information is expensive though (see the documentation).
Edit
As you've stated, location information can be very useful, so it's a shame that it's expensive to obtain. Unfortunately, there's nothing Log4J can do about that - it's down to java's architecture.
One cheaper method that's commonly used to obtain the class name at least, is to ensure that the Logger being logged to is named after the class in which it's used (see documentation here). Then, you can obtain the class name in an appender by calling LogEvent.getLoggerName(). Note, however, that if you're writing a general Appender implementation that may be reused across several projects, it would be bad practice to assume that this would always be the calling class's name. Instead, it should be interpreted as "the functional context that the logging call came from, as determined by the application".
In Java documentation for a static method URL.setURLStreamHandlerFactory, there is a warning that "This method can be called at most once in a given Java
Virtual Machine".
http://docs.oracle.com/javase/7/docs/api/java/net/URL.html#setURLStreamHandlerFactory(java.net.URLStreamHandlerFactory)
I briefly looked at the source code, and there is a one static instance variable in URL class:
static URLStreamHandlerFactory factory;
and setURLStreamHandlerFactory is merely assigning the factory to this variable:
public static void setURLStreamHandlerFactory(URLStreamHandlerFactory fac) {
synchronized (streamHandlerLock) {
if (factory != null) {
throw new Error("factory already defined");
}
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkSetFactory();
}
handlers.clear();
factory = fac;
}
}
Allowing this method to be called multiple times would result in overwriting this factory instance variable, but I don't see WHY Java would want to prevent this behavior.
WHY does Java require that this method can be called only once per JVM?
There seem to be no precise reason.
Interestingly, the Eclipse "Runnable JAR File Exporter" functionality registers a custom URLStreamHandlerFactory named RsrcURLStreamHandlerFactory.
URLStreamHandlerFactory itself wraps an other URLStreamHandlerFactory and provides a method setURLStreamHandlerFactory to overwrite it. Quoting from the method's docs:
Allow one other URLStreamHandler to be added.
URL.setURLStreamHandlerFactory does not allow
multiple factories to be added.
The chained factory is called for all other protocols,
except "rsrc". Use null to clear previously set Handler.
This setURLStreamHandlerFactory can be called multiple times and should provide some evidence of the fact that changing the handler should not cause any strange behaviour.
Even more Interestingly, I spotted a 1998 JDK feature request on the fact that setURLStreamHandlerFactory should be allowed to be called multiple times so that several handlers could be chained together. The feature request was resolved as Future Project but evidently was never implemented.
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.
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!