Java question about a .class generated with Java 14
I have a simple class like this:
class ClassWithDefaultConstructor{}
I am working with this JDK:
C:\JavaSE14Folder>java -version
java version "14" 2020-03-17
Java(TM) SE Runtime Environment (build 14+36-1461)
Java HotSpot(TM) 64-Bit Server VM (build 14+36-1461, mixed mode, sharing)
As you can see I am using the latest version of the JDK.
I create this .class like this:
C:\JavaSE14Folder>javac -d . ClassWithDefaultConstructor.java
The .class is created later on i try this command:
C:\JavaSE14Folder>javap ClassWithDefaultConstructor.class
And I see the following:
Compiled from "ClassWithDefaultConstructor.java"
class ClassWithDefaultConstructor {
ClassWithDefaultConstructor();
}
Two things here made me happy; first the default constructor is created and I see that the visibility of the constructor is the same of the class, but three things made feel sad.
My questions are:
- Why the constructor has no body and terminates with
;
? - Why the constructor hasn't a call to the java.lang.Object constructor?
- Why this class is not extending
java.lang.Object
?
I did expect something like this:
class ClassWithDefaultConstructor extends java.lang.Object {
ClassWithDefaultConstructor(){
super();
}
}
I expected a bytecode something like this post:
Post
Did I miss something?
If I put the command like this:
C:\JavaSE14Folder>javap -c ClassWithDefaultConstructor.class
Compiled from "ClassWithDefaultConstructor.java"
class ClassWithDefaultConstructor {
ClassWithDefaultConstructor();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."
<init>":
()V
4: return
}
Is different but still I don't see my stuff like extending Object and so.
I would love see something like this at least like in the post:
Compiled from "test.java"
public class test extends java.lang.Object{
In summary, I don't see the compiler inserting those implicit lines.
In this Java Question about a .class generated with Java 14 states that happens the same on the newer versions of Java.
Same output using:
C:\Program Files\Java\jdk1.8.0_121\bin
Solution 1:
Bytecode != Java source code.
What is actually in the classfile is just random bytes. What you are seeing is javap
's textual representation of the bytecode, which is designed to be familiar to Java programmers who don't know much about bytecode, and hence uses Java like syntax where possible. But it is not and is not meant to be actual Java source code.
If you used a different disassembler such as Krakatau, the output would look very different, but it would still be a representation of the same binary classfile.
Solution 2:
From javap
's documentation:
"The javap command disassembles one or more class files."
It does not decompile the class file, that is, it is not intended to create valid java source code.
"1. Why the constructor has no body and terminates with ;?"
it is not decompiled code, not valid Java, just an indication there is such constructor.
"2. Why the constructor hasn't a call to the java.lang.Object constructor?"
it is being omitted by javap
, but it is there, displayed if correct options were used (see below).
"3. Why this class is not extending java.lang.Object?"
same as previous, it is, just not displayed by javap
.
To see more details, we must add the -v
(verbose) option to the javap
call. Here the output if using javap -c -v ClassWithDefaultConstructor
(line numbers added by me):
1 Classfile /C:/tmp/ClassWithDefaultConstructor.class
2 Last modified 16 Jan 2022; size 228 bytes
3 SHA-256 checksum 101973fdf86b3e7facf263214f6932a9353ef7be914efec9963be3a578b3ddaf
4 Compiled from "ClassWithDefaultConstructor.java"
5 class ClassWithDefaultConstructor
6 minor version: 0
7 major version: 61
8 flags: (0x0020) ACC_SUPER
9 this_class: #7 // ClassWithDefaultConstructor
10 super_class: #2 // java/lang/Object
11 interfaces: 0, fields: 0, methods: 1, attributes: 1
12 Constant pool:
13 #1 = Methodref #2.#3 // java/lang/Object."<init>":()V
14 #2 = Class #4 // java/lang/Object
15 #3 = NameAndType #5:#6 // "<init>":()V
16 #4 = Utf8 java/lang/Object
17 #5 = Utf8 <init>
18 #6 = Utf8 ()V
19 #7 = Class #8 // ClassWithDefaultConstructor
20 #8 = Utf8 ClassWithDefaultConstructor
21 #9 = Utf8 Code
22 #10 = Utf8 LineNumberTable
23 #11 = Utf8 SourceFile
24 #12 = Utf8 ClassWithDefaultConstructor.java
25 {
26 ClassWithDefaultConstructor();
27 descriptor: ()V
28 flags: (0x0000)
29 Code:
30 stack=1, locals=1, args_size=1
31 0: aload_0
32 1: invokespecial #1 // Method java/lang/Object."<init>":()V
33 4: return
34 LineNumberTable:
35 line 1: 0
36 }
37 SourceFile: "ClassWithDefaultConstructor.java"
line number 10: super_class: #2 // java/lang/Object
gives us the super class, that is, Object
line number 32: 1: invokespecial #1 // Method java/lang/Object."<init>":()V
this is calling the constructor of Object
for the actual instance (previous line aload_0
=this
) - <init>
is the name used for constructors (independent of class name) - that is the equivalent to super()
.