Исключение ClassNotFound в предложении catch
public class dummy {
public static void main(String[] args) { System.out.println("hello world"); }
public void init() {
//"dummy2" class defined in a different jar
dummy2 d = new dummy2();
try { d.run(); }
//"dummyexception" class defined in a different jar
catch (dummyexception e) { e.printStackTrace(); }
catch (Exception e) { e.printStackTrace(); }
}
public void init2() {
Runnable r = new Runnable() {
@Override
public void run() {
//"dummy2" class defined in a different jar
dummy2 d = new dummy2();
try { d.run(); }
//"dummyexception" class defined in a different jar
catch (dummyexception e) { e.printStackTrace(); }
catch (Exception e) { e.printStackTrace(); }
}
};
}
}
Теперь перед запуском я удалил зависимую банку из пути к классам. Я получил 'ClassNotFoundException
"для класса"dummyexception
ссылаться в методе init()
а не для использования в методе init2()
, Интересно нетClassNotFoundException
"для класса"dummy2
ссылаться в методе init()
,
3 ответа
Теперь перед запуском я удалил зависимую банку из пути к классам. Я получаю ClassNotFoundException для класса "dummyexception", на который ссылается метод init(), а не для использования в методе init2().
Учебный класс dummy2
будет загружаться только тогда, когда будет запущен метод init. Несмотря на dummyexcetion
является параметром catch, поэтому JVM обрабатывает этот класс как метод java. Полное имя для dummyexception
класс помещается в файл jvm *.class constant_pool и JVM проверяет доступность класса перед dummy
был загружен.
Давайте рассмотрим пример:
public class Dummy {
public void init(){
DummyExternal dummy = new DummyExternal();
try {
dummy.run();
} catch(DummyException e) {
} catch(Exception e){ }
}
public void init2(){
new Runnable() {
@Override
public void run() {
DummyExternal dummy = new DummyExternal();
try {
dummy.run();
} catch(DummyException e) {
e.printStackTrace();
} catch(Exception e){}
}
}.run();
}
public static void main(String[] args){
System.out.println("hello world");
}
}
public class DummyException extends RuntimeException {
private static final long serialVersionUID = 2049347223914508696L;
static {
System.out.println("DummyException");
}
}
public class DummyExternal implements Runnable {
static {
System.out.println("DummyExternal");
}
@Override
public void run() {
System.out.println("DummyExternal");
}
}
В результате мы будем иметь:
-rw-r -r-- 1 такой персонал 756B 19 мая 08:26 Пустышка $ 1.класс
-rw-r -r-- 1 такой персонал 956B 19 мая 08:26 Dummy.class
-rw-r -r-- 1 такой персонал 545B 19 мая 08:26 DummyException.class
-rw-r -r-- 1 такой персонал 569B 19 мая 08:26 DummyExternal.class
команда java Dummy
Распечатать hello world
, Так нет DummyExternal
или же DummyException
класс был загружен.
Удалить DummyExternal
файл класса: rm DummyExternal.class
, Результат java Dummy
не меняй.
Давайте удалим DummyException
файл класса: rm DummyException.class
,
И после исполнения java Dummy
мы получаем интересную трассировку стека.
Exception in thread "main" java.lang.NoClassDefFoundError: DummyException
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2442)
at java.lang.Class.getMethod0(Class.java:2685)
at java.lang.Class.getMethod(Class.java:1620)
at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:494)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:486)
Caused by: java.lang.ClassNotFoundException: DummyException
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
... 6 more
Такое поведение обусловлено механизмом обработки исключений. Если class является параметром catch, генерируют обработчики исключений, которые должны быть разрешены при обработке исключения. Механизм обработки исключений аналогичен вызову метода и разрешению ClassLoader DummyException
из постоянного пула до загрузки класса.
Предположение здесь - методы проверяются в лексографическом порядке, и для каждого метода обработчики исключений проверяются перед локальными переменными.
Если я правильно понимаю, вы сначала скомпилировали свой класс, предоставив все зависимые jar
файлы. И именно поэтому ваш класс успешно скомпилирован. И тогда вы удалили все зависимые jar
файлы перед запуском вашей программы. И тогда вы получили ошибку.
Мой взгляд на это:
По моему мнению, вы не должны получать никаких ошибок, потому что init()
а также init2()
, которые используют зависимые банки, не вызываются никакими функциями.
Какова связь между не вызываемыми функциями и генерацией ошибок?
Когда вы компилируете свои классы, JVM создает файлы классов. В этих файлах классов JVM создает symbolic string references
к вызову методов и классов путем поиска классов в classpath
, Если он не находит ссылочные классы, вы получите ошибки во время компиляции, и ваши классы не будут компилироваться. Если он найдет его, значит, ваша компиляция прошла успешно, а затем JVM добавит symbolic string references
внутри файла класса. Там нет актуального pointer to methods and classes
на данный момент.
Теперь, когда вы запускаете вашу программу, ваши вызовы методов находятся в виде тех symbolic string references
в файле класса. На данный момент эти symbolic references
превращаются в actual pointers to classes and methods
, На данный момент ваш class loader
будет искать эти зависимые классы only if
ссылочные методы вызываются из некоторого метода. Если он не находит зависимые классы в пути к классам, генерируется ошибка. Замечания: class loader
не будет искать зависимые классы, если методы не вызываются. Symbolic instructions
будет проигнорировано, и ошибка не будет сгенерирована.
Что происходит в вашем случае?
Я не вижу твоего init()
а также init2()
быть вызванным кем-либо. Что значит class loader
не нужно искать dependent jars
а также create pointer to these methods
, Это означает, что вы не должны получать никаких ошибок Unless
что-то вызывает эти методы.