Jim*_*Jim 5 multithreading tomcat servlets log4j web-applications
我试图在关闭 Tomcat 时关闭线程。
具体来说,我正在尝试关闭 log4j 看门狗(用于文件更改),并且我正在尝试关闭使用我的 Web 应用程序中的类的执行程序。
关闭时,我在 Catalina.out 中看到异常。
对于 Log4J,我看到:
信息:非法访问:此 Web 应用程序实例已停止
。无法加载 org.apache.log4j.helpers.NullEnumeration。
最终的后续堆栈跟踪是由出于
调试目的抛出的错误以及尝试终止
导致非法访问的线程引起的,并且没有功能影响。Throwable
发生:java.lang.IllegalStateException
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1587)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1546)
at org.apache .log4j.Category.getAllAppenders(Category.java:413)
在 org.apache.log4j.Category.closeNestedAppenders(Category.java:226)
在 org.apache.log4j.Hierarchy.shutdown(Hierarchy.java:467)
在 org.apache.log4j.LogManager.shutdown(LogManager.java:267) )
在 com.listeners.myListener$1.run(myListener.java:232)
线程“Thread-14”中的异常 java.lang.NoClassDefFoundError:
org.apache.log4j.helpers.NullEnumeration
在 org.apache.log4j.Category.getAllAppenders (Category.java:413)
at org.apache.log4j.Category.closeNestedAppenders(Category.java:226)
at org.apache.log4j.Hierarchy.shutdown(Hierarchy.java:467)
at org.apache.log4j.LogManager。关机(LogManager.java:267)
对于执行者部分:
信息:非法访问:此 Web 应用程序实例已停止
。无法加载 com.my.class.SomeClass。最终的
后续堆栈跟踪是由出于调试
目的抛出的错误以及尝试终止导致
非法访问的线程引起的,并且没有功能影响。Throwable发生:
java.lang.IllegalStateException
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1587)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1546)
at Exception in thread “线程 13” java.lang.NoClassDefFoundError:
com.my.class.SomeClass
我做的是ServletContextListener在contextDestroyed我加入关闭挂钩如下:
public void contextDestroyed(ServletContextEvent arg0) {
Runtime.getRuntime().addShutdownHook(new Thread(){
@Override
public void run(){
LogManager.shutdown();
}
});
}
public void contextDestroyed(ServletContextEvent arg0) {
Runtime.getRuntime().addShutdownHook(new Thread(){
@Override
public void run(){
SomeClass.updater.shutdown();
}
});
}
Run Code Online (Sandbox Code Playgroud)
我在这里做错了什么?为什么会出现异常?
更新:
SomeClass.updater是一个public static ScheduledExecutorService.
LogManager是org.apache.log4j.LogManager
UPDATE2:
按照 BGR 的回答后,我直接做
public void contextDestroyed(ServletContextEvent arg0) {
SomeClass.updater.shutdown();
}
Run Code Online (Sandbox Code Playgroud)
和
public void contextDestroyed(ServletContextEvent arg0) {
LogManager.shutdown();
}
Run Code Online (Sandbox Code Playgroud)
我没有从 Log4j 得到异常,但我得到以下异常,SomeClass.updater它是一个public static ScheduledExecutorService:
信息:非法访问:此 Web 应用程序实例已停止
。无法加载 java.util.concurrent.ExecutorService。该
最终以下堆栈跟踪被抛出的错误造成的
调试目的,以及试图终止该线程
引起的非法访问,并没有功能的影响。Throwable
发生:
在 org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1587)
在 org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1546) 的 java.lang.IllegalStateException
为什么?这些类是否已经被垃圾收集了?
我会在 servlet 的 init() 方法中注册 shutdown hooks,而不是 contextDetroyed(),但无论如何,为什么首先需要 Shutdown hooks?
SomeClass.updater.shutdown();直接在contextDestroyed()方法中调用不行吗?
编辑
contextDestroyed()侦听器的执行器服务太迟了。正如 javadoc 中所述,在任何 ServletContextListener 收到上下文销毁通知之前,所有 servlet 和过滤器都将被销毁。
destroy()而根据 javadoc重写 servlet应该没问题。此方法使 servlet 有机会清理所持有的任何资源(例如,内存、文件句柄、 线程...
@Override
public void destroy( ) {
myThreadExecutor.shutdown();
super.destroy( );
}
Run Code Online (Sandbox Code Playgroud)