ABOUT ME

-

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 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다.

    abstract class ClassLoader에 정의되어 있고
    class의 binary 이름을 전달하면 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는 상관이 없겠구나... 싶다

    반응형

    댓글

Designed by Tistory.