2012-02-29 6 views
0

런타임에 사용할 수없는 다른 클래스를 참조하는 클래스 파일을로드 할 때 매우 이상한 Java 클래스 경로 동작이 있습니다.이상한 Java 클래스 경로/클래스 로더 동작

매개 변수의 클래스를 상속하는 클래스에 캐스팅 된 매개 변수를 사용하여 다른 클래스의 생성자를 호출하는 (런타임 손길없는 메서드에서) 클래스를로드하면 매개 변수 클래스를 클래스에서 찾을 수없는 예외가 발생합니다. if 로드 할 클래스 만 해당 클래스의 메소드에서 참조하는 다른 클래스는 클래스 경로에 없습니다.

나는 다음과 같은 자바 사용하고 있습니다 : 여기

java version "1.6.0_18" 
Java(TM) SE Runtime Environment (build 1.6.0_18-b07) 
Java HotSpot(TM) 64-Bit Server VM (build 16.0-b13, mixed mode) 
(Windows Server 2008 R2) 

은 샘플입니다 : 이제

public class A 
{ 
    public static void main(String[] args) 
    { 
    System.out.println("it works"); 
    } 

    public void foo() 
    { 
    new B((D)null); 
    } 
} 

public class B 
{ 
    public B(C c) { 
    } 
} 

public class C 
{ 
} 


public class D extends C 
{ 
} 

내가 클래스를 컴파일하고, 내가 클래스 경로에있는 모든 클래스 파일을 클래스 A를 실행하면 , 그것은 "효과가있다". 내가 모든 클래스가 클래스 경로에서 클래스 A를 excepet 제거하면

는, 다음과 같은 오류가 발생합니다 : 클래스 C 런타임에 필요하지 말아야

Exception in thread "main" java.lang.NoClassDefFoundError: C 
Caused by: java.lang.ClassNotFoundException: C 
     at java.net.URLClassLoader$1.run(Unknown Source) 
     at java.security.AccessController.doPrivileged(Native Method) 
     at java.net.URLClassLoader.findClass(Unknown Source) 
     at java.lang.ClassLoader.loadClass(Unknown Source) 
     at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) 
     at java.lang.ClassLoader.loadClass(Unknown Source) 
Could not find the main class: A. Program will exit. 

있지만.

에 따라 별자리 작동 (클래스 A의 교체 "새로운 B ((D) 널 (null))") :도 (대신 D의 C 캐스팅, C가 어떤 클래스를 상속하지 않습니다) 작품

public class A 
{ 
    public static void main(String[] args) 
    { 
    System.out.println("it works"); 
    } 

    public void foo() 
    { 
    D d = (D)null; 
    d.toString(); 
    B b = (B)null; 
    b.toString(); 
    new B(null); 
    } 
} 

public class B 
{ 
    public B(C c) { 
    } 
} 

public class C 
{ 
} 


public class D extends C 
{ 
} 

에 따라 별자리

public class A 
{ 
    public static void main(String[] args) 
    { 
    System.out.println("it works"); 
    } 

    public void foo() 
    { 
    new B((C)null); 
    } 
} 

public class B 
{ 
    public B(C c) { 
    } 
} 

public class C 
{ 
} 


public class D extends C 
{ 
} 

예상되는 동작입니까, 아니면 Java 버그입니까?

+0

'런타임에는 클래스 C가 필요하지 않습니다.'런타임에는 가장 확실하게 필요합니다. D는 C이므로, C가 필요 없다고 말하는 것은 논리적으로 불가능합니다. – Woot4Moo

+0

이것은 사실이지만, C에 명시 적으로 캐스트하면 런타임시에도 사용할 수 없으므로 작동합니다. 클래스 B, C 및 D는 main 메소드가 println 만 가지고 있지만 다른 것은 없으며 foo는 호출되지 않습니다. – dominik

+0

IDE 또는 명령 줄을 통해이 작업을 수행하고 있습니까? 두 환경에서 시도해보십시오. 때로는 Eclipse가 "도움이되는"것을 선호합니다. – Woot4Moo

답변

0

나는 JSR을 통과하지 못했지만, 인터프리터가 클래스 파일을 해석 할 때 필요한 메소드 만 수행하면 모든 것이 가능할 것이라고 추측합니다. 이 경우 A이 필요하며 foo()도 해석되면 C이 필요합니다. 이 모든 일은 A이로드 될 때 발생합니다. 그래서 오류가 발생했습니다 ...

+0

C가 간접적으로 필요하다는 것을 알고 있습니다. 그러나 왜 D d = (D) 널입니까; 'd.toString(); Bb = (B) 널; b.toString(); 및 '새 B ((C) 널); ' 작동합니까? 이 모든 버전에는 B, C 및 D 클래스가 필요합니다. – dominik

+0

섹션 5.5를 참조하십시오. "런타임에 값이 null이면 캐스트가 허용됩니다."http : //java.sun.co.kr/docs/books/jls/second_edition/html/conversions.doc.html – kosa

1

refer section 5.5 "실행시의 값이 null이면 캐스팅이 허용되면"null 캐스팅이 작동하는 이유입니다.

+0

그게 .. 모든 경우 .. – Kashyap

+0

null casting이 항상 작동한다는 것을 설명합니다. 문제는 캐스팅 null에 관한 것이 아닙니다. 내 주요 질문은 클래스 로더가 클래스 C를로드해야한다고 생각하는 이유입니다. foo는 런타임에 호출되지 않습니다. 그리고 왜 클래스 C가 클래스 C를 파생 시켰는지를 결정합니다. 'public void foo() {새로운 B (새로운 C())}'ALSO WORKS; 'public void foo() {새 B (새 D())}'작동하지 않습니다. – dominik