문제

데스크톱 응용 프로그램이 대화해야 할 앱 서버에서 클래스로드를 동적으로 시작할 수 있도록 사용자 정의 클래스 로더가 있습니다. 우리는 이것을 수행 해야하는 항아리의 양이 말도 안되기 때문에 (우리가 배송하고 싶다면) 이것을했습니다. 또한 AppServer 라이브러리에서 런타임에 동적으로 클래스를로드하지 않으면 버전 문제가 있습니다.

이제, 나는 두 개의 다른 appservers와 대화 해야하는 문제를 겪었고, 수업에 따라 내가 먼저로드 할 수 있다는 것을 알았습니다 ... 실제로 JVM을 죽이지 않고 클래스의 하역을 강요 할 수있는 방법이 있습니까?

이것이 말이되기를 바랍니다

도움이 되었습니까?

해결책

클래스를 내릴 수있는 유일한 방법은 사용 된 클래스 로더가 수집 된 경우입니다. 즉, 모든 단일 클래스와 클래스 로더 자체에 대한 언급은 Dodo의 길을 가야합니다.

문제에 대한 가능한 해결책 중 하나는 모든 JAR 파일에 대한 클래스 로더와 특정 클래스의 실제로드를 특정 JAR 클래스 로더에 위임하는 각 AppServers에 대한 클래스 로더를 갖는 것입니다. 이렇게하면 모든 앱 서버의 다른 버전의 JAR 파일을 가리킬 수 있습니다.

그러나 이것은 사소한 것이 아닙니다. OSGI 플랫폼은 각 번들마다 클래스 로더가 있고 종속성이 플랫폼에 의해 해결 되므로이 작업을 수행하기 위해 노력합니다. 아마도 좋은 해결책은 그것을 살펴 보는 것일 것입니다.

OSGI를 사용하지 않으려면 하나의 구현은 하나의 인스턴스를 사용하는 것일 수 있습니다. jarclassloader 모든 JAR 파일에 대한 클래스.

클래스 로더를 확장하는 새로운 멀티 클래스 로더 클래스를 만듭니다. 이 클래스에는 내부적으로 jarclassloader의 배열 (또는 목록)이 있으며 정의가 찾을 수있을 때까지 모든 내부 클래스 로더를 통해 반복하거나 noclassDeffoundException이 발생합니다. 클래스에 새로운 jarclassloader를 추가하기 위해 몇 가지 액세서 방법을 제공 할 수 있습니다. Multiclassloader의 인터넷에는 몇 가지 가능한 구현이 있으므로 자신의 글을 쓸 필요조차 없습니다.

서버에 대한 모든 연결에 대해 멀티 클래스 로더를 시동하는 경우 원칙적으로 모든 서버가 동일한 클래스의 다른 버전을 사용할 수 있습니다.

나는 사용자 정의 스크립트가 포함 된 클래스를 메모리에서로드하고 언로드 해야하는 프로젝트에서 멀티 클래스 로더 아이디어를 사용했으며 잘 작동했습니다.

다른 팁

예, 클래스를로드하고 나중에 "언로드"하는 방법이 있습니다. 트릭은 고급 클래스 로더 (시스템 클래스 로더)와 앱 서버의 클래스 로더 사이에있는 자체 클래스 로더를 구현하고 앱 서버의 클래스 로더가 클래스로드를 상단 로더로 위임하기를 희망하는 것입니다. .

클래스는 패키지, 이름 및 원래로드 된 클래스 로더로 정의됩니다. 프로그램 JVM을 시작할 때로드 된 첫 번째 "프록시"클래스 로더를 프로그램하십시오. 워크 플로 :

  • 프로그램이 시작되고 실제 "메인"클래스는이 프록시 클래스 로더에 의해로드됩니다.
  • 그런 다음 일반적으로로드되는 모든 클래스 (즉, 계층 구조를 중단 할 수있는 다른 클래스 로더 구현을 통해서는) 가이 클래스 로더에 위임됩니다.
  • 프록시 클래스 로더 대의원 java.x 그리고 sun.x 시스템 클래스 로더 (이것들 안됩니다 시스템 클래스 로더 이외의 다른 클래스 로더를 통해로드하십시오).
  • 교체 가능한 모든 클래스의 경우 클래스 로더를 인스턴스화하고 (실제로 클래스를로드하고 부모 클래스 로더에 위임하지는 않음)이를 통해로드하십시오.
  • 클래스의 패키지/이름을 키로, 클래스 로더를 데이터 구조 (예 : 해시 맵)의 값으로 저장하십시오.
  • 프록시 클래스 로더가 이전에로드 된 클래스에 대한 요청을받을 때마다 이전에 저장된 클래스 로더에서 클래스를 반환합니다.
  • 클래스 로더가 클래스의 바이트 배열을 찾거나 데이터 구조에서 키/값 쌍을 "삭제"하고 클래스를 변경하려는 경우 클래스를 다시로드하는 것으로 충분해야합니다.

바로 거기에서 끝나지 않아야합니다 ClassCastException 또는 LinkageError 등.

클래스 로더 계층 구조에 대한 더 많은 정보를 원하시면 (예, 바로 여기에서 구현하고있는 것입니다.-) Ted Neward의 "서버 기반 Java 프로그래밍" - 그 책은 내가 원하는 것과 매우 유사한 것을 구현하는 데 도움이되었습니다.

나는 클래스 로더를 gging하지 않고 개별 클래스를 내릴 수있는 커스텀 클래스 로더를 썼습니다. JAR 클래스 로더

클래스 로더는 까다로운 문제가 될 수 있습니다. 여러 클래스 로더를 사용하고 상호 작용이 명확하고 엄격하게 정의되지 않은 경우 특히 문제가 발생할 수 있습니다. 실제로 클래스를 내릴 수 있으려면 youllre로 이동하는 클래스를 내리려고하는 모든 클래스 (및 해당 인스턴스)에 대한 모든 참조를 제거해야한다고 생각합니다.

이런 종류의 일을 해야하는 대부분의 사람들은 결국 사용됩니다. 오지. Osgi는 정말 강력하고 놀랍게도 가볍고 사용하기 쉽습니다.

클래스 로더를 내릴 수 있지만 특정 클래스를 내릴 수는 없습니다. 보다 구체적으로 당신은 당신의 제어가없는 클래스 로더에서 생성 된 클래스를 내릴 수 없습니다.

가능하면 자신의 클래스 로더를 사용하여 언로드 할 수 있습니다.

클래스는 클래스 로더 인스턴스에 대한 강력한 참조를 가지고 있으며 그 반대도 마찬가지입니다. 그들은 자바 물체와 같이 수집 된 쓰레기입니다. 도구 인터페이스 또는 이와 유사한 도구에 도달하지 않으면 개별 클래스를 제거 할 수 없습니다.

메모리 누출을 얻을 수 있습니다. 클래스 나 클래스 로더 중 하나에 대한 강력한 언급은 모든 것을 누출합니다. 이것은 예를 들어 Threadlocal, Java.sql.drivermanager 및 Java.beans의 Sun 구현에서 발생합니다.

언로드 클래스가 작동했는지 지켜보고 있다면 jconsole 또는 무언가를 추가 해보십시오 java.lang.System.gc() 수업이 끝나면 언로드 로직. 그것은 쓰레기 수집기를 명시 적으로 트리거합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top