How does this happen internally? What mechanism is used? JNI, reflection or something different? Does the compiler include the extends
clause, perhaps?

- 149
- 1
- 8
-
3Correct. If your class doesn't explicitly extend another class, then the compiler ensures that it extends the primordial class `Object`. This is covered in great detail in [JLS-8.1.4 Superclasses and Subclasses](https://docs.oracle.com/javase/specs/jls/se9/html/jls-8.html#jls-8.1.4) – Elliott Frisch Mar 06 '19 at 23:04
-
I think this is a good question, assuming it isn't a duplicate. – RaminS Mar 06 '19 at 23:06
-
I don't see it being mentioned that the compiler injects `extends Object` in your link, @ElliottFrisch. – RaminS Mar 06 '19 at 23:11
-
2*Given a (possibly generic) class declaration C
(n ≥ 0, C ≠ Object), the direct superclass of the class type C – Elliott Frisch Mar 06 '19 at 23:17is the type given in the extends clause of the declaration of C if an extends clause is present, **or Object otherwise.*** -
Of course, and that is widely known—even by the OP. The question what the process by which this happens is (i.e. does the compiler inject `extends Object` in the bytecode, or does this happen in some other way?) – RaminS Mar 06 '19 at 23:20
-
@Gendarme I didn't find this question on the stack, so I asked. And thanks for editing the question. – JonyStack Mar 07 '19 at 10:02
2 Answers
Not completely correct.
All classes extend Object if they don't already extend another class, with one exception: java.lang.Object
itself doesn't extend any class.
The compiler embeds the superclass java.lang.Object
in the class file if the code doesn't specify another superclass.
You can even see it yourself if you open the .class
file with your favorite editor, you can see the string java/lang/Object
embedded in binary data.
(You can compile a very simple source file like public class A { }
to observe this best)

- 30,799
- 15
- 56
- 79
-
All classes extend Object. Many of them do not extend Object *directly*. – chrylis -cautiouslyoptimistic- Mar 06 '19 at 23:18
-
1@chrylis No they don't. Object doesn't extend Object. Not sure how I can make that clearer in my answer? And oh - all classes inherit java.lang.Object but they only extend their direct superclass. – Erwin Bolwidt Mar 06 '19 at 23:23
-
I would make it clear that a class in **some way or another** inherits behavior from `java.lang.Object`, if it's any class other than `java.lang.Object`. Even if it directly extends another class, some base class extends `java.lang.Object`. – Rohan Mar 07 '19 at 00:18
-
I don't understand why you are talking about multi-level inheritance (this conversation on the stack already exists). But I got my answer. Thank you @Erwin Bolwidt . If no one answers this question in more detail (i mean how javac it does), I'll just close it. – JonyStack Mar 07 '19 at 10:21
-
1To complete the picture, the compiler will always include a super class and the JVM’s verifier will reject a class if it doesn’t have a super class (unless it’s the `java/lang/Object` class itself). – Holger Mar 07 '19 at 10:46
This is an interesting question about the internals of the java compiler. I found a list of docs providing a high level view of javac [1][2][3][4]. Source code for a specific implementation like OpenJdk can be found online too [source].
Compilation consists of 3 high level steps [5]:
- "parse and enter"
- "annotation processing"
- "analyse and generate"
I wrote some code to test these steps out using the Compiler Tree API which provides an interface to 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());
}
}
Running the above code with Step 1 shows the following output:
class Test {
private int x;
}
So the AST doesn't contain references to java.lang.Object
. Next, I uncommented "Step 3, Analyse" and re-ran my code with the resulting output:
class Test {
Test() {
super();
}
private int x;
}
Notice that the Test()
constructor and super()
was added in this step,
which also corresponds to the explanation for Step 3 [5] :
While analysing the tree, references may be found to classes which are required for successful compilation, but which were not explicitly specified for compilation.
Finally, I uncommented Step 3, Generate
, which creates the Test.class
file. Calling javap -c Test.class
, the resulting bytecode is blelow :
class Test {
Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
}
So my conclusion is that the bytecode generation step adds the java.lang.Object
related logic.

- 9,102
- 5
- 39
- 43
-
Irrelevant. The superclass appears in the class file header, not just in the bytecode. – user207421 Mar 08 '19 at 23:01
-
My point is that java.lang.Object is added is the code generation step of the compilation pipeline as opposed to the parser, annotation or analysis steps. If you disagree, please provide evidence so we can learn from it. Thanks. – Dhruv Gairola Mar 08 '19 at 23:56