Когда в Java происходит сбой динамически загружаемого класса, который ссылается на несуществующие классы / методы? - PullRequest
4 голосов
/ 20 января 2011

Предположим, я динамически загружаю класс Java C, который ссылается на несуществующий класс / методы. Такой случай может возникнуть, когда C был написан для более новой версии Java. Когда произойдет сбой - как только загрузится C или когда будет запущен метод, который вызывает несуществующий класс / метод? Меняется ли это с ВМ - включая другие версии Java, такие как Java ME?

Ответы [ 4 ]

4 голосов
/ 20 января 2011

Когда произойдет сбой?

как только C будет загружен?

Нет. Только если при загрузке он ссылается на несуществующий класс (т.е. у вас есть атрибут класса этого типа)

или когда запускается метод, который вызывает несуществующий класс / метод?

Да. Это будет так.

Например, это хорошо работает.

C:\>more > A.java
class A {}
^C
C:\>more > B.java
class B {
   public void method() {
      A a = new A();
    }
    public void other() {
       System.out.println("Hello there");
    }
    public static void main( String ... args ) {
        B b = new B();
        b.other();
    }
}

C:\>javac A.java B.java

C:\>erase A.class

C:\>java B
Hello there

Класс B загружается Java, но, поскольку ни один из кодов, используемых method, не работает хорошо.

В отличие от:

C:\>more > A.java
class A {}

C:\>more > B.java
class B {
   void method() {
      A a = new A();
   }
   public static void main( String ... args ) {
       B b = new B();
       b.method();
   }
}
^C
C:\>javac A.java B.java

C:\>erase A.class

C:\>java B
Exception in thread "main" java.lang.NoClassDefFoundError: A
        at B.method(B.java:3)
        at B.main(B.java:7)
Caused by: java.lang.ClassNotFoundException: A
        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)
        ... 2 more

Сбой, потому что B попытался получить доступ к A.

2 голосов
/ 20 января 2011

По крайней мере на обычной старой Java я обнаружил, что она потерпит неудачу в тот момент, когда вы ссылаетесь на сломанный класс или метод:

Пример из моей недавней истории:

Я использую редактор Java (написанный на Java) с простой системой плагинов. Я обновил редактор, но использовал плагин, скомпилированный со старой версией редактора, который все еще ссылался на класс, где для краткости мы будем называть Foo, который был перемещен из внутреннего класса в пакет сам по себе.

Когда я вызвал плагин, он не потерпел неудачу, пока не попытался создать экземпляр Foo. Поскольку Foo не было в том месте, где код плагина сказал, что это будет, он выбросил NoClassDefFoundError .

Кстати, между как минимум версиями Java, такими как Java 1.5 и Java 1.6, вам обычно не нужно беспокоиться об их удалении или перемещении, поскольку люди будут кричать о кровавом убийстве, если вы возитесь с установленным API. 1013 *

1 голос
/ 20 января 2011

Этот шаг называется «разрешением», при этом загружаются другие классы, на которые ссылается этот класс.

Спецификация языка позволяет изменять время выполнения этого шага. Это может быть сделано наиболее охотно, в начале VM, рекурсивно разрешая все классы, на которые прямо или косвенно ссылаются основные классы. Или это можно сделать самым ленивым, разрешив класс только тогда, когда это абсолютно необходимо.

Мой опыт работы с серверными JVM заключается в том, что это сделано как можно позже. Таким образом, до тех пор, пока не будет выполнен код, ссылающийся на отсутствующие классы, ошибок не будет.

Это также зависит от того, как вы загружаете свой класс. java.lang.Classloader.loadClass(name) не делает разрешение. Однако существует защищенный метод loadClass(name,resolve), который вы можете использовать для принудительного разрешения во время загрузки. Однако его точное поведение плохо документировано.

0 голосов
/ 20 января 2011

Не удастся загрузить. Это может быть довольно раздражающим, но, конечно, недостаточно быть осторожным. Способ обойти это - динамически загружать разные классы в зависимости от того, какие другие определения, которые вы знаете, доступны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...