3월 23, 2019 10:13:55 오후 org.apache.catalina.loader.WebappClassLoaderBase clearReferencesJdbc

경고: The web application [ROOT] registered the JDBC driver [net.sf.log4jdbc.sql.jdbcapi.DriverSpy] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.

3월 23, 2019 10:13:55 오후 org.apache.catalina.loader.WebappClassLoaderBase clearReferencesJdbc

경고: The web application [ROOT] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.

3월 23, 2019 10:13:55 오후 org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads

경고: The web application [ROOT] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:

 java.lang.Object.wait(Native Method)

 java.lang.ref.ReferenceQueue.remove(Unknown Source)

 com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:64)

 java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

 java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

 java.lang.Thread.run(Unknown Source)


톰캣이 시작하거나 종료할 때는 발생하지 않고, 서버를 중지 시키지 않은 상태에서 파일을 리로드 시키거나 재시작 할 때 에러가 발생했다.

localhost:8080은 잘 뜨나 도대체 이 에러가 갑자기 왜 발생하는지 궁금해졌다.


에러가 발생하는 원인은 톰캣 때문이 아닌 JVM, library 때문이라고 한다.


- Application, Library code에 의해 발생

  • JDBC driver
  • Logging framework
  • ThreadLocal의 object를 저장하고 remove하지 않아서
  • 쓰레드를 시작시키고 멈추지 않아서
- Java API에 의해서도 발생
  • Using the javax.imageio API (the Google Web Toolkit can trigger this)
  • Using java.beans.Introspector.flushCaches() (Tomcat does this to prevent memory leaks caused by this caching)
  • Using XML parsing (the root cause is unknown due to a bug in the JRE)
  • Using RMI (somewhat ironically, causes a leak related to the garbage collector)
  • Reading resources from JAR files


나한테 뜬 에러는 JDBC 관련된 것, ThreadLocal에 객체를 저장하고 지우지 않아서, 쓰레드를 시작하고 중지 시키지 않아서 발생한 것 같다.

그러므로 쓰레드에 대해 간단하게 알아보자.



Java Thread

자바 쓰레드의 정의를 알기 전에 프로세스에 대해 알아야 한다.

프로그래밍 언어로 코딩을 하여 만든 것을 "프로그램"이라고 한다. 그리고 프로그램을 "실행" 시켜 동작하게 만들면 이것을 "프로세스"라고 한다.

이 프로세스는 보통 하나의 처리 경로를 가지고 있고, 직렬적이다. 즉 어떠한 일을 수행할 때 프로그래머가 원하는 순서대로 일을 처리하는 것이다.

그러나 순서가 필요 없는 작업을 할 때 따로 따로 분리해서 동시에 처리를 할 수 있는데, 이 때 자바의 쓰레드를 이용하는 것이다.

자바 쓰레드를 이용하면 하나의 프로세스에서도 병렬적 처리, 즉 여러 개의 경로를 가질 수 있다.

그리고 Thread클래스를 상속 받거나 Runnable 인터페이스를 구현해서 만들어진다. Thread클래스의 start() 메소드를 통해 시작하고 stop() 메소드를 ㅗ통해 중지된다. 그러나 한 두개 쓰레드를 쓸 경우가 아니라면, 쓰레드를 관리하기 위해서 ThreadPool을 사용한다.

Thread의 stop메소드와 ExecutorService의 shutdownNow메소드에는 차이가 있다고 한다.

Thread - stop() : 쓰레드를 무조건 중지 시킨다. 무한반복( while(true)와 같은 )이 있어도 중지를 시킨다.

ExecutorService - shutdownNow() : shutdownNow는 내부 관리되고 있는 쓰레드들이게 인터럽트를 호출만해준다. stop메소드처럼 무한반복문을 중지시키지 못한다. 그리고 내부에는 인터럽트 되어 지지 않는 sleep과 같은 메소드를 통해 대기 상태를 이루고 있다.



+

에러에 뜬 클래스파일의 소스코드를 보니 뭔 말인지 모르겠어서 공부가 더 필요하다.

해결법을 찾아내면 추가하겠다.








REFERENCE

https://knight76.tistory.com/947

https://atin.tistory.com/438

'Development > JAVA' 카테고리의 다른 글

NPE(NullPointerException) 원인과 예방  (0) 2018.10.05

+ Recent posts