ABOUT ME

-

인기 태그


kafka elastic_search redis
Today
-
Yesterday
-
Total
-
  • xstream + spring dev-tools 썼더니 문제가 발생했다.
    개발하면서/코드보면서 2021. 3. 27. 14:42
    반응형

    개인 프로젝트에서 이것저것 수정하다 보니 XStream 사용하는 부분에 오류가 발생했다.
    한꺼번에 많은 수정을 한 게 가장 큰 실수였고 문제의 원인을 gradle 설정이나 XStream 설정이
    잘못된 줄 알고 엄한 곳에서 삽질했다.
    하지만 결국엔 찾지 못해 원복 했다.... JUnit Test 실행할 때는 정상 동작하는데 Application 실행하면 발생했다.

    일주일 정도 지났나? 다시 시도하였다. 이번에는 한 개 수정 -> 실행 -> 어 되네? 의 반복으로 진행했고
    (당연히 그래야 하는데...ㅎ;;) spring-devtools 추가했을 때 오류가 나는 것을 발견하였다.

     

    그래서 해결은 어떻게 했나?

    stackoverflow.com/questions/59176413/error-using-xstream-in-spring-context-duplicatefieldexception

    stackoverflow.com/questions/33957612/a-classloader-proplem-related-to-spring-boot-devtools


    multi-module layout일때
    PROJECT_HOME/[sub-project]/src/main/resources/META-INF 에 spring-devtools.properties 파일을 만들고
    restart.include.xstream=/xstream-[\\w\\d-\\.]+\\.jar  를 입력하면 끝!!

     

    해결은 했지만 개인 프로젝트에서 동적으로 클래스 로딩하는 기능도 필요해서 겸사겸사 class loading을 알아보기로 했다.


    class loader

    www.baeldung.com/java-classloaders

    www.geeksforgeeks.org/classloader-in-java/

    cr.openjdk.java.net/~iris/se/11/latestSpec/api/java.base/java/lang/ClassLoader.html#binary-name

     

    class loader가 하는 일

    class들을 로딩할 책임이 있는 object이다. ClassLoader 이름의 abstract class로 정의되어있고
    class의 binary name을 전달하면 class loader는 해당 class를 생성하거나 찾으려고 시도한다.
    또한 resources(".class file", "config file", 'image file")를 찾는 역할도 한다.

     

    Run-time Built-in class loader

    * Bootstrap class loader

    jre/lib/rt.jar 에 있는 클래스 로드 (java.lang.Object, Class)

     

    * Platform class loader

    Bootstrap class loader를 부모로 갖는 클래스 로더

    java.ext.dirs 환경 변수의 값에 해당하는 클래스, 값이 없다면 $JAVA_HOME/jre/lib/ext/*.jar에 있는 클래스 로드

     

    * System class loader

    프로그램 실행 시 -classpath 지정한 클래스와 Jar에 있는 Manifest 파일 Class-Path의 값에 맞는 클래스 로드

     

     

    class loader가 지켜야 할 3가지 원칙

    1. Delegation Principle

    클래스 로딩이 필요한 경우 부모 class loader에게 위임한다는 원칙

     

     

    2. Visibility Principle

    하위 classloader는 상위 classloader가 로드한 클래스는 볼 수 있지만 상위 class loader는 하위 class loader가
    로드한 클래스는 볼 수 없다는 원칙

     

    3. Uniqueness Principle

    한번 로드한 클래스는 다시 로드하지 않아야 한다는 원칙

     

    JDK11 loadClass method

     

    Load-time dynamic loading, Run-time dynamic loading

    Load-time은 class 로딩할 때 필요한 class들을 동적으로 로딩

    Run-time은 Class.forName method로 class를 로딩

    devtools을 적용하면 뭔 일이 일어나는 건가?

    8.2.6. Customizing the Restart Classloader 에 이렇게 설명하고 있다.

    기본으로 IDE로 연 프로젝트는 "restart" loader가 load하고 .jar(dependency에 정의한) class들은
    System class loader가 load 한다. multi-module 프로젝트이거나, 해당 프로젝트의 모든 module이
    IDE에 연게 아니라면 수정이 필요할 수 있다. META-INF/spring-devtools.properties 파일을 생성하고
    restart.exclude 하면 "base" class loader로 로딩 restart.include 정의하면 "restart" class loader로 로딩한다.

     

    XStream은 "base" class loader에서 로딩, 내가 만든 entity class는 "restart" class loader에 로딩이 되어
    오류가 났고 restart.include 설정으로 XStream을 "restart" class loader에서 로딩하도록 한 것이구나!!!


    Lombok은 왜 되지? 생각했는데 compile때 적용되는 거라 class loader는 상관이 없겠구나... 싶다

    반응형

    댓글 0

Designed by Tistory.