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