2016-10-16 6 views
1

동적으로로드 된 jar 파일에서 클래스를로드하려고합니다. 현재 루트 클래스 Object가 아닌 클래스로 확장되지 않는 클래스를로드 할 수 있지만 사용자 정의 클래스를 확장하는 클래스를로드 할 수 없습니다. 내 문제에 대한 자세한 설명은 다음과 같습니다. I가 프로젝트 A를 수출동적으로로드 된 jar 파일에서 수퍼 클래스로 Java 클래스로드

class B1 { 
} 

class B2 extends A { 
} 

: 프로젝트 B에서

class A { 
} 

, 클래스 B1과 같은 클래스 B2가 있습니다 :

프로젝트 A의

는 클래스 A가 같이있다 a.jar, 프로젝트 B를 b.jar로 변경하십시오. 테스트 코드는 다음과 같습니다

File f = new File("Z:\\Jars\\b.jar"); 
URLClassLoader urlClassLoader = new URLClassLoader(new URL[] { f.toURL() }, 
     System.class.getClassLoader()); 

Class<?> classB1 = (Class<?>) urlClassLoader.loadClass("b.B1"); 
System.out.println("B1 is loaded"); 

Class<?> classB2 = (Class<?>) urlClassLoader.loadClass("b.B2"); 
System.out.println("B2 is loaded"); 

클래스 B1이 성공적으로로드되어 있지만 클래스 B2 인해 클래스 a.A에로드되지 않습니다 발견되지 않는 예외 :

java -cp a.jar;b.jar; a.Main 
B1 is loaded 
Exception in thread "main" java.lang.NoClassDefFoundError: a/A 
Caused by: java.lang.ClassNotFoundException: a.A 
     at java.net.URLClassLoader.findClass(Unknown Source) 
     at java.lang.ClassLoader.loadClass(Unknown Source) 
     at java.lang.ClassLoader.loadClass(Unknown Source) 
     ... 12 more 

가 어떻게이 문제를 해결할 수 있습니까? 감사합니다. .

추신. 에 a.jar를 포함하여, 클래스 B2로드 있지만 다음 테스트에 실패 할 수있다 :

Class<A> classB2 = (Class<A>) urlClassLoader.loadClass("b.B2"); 
A ab2 = classB2.newInstance(); 

첫 번째 라인은 미세하지만 두 번째 줄에 다음과 같은 예외 트리거 :

Exception in thread "main" java.lang.ClassCastException: b.B2 cannot be cast to a.A 
    at a.Main.main(Main.java:22) 

B2 인을 A 인스턴스, 왜 이런 일이 일어 났는지 생각해?

+0

클래스 A를 포함하지 않고 jar b.jar을 어떻게 작성 하시겠습니까? b.jar에서 A.class를 수동으로 제거 하시겠습니까? – Mahesh

+0

Eclipse를 사용 중이 었는데 프로젝트 B를 프로젝트 A에 의존하도록 설정 했으므로 프로젝트 B를 빌드하고 jar 파일을 내보낼 수 있습니다. 위의 데모 케이스의 경우 a.jar를 포함하여 문제가 해결되었으며 클래스 B2를로드하고 A로 캐스팅 할 수 있습니다. – DeepParticle

+1

http://stackoverflow.com/questions/2591779/cast-across-classloader의 첫 번째 대답은 다음과 같습니다. 서로 다른 클래스 로더에 의해로드 된 동일한 클래스의 클래스를 서로 캐스팅 할 수 없다는 점입니다. – DeepParticle

답변

0

a.A 두 개의 클래스는 스레드의 기본 클래스 로더에 의해로드되고 다른 클래스는 사용자 정의 클래스 로더에 의해로드됩니다.

a.A을 인쇄하지만 다른 클래스 로더에서 인쇄 할 수있는 클래스가 두 개 있기 때문에 메시지가 혼란 스럽습니다. 당신이해야 할 것은 스레드로드됩니다 a.A 기본 클래스 로더에서이며 같은 이름을 가지고 일하지만 당신도이를 사용할 수 없습니다 때문입니다

Class classB2 = urlClassLoader.loadClass("b.B2") 
Object ab2 = classB2.newInstance(); 

입니다. 이 약

또 다른 방법은 단 하나의 클래스 로더가이 a.A

File f = new File("Z:\\Jars\\b.jar"); 
URLClassLoader urlClassLoader = new URLClassLoader(new URL[] { f.toURL() }); 

으로이 a.A 그래서 그 이름의 하나의 클래스가로드 ClassLoader.getSystemClassLoader()을 사용합니다로드하는 것입니다.

+0

명확한 설명에 감사드립니다.당신이 제안한 컨텍스트 클래스 로더는 나를위한 새로운 컨셉이다. 나는 그것을 작동시킬 수 있는지 알게 될 것이다. – DeepParticle

+0

@Depeparticle 현재 스레드가 클래스를로드하는 데 사용하는 스레드입니다. –

+1

컨텍스트 클래스 로더 – the8472

관련 문제