Java, Classpath, Classloading => 동일한 jar / 프로젝트의 여러 버전
숙련 된 코더에게는 이것이 어리석은 질문 일 수 있음을 알고 있습니다. 그러나 내 프로젝트에 사용 된 다른 프레임 워크 / jar 중 일부에 필요한 라이브러리 (http 클라이언트)가 있습니다. 그러나 모두 다음과 같은 다른 주요 버전이 필요합니다.
httpclient-v1.jar => Required by cralwer.jar
httpclient-v2.jar => Required by restapi.jar
httpclient-v3.jar => required by foobar.jar
클래스 로더가 지능적으로 어떻게 분리되어 있습니까? 아닐까요? 클래스가 세 개의 항아리 모두에서 동일한 경우 클래스 로더는 이것을 어떻게 처리합니까? 어느 것이로드되고 왜?
Classloader는 정확히 하나의 항아리 만 집어 올리거나 임의로 클래스를 혼합합니까? 예를 들어 클래스가 Version-1.jar에서로드 된 경우 동일한 클래스 로더에서로드 된 다른 모든 클래스는 모두 동일한 jar로 이동합니까?
이 문제를 어떻게 처리합니까?
항아리를 "required.jar"에 어떻게 든 "병입"하여 트릭에 의해 "하나의 단위 / 패키지"로 표시 Classloader
되거나 링크되어 있습니까?
클래스 로더 관련 문제는 매우 복잡한 문제입니다. 어쨌든 몇 가지 사실을 명심해야합니다.
응용 프로그램의 클래스 로더는 일반적으로 단일 클래스 이상입니다. 부트 스트랩 클래스 로더는 적절한 것으로 위임합니다. 새 클래스를 인스턴스화하면보다 구체적인 클래스 로더가 호출됩니다. 로드하려는 클래스에 대한 참조를 찾지 못하면 부트 스트랩 클래스 로더에 도달 할 때까지 상위 클래스에 위임합니다. 로드하려는 클래스에 대한 참조를 찾지 못하면 ClassNotFoundException이 발생합니다.
동일한 이진 이름을 가진 두 개의 클래스가 있고 동일한 클래스 로더로 검색 할 수 있으며로드 할 클래스 중 하나를 알고 자하는 경우 특정 클래스 로더가 클래스 이름을 분석하는 방법 만 검사 할 수 있습니다.
Java 언어 사양에 따르면 클래스 이진 이름에는 고유성 제약 조건이 없지만 내가 볼 수있는 한 각 클래스 로더마다 고유해야합니다.
동일한 이진 이름으로 두 개의 클래스를로드하는 방법을 알아낼 수 있으며 기본 동작을 재정의하는 두 개의 다른 클래스 로더가 클래스 (및 모든 종속성)를로드해야합니다. 대략적인 예 :
ClassLoader loaderA = new MyClassLoader(libPathOne);
ClassLoader loaderB = new MyClassLoader(libPathTwo);
Object1 obj1 = loaderA.loadClass("first.class.binary.name", true)
Object2 obj2 = loaderB.loadClass("second.class.binary.name", true);
나는 항상 클래스 로더 커스터마이징이 까다로운 작업이라는 것을 알았습니다. 가능한 경우 여러 호환되지 않는 종속성을 피하는 것이 좋습니다.
각 클래스로드는 정확히 하나의 클래스를 선택합니다. 일반적으로 첫 번째가 발견되었습니다.
OSGi 는 동일한 jar의 여러 버전 문제를 해결하는 것을 목표로합니다. Equinox 와 Apache Felix 는 OSGi에 대한 일반적인 오픈 소스 구현입니다.
클래스 로더는 먼저 클래스 경로에 있었던 jar에서 클래스를로드합니다. 일반적으로 호환되지 않는 라이브러리 버전은 패키지에 차이가 있지만 실제로는 호환되지 않으며 jarjar로 대체 할 수 없습니다.
클래스 로더는 주문형 클래스를로드합니다. 즉, 응용 프로그램 및 관련 라이브러리에서 먼저 필요한 클래스는 다른 클래스보다 먼저로드됩니다. 종속 클래스로드 요청은 일반적으로 종속 클래스의로드 및 링크 프로세스 중에 발행됩니다.
LinkageError
클래스 로더에 대해 중복 클래스 정의가 발생 했다는 일반적으로 (로드 로더의 클래스 경로에 동일한 이름의 클래스가 두 개 이상있는 경우) 먼저로드 할 클래스를 판별하려고 시도하지 않는다는 메시지가 표시 될 수 있습니다. 때로는 클래스 로더가 클래스 경로에서 발생하는 첫 번째 클래스를로드하고 중복 클래스를 무시하지만 로더의 구현에 따라 다릅니다.
이러한 종류의 오류를 해결하기 위해 권장되는 방법은 종속성이 충돌하는 각 라이브러리 세트에 대해 별도의 클래스 로더를 사용하는 것입니다. 이렇게하면 클래스 로더가 라이브러리에서 클래스를로드하려고하면 다른 라이브러리 및 종속성에 액세스 할 수없는 동일한 클래스 로더가 종속 클래스를로드합니다.
URLClassLoader
for require를 사용하여 diff-2 버전의 jar에서 클래스를로드 할 수 있습니다 .
URLClassLoader loader1 = new URLClassLoader(new URL[] {new File("httpclient-v1.jar").toURL()}, Thread.currentThread().getContextClassLoader());
URLClassLoader loader2 = new URLClassLoader(new URL[] {new File("httpclient-v2.jar").toURL()}, Thread.currentThread().getContextClassLoader());
Class<?> c1 = loader1.loadClass("com.abc.Hello");
Class<?> c2 = loader2.loadClass("com.abc.Hello");
BaseInterface i1 = (BaseInterface) c1.newInstance();
BaseInterface i2 = (BaseInterface) c2.newInstance();
'Programing' 카테고리의 다른 글
document ()와 함께 copy-of를 사용하여 XHTML 출력에 SVG 추가 (0) | 2020.07.26 |
---|---|
실패 후 Internet Explorer가 Ajax 호출에서 HTTP 포스트 본문을 보내지 않는 이유는 무엇입니까? (0) | 2020.07.26 |
RESTful 웹 서비스-다른 서비스의 요청을 인증하는 방법? (0) | 2020.07.26 |
WordPress에 간단한 jQuery 스크립트를 어떻게 추가합니까? (0) | 2020.07.25 |
도커 컨테이너에 인터넷이 없습니다. (0) | 2020.07.25 |