2014-11-17 7 views
0

런타임시 JDBC 드라이버 jar를로드하는 REST 서비스를 만들었습니다.런타임시 드라이버 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을 모두 폐쇄하고 : 다음은이 작업을 수행하는 코드이다. 그러나 얼마 동안 그것을 실행 한 후에 나는 java.lang.OutOfMemoryError : PermGen space을 tomcat 서버에 가지고 있습니다.

나는 힙 덤프를했다, 그리고 이클립스 메모리 분석기를 사용하여 열고 그 아래 누출 의심되는 메시지를 발견 : "org.apache.catalina.loader.WebappClassLoader"의 13 인스턴스 java.net "에 의해로드를 .URLClassLoader @ 0xc155fc10 "은 14,083,776 (32.21 %) 바이트를 차지합니다. 런타임시 드라이버 jar의로드로 인한 것으로 알고 있지만 해결 방법을 찾을 수 없습니다.

+0

드라이버가 tomcat의 libs/폴더에 있습니까? – nablex

+0

아니요, 외부 경로에서 읽습니다. – sf9251

+0

코드가 정확히 어디에서 실행됩니까? 클래스 로더 생성은 드라이버 당 한 번만 수행됩니까? 아니면 특정 호출이 완료 될 때마다 수행됩니까? – Gimby

답변

0

JDBC 드라이버 클래스를로드하면 java.sql.DriverManager으로 등록됩니다. 시스템 클래스 로더를 부모 URLClassLoader의 부모로 만들려고해도 나는 WebappClassLoader에서 AccessControlContext을 상속받을 것이므로 참조해야합니다. Eclipse Memory Analyzer (MAT)를 사용하여 참조를 분석하면 - see this blog post for instructions을 확인할 수 있습니다.

사실 JDBC 드라이버가 실제로 누출의 원인이라고 가정하면 문제의 해결책은 java.sql.DriverManager.deregisterDriver()으로 전화하여 명시 적으로 드라이버 등록을 취소하는 것이 좋습니다. contextDestroyed()이 바람직하고 ServletContextListener입니다.

일반적으로 내 ClassLoader leak prevention library은 등록 취소를 처리 할 수 ​​있지만 드라이버는 별도의 클래스 로더에로드되어 있으므로 상자에서 작동하지 않습니다. 그러나 서브 클래 싱/수정 작업을 수행 할 수는 있습니다. 이점은 더 많은 누출 방지 기능을 무료로 제공한다는 것입니다.

당신이 정말로 원하는 런타임에 응용 프로그램 외부에서 드라이버를로드 할 필요 여부

- 운이 아니라, 그 별도의 질문은 ...

좋은!