오픈소스 라이브 클래스丨빅데이터 통합 프레임워크 춘준 클래스 로더 격리 방안 탐색 및 실습

이번 호에서는 지칠 줄 모르는 동급생들의 생방송 "ChunJun Class Loader Isolation"을 살펴보도록 하겠습니다. ChunJun Class Loader Isolation 솔루션은 우리가 최근에 탐색한 새로운 솔루션입니다. 이 솔루션은 아직 성숙하지 않았습니다. 공유하겠습니다. 이 솔루션에 대해 논의할 수 있습니다. 새로운 아이디어가 있으면 github에 문제나 홍보를 제출할 수 있습니다.

1. 클래스 충돌을 해결하기 위한 자바 클래스 로더의 기본 아이디어

프로그램을 배우기 전에 먼저 클래스 충돌을 해결하기 위한 Java 클래스 로더의 기본 개념을 소개하겠습니다.

01 클래스패스란?

Classpath는 JVM이 클래스를 검색하는 방법을 JVM에 지시하는 데 사용되는 환경 변수입니다.

Java는 컴파일된 언어이기 때문에 소스 코드 파일은 .java이고 컴파일된 .class 파일은 JVM에서 실제로 실행할 수 있는 바이트 코드입니다. 따라서 JVM은 com.dtstack.HelloWorld 클래스가 로드되는 경우 해당 HelloWorld.class 파일을 검색할 위치를 알아야 합니다.

따라서 Classpath는 디렉토리 모음이며, 설정하는 검색 경로는 운영 체제와 관련됩니다. 예를 들면 다음과 같습니다.

Windows 시스템에서는 ;을 사용하여 구분하고 공백이 있는 디렉토리는 ""로 묶습니다. 다음과 같이 보일 수 있습니다.

C:\work\project1\bin;C:\shared;"D:\내 문서\project1\bin"

MacOS 및 Linux 시스템에서는 :로 구분되어 다음과 같이 보일 수 있습니다.

/usr/shared:/usr/local/bin:/home/wujuan/bin

JVM을 시작할 때 Classpath 변수를 설정하는 것은 실제로 -Classpath 또는 -cp 매개변수를 java 명령에 전달하는 것입니다.

java - 클래스 경로 .;/Users/lzq/Java/a;/Users/lzq/Java/b com.dtstack.HelloWorld

시스템 환경 변수가 설정되지 않고 -cp 매개변수가 전달되지 않은 경우 JVM의 기본 클래스 경로는 현재 디렉토리입니다.

자바 com.dtstack.HelloWorld

02 Jar 패키지의 클래스는 언제 로드되나요?

● 항아리 패키지

Jar 패키지는 접미사 이름이 다른 zip 패키지입니다. 흩어져 있는 .class 클래스를 관리하는 데 사용됩니다.

jar 패키지를 생성하려면 zip 명령을 사용하십시오. zip -r ChunJun.zip ChunJun

자바 -cp ./ChunJun.zip com.dtstack.HelloWorld

● 로드

"Loading" 단계는 전체 "Class Loading" 프로세스의 한 단계이며 독자가 이 두 가지 유사해 보이는 용어를 혼동하지 않기를 바랍니다. 로딩 단계에서 Java 가상 머신은 다음 세 가지 작업을 수행해야 합니다.

1. 클래스의 정규화된 이름을 통해 이 클래스를 정의하는 이진 바이트 스트림을 얻습니다.

2. 이 바이트 스트림이 나타내는 정적 저장 구조를 메서드 영역의 런타임 데이터 구조로 변환합니다.

3. 메서드 영역에서 이 클래스의 다양한 데이터에 대한 액세스 항목으로 메모리에서 이 클래스를 나타내는 java.lang.Class 개체를 생성합니다.

● 분석

클래스 또는 인터페이스 해결

현재 코드가 있는 클래스가 D라고 가정하면 확인되지 않은 기호 참조 N이 클래스 또는 인터페이스 C에 대한 직접 참조로 구문 분석되는 경우 가상 머신은 다음 세 단계를 포함해야 하는 전체 구문 분석 프로세스를 완료합니다.

1. C가 어레이 유형이 아닌 경우 가상 머신은 N을 나타내는 완전한 이름을 D의 클래스 로더에 전달하여 클래스 C를 로드합니다.

로드 프로세스 동안 메타데이터 검증 및 바이트코드 검증의 필요성으로 인해 부모 클래스 또는 이 클래스의 구현된 인터페이스 로드와 같은 다른 관련 클래스 로드 작업이 트리거될 수 있습니다. 이 로드 프로세스에서 예외가 발생하면 구문 분석 프로세스가 실패합니다.

2. C가 배열 유형이고 배열의 요소 유형이 객체인 경우, 즉 N의 디스크립터는 클래스가 됩니다.

"[Ljava/lang/Integer, 그것은 첫 번째 점의 규칙에 따라 배열 요소 유형을 로드합니다.

N의 디스크립터가 위와 같은 형태일 경우, 로딩될 요소의 타입은 "java.lang.Integer"이고, 가상머신은 배열의 차원과 요소를 나타내는 배열 객체를 생성한다.

3. 위의 두 단계에서 예외가 없다면 C는 실제로 가상 머신에서 유효한 클래스나 인터페이스가 되었지만 파싱이 완료되기 전에 D가 C에 접근할 수 있는지 여부를 확인하기 위해 심볼 참조 검증이 필요하다. 접근 권한이 없는 것으로 확인되면 java.lang, llegalAccessError 예외가 발생합니다.

03 클래스 로드를 트리거하는 작업은 무엇입니까?

클래스 로딩 프로세스의 첫 번째 단계가 "로드"되어야 하는 상황과 관련하여 Java 가상 머신 사양에는 필수 제약 조건이 없으며 자유롭게 파악하기 위해 가상 머신의 특정 구현에 남겨둘 수 있습니다. 그러나 초기화 단계의 경우 "Java Virtual Machine Specification"은 클래스가 즉시 "초기화"되어야 하는 6가지 상황만 있다고 엄격하게 규정하고 있습니다.파일

● 장면 1

new, getstatic, putstatic 또는 invokestatic의 네 가지 바이트코드 명령어를 만날 때 유형이 초기화되지 않은 경우 해당 초기화 단계를 먼저 트리거해야 합니다. 이 네 가지 명령어를 생성할 수 있는 일반적인 Java 코드 시나리오는 다음과 같습니다.

1. new 키워드를 사용하여 객체를 인스턴스화할 때.

2. 어떤 유형의 정적 필드를 읽거나 설정할 때(final에 의해 수정된 정적 필드를 제외하고는 결과가 컴파일 시간에 상수 풀에 넣어집니다.)

3. 유형의 정적 메소드를 호출할 때.

● 장면 2

java.lang.reflect 패키지의 메소드를 사용하여 유형에 대한 리플렉션 호출을 수행할 때 유형이 초기화되지 않은 경우 해당 초기화가 먼저 트리거되어야 합니다.

● 장면 3

클래스를 초기화할 때 상위 클래스가 초기화되지 않은 것으로 확인되면 먼저 상위 클래스의 초기화를 트리거해야 합니다.

● 장면 4

가상 머신이 시작될 때 사용자는 실행할 메인 클래스(main() 메서드를 포함하는 클래스)를 지정해야 하며 가상 머신은 이 메인 클래스를 먼저 초기화합니다.

● 시나리오 5

JDK 7에서 추가된 새로운 동적 언어 지원을 사용할 때 java.lang.invoke.MethodHandle 인스턴스의 최종 구문 분석 결과가 REF_getStatic, REF_putStatic, REF_invokeStatic, REF_newInvokeSpecial인 경우 4가지 유형의 메소드 핸들이 있고 이 메소드 핸들의 해당 클래스는 다음과 같습니다. 처리되지 않음 과도하게 초기화된 경우 먼저 초기화를 트리거해야 합니다.

●시나리오 6

인터페이스가 JDK 8에 의해 추가된 새로운 기본 메소드(default 키워드로 수정된 인터페이스 메소드)를 정의할 때, 이 인터페이스의 구현 클래스가 초기화되면 인터페이스가 그 전에 초기화되어야 합니다.

유형 초기화를 트리거하는 위의 6가지 시나리오에 대해 Java Virtual Machine 사양은 "있다만"이라는 매우 강력한 한정자를 사용합니다. 이 6가지 시나리오의 동작을 유형에 대한 주도권을 잡기라고 합니다. 인용. 그 외에 초기화를 트리거하지 않는 모든 참조 형식을 수동 참조라고 합니다.

04 부모 위임 메커니즘은 무엇입니까?

부모 위임 메커니즘은 로더의 계층적 관계에 따라 레이어별로 위임하는 방식으로, 예를 들어 아래 그림의 커스텀 클래스 로더가 클래스를 로드하고자 하는 경우 자체적으로 로드하는 것이 아니라 사용자 정의 클래스 로더 -> 앱 클래스 로더 -> Ext 클래스 로더 -> 부트스트랩 클래스 로더에서 위임하고 싶은 클래스가 BootStrap ClassLoader에 없으면 계층적 관계를 통해 계층적으로 수행됩니다. 역 주기로 로드됩니다.

파일

05 부모 위임 메커니즘을 깨는 방법?

그렇다면 부모 위임 메커니즘을 깨는 방법은 실제로 loadclass 메서드를 다시 작성하여 달성할 수 있습니다. 구체적인 프로세스는 동영상을 통해 배울 수 있으므로 여기서는 자세히 설명하지 않겠습니다.

파일 파일

2. Flink 클래스 로딩 격리 방식

다음으로 Flink 클래스 로딩 격리 방식을 소개하겠습니다.Flink에는 Parent-First 및 Child-First의 두 가지 클래스 로더가 있으며 차이점은 다음과 같습니다.

1.부모 우선

Java의 상위 위임과 유사한 클래스 로딩 메커니즘. Parent First ClassLoader의 실제 로직은 URL ClassLoader입니다.

2.어린이 우선

먼저 classloader.parent-first-patterns.default 와 classloader.parent-first-patterns.additional 로 이어진 목록을 사용하여 일치시키고, 클래스 이름 접두어가 일치하면 먼저 상위 위임으로 이동합니다. 그렇지 않으면 ChildFirstClassLoader를 사용하여 먼저 로드하십시오.

아동 우선 문제

새로운 ChildFirstClassLoader가 생성될 때마다 장기간 실행하면 Session과 같은 TaskManager가 항상 닫히지 않습니다. 작업이 여러 번 실행되면 메타데이터 공간이 폭발하여 작업이 실패합니다.

차일드 퍼스트 로딩 원칙

파일

파일

파일 파일

01 Flink는 클래스 누출을 어떻게 방지합니까?

몇 가지 버그와 처리 방법이 포함된 Flink의 jira를 참조할 수 있습니다.

https://issues.apache.org/jira/browse/FLINK-16245

https://issues.apache.org/jira/browse/FLINK-11205

주로 다음 두 가지 방법을 통해 Flink가 클래스 누출을 방지하는 방법:

  1. 실제 UserClassloader를 래핑하기 위해 위임된 클래스 로더 레이어를 추가합니다.

  2. 작업이 종료될 때 해제되지 않은 리소스를 해제하는 인터페이스를 사용자에게 제공하는 콜백 후크를 추가합니다.

KinesisProducer는 이 후크를 사용합니다.

최종 런타임 컨텍스트 ctx = getRuntimeContext();

ctx.registerUserCodeClassLoaderReleaseHookIfAbsent(

KINESIS_PRODUCER_RELEASE_HOOK_NAME,

()-> this.runClassLoaderReleaseHook

(ctx.getUserCodeClassLoader()));

02 Flink는 사용자 코드에서 동적으로 로드된 클래스를 언로드합니다.

사용자 코드에서 동적으로 로드된 클래스를 언로드합니다. 동적 사용자 코드 클래스 로드(세션)와 관련된 모든 시나리오는 다시 언로드 되는 클래스에 따라 다릅니다 .

클래스 언로드는 가비지 수집기가 클래스의 개체가 더 이상 참조되지 않는 것을 발견한 다음 클래스(관련 코드, 정적 변수, 메타데이터 등)가 제거됨을 의미합니다.

TaskManager가 작업을 시작하거나 다시 시작할 때 지정된 작업의 코드가 로드되며 이러한 클래스를 언로드할 수 없으면 시간이 지남에 따라 클래스의 업데이트된 버전이 계속 로드되고 누적될 수 있으므로 메모리 누수가 발생할 수 있습니다. 이 현상으로 인해 OutOfMemoryError: Metaspace의 일반적인 예외가 자주 발생합니다.

클래스 누수 및 제안된 수정 사항의 일반적인 원인:

● 남아있는 스레드

애플리케이션 코드의 기능 /sources/sink가 모든 스레드를 닫는지 확인하십시오. 지연된 종료 스레드는 리소스 자체를 소비할 뿐만 아니라 객체 참조를 점유하여 가비지 수집 및 클래스 언로드를 방지합니다.

● 인턴

함수/소스/싱크의 수명을 넘어서는 특수 구조에서 개체를 캐싱하지 마십시오. Guava의 Interner 또는 Avro 직렬 변환기의 클래스 또는 개체와 같은 것입니다.

● JDBC

JDBC 드라이버가 사용자 클래스 로더 외부에서 참조를 누출합니다. 이러한 클래스가 한 번만 로드되도록 하려면 드라이버 JAR 패키지를 Flink의 lib/ 디렉토리에 배치하거나 classloader-parent-first-patterns-additional을 통해 상위 우선 로드 클래스 목록에 드라이버 클래스를 추가할 수 있습니다.

사용자 코드 클래스로더를 해제하는 후크는 동적으로 로드된 클래스를 언로드하는 데 도움이 될 수 있습니다. 이러한 후크는 클래스로더가 언로드되기 전에 실행됩니다. 일반적으로 일반 함수 수명 주기 작업(예: 일반적인 close()메서드)의 일부로 리소스를 닫고 언로드하는 것이 가장 좋습니다. 어떤 경우에는(정적 필드와 같은) 클래스 로더가 더 이상 필요하지 않은 즉시 언로드하는 것이 좋습니다.

클래스 로더를 해제하기 위한 후크는 다음을 통해 수행할 수 있습니다.

RuntimeContext.registerUserCodeClassLoaderReleaseHookIfAbsent()등록하는 방법.

03 Flink는 Classloader 소스 코드를 제거합니다.

BlobLibraryCacheManager$ResolvedClassLoader

비공개 무효 runReleaseHooks() {

Set<map.entry> hooks = releaseHooks.entrySet();

if (!hooks.isEmpty()) {

    for (Map.EntryhookEntry : hooks) {

        try {

            LOG.debug("Running class loader shutdown hook: {}.", hookEntry.getKey());

            hookEntry.getValue().run();

        } catch (Throwable t) {

            LOG.warn(

                    "Failed to run release hook '{}' for user code class loader.",

                    hookEntry.getValue(),

                    t);

        }

    }

    releaseHooks.clear();

}

}

3. ChunJun이 클래스 로딩 격리를 구현하는 방법

다음으로 ChunJun이 클래스 로딩 격리를 구현하는 방법을 소개하겠습니다.

01 Flink jar 업로드 타이밍

먼저 Jar 패키지를 업로드해야 하며 전체 프로세스는 다음 그림과 같습니다.

파일

● 원사 퍼잡

작업을 제출할 때 jar 패키지를 업로드하면 다음 위치에 배치됩니다.

hdfs://flink03:9000/user/root/.flink/application_1654762357754_0140。

● 얀 세션

세션을 시작할 때 Yarn의 앱은 Jar 패키지 메커니즘을 업로드하고 세션에 작업을 제출할 때 Flink의 Blob 서버가 이를 수신합니다.

02 Yarn의 분산 캐시

파일

03 Yarn의 분산 캐시

분산 캐시 메커니즘은 각 NM에 의해 구현되며 주요 기능은 후속 작업을 사용하기 위해 응용 프로그램에 필요한 파일 리소스를 로컬에 캐시하는 것입니다. 리소스 캐시는 시간에 따라 트리거됩니다. 즉, 리소스를 사용하는 첫 번째 작업이 트리거되며 후속 작업은 캐시할 필요가 없으며 직접 사용할 수 있습니다.

리소스 유형 및 리소스 가시성을 기반으로 NM은 리소스를 다양한 유형으로 분류할 수 있습니다.

리소스 가시성 분류

● 공개

노드의 모든 사용자는 이 리소스를 공유할 수 있습니다. 한 사용자의 응용 프로그램이 이러한 리소스를 로컬로 캐시하는 한 다른 모든 사용자의 응용 프로그램에서 사용할 수 있습니다.

● 비공개

노드에 있는 동일한 사용자의 모든 응용 프로그램은 리소스를 공유하므로 사용자의 응용 프로그램 중 하나가 로컬에서 리소스를 캐시하는 한 사용자의 모든 응용 프로그램에서 사용할 수 있습니다.

● 신청

이 리소스는 노드에 있는 동일한 애플리케이션의 모든 컨테이너가 공유합니다.

자원 유형 분류

● 아카이브

아카이브 파일은 .jar, .zip, .tar.gz, .tgz 및 .tar의 5가지 유형의 아카이브 파일을 지원합니다.

● 파일

일반 파일, NM은 처리 없이 해당 파일을 로컬 디렉토리에 다운로드합니다.

● 패턴

위의 두 파일의 혼합

YARN은 자원, 유형, 타임스탬프 및 패턴의 4개 필드가 동일한지 여부를 비교하여 두 개의 자원 요청이 동일한지 여부를 판단합니다. 각 노드에 캐시된 파일이 사용자에 의해 수정되면 다음에 HDFS에서 파일을 다시 다운로드하는 데 사용할 때 캐시 업데이트가 자동으로 트리거됩니다.

분산 캐시의 주요 기능은 많은 수의 디스크 읽기 및 쓰기를 포함하는 파일 다운로드입니다.따라서 전체 프로세스는 비동기식 동시성 모델을 채택하여 파일 다운로드 속도를 높여 동기식 모델이 가져오는 성능 오버헤드를 방지합니다.

04 Yarn의 분산 캐시

NodeManager는 라운드 로빈 할당 전략을 사용하여 이러한 세 가지 유형의 리소스를 yarn.nodemanager.local-dirs로 지정된 디렉터리 목록에 저장합니다.각 디렉터리에서 리소스는 다음과 같은 방식으로 저장됩니다.

● 공공 자원

${yarn.nodemanager.local-dirs}/filecache/ 디렉터리에 저장되며, 각 리소스는 임의의 정수로 명명된 디렉터리에 별도로 저장되며 디렉터리의 접근 권한은 0755입니다.

● 개인 자원

${yarn.nodemanager.local-dirs}/usercache/${user}/filecache/ 디렉토리에 저장됩니다(여기서 ${user}는 애플리케이션 제출자, 기본적으로 NodeManager 개시자), 각 리소스는 임의의 정수로 명명된 디렉터리에 별도로 저장되며 디렉터리의 접근 권한은 0710이다.

● 애플리케이션 리소스

${yarn.nodemanager.local-dirs}/usercache/${user}/${appcache}/${appid}/filecache/ 디렉토리(여기서 ${appid}는 애플리케이션 ID)에 저장되며 각 리소스는 임의의 정수로 명명된 디렉토리에 별도로 있으며 디렉토리의 액세스 권한은 0710입니다.

Container의 작업 디렉토리는 ${yarn.nodemanager.local-dirs}/usercache/${user}/${appcache}/${appid}/${containerid} 디렉토리에 있으며 주로 jar 패키지 파일과 사전 파일에 해당하는 소프트 링크가 있습니다.파일

05 플링크 블롭서버

파일

06 빠르게 제출하고 jar 패키지 업로드를 줄이는 방법

Flink libs 아래의 jar 패키지, Flink Plugins 아래의 jar 패키지, Flink 작업의 jar 패키지(ChunJun용, 모든 커넥터 및 코어), Flink jar 사용자 정의 jar 패키지.

● 퍼잡

미리 HDFS에 업로드할 수 있는 경우:

  1. Flink lib, Flink 플러그인, ChunJun jar를 미리 HDFS에 업로드합니다.

  2. 작업을 제출할 때 yarn.provided.lib.dirs를 통해 HDFS의 경로를 지정합니다.

미리 HDFS에 업로드할 수 없는 경우:

  1. 작업을 제출하고 HDFS의 고정된 위치에 업로드합니다.제출 시 HDFS에 해당 jar(캐시 정책 포함)가 있는지 확인하고 로컬 경로를 원격 경로로 교체합니다.

  2. 콜백 후크를 사용하여 비정상적인 작업을 종료하는 정크 파일을 지웁니다.

● 시온

미리 HDFS에 업로드할 수 있는 경우:

  1. Flink lib, Flink 플러그인, ChunJun jar를 미리 HDFS에 업로드합니다.

  2. 세션을 시작할 때 yarn.provided.lib.dirs를 통해 HDFS의 경로를 지정할 수 있습니다.

  3. 작업을 제출할 때 핵심 패키지를 업로드할 필요가 없습니다.

미리 HDFS에 업로드할 수 없는 경우:

  1. 세션이 시작될 때 모든 jar를 HDFS에 업로드합니다. 원사에 의해 지정됩니다.

  2. Flink 작업이 세션에 제출되면 jar 패키지를 제출할 필요가 없습니다.

파일

07 클래스 로딩 격리 시 발생하는 문제 분석

● 사고분석

  1. 먼저 다른 플러그인(커넥터)을 다른 클래스로더에 넣습니다.

  2. 그런 다음 자식 우선 로드 전략을 사용합니다.

  3. x not cast x 오류가 발생하지 않는지 확인하십시오.

  4. 메타데이터 공간은 메모리 누수가 발생하지 않아 작업 오류가 발생합니다.

  5. 커넥터 jar 패키지를 캐시하려면.

● 발생한 문제

  1. Flink 작업에는 여러 운영자가 있을 수 있으며 커넥터는 운영자입니다. Flink는 기본적으로 작업 수준에 대해 새로 생성된 Classloader이며 각 커넥터를 별도의 Classloader에 넣는 것은 불가능합니다.

  2. 자식 우선 로드 전략은 세션 모드에서 매번 새로운 클래스 로더를 생성하므로 메타데이터 공간에서 메모리 누수가 발생합니다.

  3. 커넥터 간에 공용 클래스를 사용하면 오류가 발생합니다.

  4. 질문 2와 유사하게, 주로 일부 스레드 풀로 인해 데몬 스레드는 일부 클래스 개체 또는 클래스 클래스 개체에 대한 참조를 보유합니다.

  5. 네이티브 원사를 사용하여 업로드하는 경우 앱 클래스 로더에 배치됩니다. 그런 다음 앱 클래스 로더로 로드할 것으로 예상되지 않는 일부 클래스가 로드됩니다.

파일

08 Flink JobGraph 클래스패스 사용

/** 이 작업을 실행하는 데 필요한 JAR 파일 세트. */

개인 최종 ListuserJars = new ArrayList();

/** 이 작업을 실행하는 데 필요한 사용자 정의 파일 세트. */

개인 최종 MapuserArtifacts = 새로운 HashMap<>();

/** 이 작업을 실행하는 데 필요한 클래스 경로 목록. */

개인 ListClasspaths = Collections.emptyList();

  1. 클라이언트 측 처리인 JobGraph는 userJars, userArtifacts 및 Classpaths의 세 가지 속성을 처리합니다.

  2. 클래스 경로는 커넥터의 계층 구조만 남습니다.

  3. 세션을 시작할 때 jar를 업로드하면 jar가 Yarn의 모든 NodeManager 노드에 캐시됩니다.

  4. jobmanager 및 taskmanager가 Classloader를 빌드할 때 Classpath의 경로를 수정하고 현재 노드 NodeManager의 캐시 경로로 교체합니다.

  5. 다양한 커넥터에 따라 Flink Job의 Classloader를 빌드합니다.

  6. 빌드된 클래스로더를 캐시하면 다음 작업에 동일한 클래스로더를 사용할 수 있습니다. 메모리 누수를 피하십시오.

  7. 새 ChildFirstCacheClassloader에서 loadclass 메서드를 다시 작성하여 다른 커넥터 URL에 따라 별도의 Classloader를 생성합니다.

4. 발생한 문제 및 문제 해결 계획은?

jar 패키지 충돌에 대한 일반적인 예외는 클래스를 찾을 수 없음(java.lang.ClassNotFoundException), 특정 메소드를 찾을 수 없음(java.lang.NoSuchMethodError), 필드 오류(java.lang.NoSuchFieldError) 또는 클래스 오류(java.lang.LinkageError)입니다. .

● 일반적인 해결 방법은 다음과 같습니다.

1. 첫 번째 방법은 프로젝트 파일의 종속성 트리를 입력하는 것입니다.jar 패키지 종속성에 따라 동일한 jar 패키지가 여러 버전에 종속되는지 여부를 판별합니다.문제가 확인되면 잘못된 jar 패키지를 직접 확인할 수 있습니다. 제외된.

2. 종속성 트리를 보고 충돌하는 특정 jar 패키지를 확인할 수 없는 경우 jvm 매개변수를 추가하여 프로그램을 시작하고 클래스에서 로드한 특정 jar 정보를 인쇄할 수 있습니다(-verbose:class).

3. 위의 단계를 거친 후 jar 패키지 충돌 문제를 기본적으로 해결할 수 있으며 특정 문제를 자세히 분석해야 합니다.

● 공용 권장 도구

1.Maven 도우미

주로 클래스 충돌 문제 해결을 위한 IDEA 플러그인입니다.

2. 제이스택

일부 교착 상태 문제는 이 도구 jstack 호출 스택을 통해 볼 수 있습니다.

3.아서스

일부 성능 문제 및 Classloader 누수 문제를 해결합니다.

4. 비주얼 VM

일부 개체 메모리 누수, 덤프 파일 분석 등의 문제를 해결합니다.

캥거루 클라우드 오픈소스 프레임워크 DingTalk Technology Exchange Group(30537511), 빅데이터 오픈소스 프로젝트에 관심 있는 학생을 환영하며, 최신 기술정보를 공유하고 참여, 오픈소스 프로젝트 라이브러리 주소: https://github.com/DTStack/Taier

{{o.name}}
{{m.name}}

Supongo que te gusta

Origin my.oschina.net/u/3869098/blog/5583107
Recomendado
Clasificación