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

NullPointException은 자바 프로그램 뿐만 아니라 다양한 개발언어에서 자주 발생합니다. 여러가지 원인이 있을 수 있으나 거의 대부분은 객체가 제대로 생성되지 않은 경우입니다. 객체가 생성되지 않았다는 것은 프로그램을 가동시키는 VM에서 해당 하는 주소를 찾아갔을 때 아무 값도 없다는 뜻입니다. 


가령 객체 A를 생성한후 A를 참조 받아 B가 작업을 해야하는데 B가 작 하려 할 때 A가 없는 경우입니다.


1. NullPointException 발생시키기


* AClass에 string_null값이 초기화 되지 않았습니다. NULL 입니다.


 

1
2
3
4
5
6
  class AClass {
    String  string_null;
    AClass(){
        //i="1";
    }
    public String getNullString() { return string_null;}
cs


* 위 Class를 실행합니다. 변수 string_null이 값이 "1"인지 비교하려 했지만 NullpointException이 발생하며 프로그램이 죽어 버립니다.


 

1
2
3
4
5
        AClass aClass = new AClass();
        if(aClass.getNullString().equals("1")) {
            System.out.print(" 정상입니까 ? ");
        }
 
cs


[실행 결과]


* 오류가 나며 프로그램이 종료되어버립니다.


 

1
2
3
4
5
6
7
8
9
10
Exception in thread "main" java.lang.NullPointerException
    at Main.main(Main.java:14)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
 
Process finished with exit code 1
 
cs


2. 오류 피하기


NPE를 피하는 방법은 여러가지가 있습니다. 주로 객체를 생성하고 참조할 때는 Null을 Return하지 않고 부득이 하게 참조하는 경우는 Null이 발생할 경우를 대비하는 코딩을 하시면 됩니다.


1) 비교할 문자열을 먼저 넣고 코딩하면 오류가 발생하지 않습니다.

 

1
2
3
      if(("1").equals(aClass.getNullString())) {
            System.out.print(" 정상입니다!");
        }
cs


2)  String 객체의 경우 toString 보다는 String.valueOf 메소를 사용하세요.

 

1
2
3
4
5
        // NullPointException 오류 발생 !
        System.out.printf("i = %s \n", aClass.getNullString().toString());
        // NullPointException 미발생 !
        System.out.printf("i = %s \n"String.valueOf(aClass.getNullString()));
 
cs

 


3) try catch 구문을 사용

* NullPointException의 에외를 처리합니다.

 

1
2
3
4
5
6
        try {
            System.out.printf("i = %s \n", aClass.getNullString().toString());
 
        } catch (NullPointerException npe) {
            System.out.println(" Null Opint Exception!!");
        }
cs


4) null인지 비교합니다.

 

1
2
3
4
5
        if(aClass.getNullString() != null) {
            System.out.printf("i = %s \n", aClass.getNullString().toString());
        } else {
            System.out.println(" Null Opint Exception!!");
        }
cs


5) Apache Common 유틸을 사용하여 코딩을 합니다.

* 패키지 : org.apache.commons.lang3.StringUtils

* marven을 이용하여 jar를 추가하시면 쉽게 사용하실 수 있습니다.


 

1
2
3
4
5
6
7
8
  //Apache Common의 StringUtil사용
        if(StringUtils.equals(aClass.getNullString(),"1")) {
            System.out.println(" StringUtil Use");
        }
 
        String a =StringUtils.defaultString(aClass.getNullString(),"기본값!");
 
        System.out.printf("i = %s \n", a);
cs



[요약]

NPE는 많은 경우에 발생할 수 있습니다. String Object 말고도 여러 Array,File 등 객체가 제대로 생성되지 않고 참조하는 경우가 제법 많습니다.이러한 오류를 해결하는 근본 습관이 있습니다. 가령 Server에서 데이터를 받아와야 동작하는 프로그램을 만들 때라면 데이터를 못받는 경우를 가정하고 프로그램을 설계하시면 오류를 많이 줄 일 수 있습니다.











출처: https://m.blog.naver.com/sangrime/220627761646


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

Tomcat memory leak 현상  (1) 2019.03.23

+ Recent posts