Порядок загрузчика классов в Java во время компиляции и выполнения

Я создал ниже класс с квалифицированным именем java.lang.String в Яве.

package java.lang;

public class String {
    public int getValue() {
        return 42;
   }
}

В основной класс я добавил код ниже.

public class Main {

    public static void main(String[] args) {
        String s = new String();
        System.out.println(s.getValue());
    }
}

Код компилируется просто отлично. Когда я запускаю код, он завершается с ошибкой ниже.

 Exception in thread "main" java.lang.NoSuchMethodError:    java.lang.String.getValue()I
at com.Main.main(Main.java:12)

Я должен понять java.lang.String загружается загрузчиком классов начальной загрузки во время выполнения из файла rt.jar.

Итак, я думаю, что порядок загрузки классов должен отличаться во время компиляции и во время выполнения. Можете ли вы дать порядок загрузки классов во время компиляции и выполнения.

1 ответ

Решение

Прежде всего, этот тест не будет работать в Java 9 или новее. Попытка скомпилировать String класс выдаст эту ошибку:

java/lang/String.java:1: error: package exists in another module: java.base
package java.lang;
^

На Java 8 я получаю поведение, которое вы видите. Предполагая, что изменено String класс находится в том же исходном дереве, Main класс компилируется, но выдает исключение при попытке его запустить.

Это, как представляется, было сообщено как ошибка 4929425. Решение было это ошибка документации, и они уточнили документацию для javac команда... хотя, возможно, не достаточно.

Во всяком случае, есть разница, и она тонкая.

java Команда просто ищет в следующем порядке:

  • начальный путь
  • каталоги расширения
  • Путь к классам

javac Команда сначала ищет исходный каталог. Если он находит там исходный файл, он ищет соответствующий файл класса в том же месте и (при необходимости) компилирует или перекомпилирует его. Если исходный файл не найден, он ищет пути к классам для файла класса, как описано выше для java,

Обратите внимание, что требуется очень тщательное чтение javac ручной ввод, чтобы дразнить это. Это легко пропустить. ( https://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html)

(IMO, они могут сделать страницу руководства более понятной. Однако это несоответствие имеет значение только в том случае, если вы пытаетесь переопределить какой-либо класс в пути к начальной загрузке или в каталоге расширений. И вы делаете это неправильно. По сути, это крайний случай. Проблема с четким документированием непонятных крайних случаев заключается в том, что вы можете сделать документацию более запутанной для обычного случая.)

Другие вопросы по тегам