2016-07-26 1 views
1

같은 클래스의 여러 버전을 JVM에로드 할 수 있습니까? 나는 "XYZ"클래스의 버전을 주 스레드에로드하고 여러 작업을 수행하는 여러 개의 스레드가 있습니다. 자식 스레드에 "XYZ"클래스의 다른 버전을로드하려고합니다.클래스 파일의 여러 버전을 JVM에로드

이 것이 가능합니까? 각 자식 스레드에 대해 새로운 컨텍스트 클래스 로더를 만들고이 컨텍스트 클래스 로더를 사용하여 다른 버전의 클래스를로드하려고 생각했습니다. 지금은 컨텍스트 클래스 로더에 URLClassLoader를 사용하고 있지만 작동하지 않는 것 같습니다. 작업을 수행하기 위해 사용자 정의 클래스 로더를 작성해야합니까?

여기에 제가 지금까지 가지고있는 코드가 있습니다. I 클래스 "XYZ"의 정적 필드에 다른 값을 갖고 싶어하기 때문에

final Thread builderThread = new Thread("Child Thread " + buildToken) { 
     @Override 
     public void run() { 
      futureTask.run(); 
     } 
    }; 

    try { 
     URL url = new URL("file:///path to the jar file"); 
     URLClassLoader classLoader = new URLClassLoader(new URL[]{url}); 
     classLoader.loadClass("XYZ"); 
     builderThread.setContextClassLoader(classLoader); 
    } 

I 클래스의 다른 버전을 갖고 싶어하는 이유입니다.

+4

디자인 문제라고 생각합니다.정적 필드가 다른 경우 정적 인 필드 만 변경하면됩니다. – TMichelsen

+0

글쎄요, XYZ는 많은 곳에서 사용되는 레거시 클래스입니다.이 변경 작업에는 많은 노력이 필요합니다. – ajaymysore

+0

getter 메서드를 통해 정적 필드를 노출하고 호출자 컨텍스트를 기반으로 다른 값을 반환 할 수 있습니까? 리팩토링이 많이 필요합니까? 덕분에 –

답변

2

네, 가능하며 올바른 경로에 URLClassLoader으로 있습니다. 클래스 로더의 범위는 static 필드에 포함하려는 범위에 따라 결정됩니다. 예를 들어, 각 작업 또는 스레드가 해당 필드의 자체 복사본을 가져야하는 경우 각 작업 또는 스레드마다 고유 한 클래스 로더가 있어야합니다.

알고 있어야 할 몇 가지 다른 문제가 있습니다. 먼저 여러 클래스를로드하려는 클래스 은 시스템 클래스 경로에이 없어야합니다. 이는 클래스 로더가 계층 구조에 있고 클래스를로드하기 전에 부모에게 위임하기 때문입니다. 시스템 클래스 로더가 클래스를 찾으면 클래스를 한 번만로드하고 다른 클래스 로더는 시스템 클래스 로더가로드 한 클래스를 사용합니다.

둘째, JVM은 클래스가 모두 동일하다는 사실에도 불구하고 클래스의 각로드를 고유 한 클래스로 취급합니다. 즉, 동적으로로드되는 클래스의 인스턴스는 클래스 로더의 범위에 한정되어야합니다. 각 작업에 고유 한 클래스 로더가 있으면 작업간에 인스턴스를 전달할 수 없습니다. 그리고 나머지 애플 리케이션은 클래스에 대해 알 필요가없는 시스템 클래스 로더를 사용하기 때문에 분명히 인스턴스를 다른 앱에 게시 할 수 없습니다. (당신은 동적으로로드 된 클래스는 슈퍼 클래스 또는 시스템 클래스 로더 가 알지 않는 슈퍼가있는 경우 다소. 그럼 당신은 그 유형으로 인스턴스를 게시 할 수 있습니다이 문제를 해결 얻을 수 있습니다.)

+0

. 두 번째 문제는 인스턴스를 전달할 계획이 없기 때문에 제 경우에는 문제가되지 않습니다. 그러나 첫 번째 문제는 실제 문제이며 사용자 정의 클래스 로더 작성을 고려한 이유였습니다. 상위 클래스 로더는 클래스 경로에서 이미 XYZ 클래스의 버전을로드했습니다. 부모 클래스 로더에 위임하기 전에 클래스 자체를로드하려고하는 사용자 정의 클래스 로더를 작성하려고합니다. 나는 뛰어 넘어야 할 몇 가지 함정이 있다는 것을 알고 있습니다. 예를 들어, XYZ 클래스를 제외하고 모든 클래스는 동일한 클래스 로더 계층을 따라야합니다. 생각? – ajaymysore

+0

@ajaymysore 그럴 수도 있습니다. 그러나이 모든 것이 동일한 JVM에서 수행되어야하는 이유가 있습니까? 당신은'XYZ'의 오래된 정의를 사용하는 별도의 도우미 응용 프로그램이 있다면 classloader 헛소리를 피할 수 있습니다. 기본적으로 주요 응용 프로그램이 호출하는 일종의 서버입니다. –

0

이유를 내가 원하는 이유 "XYZ"클래스의 정적 필드에 대해 다른 값을 갖기를 원하기 때문에 다른 버전의 클래스가 있어야합니다.

이것은 실제로 나에게 해킹처럼 보입니다. 이 클래스에 다른 값을 주입 할 다른 방법이 없습니까?

각 스레드에 대해 일종의 Context 인스턴스를 전달하고 static 필드 대신 Context의 설정을 사용하도록 클래스를 변환하는 것은 어떻습니까? ThreadLocal을 사용하여 각 스레드가 정적 필드 정보를 얻을 수 있도록 할 수도 있습니다.

다른 버전의 클래스를로드하면 디버깅이 매우 어렵습니다 (불가능하지는 않지만). 내가 여러 클래스 로더를 사용하는 사람들에 대해 들어 본 유일한 시간은 보안 문제 (종종 웹 서버 환경에서)와 웹 클래스와 외부 관리 클래스 사이의 분리에 대한 신중한 포인트가있는 경우입니다.

관련 문제