다음을 통해 공유


Java 8에서 Java 11로 전환

코드를 Java 8에서 Java 11로 전환하기 위한 모두에게 적합한 솔루션은 없습니다. 사소한 애플리케이션이 아닌 경우 Java 8에서 Java 11로 이동하는 것은 상당한 양의 작업이 될 수 있습니다. 잠재적인 문제로는 제거된 API, 사용되지 않는 패키지, 내부 API 사용, 클래스 로더 변경, 가비지 수집 변경 등이 있습니다.

일반적으로 이 방법은 다시 컴파일하지 않고 Java 11에서 실행하거나 JDK 11로 먼저 컴파일하는 것입니다. 가능한 한 빨리 애플리케이션을 가동하고 실행하는 것이 목표인 경우 Java 11에서 실행하려고 하는 것이 가장 좋은 방법인 경우가 많습니다. 라이브러리의 경우 목표는 JDK 11로 컴파일 및 테스트되는 아티팩트를 게시하는 것입니다.

Java 11로 전환하는 것이 좋습니다. 새로운 기능이 추가되었으며 Java 8 이후 향상된 기능이 추가되었습니다. 이러한 기능과 향상된 기능은 시작, 성능, 메모리 사용량을 향상시키고 컨테이너와 더 나은 통합을 제공합니다. 또한 개발자 생산성을 향상시키는 API에 대한 추가 및 수정이 있습니다.

이 문서에서는 코드를 검사하는 도구를 다룹니다. 또한 발생할 수 있는 문제 및 해결을 위한 권장 사항도 다룹니다. Oracle JDK 마이그레이션 가이드와 같은 다른 가이드도 참조해야 합니다. 기존 코드를 모듈식으로 만드는 방법은 여기서 다루지 않습니다.

도구 상자

Java 11에는 잠재적인 문제를 파악하는 데 유용한 두 가지 도구인 jdeprscanjdeps가 있습니다. 이러한 도구는 기존 클래스 또는 jar 파일에 대해 실행할 수 있습니다. 다시 컴파일하지 않고도 전환 작업을 평가할 수 있습니다.

jdeprscan은 사용되지 않거나 제거된 API의 사용을 찾습니다. 사용되지 않는 API의 사용은 차단 문제가 아니지만 살펴볼 내용입니다. 업데이트된 jar 파일이 있나요? 사용되지 않는 API 사용을 해결하기 위해 문제를 기록해야 합니까? 제거된 API 사용은 Java 11에서 실행하기 전에 해결해야 하는 차단 문제입니다.

jdeps- Java 클래스 종속성 분석기입니다. 이 --jdk-internals 옵션을 사용하면, jdeps는 어떤 클래스가 어떤 내부 API에 의존하는지를 알려줍니다. Java 11에서 내부 API를 계속 사용할 수 있지만 사용량을 바꾸는 것이 우선되어야 합니다. OpenJDK 위키 페이지 Java 종속성 분석 도구 에는 일반적으로 사용되는 일부 JDK 내부 API를 대체할 것을 권장합니다.

Gradle 및 Maven 모두에 대한 jdepsjdeprscan 플러그 인이 있습니다. 빌드 스크립트에 이러한 도구를 추가하는 것이 좋습니다.

Java 컴파일러 자체인 javac는 도구 상자의 또 다른 도구입니다. jdeprscanjdeps에서 발생하는 경고 및 오류는 컴파일러에서 나옵니다. jdeprscan 및 jdeps를 사용하는 이점은 타사 라이브러리를 포함하여 기존 jar 및 클래스 파일에 대해 이러한 도구를 실행할 수 있다는 것입니다.

jdeprscanjdeps가 수행할 수 없는 작업은 캡슐화된 API에 액세스하기 위해 리플렉션을 사용하는 것에 대해 경고하는 것입니다. 리플렉티브 액세스는 런타임에 확인됩니다. 궁극적으로 Java 11에서 코드를 실행하여 확실하게 알고 있어야 합니다.

jdeprscan 사용

jdeprscan을 사용하는 가장 쉬운 방법은 기존 빌드에서 jar 파일을 제공하는 것입니다. 컴파일러 출력 디렉터리 또는 개별 클래스 이름과 같은 디렉터리를 제공할 수도 있습니다. 이 --release 11 옵션을 사용하여 사용되지 않는 API의 가장 전체 목록을 가져옵니다. 레거시 API 중에서 어떤 것을 우선하여 작업할지 결정하려면 설정을 --release 8으로 다시 조정하세요. Java 8에서 더 이상 사용되지 않는 API는 더 최근에 사용되지 않는 API보다 더 빨리 제거될 가능성이 높습니다.

jdeprscan --release 11 my-application.jar

jdeprscan 도구는 종속 클래스를 확인하는 데 문제가 있는 경우 오류 메시지를 생성합니다. 예: error: cannot find class org/apache/logging/log4j/Logger. 종속 클래스를 --class-path 애플리케이션 클래스 경로에 추가하거나 사용하는 것이 좋지만 도구는 해당 클래스 없이 검사를 계속합니다. 인수는 --class-path입니다. 클래스 경로 인수의 다른 변형은 작동하지 않습니다.

jdeprscan --release 11 --class-path log4j-api-2.13.0.jar my-application.jar
error: cannot find class sun/misc/BASE64Encoder
class com/company/Util uses deprecated method java/lang/Double::<init>(D)V

이 출력은 com.company.Util 클래스가 java.lang.Double 클래스의 더 이상 사용되지 않는 생성자를 호출하고 있음을 알려줍니다. javadoc는 사용되지 않는 API 대신 API를 사용하도록 권장합니다. API가 제거되었기 때문에 어떤 작업도 error: cannot find class sun/misc/BASE64Encoder를 해결할 수 없습니다. Java 8부터 java.util.Base64 사용해야 합니다.

Java 8 이후 API가 더 이상 사용되지 않는 것을 파악하려면 실행 jdeprscan --release 11 --list 합니다. 제거된 API 목록을 얻으려면 다음을 실행합니다 jdeprscan --release 11 --list --for-removal.

jdeps 사용

JDK 내부 API에 대한 종속성을 찾는 옵션과 함께 --jdk-internals를 사용합니다. --multi-release 11 다중 릴리스 jar 파일이므로 이 예제에는 명령줄 옵션이 필요합니다. 이 옵션이 없으면 jdeps 는 다중 릴리스 jar 파일을 찾으면 불만을 제기합니다. 이 옵션은 검사할 클래스 파일의 버전을 지정합니다.

jdeps --jdk-internals --multi-release 11 --class-path log4j-core-2.13.0.jar my-application.jar
Util.class -> JDK removed internal API
Util.class -> jdk.base
Util.class -> jdk.unsupported
   com.company.Util        -> sun.misc.BASE64Encoder        JDK internal API (JDK removed internal API)
   com.company.Util        -> sun.misc.Unsafe               JDK internal API (jdk.unsupported)
   com.company.Util        -> sun.nio.ch.Util               JDK internal API (java.base)

Warning: JDK internal APIs are unsupported and private to JDK implementation that are
subject to be removed or changed incompatibly and could break your application.
Please modify your code to eliminate dependence on any JDK internal APIs.
For the most recent update on JDK internal API replacements, please check:
https://wiki.openjdk.java.net/display/JDK8/Java+Dependency+Analysis+Tool

JDK Internal API                         Suggested Replacement
----------------                         ---------------------
sun.misc.BASE64Encoder                   Use java.util.Base64 @since 1.8
sun.misc.Unsafe                          See http://openjdk.java.net/jeps/260   

출력은 JDK 내부 API 사용을 제거하는 데 유용한 조언을 제공합니다. 가능한 경우 대체 API가 제안됩니다. 패키지가 캡슐화된 모듈의 이름은 괄호로 지정됩니다. 모듈 이름은 --add-exports 또는 --add-opens과 함께 사용할 수 있으며, 이는 캡슐화를 명시적으로 중단해야 할 때 필요합니다.

sun.misc.BASE64Encoder 또는 sun.misc.BASE64Decoder를 사용하면 Java 11에서 java.lang.NoClassDefFoundError가 생성됩니다. 이러한 API를 사용하는 코드는 java.util.Base64를 사용하도록 수정해야 합니다.

지원되지 않는 모듈 jdk.unsuped에서 오는 API를 사용하지 않도록 합니다. 이 모듈의 API는 제안된 대체로 JDK JEP(향상된 제안) 260 을 참조합니다. 간단히 말해서 JEP 260은 대체 API를 사용할 수 있을 때까지 내부 API를 사용할 수 있다고 말합니다. 코드에서 JDK 내부 API를 사용할 수 있지만 적어도 잠시 동안 계속 실행됩니다. 일부 내부 API의 대체를 가리키므로 JEP 260을 살펴보세요. 예를 들어 일부 sun.misc.Unsafe API 대신 변수 핸들을 사용할 수 있습니다.

jdeps는 JDK 내부 사용을 검사하는 것 이상을 수행할 수 있습니다. 종속성을 분석하고 모듈 정보 파일을 생성하는 데 유용한 도구입니다. 자세한 내용은 설명서를 살펴보세요.

javac 사용하기

JDK 11을 사용하여 컴파일하려면 스크립트, 도구, 테스트 프레임워크 및 포함된 라이브러리를 빌드하기 위한 업데이트가 필요합니다. -Xlint:unchecked javac에 대한 옵션을 사용하여 JDK 내부 API 및 기타 경고 사용에 대한 세부 정보를 가져옵니다. --add-opens 또는 --add-reads을 사용하여 캡슐화된 패키지를 컴파일러에 노출해야 할 수도 있습니다(JEP 261 참조).

라이브러리는 패키징을 다중 릴리스 jar 파일로 고려할 수 있습니다. 다중 릴리스 jar 파일을 사용하면 동일한 jar 파일에서 Java 8 및 Java 11 런타임을 모두 지원할 수 있습니다. 빌드에 복잡성을 더합니다. 이 문서는 다중 릴리스 jar를 빌드하는 방법을 다루지 않습니다.

Java 11에서 실행

대부분의 애플리케이션은 수정 없이 Java 11에서 실행되어야 합니다. 가장 먼저 시도할 작업은 코드를 다시 컴파일하지 않고 Java 11에서 실행하는 것입니다. 실행의 요점은 실행에서 나오는 경고 및 오류를 확인하는 것입니다. 이 접근 방식은 어떤 결과를 낳습니다.
애플리케이션은 수행해야 하는 최소값에 집중하여 Java 11에서 더 빠르게 실행됩니다.

발생할 수 있는 대부분의 문제는 코드를 다시 컴파일하지 않고도 해결할 수 있습니다. 코드에서 문제를 해결해야 하는 경우 수정하지만 JDK 8을 사용하여 계속 컴파일합니다. 가능하면 JDK 11로 컴파일하기 전에 버전 11에서 애플리케이션java 실행하도록 작업하세요.

명령줄 옵션 확인

Java 11에서 실행하기 전에 명령줄 옵션을 빠르게 검색합니다. 제거된 옵션 으로 인해 JVM(Java Virtual Machine)이 종료됩니다. 이 검사는 Java 8에서 크게 변경되었으므로 GC 로깅 옵션을 사용하는 경우에 특히 중요합니다. JaCoLine 도구는 명령줄 옵션의 문제를 감지하는 데 사용하기에 좋은 도구입니다.

타사 라이브러리 확인

잠재적인 문제의 원인은 제어하지 않는 타사 라이브러리입니다. 타사 라이브러리를 최신 버전으로 사전에 업데이트할 수 있습니다. 또는 애플리케이션을 실행하지 못하는 항목을 확인하고 필요한 라이브러리만 업데이트할 수 있습니다. 모든 라이브러리를 최신 버전으로 업데이트할 때 발생하는 문제는 애플리케이션에 오류가 있을 경우 근본 원인을 찾기가 더 어려워진다는 점입니다. 일부 업데이트된 라이브러리로 인해 오류가 발생했나요? 또는 런타임의 일부 변경으로 인해 오류가 발생합니까? 필요한 것만 업데이트하는 문제는 해결하는 데 몇 번의 반복이 필요할 수 있다는 것입니다.

여기서 권장 사항은 가능한 한 적은 수의 변경을 수행하고 별도의 노력으로 타사 라이브러리를 업데이트하는 것입니다. 타사 라이브러리를 업데이트하는 경우 Java 11과 호환되는 가장 최신 버전이 필요한 경우가 많습니다. 현재 버전보다 훨씬 뒤처진 정도에 따라 보다 신중한 접근 방식을 취하고 첫 번째 Java 9+ 호환 버전으로 업그레이드할 수 있습니다.

릴리스 정보를 살펴보는 것 외에도 jdepsjdeprscan을 사용하여 jar 파일을 평가할 수 있습니다. 또한 OpenJDK 품질 그룹은 OpenJDK 버전에 대해 많은 FOSS(무료 오픈 소스 소프트웨어) 프로젝트의 테스트 상태를 나열하는 품질 아웃리치 위키 페이지를 유지 관리합니다.

가비지 수집을 명시적으로 설정

병렬 GC(병렬 가비지 수집기)는 Java 8의 기본 GC입니다. 애플리케이션이 기본값을 사용하는 경우 명령줄 옵션을 -XX:+UseParallelGC사용하여 GC를 명시적으로 설정해야 합니다. 기본값은 Java 9에서 G1GC(가비지 첫 번째 가비지 수집기)로 변경되었습니다. Java 8과 Java 11에서 실행되는 애플리케이션을 공정하게 비교하려면 GC 설정이 동일해야 합니다. GC 설정 실험은 Java 11에서 애플리케이션의 유효성을 검사할 때까지 연기되어야 합니다.

명시적으로 기본 옵션 설정

HotSpot VM에서 실행하는 경우 명령줄 옵션을 -XX:+PrintCommandLineFlags 설정하면 VM에서 설정한 옵션 값, 특히 GC에서 설정한 기본값이 덤프됩니다. Java 8에서 이 플래그를 사용하여 실행하고 Java 11에서 실행할 때 인쇄된 옵션을 사용합니다. 대부분의 경우 기본값은 8에서 11까지 동일합니다. 그러나 8의 설정을 사용하면 패리티가 보장됩니다.

명령줄 옵션을 --illegal-access=warn 설정하는 것이 좋습니다. Java 11에서는 리플렉션을 사용하여 JDK 내부 API에 액세스하면 잘못된 반사 액세스 경고가 발생합니다. 기본적으로 경고는 첫 번째 잘못된 액세스에 대해서만 발급됩니다. 설정 --illegal-access=warn 하면 모든 잘못된 반사 액세스에 대한 경고가 발생합니다. 경고하도록 설정된 옵션으로 잘못된 액세스가 있는 경우 더 많은 사례를 찾을 수 있습니다. 그러나 중복 경고도 많이 표시됩니다.
애플리케이션이 Java 11에서 실행되면 Java 런타임의 향후 동작을 모방하도록 설정합니다 --illegal-access=deny . Java 16부터 기본값은 .입니다 --illegal-access=deny.

ClassLoader 주의 사항

Java 8에서는 시스템 클래스 로더를 URLClassLoader로 캐스팅할 수 있습니다. 이 작업은 일반적으로 런타임 시 클래스 경로에 클래스를 삽입하려는 애플리케이션 및 라이브러리에서 수행됩니다. 클래스 로더 계층 구조가 Java 11에서 변경되었습니다. 시스템 클래스 로더(애플리케이션 클래스 로더라고도 함)는 이제 내부 클래스입니다. 캐스팅을 하면 URLClassLoader은(는) 런타임에 ClassCastException가 발생합니다. Java 11에는 런타임에 클래스 경로를 동적으로 보강할 API가 없지만 내부 API 사용에 대한 명백한 주의 사항과 함께 리플렉션을 통해 수행할 수 있습니다.

Java 11에서 부팅 클래스 로더는 코어 모듈만 로드합니다. null 부모로 클래스 로더를 만드는 경우 모든 플랫폼 클래스를 찾을 수 없습니다. Java 11에서는 이러한 경우 ClassLoader.getPlatformClassLoader() 대신 부모 클래스 로더로 null를 전달해야 합니다.

지역 데이터 변경 사항

Java 11의 로캘 데이터에 대한 기본 원본은 JEP 252 를 사용하여 유니코드 컨소시엄의 공통 로캘 데이터 리포지토리로 변경되었습니다. 이는 지역화된 서식에 영향을 미칠 수 있습니다. 필요한 경우 Java 8 로캘 동작으로 되돌리도록 시스템 속성을 java.locale.providers=COMPAT,SPI 설정합니다.

잠재적 이슈

다음은 발생할 수 있는 몇 가지 일반적인 문제입니다. 이러한 문제에 대한 자세한 내용은 링크를 따르세요.

인식할 수 없는 옵션

제거된 명령줄 옵션이 있는 경우, 애플리케이션은 Unrecognized option: 또는 Unrecognized VM option를 출력한 후 잘못된 옵션의 이름을 표시합니다. 인식할 수 없는 옵션으로 인해 VM이 종료됩니다. 사용되지 않지만 제거되지 않은 옵션은 VM 경고를 생성합니다.

일반적으로 제거된 옵션에는 대체 항목이 없으며 유일한 방법은 명령줄에서 옵션을 제거하는 것입니다. 가비지 수집 로깅에 대한 옵션은 예외입니다. 통합 JVM 로깅 프레임워크를 사용하기 위해 Java 9에서 GC 로깅이 다시 적용되었습니다. Java SE 11 도구 참조의 JVM 통합 로깅 프레임워크를 사용하여 로깅 활성화 섹션에서 "레거시 가비지 컬렉션 로깅 플래그를 Xlog 구성에 매핑하기"를 참조하세요.

VM 경고

사용되지 않는 옵션을 사용하면 경고가 발생합니다. 옵션은 대체되었거나 더 이상 유용하지 않을 때 더 이상 사용되지 않습니다. 제거된 옵션과 마찬가지로 명령줄에서 이러한 옵션을 제거해야 합니다. 경고 VM Warning: Option <option> was deprecated 는 옵션이 계속 지원되지만 나중에 해당 지원이 제거될 수 있음을 의미합니다. 더 이상 지원되지 않으며 경고를 VM Warning: Ignoring option생성하는 옵션입니다. 더 이상 지원되지 않는 옵션은 런타임에 영향을 주지 않습니다.

웹 페이지 VM 옵션 탐색기는 JDK 7 이후 Java에 추가되거나 Java에서 제거된 옵션의 전체 목록을 제공합니다.

오류: Java Virtual Machine을 만들 수 없습니다.

이 오류 메시지는 JVM에서 인식할 수 없는 옵션이 발견되면 출력됩니다.

경고: 불법적인 반사 접근 작업이 발생했습니다.

Java 코드가 리플렉션을 사용하여 JDK 내부 API에 액세스하는 경우 런타임에 잘못된 반사 액세스 경고가 발생합니다.

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by my.sample.Main (file:/C:/sample/) to method sun.nio.ch.Util.getTemporaryDirectBuffer(int)
WARNING: Please consider reporting this to the maintainers of com.company.Main
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

즉, 모듈이 리플렉션을 통해 액세스되는 패키지를 내보내지 않았습니다. 패키지는 모듈에 캡슐화 되며 기본적으로 내부 API입니다. 경고는 Java 11에서 시작하고 실행하기 위한 첫 번째 노력으로 무시될 수 있습니다. Java 11 런타임은 레거시 코드가 계속 작동할 수 있도록 반사 액세스를 허용합니다.

이 경고를 해결하려면 내부 API를 사용하지 않는 업데이트된 코드를 찾습니다. 업데이트된 코드 --add-exports 로 문제를 해결할 수 없는 경우 명령줄 옵션을 --add-opens 사용하여 패키지에 대한 액세스를 열 수 있습니다. 이러한 옵션을 사용하면 다른 모듈에서 한 모듈의 보고되지 않은 형식에 액세스할 수 있습니다.

--add-exports 옵션을 사용하면 대상 모듈이 원본 모듈의 명명된 패키지의 공용 형식에 액세스할 수 있습니다. 경우에 따라 코드는 비공용 멤버 및 API에 액세스하는 데 사용합니다 setAccessible(true) . 이를 딥 리플렉션이라고 합니다. 이 경우 패키지의 비공용 멤버에 대한 코드 액세스 권한을 부여하는 데 사용합니다 --add-opens . --add-exports 또는 --add-opens를 사용할지 확실하지 않은 경우 --add-exports로 시작합니다.

--add-exports 또는 --add-opens 옵션은 장기적인 솔루션이 아닌 해결 방안으로 간주되어야 합니다. 이러한 옵션을 사용하면 JDK 내부 API가 사용되지 않도록 하는 모듈 시스템의 캡슐화가 중단됩니다. 내부 API가 제거되거나 변경되면 애플리케이션이 실패합니다. 와 같은 --add-opens명령줄 옵션에서 액세스를 사용하도록 설정한 경우를 제외하고 Java 16에서는 반사 액세스가 거부됩니다. 이후 동작을 모방하려면 명령줄에서 설정합니다 --illegal-access=deny .

위 예제의 경고는 sun.nio.ch 패키지가 java.base 모듈에서 내보내지지 않기 때문에 발생합니다. 즉, 모듈 exports sun.nio.ch;module-info.java 파일에는 java.base이(가) 없습니다. --add-exports=java.base/sun.nio.ch=ALL-UNNAMED를 사용하여 해결할 수 있습니다. 모듈에 정의되지 않은 클래스는 명명되지 않은 모듈 에 암시적으로 속하며 문자 그대로 이름이 지정 ALL-UNNAMED됩니다.

java.lang.reflect.InaccessibleObjectException

이 예외는 캡슐화된 클래스의 필드 또는 메서드를 호출 setAccessible(true) 하려고 했음을 나타냅니다. 잘못된 반사 액세스 경고가 표시될 수도 있습니다. 이 --add-opens 옵션을 사용하여 패키지의 비공용 멤버에 대한 코드 액세스 권한을 부여합니다. 예외 메시지는 패키지를 setAccessible을 호출하려는 모듈에 대해 "열지 않는다"는 것을 알려줍니다. 모듈이 "명명되지 않은 모듈"인 경우 UNNAMED-MODULE 옵션에서 대상 모듈로 사용합니다.

java.lang.reflect.InaccessibleObjectException: Unable to make field private final java.util.ArrayList jdk.internal.loader.URLClassPath.loaders accessible: 
module java.base does not "opens jdk.internal.loader" to unnamed module @6442b0a6

$ java --add-opens=java.base/jdk.internal.loader=UNNAMED-MODULE example.Main

java.lang.NoClassDefFoundError

NoClassDefFoundError 는 분할 패키지 또는 제거된 모듈 참조로 인해 발생할 가능성이 큽니다.

분할 패키지로 인한 NoClassDefFoundError

분할 패키지는 둘 이상의 라이브러리에서 패키지를 찾을 때입니다. 분할 패키지 문제의 증상은 클래스 경로에 있는 것으로 알고 있는 클래스를 찾을 수 없다는 것입니다.

이 문제는 모듈 경로를 사용하는 경우에만 발생합니다. Java 모듈 시스템은 패키지를 명명 된 모듈 하나로 제한하여 클래스 조회를 최적화합니다. 런타임은 클래스를 검색할 때 모듈 경로를 클래스 경로보다 우선시합니다. 패키지가 모듈과 클래스 경로 간에 분할되는 경우 모듈만 클래스 조회를 수행하는 데 사용됩니다. 이로 인해 NoClassDefFound 오작동이 발생할 수 있습니다.

분할 패키지를 확인하는 쉬운 방법은 모듈 경로 및 클래스 경로를 jdeps에 연결하고 애플리케이션 클래스 파일의 경로를 경로<로 >사용하는 것입니다. 분할 패키지가 있는 경우 jdeps는 경고를 Warning: split package: <package-name> <module-path> <split-path>출력합니다.

이 문제는 분할 패키지를 명명된 모듈에 추가하는 데 사용하여 --patch-module <module-name>=<path>[,<path>] 해결할 수 있습니다.

Java EE 또는 CORBA 모듈을 사용하여 발생한 NoClassDefFoundError

애플리케이션이 Java 8에서 실행되지만 a java.lang.NoClassDefFoundError 또는 a java.lang.ClassNotFoundException를 throw하는 경우 애플리케이션이 Java EE 또는 CORBA 모듈의 패키지를 사용하고 있을 수 있습니다. 이러한 모듈은 Java 9에서 더 이상 사용되지 않으며 Java 11에서 제거되었습니다.

이 문제를 해결하려면 프로젝트에 런타임 종속성을 추가합니다.

제거된 모듈 영향을 받는 패키지 제안된 종속성
XML Web Services용 Java API(JAX-WS) java.xml.ws JAX WS RI 런타임
XML 바인딩용 Java 아키텍처(JAXB) java.xml.bind JAXB 런타임
JAV(JavaBeans Activation Framework) java.activation JavaBeans(TM) 활성화 프레임워크
일반 주석 .ws.annotation java.xml Javax 주석 API
CORBA(Common Object Request Broker Architecture) java.corba GlassFish CORBA ORB
JTA(Java Transaction API) java.transaction Java 트랜잭션 API

-Xbootclasspath/p는 더 이상 지원되지 않는 옵션입니다.

-Xbootclasspath/p 지원이 제거되었습니다. --patch-module를 대신 사용하세요. --patch-module 옵션은 JEP 261에 설명되어 있습니다. "패치 모듈 콘텐츠"라는 레이블이 지정된 섹션을 찾습니다. --patch-modulejavacjava 와 함께 사용하여 모듈의 클래스를 재정의하거나 보강할 수 있습니다.

--patch-module이 실제로 수행하는 일은 패치 모듈을 모듈 시스템의 클래스 조회에 삽입하는 것입니다. 모듈 시스템은 먼저 패치 모듈에서 클래스를 가져옵니다. 이는 Java 8에서 부트클래스 경로를 미리 보류하는 것과 동일한 효과입니다.

지원되지 않는 클래스 버전 오류

이 예외는 이전 버전의 Java에서 최신 버전의 Java로 컴파일된 코드를 실행하려고 한다는 것을 의미합니다. 예를 들어 JDK 13으로 컴파일된 jar을 사용하여 Java 11에서 실행 중입니다.

Java 버전 클래스 파일 형식 버전
8 (여덟) 52
9 53
10 54
11 55
12 56
13 57

다음 단계

애플리케이션이 Java 11에서 실행되면 클래스 경로에서 모듈 경로로 라이브러리를 이동하는 것이 좋습니다. 애플리케이션이 의존하는 라이브러리의 업데이트된 버전을 찾습니다. 사용 가능한 경우 모듈식 라이브러리를 선택합니다. 애플리케이션에서 모듈을 사용할 계획이 없는 경우에도 가능한 한 모듈 경로를 사용합니다. 모듈 경로를 사용하면 클래스 경로보다 클래스 로드 성능이 향상됩니다.