Spring ApplicationContext - 资源泄漏:'context'永远不会关闭

时间:2013-01-06 16:17:20

标签: java eclipse spring spring-mvc

在spring MVC应用程序中,我使用以下方法初始化其中一个服务类中的变量:

ApplicationContext context = 
         new ClassPathXmlApplicationContext("META-INF/userLibrary.xml");
service = context.getBean(UserLibrary.class);

UserLibrary是我在我的应用程序中使用的第三方实用程序。上面的代码为'context'变量生成警告。警告如下所示:

Resource leak: 'context' is never closed

我不明白警告。由于应用程序是一个Spring MVC应用程序,因此当我在应用程序运行时引用该服务时,我无法真正关闭/销毁上下文。警告试图告诉我的是什么?

17 个答案:

答案 0 :(得分:83)

由于应用程序上下文是ResourceLoader(即I / O操作),因此它消耗了需要在某个时刻释放的资源。它也是实现AbstractApplicationContext的{​​{1}}的扩展。因此,它有一个Closable方法,可以在try-with-resources statement中使用。

close()

你是否真的需要创建这个上下文是一个不同的问题(你链接到它),我不会对此发表评论。

当应用程序停止时,上下文是隐式关闭的,但这不够好。 Eclipse是对的,您需要采取措施为其他情况手动关闭它,以避免类加载器泄漏。

答案 1 :(得分:38)

close()未在ApplicationContext界面中定义。

安全摆脱警告的唯一方法是以下

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(...);
try {
    [...]
} finally {
    ctx.close();
}

或者,在Java 7中

try(ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(...)) {
    [...]
}

基本区别在于,由于您明确地实例化了上下文(即使用new),因此您知道要实例化的类,因此您可以相应地定义变量。

如果你没有实例化AppContext(即使用Spring提供的那个),那么就无法关闭它。

答案 2 :(得分:12)

简单的演员解决了这个问题:

((ClassPathXmlApplicationContext) fac).close();

答案 3 :(得分:6)

由于Application上下文具有ClassPathXmlApplicationContext的实例,因此它具有close()方法。我只需要运行appContext对象并调用close()方法,如下所示。

ApplicationContext appContext = new ClassPathXmlApplicationContext("spring.xml");
//do some logic
((ClassPathXmlApplicationContext) appContext).close();

这将修复资源泄漏警告。

答案 4 :(得分:4)

试试这个。你需要应用强制转换来关闭applicationcontext。

   ClassPathXmlApplicationContext ctx = null;
      try {
         ctx = new ClassPathXmlApplicationContext(...);
            [...]
             } finally {
              if (ctx != null)
                  ((AbstractApplicationContext) ctx).close();       
      }

答案 5 :(得分:3)

即使我有完全相同的警告,我所做的只是在主函数之外声明ApplicationContext private static和ta-da,问题已解决。

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();
    }
}

答案 6 :(得分:1)

将上下文向下转换为ConfigurableApplicationContext。

((ConfigurableApplicationContext)context).close();

答案 7 :(得分:1)

Object obj = context.getBean("bean");
if(bean instanceof Bean) {
    Bean bean = (Bean) obj;
}

在我的情况下,泄漏消失了

答案 8 :(得分:1)

这对我来说效果最好。

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());
    }
}

答案 9 :(得分:0)

对于ApplicationContext,您不能使用close()方法,因为该方法未定义int,而是可以使用:(ClassPathXmlApplicationContext(context)).close()

答案 10 :(得分:0)

它有一个简单的解决方案,只需将Core jar输入到此链接中给出的库中 [下载春季的核心jar文件] [1] [1]:https://static.javatpoint.com/src/sp/spcorejars.zip

答案 11 :(得分:0)

铸造是解决此问题的正确方法。 我在下面一行中遇到了同样的问题。 ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);

要解决该警告,只需将ctx对象向下投射,如下所示,然后将其关闭。 ((AnnotationConfigApplicationContext) ctx).close();

答案 12 :(得分:0)

是的,界面t没有ApplicationContext方法,因此我喜欢使用课程close()明确使用该AbstractApplicationContext方法,此处您也可以使用使用注释而不是close类型的Spring Application配置类。

XML

你的AbstractApplicationContext context = new AnnotationConfigApplicationContext(SpringAppConfig.class); Foo foo = context.getBean(Foo.class); //do some work with foo context.close(); 警告现在消失了。

答案 13 :(得分:0)

您将上下文设置为静态变量,这意味着上下文可用于类中的所有静态方法,而不再局限于main方法的范围。因此,该工具不能假设它应该在方法结束时关闭,因此它不再发出警告。

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();

       }
}

答案 14 :(得分:0)

import org.springframework.context.ConfigurableApplicationContext;

((ConfigurableApplicationContext)ctx).close();

答案 15 :(得分:0)

如果您使用 ClassPathXmlApplicationContext ,则可以使用

((ClassPathXmlApplicationContext) context).close();

关闭资源泄漏问题。

如果您使用 AbstractApplicationContext ,则可以使用close方法强制转换它。

((AbstractApplicationContext) context).close();

这取决于应用程序中使用的上下文类型。

答案 16 :(得分:-1)

方法关闭已添加到ConfigurableApplicationContext界面,因此您可以做的最好的方法是访问它:

ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
                "/app-context.xml");

// Use the context...

context.close();