在运行时加载驱动程序jar文件导致Perm Gen Space Error

时间:2014-11-17 14:52:37

标签: java tomcat permgen urlclassloader

我创建了一个REST服务,我在运行时加载JDBC驱动程序jar。以下是执行此操作的代码:

Driver driverInstance;
URLClassLoader driverClassLoader;
driverClassLoader = new URLClassLoader (new URL[] { "c:/mysql.jar" }, System.class.getClassLoader());
Class<?> driverClass = driverClassLoader.loadClass("oracle.jdbc.driver.OracleDriver");
Connection conn = driverInstance.connect(connectionString, userDbCredentials);

使用此连接将数据加载到数据库后,我将关闭连接 driverClassLoader 。但经过一段时间后,我得到了 tomcat服务器中的 java.lang.OutOfMemoryError:PermGen space

我接受了堆转储,并使用eclipse Memory Analyzer打开它,我发现下面的Leak可疑消息: “org.apache.catalina.loader.WebappClassLoader”的13个实例,由“java.net.URLClassLoader @ 0xc155fc10”加载,占用14,083,776(32.21%)字节

据我所知,这是由于在运行时加载了驱动程序jar,但我无法找到解决方案。

1 个答案:

答案 0 :(得分:0)

加载JDBC驱动程序类时,它会将自己注册为java.sql.DriverManager。即使您尝试将系统类加载器作为URLClassLoader的父级,我相信它会从AccessControlContext继承WebappClassLoader,从而引用它。使用Eclipse Memory Analyzer(MAT)分析引用可以帮助验证 - see this blog post for instructions

假设JDBC驱动程序实际上是泄漏源,您的问题的解决方案是调用java.sql.DriverManager.deregisterDriver()以显式注销驱动程序,最好是contextDestroyed() ServletContextListener }。

通常情况下,您可以让我的ClassLoader leak prevention library负责取消注册,但是由于驱动程序是在一个单独的类加载器中加载的,因此它无法开箱即用。但是,您可以进行一些子类化/修改。这样做的好处是可以免费获得更多的防漏保护。

您是否真的想要并且需要在运行时从应用程序外部加载驱动程序 - 嗯,这是一个单独的问题......

祝你好运!