I am trying to implement JVM(Java8) by python as a study.
I want to execute java Main. In main method, Person instance will be initialized.
Then Person class constructor invoke special Method java/lang/Object."<init>":()V.
But I can't find the definition of that method although I saw JVM spec.
Main.java
class Main{
public static void main(String[] args){
Person p = new Person("Jeff", 17);
}
}
Person.java
public class Person {
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
}
To compile, I used javac -encoding UTF-8 -target 8 -source 8 *.java.
javap -v Main shows below
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=4, locals=2, args_size=1
0: new #7 // class Person
3: dup
4: ldc #9 // String Chisato
6: bipush 17
8: invokespecial #11 // Method Person."<init>":(Ljava/lang/String;I)V
11: astore_1
12: return
javap -v Person shows below
public Person(java.lang.String, int);
descriptor: (Ljava/lang/String;I)V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=3, args_size=3
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: aload_1
6: putfield #7 // Field name:Ljava/lang/String;
9: aload_0
10: iload_2
11: putfield #13 // Field age:I
14: return
That's JVM-ese efor a method reference. <init> means 'constructor'. ()V means: A method that takes no arguments and returns void (as in, nothing).
In other words this tuple of strings:
java/lang/Object <init> ()V
refers to the no-args constructor of java.lang.Object itself. Which definitely exists, it's part of all java distributions.
The reason it is called here is basic java reasons:
ALL classes MUST have a constructor.
ALL constructors MUST begin by invoking either another constructor in the same class, or one of the super constructors. (this(); or super(); in java).
If you fail to write a constructor, java assumes you meant to write public MyClass() {}.
If you fail to write a this() or super() on the first line, java assumes you meant to write super(); and will act as if you did.
Thus, your Person class has a constructor, and it begins by invoking its parent class's no-args constructor.
Which is java/lang/Object <init> ()V.
The only class that is supposed to break this rule is java.lang.Object itself which has no parent class and doesn't do this. With bytecode hackery you can make classes that break these rules, and a JVM will run that just fine if you really want to. But don't - code in the JVM ecosystem expects you to do these things.
A look at the source code of java.lang.Object (e.g. http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/tip/src/share/classes/java/lang/Object.java) shows that there are no explicit constructors in the Object class. As such, Object has a default constructor.
As stated in JLS 8.8.9:
If a class contains no constructor declarations, then a default constructor is implicitly declared. The form of the default constructor for a top level class, member class, or local class is as follows:
...
If the class being declared is the primordial class Object, then the default constructor has an empty body.
So, Object.<init>() is simply a constructor with an empty body.
In more recent versions (e.g. OpenJDK head), there is an explicit constructor, but, again, it has an empty body:
#IntrinsicCandidate
public Object() {}
Related
I think header of question is not clear but I try to explain here.
Lets say I have class A which takes a generic type T
class A[T] {
// Doing some thing with T
}
Now I am instantiating its object but in place of T I will pass a class at runtime like
Class.forName("com.somthing.SomeClass")
new A[com.somthing.SomeClass]() //but I don't have com.somthing.SomeClass at compile time
But how can I use above class?
You can't do that, there is not T at runtime. Type parameters "disappeas" during erasure and are replaced by java.lang.Object:
$ echo 'class A[T] { def f(t: T): T = t }' > test.scala
$ scalac test.scala
$ javap -c A.class
Compiled from "test.scala"
public class A<T> {
public T f(T);
Code:
0: aload_1
1: areturn
public A();
Code:
0: aload_0
1: invokespecial #19 // Method java/lang/Object."<init>":()V
4: return
}
Given the following block of code i would like to understand why and how, emphasis on how, the method print in Subclass is invoked:
class Super {
Super() {
// what happens so that Sub's method print() is invoked
print();
}
public void print() {
System.out.println("in super");
}
}
class Sub extends Super {
Sub() {
super();
}
public void print() {
System.out.println("in sub");
}
}
public class TestClass {
public static void main(String[] args) {
Super s = new Sub(); // "in sub".. not so much expected
s.print(); // "in sub".. as expected
}
}
My understanding is that during compile time, classes will get V-table pointervtblPtrassociated with methods 'belonging' to a class.
Class Super should therefore have reference to it's own implementation of method print().
How come the method print() in Sub is invoked in constructor of Super? What really happens here ?
Here is what Super class looks like for the JVM (actually, that is the human-readable version obtained by javap -c Super)
class Super {
Super();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: invokevirtual #2 // Method print:()V
8: return
public void print();
Code:
0: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #4 // String in super
5: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}
as you can see, the print inside Super contructor was not resolved at compile time to Super::print. A virtual call means that it is resolved at runtime, with respect to class of this.
My understanding is that during compile time, classes will get V-table pointervtblPtrassociated with methods 'belonging' to a class. Class Super should therefore have reference to it's own implementation of method print().
You have a fundamental misunderstanding about virtual methods and overriding. In Java, every non-static, non-private method is virtual. Every virtual (normal) invocation of a virtual method, from anywhere, will invoke the version associated with the class of the object on which the method is invoked. That version might or might not be inherited, and might or might not override a superclass's method.
That a virtual method invocation is performed implicitly or explicitly on this in no way changes any of that. In particular, the actual class of the object being initialized is visible to every constructor, and provides the context for all their method invocations. In fact, this is why it's rarely a good idea for a constructor to invoke a virtual method provided by its own class. Superclass constructors run before subclass constructors, so if a superclass constructor invokes a method that happens to be overridden by a subclass, then that method will run before the object is fully initialized in the way that method may assume.
As everyone knows, private fields are not inherited between classes. What intrigues me, is how it works for inner static classes.
Consider the following code:
public class Main {
public static void main(String[] args) {
new B();
}
private static class A {
private int a = 10;
private void foo() {
System.out.println("A.foo");
}
}
private static class B extends A {
{
// foo(); // compile-time error
super.foo(); // ok
// System.out.println(a); // compile-time error
System.out.println(super.a); // ok
}
}
}
Can you please explain how it is possible to access private fields of other inner class? And if it is legal, why it is possible only via "super.XXX" construct?
Inner classes were a late entry to Java. When they were added they were added as a compiler extension only, no change to the JVM.
The language spec stated that an inner class was allowed to access the private members of the class that it was declared within; that includes other inner classes.
To make it work, the compiler generates bridge methods. Using javap with Main$A from the example above looks like this:
Notice the addition of access$200 and access$300. They provide back door access to the private method and field respectively.
class Main$A {
Main$A(Main$1);
Code:
0: aload_0
1: invokespecial #3 // Method "<init>":()V
4: return
static void access$200(Main$A);
Code:
0: aload_0
1: invokespecial #2 // Method foo:()V
4: return
static int access$300(Main$A);
Code:
0: aload_0
1: getfield #1 // Field a:I
4: ireturn
}
For completeness, here is the generated code for Main$B. Notice the calls to access$200 and 300, they appear where super.a and super.foo() appeared in the Java code.
class Main$B extends Main$A {
public Main$B();
Code:
0: aload_0
1: aconst_null
2: invokespecial #1 // Method Main$A."<init>":(LMain$1;)V
5: aload_0
6: invokestatic #2 // Method Main$A.access$100:(LMain$A;)V
9: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
12: aload_0
13: invokestatic #4 // Method Main$A.access$200:(LMain$A;)I
16: invokevirtual #5 // Method java/io/PrintStream.println:(I)V
19: return
}
And if it is legal, why it is possible only via "super.XXX" construct?
private fields are not usually part of the compilers resolution path for fields, by forcing developers to specify super the compiler is making certain that private access is what was meant and not a mistake.
From JLS3 6.6.1: "A private class member or constructor is accessible only within the body of the top level class (§7.6) that encloses the declaration of the member or constructor. It is not inherited by subclasses..
Since inner class is accessible within the body of top class hence its accessible and child classes are out of the enclosing class.
Now the specification doesn't say how this should happen - that's not really the job of a specification. It's really up to the implementation programmers to make it happen, and those details are not documented in the current specs.
Please tell the reason for output we are getting.
As per me, with b.getx() we will get the reference id of object of B and b.getx().x should get value of 10 but when I run this program the output is 5.
class Base {
int x = 5;
public Base getx() {
return new Base();
}
}
class Child extends Base {
int x = 10;
public Child getx() {
return new Child();
}
public static void main(String ...s) {
Base b = new Child();
System.out.println(b.getx().x);
}
}
Field accesses (unlike method calls) are not subject to runtime dynamic dispatch, they're resolved purely based on compile-time types.
The variable b is of compile-time type Base, therefore b.getx() is also of compile-time type Base, and so b.getx().x will be compiled into an access of Base's x field, not Child's. This is confirmed by looking at the output of javap for the main method:
public static void main(java.lang.String[]);
Code:
0: new #3; //class Child
3: dup
4: invokespecial #4; //Method "<init>":()V
7: astore_1
8: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
11: aload_1
12: invokevirtual #6; //Method Base.getx:()LBase;
15: getfield #7; //Field Base.x:I
18: invokevirtual #8; //Method java/io/PrintStream.println:(I)V
21: return
you can see that b.getx().x was compiled into a getfield instruction for Base.x specifically.
Dynamic binding basically means that the method implementation that is actually called is determined at run-time, and not at compile-time. And that’s why it’s called dynamic binding – because the method that will be run is chosen at run time. Dynamic binding is also known as late binding.
Base b = new Child(); is resolve at run-time and by rules of dynamic binding(run-time polymorphism) all method related to that should bind at run-time so...
public Base getx() {
return new Base();
}
that lines return new instance of base class and you just called variable on that instance.
Dynamic Binding is runtime time process for looking the declaration at run time. It is also known as late binding in which a call to an overridden method is resolved at runtime rather than compile-time.
In an object-oriented system method overriding (dynamic Polymorphism) is done at run time. When overriding one method with another, the signatures of the two methods must be identical.
Example:
class Animal{
public void eat(){
System.out.println("Animals voice");
}
public void go(){
System.out.println("Animals can walk");
}
}
class Dog extends Animal{
public void go(){
System.out.println("Dogs can walk and run");
}
public void eat(){
System.out.println("Dogs can eat a wide range of foods");
}
}
Javadoc mentions that Object class has a public no-arg constructor. But Object's source code doesn't have any explicit constructor in it. So obviously the compiler has generated one for it. However, if I see the call stack trace when a constructor is about to return (as shown below), I do not see any call to Object.<init> in that trace.
So the question is, does Object class have a default constructor as the doc says? If yes, why do I not see it in the call stack trace?
public ConTest()
{
new Throwable().printStackTrace();
}
Result:
java.lang.Throwable
at ConTest.<init>(ConTest.java:8)
at ConTest.main(ConTest.java:16)
Super constructors are run before sub/base constructors. In your example Object's constructor has already been run when new Throwable().printStackTrace() is executed.
A more explicit version of your code:
public ConTest()
{
super();
new Throwable().printStackTrace(); // you will not see super() (Object.<init>) in this stack trace.
}
You do not see it in the stack trace, because it was already called. The exception is thrown in your code.
Your code is equivalent to writing:
public ConTest() {
super(); // this will call the Object constructor
new Throwable().printStackTrace();
}
You do not see it in the stack trace because the constructor of the super class is called before your new Throwable().printStackTace() call. What the compiler actually creates is following .
public ConTest()
{
super(); // This is the call to the base class constructor
new Throwable().printStackTrace(); // already back from the base class constructor
}
Yes,Object class have a default constructor as the doc says.
As you know insted of doing that you can check it by using javap -c ConTest in command prompt
you can see it's calling the object class default constructor() in below's code's Line No:1
C:\stackdemo>javap -c ConTest
Compiled from "ConTest.java"
public class ConTest extends java.lang.Object{
public ConTest();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: new #2; //class java/lang/Throwable
7: dup
8: invokespecial #3; //Method java/lang/Throwable."<init>":()V
11: invokevirtual #4; //Method java/lang/Throwable.printStackTrace:()V
14: return
public static void main(java.lang.String[]);
Code:
0: new #5; //class ConTest
3: dup
4: invokespecial #6; //Method "<init>":()V
7: astore_1
8: return
}
Thank you
As Suggested above super() is the first call in the constructor and for method More Information here
When you compile a class, the Java compiler creates an instance initialization method for each constructor you declare in the source code of the class. Although the constructor is not a method, the instance initialization method is. It has a name, <init>, a return type, void, and a set of parameters that match the parameters of the constructor from which it was generated