Это интересный вопрос о внутренностях компилятора Java.Я нашел список документов, обеспечивающих высокий уровень просмотра javac [1] [2] [3] [4] .Исходный код для конкретной реализации, такой как OpenJdk, также можно найти в сети [source] .
Компиляция состоит из 3 шагов высокого уровня [5] :
- "разобрать и ввести"
- "обработка аннотаций"
- "анализировать и генерировать"
Я написал некоторый код для проверки этих шагов, используя API дерева компиляторов, который предоставляет интерфейс для javac.
static class TestFileObject extends SimpleJavaFileObject {
public TestFileObject() {
super(URI.create("Test.java"), JavaFileObject.Kind.SOURCE);
}
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return "class Test { private int x; }";
}
}
public static void main(String[] args) throws IOException {
JavacTool tool = JavacTool.create();
JavacTask task = tool.getTask(null, null, null, null, null,
com.sun.tools.javac.util.List.of(new TestFileObject()));
// Step 1, Parse
Iterator<? extends CompilationUnitTree> trees = task.parse().iterator();
// Step 3, Analyze
// Iterator<? extends Element> elements = task.analyze().iterator();
// Step 3, Generate
// Iterator<? extends JavaFileObject> files = task.generate().iterator();
while(trees.hasNext()) {
CompilationUnitTree cu = trees.next();
System.out.println(cu.getTypeDecls());
}
}
Запуск вышеуказанногокод с шагом 1 показывает следующий вывод:
class Test {
private int x;
}
Таким образом, AST не содержит ссылок на java.lang.Object
.Затем я раскомментировал «Шаг 3, проанализировать» и повторно запустил свой код с полученным результатом:
class Test {
Test() {
super();
}
private int x;
}
Обратите внимание, что на этом шаге были добавлены конструктор Test()
и super()
, что также соответствуетк объяснению для шага 3 [5] :
При анализе дерева можно найти ссылки на классы, которые необходимы для успешной компиляции, но которые не были явно указаны длякомпиляция.
Наконец, я раскомментировал Step 3, Generate
, который создает файл Test.class
.При вызове javap -c Test.class
результирующий байт-код выглядит следующим образом:
class Test {
Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
}
Поэтому я пришел к выводу, что шаг генерации байт-кода добавляет java.lang.Object
связанную логику.