因此,我们必须使用的Log4j这样我们的J2EE应用程序
public class CustomerController
{
private static Logger logger = Logger.getLogger(CustomerController.class);
public CustomerService customerservice = null;
public CustomerController() throws Exception
{
PropertyConfigurator.configureAndWatch("c:\log4j.property", 50000);
customerservice = ServiceManagerSingleton.getCustomerServiceInstance();
}
}
这样我们就可以更改日志级别的实时。 非常便利。 我们的大部分课程都设置了,就像该控制器。 我们使用单例模式让我们只有eash类的一个实例; 一个调用PropertyConfigurator.configureAndWatch()为每类一次。
问题:一个星期两次关于我们的应用服务器死亡,并创建一个堆转储。 从IBM使用堆分析我们可以看出,似乎有很多相关的Log4j的线程:
808 (0%) [200] 9 org/apache/log4j/PropertyWatchdog 0x14282ad8
关于30,000总。 因此,这是可能的突然崩溃的原因。
- 我们是否正确设置此功能?
- 当EAR重新部署碰巧所有这些线程是什么?
真的是你需要做的是使用你的应用程序服务器的启动程序(它们都是不同的)来初始化log4j的系统。 因为Log4j的依赖于静态变量,它不能真正独立在自己的耳边工作(它那种可以,但真的会依赖于应用程序服务器上)。 在大多数情况下,配置是真的要成为全球整个应用程序服务器。
你需要确保PropertyConfigurator.configureAndWatch方法只调用一次。 要做到这一点的方法之一是把东西在JNDI。
很多这将取决于哪些应用服务器是给你的。 例如,我们使用JBoss和Log4J的配置为它的一部分,而你只是改变的log4j.xml文件,包括你的类所需要的。 JBoss的保证,它是动态的。
编辑: 这是为WebSphere创建自定义服务的指示,和里面,你会创造你的log4j的配置,并做好你该文件的监控。 需要注意几个问题。 你将不得不在程序中添加log4j.jar应用服务器本身的类路径,使其可用于战争或耳(我敢肯定,将工作,反正),和定制服务很可能不会耳内工作。
这里是将保持在战争或耳一切,但在动态加载更改日志为代价的替代品。
CustomerController实例多久产生的? 一旦每个请求的? 因为我相信,到configureAndWatch()将产生每个调用一个新的线程。
另外,如果你不知道, log4j的文档告诫不要使用此功能在J2EE环境:
由于发射到configureAndWatch单独wathdog线程,因为没有办法阻止这个线程log4j的1.2,该方法到configureAndWatch是不安全的在J2EE环境中使用的应用程序被回收。
我知道你不使用Spring,但在我看来Spring类Log4jWebConfigurer 有一个更好的解释为什么这个功能在J2EE危险:
警告:Log4j的看门狗线程不会终止,直到VM停机; 特别是,它并没有在日志管理关机终止。 因此,建议不要使用配置文件在生产J2EE环境令人耳目一新; 看门狗线程不会在应用程序关闭停在那里。
更新:看看log4j的来源,每次调用到configureAndWatch()确实创造一个新的线程 。
所有记录共享相同的配置文件,所以如果每一个使用记录器类包含此intialization代码,每个到configureAndWatch()调用可能会催生新的观察者线程。 (恕我直言,Log4j的应该知道更好,允许每个配置文件最多一个观察者主题,但显然事实并非如此)
你看的logback,log4j的继任者? 它涉及重载它的配置无论是在线程或通过JMX 。 这两种方法都避免通过调用PropertyConfigurator.configureandWatch()或DOMConfigurator.configurator头痛。 正如有趣的是,通过一个配置文件(不需要自定义代码)使螺纹的方法。