JAR을 동적으로로드하는 응용 프로그램을 개발하고 있습니다. JAR에는 사용하는 클래스 묶음의 정의가 들어 있습니다. 동적으로로드 된 JAR에있는 Exception 파생 클래스를 잡으려고 할 때까지 모든 것이 잘 진행되었습니다.Java에서 예외 클래스는 필요하기 전에 클래스 로더가 사용할 수 있어야하는 이유는 무엇입니까?
다음 코드는 문제를 보여줍니다 (DynamicJarLoader
실제로 JAR를로드하는 클래스이며, 모두 TestClass
및 MyException
외부 JAR에) :
public static void main(String[] args) {
DynamicJarLoader.loadFile("../DynamicTestJar.jar");
try {
String foo = new TestClass().testMethod("42");
} catch(MyException e) { }
}
내가 그것을 실행하려고, 난이 얻을 : 내가 catch(Exception e)
와 catch(MyException e)
를 교체 할 경우
Exception in thread "main" java.lang.NoClassDefFoundError: dynamictestjar/MyException
Caused by: java.lang.ClassNotFoundException: dynamictestjar.MyException
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
Could not find the main class: dynamicjartestapp.Main. Program will exit.
, 프로그램은 잘 실행됩니다. 즉, Java 은이며, JAR이 이미로드 된 후 TestClass
을 찾을 수 있습니다. 그래서 JVM은 프로그램이 실행될 때 (그리고 특정 try-catch 블록에 도달 할 때) 필요하지 않을 때가 아니라 모든 Exception 클래스를 정의해야합니다.
왜 이런 일이 발생합니까?
편집
나는 몇 가지 추가 테스트를 실행했습니다, 이것은 실제로 매우 이상하다.
이package dynamictestjar;
public class MyException extends RuntimeException {
public void test() {
System.out.println("abc");
}
}
이 코드가 실행 :
public static void main(String[] args) {
DynamicJarLoader.loadFile("../DynamicTestJar.jar");
String foo = new TestClass().testMethod("42");
new MyException().test(); //prints "abc"
}
이되지 않습니다
는public static void main(String[] args) {
DynamicJarLoader.loadFile("../DynamicTestJar.jar");
String foo = new TestClass().testMethod("42");
new MyException().printStackTrace(); // throws NoClassDefFoundError
}
내가 넷빈즈에서 내 테스트를 실행할 때마다 지적한다이 MyException
의 전체 소스입니다 모든 것이 계획대로 진행됩니다. 기묘함은 Java의 눈에서 강제로 외부 항아리를 제거하고 명령 줄에서 테스트 응용 프로그램을 실행할 때만 시작됩니다.
public static void main(String[] args) {
DynamicJarLoader.loadFile("../DynamicTestJar.jar");
String foo = new TestClass().testMethod("42");
class tempClass {
public void test() {
new MyException().printStackTrace();
}
}
new tempClass().test(); // prints the stack trace, as expected
}
바이트 코드 재주문이로드 파일 명령문 앞에 Exception을 참조하면이 문제가 발생할 수 있지만 필자는 이러한 문제에 대해서는 충분히 잘 알고 있지 않습니다. – Yishai
이 방법으로 JAR을로드하는 것을 정당화하는 것은 아무것도 없습니다. 간단한 예입니다 만, 본격적인 코드의 이유는 무엇입니까? – duffymo
@duffymo : 애플릿은 두 개로 나뉩니다. 더 큰 절반은 로컬 컴퓨터에 설치되므로 사용자는 매번 다운로드하지 않습니다 (다소 크기가 큽니다). 실제 애플릿은 다른 애플릿을로드 한 다음 필요한 로직을 수행합니다. "로드 중"이라 함은 실제로 클래스 경로를 동적으로 변경하여 Jar를 가리키는 것을 의미합니다. 아마도 이것을 달성하는 더 좋은 방법이 있을까요? –