Spring ApplicationContext - Resource leak: 'context' is never closed
JavaEclipseSpringSpring MvcJava Problem Overview
In a spring MVC application, I initialize a variable in one of the service classes using the following approach:
ApplicationContext context =
new ClassPathXmlApplicationContext("META-INF/userLibrary.xml");
service = context.getBean(UserLibrary.class);
The UserLibrary is a 3rd party utility which I am using in my application. The above code generates a warning for the 'context' variable. The warning is shown below:
Resource leak: 'context' is never closed
I don't understand the warning. As the application is a Spring MVC application, I can't really close/destroy the context as I refer to the service while the application is running. What exactly is the warning trying to tell me?
Java Solutions
Solution 1 - Java
Since the app context is a ResourceLoader
(i.e. I/O operations) it consumes resources that need to be freed at some point. It is also an extension of AbstractApplicationContext
which implements Closable
. Thus, it's got a close()
method and can be used in a try-with-resources statement.
try (ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("META-INF/userLibrary.xml")) {
service = context.getBean(UserLibrary.class);
}
Whether you actually need to create this context is a different question (you linked to it), I'm not gonna comment on that.
It's true that the context is closed implicitly when the application is stopped but that's not good enough. Eclipse is right, you need to take measures to close it manually for other cases in order to avoid classloader leaks.
Solution 2 - Java
close()
is not defined in ApplicationContext
interface.
The only way to get rid of the warning safely is the following
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(...);
try {
[...]
} finally {
ctx.close();
}
Or, in Java 7
try(ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(...)) {
[...]
}
The basic difference is that since you instantiate the context explicitly (i.e. by use of new
) you know the class you are instantiating, so you can define your variable accordingly.
If you were not instantiating the AppContext (i.e. using the one provided by Spring) then you couldn't close it.
Solution 3 - Java
A simple cast solves the issue:
((ClassPathXmlApplicationContext) fac).close();
Solution 4 - Java
As the Application context has an instance of ClassPathXmlApplicationContext and the same has a close() method. I would simply CAST the appContext object and invoke the close() method as below.
ApplicationContext appContext = new ClassPathXmlApplicationContext("spring.xml");
//do some logic
((ClassPathXmlApplicationContext) appContext).close();
This will fix the Resource Leak warning.
Solution 5 - Java
try this. you need to apply cast to close applicationcontext.
ClassPathXmlApplicationContext ctx = null;
try {
ctx = new ClassPathXmlApplicationContext(...);
[...]
} finally {
if (ctx != null)
((AbstractApplicationContext) ctx).close();
}
Solution 6 - Java
Even I had the exact same warning, all I did was declare ApplicationContext
outside the main function as private static
and ta-da, problem fixed.
public class MainApp {
private static ApplicationContext context;
public static void main(String[] args) {
context = new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld objA = (HelloWorld) context.getBean("helloWorld");
objA.setMessage("I'm object A");
objA.getMessage();
HelloWorld objB = (HelloWorld) context.getBean("helloWorld");
objB.getMessage();
}
}
Solution 7 - Java
Downcast the context to ConfigurableApplicationContext.
((ConfigurableApplicationContext)context).close();
Solution 8 - Java
Casting is the correct resolution for this issue.
I faced the same issue using the below line.
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
To resolve the warning just downcast the ctx
object like below and then close it.
((AnnotationConfigApplicationContext) ctx).close();
Solution 9 - Java
Object obj = context.getBean("bean");
if(bean instanceof Bean) {
Bean bean = (Bean) obj;
}
In my case leak disappears
Solution 10 - Java
This worked out best for me.
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
private static ApplicationContext con;
public static void main(String[] args) {
con = new ClassPathXmlApplicationContext("config.xml");
Employee ob = (Employee) con.getBean("obj");
System.out.println("Emp Id " + ob.getEmpno());
System.out.println("Emp name " + ob.getEmpname());
}
}
Solution 11 - Java
If you are using the ClassPathXmlApplicationContext then you can use
((ClassPathXmlApplicationContext) context).close();
to close the resource leak problem.
If you are using the AbstractApplicationContext then you can cast this with close method.
((AbstractApplicationContext) context).close();
It depends on the type of context using in the application.
Solution 12 - Java
import org.springframework.context.ConfigurableApplicationContext;
((ConfigurableApplicationContext)ctx).close();
Solution 13 - Java
You make the context a static variable, which means that the context is available to all the static methods in the class, and not limited to the scope of the main method anymore. So the tool can't assume that it should be closed at the end of the method anymore, so it doesn't issue the warning anymore.
public class MainApp {
private static ApplicationContext context;
public static void main(String[] args) {
context =
new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
}
}
Solution 14 - Java
Yes, interface ApplicationContext
doesn't have close()
method, so I like to use class AbstractApplicationContext
to use that close
method explicitly and also here you can use your Spring Application configuration class using annotation instead of XML
type.
AbstractApplicationContext context = new AnnotationConfigApplicationContext(SpringAppConfig.class);
Foo foo = context.getBean(Foo.class);
//do some work with foo
context.close();
your Resource leak: 'context' is never closed
warning is gone now.
Solution 15 - Java
it has a simple solution just input the Core jar into the libraries, given at this link [download the core jar files for spring][1] [1]: https://static.javatpoint.com/src/sp/spcorejars.zip
Solution 16 - Java
for ApplicationContext you can't use close() method because this method doesn't define int it but instead you can use:(ClassPathXmlApplicationContext(context)).close()
Solution 17 - Java
The method close has been added to ConfigurableApplicationContext interface, so the best you can do to get access to it is:
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
"/app-context.xml");
// Use the context...
context.close();