I'm looking for verification/correction on the following.
Assume the following inheritance hierarchy -
class A {
void m1() { System.out.print(System.currentTimeMillis()); }
void m2() { System.out.print(new Date()); } // current date
}
class B extends A {
int x;
void m1() { System.out.print(x); } // overriding
void m99() { System.out.print(++x); }
}
Also assume that, class B is instantiated at some point in the application, i.e. the following statement is executed -
B b = new B();
(Paragraph-A) When the application is built, both classes A and B are loaded into memory
by the static loader.
Both classes are in memory, along with the definitions of all their member methods.
When B is instantiated with the above statement, a memory space in the heap
is allocated for that object b.
The methods m1(), m2() and m99() all have their definitions in this space of b.
These method definitions are only references to the method "templates" existing
in the class definitions. In the class, these methods are sequences of operations--
parameterized operations if
the method is executing on any parameter and/or global variable.
When one of the methods, say b.m99() is invoked at runtime,
JRE goes to class definition of B to get that "template" (sequence of operations),
looks up the current values of the fields of b,
fills in that "template" with the current values of these field(s),
also pushes these current values to the stackspace and runs the methods by executing these operations it found on the class definition.
If the method is inherited from a superclass, Eg. m2() above, the definition of that
method in the class (the definition mentioned in Paragraph-A above) is itself a reference to the definition of m2() in class A.
At runtime, when b.m2() is executed, JRE goes directly to class A to find that "template" for the low-level operations to execute.
These references to method definitions are checked at compile time and put into the bytecode. Eg. in the bytecode for the above case, class B has, a direct reference to method m2() of class A for method m2() it's inheriting from A.
Is this all accurate? If not, where/why not?
Generally, execution environments for Java can get implemented in various ways and it is impossible to say what “Java” does in general.
When the application is built, both classes A and B are loaded into memory
by the static loader.
Both classes are in memory, along with the definitions of all their member methods.
The standard way of deployment is to compile Java source code to bytecode. When the application is executed, the classes will be loaded. There is no such thing as a “static loader”. There are different class loaders. When the class files are delivered on the class path, they will be loaded by the application class loader.
When B is instantiated with the above statement, a memory space in the heap
is allocated for that object b.
The methods m1(), m2() and m99() all have their definitions in this space of b.
As said by Andreas, the method definitions are part of the JVM’s class representation. The object only contains a reference (pointer) to the class.
These method definitions are only references to the method "templates" existing
in the class definitions. In the class, these methods are sequences of operations--
parameterized operations if the method is executing on any parameter and/or global variable.
The terms “definitions” and “templates” and the way you use them, are creating unnecessary confusion. The instruction sequences are part of a methods definition. There is a reference from the object to these definitions, either indirectly via the already mentioned reference to the class, or directly via a table of method pointers, known as “vtable”, a widespread optimization.
When one of the methods, say b.m99() is invoked at runtime, JRE goes to class definition of B to get that "template" (sequence of operations), looks up the current values of the fields of b, fills in that "template" with the current values of these field(s), also pushes these current values to the stackspace and runs the methods by executing these operations it found on the class definition.
You should forget about that term “template”. The method definition contains a sequence of executable instructions and the JVM will execute these instructions. For instance methods, a pointer to the object data becomes the implicit first argument. No template will be filled with anything.
If the method is inherited from a superclass, Eg. m2() above, the definition of that
method in the class (the definition mentioned in Paragraph-A above) is itself a reference to the definition of m2() in class A.
At runtime, when b.m2() is executed, JRE goes directly to class A to find that "template" for the low-level operations to execute.
This is an implementation detail, but hold your breath…
These references to method definitions are checked at compile time and put into the bytecode. Eg. in the bytecode for the above case, class B has, a direct reference to method m2() of class A for method m2() it's inheriting from A.
This is not, how Java works. In Java, the compiler will check for the presence of the invoked method, which succeeds as B inherits the method from A and its accessible, then, it will record an invocation as written in source code, for m2() invoked on B.
The fact that B inherits the method, is an implementation detail of B and allowed to change. A future version of B may override the method. If that happens, A.m2() may even get removed. Or a class C may get introduced between A and B (C extends A and B extends C), which are all backwards compatible changes.
But back to the previous section, at runtime, an implementation may utilize the knowledge about actual inheritance. A JVM could search the super type hierarchy each time, a method is invoked, that would be valid but not very efficient.
A different strategy is to have the “vtable” mentioned above. Such a table is created for each class when it is initialized, starting with a copy of all superclass methods, entries of overridden methods replaced, and newly declared methods at the end.
So when an invocation instruction is executed the first time, it gets linked by determining the associated index in the vtable. Then, every invocation only needs to fetch the method pointer from the vtable of the object’s actual class, without ever traversing the class hierarchy.
That’s still only the way, an interpreted or less optimized execution works. When the JVM decides to optimize the invoking code further, it may predict the actual target of the method invocation. There are two ways in your example
the JVM uses the knowledge that A.m2() has never overridden (it would have to remove such an optimization when a new class is loaded which does override the method)
It analyzes the code path, to determine that for B b = new B(); b.m2(); the target is fixed as the result of new B() is always of type B, not a superclass and not a subclass.
When the target is predicted, it can be inlined. Then, the optimized code simply does System.out.print(new Date()); and when there’s no other use of the B instance, even the allocation may get eliminated.
So what the JVM does at runtime, may be entirely different than what has written in source code. Only the perceivable result (the date is printed) will be the same.
The methods m1(), m2() and m99() all have their definitions in this space of b.
Incorrect. The space allocated for b (the instance of B) references the class itself, i.e. the space allocated for class B, where the method definitions are stored.
The space allocated for an object instance consists of an object header and the data of the instance, i.e. the values of the fields. See e.g. What is in java object header for more information about the object header.
Eg. in the bytecode for the above case, class B has, a direct reference to method m2() of class A for method m2() it's inheriting from A.
Incorrect. The bytecode for class B knows nothing about method m2().
Remember, class A may be compiled separately from class B, so you can remove method m2 without recompiling class B.
UPDATE
From comment:
How then is it known what to execute when b.m2() is run? I don't think JRE goes to the super-class of B, looks to see an m2() there, if no such method then goes to super-super class, ... Too inefficient in runtime. Must be a direct reference to m2(). m2() is a member of B -- even though inherited.
As already stated in the answer, m2() is NOT a member of B. If you run the Java Disassembler, i.e. run javap B.class on the command-line, you'll see:
class B extends A {
int x;
B();
void m1();
void m99();
}
As you can see, the compiler has added the default constructor for you, but has not added any m2() method.
Now create this class:
class C {
public static void main(String[] args) {
B b = new B();
b.m2();
}
}
Then disassemble it with the -c switch, i.e. javap -c C.class:
class C {
C();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #16 // class B
3: dup
4: invokespecial #18 // Method B."<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #19 // Method B.m2:()V
12: return
}
As you can see, the compiler generates an instruction to call B.m2(), even though we already saw that B.class doesn't know about m2().
This means that what you postulated is exactly what happens, i.e. the JVM needs to resolve the method to class A at runtime, by walking up the superclass chain.
If m2() is removed from class A and recompiled, without recompiling class C, you will get NoSuchMethodError: 'void B.m2()' when running the code.
It's all visible in the .class files if you use a disassembler like javap. The bytecode for class B does not contain method m2. Further reading about Java handles inheritance here.
Related
Lets say I have a class A.java,
When I will execute a constructor method of A, it will create a memory space for xyz Object.
A xyz = new A();
The reference to memory may be something like,
[xyz] ---> '0x34524'
Thats basics of OOP. Simple enough!
Now,
What happens if a class is inheriting from different parent classes? How many object space will be created in memory?
Lets say we have,
and then we create an object of class D.java,
D omg = new D();
Here as we know that D's object will call construct of C.java and so on until A.java. Does this mean that in memory we are having 4 different memory reference, because we are instantiating all of the four objects (one directly and another 3 indirectly)?
[omg] ---> '0x34525'
[C] ---> '0x34526'
[B] ---> '0x34527'
[A] ---> '0x34528'
Note :
This isn't homework question, this is just a curiosity question.
I am aware of the fact that if we have a instance variable inside an A.java then we will not create only object A but we will be creating other internal object whenever we hit new keyword.
First, a tid bit... calling the constructor of an object does not allocate it. In bytecode, the initialization new Object() is expressed as something to the effect of...
new java/lang/Object
invokespecial java/lang/Object <init>()V
The new instruction takes care of allocating the space and acquiring a reference to the yet uninitialized object, while the invokespecial handles calling the constructor itself (which is internally compiled to a void method named <init>, hence the descriptor <init>()V).
Moving on, internals of object allocation and representation on the heap are entirely JVM specific. However, as far as I know, there is only one allocated object per allocated object, no matter its number of super classes. The object itself in memory has space for the instance fields of both its own class and its super classes. It must also have space for a virtual method table, in order to do virtual dispatch when performing virtual method calls (e.g. via invokevirtual) for the object.
Internally, the Oracle HotSpot JVM manages things called oops, or ordinary object pointers. You can read more about the HotSpot memory layout here. Feel free to browse the HotSpot source repository.
JVM allocates memory for only one object (here D)
memory allocation and initialization happens bottom(here D) to top(Object)
initialization/calling constructors happens Top(Object) to Bottom(here D)
reference :
http://www.artima.com/designtechniques/initialization.html
I have not read this anywhere but its my experience.
When you call new D(), the constructor chain begins, it first creates an java.lang.Object and then extends it to an A, I mean after creating the Object (which is root of all objects), A is initialized on it, by adding memory for A's members, including fields and methods (which are a pointer to some code!). And then it extends to B and so on.
In the process of extension if a method is overriden, the method pointer in the object will point to new code.
It will be only one reference to D.
The ASM guide talks about constructors:
package pkg;
public class Bean {
private int f;
public int getF() {
return this.f;
}
public void setF(int f) {
this.f = f;
}
}
The Bean class also has a default public constructor which is
generated by the compiler, since no explicit constructor was defined
by the programmer. This default public constructor is generated as
Bean() { super(); }. The bytecode of this constructor is the
following:
ALOAD 0
INVOKESPECIAL java/lang/Object <init> ()V
RETURN
The first instruction pushes this on the operand stack. The second
instruction pops this value from the stack, and calls the <init>
method defined in the Object class. This corresponds to the super()
call, i.e. a call to the constructor of the super class, Object. You
can see here that constructors are named differently in compiled and
source classes: in compiled classes they are always named <init>,
while in source classes they have the name of the class in which they
are defined. Finally the last instruction returns to the caller.
How is the value of this already known to the JVM before the first instruction of the constructor?
At the JVM level, first the object is allocated, uninitialized, then the constructor is invoked on that object. The constructor is more-or-less an instance method executed on the uninitialized object.
Even in the Java language, this exists and has all its fields at the first line of the constructor.
The first thing to understand, is how object instantiation work on the bytecode level.
As explained in JVMS, §3.8. Working with Class Instances:
Java Virtual Machine class instances are created using the Java Virtual Machine's new instruction. Recall that at the level of the Java Virtual Machine, a constructor appears as a method with the compiler-supplied name <init>. This specially named method is known as the instance initialization method (§2.9). Multiple instance initialization methods, corresponding to multiple constructors, may exist for a given class. Once the class instance has been created and its instance variables, including those of the class and all of its superclasses, have been initialized to their default values, an instance initialization method of the new class instance is invoked. For example:
Object create() {
return new Object();
}
compiles to:
Method java.lang.Object create()
0 new #1 // Class java.lang.Object
3 dup
4 invokespecial #4 // Method java.lang.Object.<init>()V
7 areturn
So the constructor invocation via invokespecial shares the behavior of passing this as the first argument with invokevirtual.
However, it must be emphasized that a reference to an uninitialized reference is treated specially, as you are not allowed to use it before the constructor (or the super constructor when you’re inside the constructor) has been invoked. This is enforced by the verifier.
JVMS, §4.10.2.4. Instance Initialization Methods and Newly Created Objects:
… The instance initialization method (§2.9) for class myClass sees the new uninitialized object as its this argument in local variable 0. Before that method invokes another instance initialization method of myClass or its direct superclass on this, the only operation the method can perform on this is assigning fields declared within myClass.
When doing dataflow analysis on instance methods, the verifier initializes local variable 0 to contain an object of the current class, or, for instance initialization methods, local variable 0 contains a special type indicating an uninitialized object. After an appropriate instance initialization method is invoked (from the current class or its direct superclass) on this object, all occurrences of this special type on the verifier's model of the operand stack and in the local variable array are replaced by the current class type. The verifier rejects code that uses the new object before it has been initialized or that initializes the object more than once. In addition, it ensures that every normal return of the method has invoked an instance initialization method either in the class of this method or in the direct superclass.
Similarly, a special type is created and pushed on the verifier's model of the operand stack as the result of the Java Virtual Machine instruction new. The special type indicates the instruction by which the class instance was created and the type of the uninitialized class instance created. When an instance initialization method declared in the class of the uninitialized class instance is invoked on that class instance, all occurrences of the special type are replaced by the intended type of the class instance. This change in type may propagate to subsequent instructions as the dataflow analysis proceeds.
So code creating an object via the new instruction can’t use it in any way before the constructor has been called, whereas a constructor’s code can only assign fields before another (this(…) or super(…)) constructor has been called (an opportunity used by inner classes to initialize their outer instance reference as a first action), but still can’t do anything else with their uninitialized this.
It’s also not allowed for a constructor to return when this is still in the uninitialized state. Hence, the automatically generated constructor bears the required minimum, invoking the super constructor and returning (there is no implicit return on the byte code level).
It’s generally recommended to read The Java® Virtual Machine Specification (resp. its Java 11 version) alongside to any ASM specific documentation or tutorials.
My problem is that I can't understand how method resolution works in the following case: Suppose, we have two packages, A and B. There are two classes, A is placed within A, B within B.
A:
package com.eka.IO.a;
import com.eka.IO.b.B;
public class A {
void foo() {
System.out.println("parent");
}
public static void main(String... args) {
B obj = new B();
obj.foo();
}
}
B:
package com.eka.IO.b;
import com.eka.IO.a.A;
public class B extends A {
public void foo() {
System.out.println("child");
}
}
The code above prints "child", which is perfectly OK. But if I change the method main the following way:
public static void main(String... args) {
A obj = new B();
obj.foo();
}
the code prints "parent", and I don't understand why. (obj has runtime type B, B has a public method foo)
Next, I change foo's visibility to public,
public class A {
public void foo() {
and the code prints "child" again.
As far as I know, instance methods are resolved at runtime, using the following principle:
JVM checks the runtime class of the object.
JVM looks for the method of runtime class
If method is found, JVM calls it, otherwise moves to the parent runtime class.
In my example, in any of three cases, runtime class for obj is always B. B's method foo is always public. Why in the second case JVM calls A's method?
Up:
Good answers, but still some things are unclear for me.
a) It's the compiler that checks whether a method overrides another method. (Hope, I'm right).
b) in case of A obj = new B(); the compiler generates the following code:
INVOKEVIRTUAL com/eka/IO/a/A.foo ()V
b1)if A's foo is declared without modifier (package visibility), then JVM calls A's method.
b2)if A's foo is declared public, then JVM calls B's method.
The unclear thing is why in the second case INVOKEVIRTUAL actually calls B.foo. How does it know, that B overrides the method?
The process is slightly different than you described it. First, Java will only make the methods that exist in the declared class and are visible at the current scope available. This is already done at compile time.
At runtime,
JVM checks the runtime class of the object.
JVM checks whether the object's runtime class has overridden the method of the declared class.
If so, that's the method called. Otherwise, declared class's method is called.
Now, the tricky part is "has it been overridden"?
A class can't override a method that is not visible to it. It can declare a method by the same name and with the same arguments, but this method is not considered to be overriding the original method. It's simply a new method, just like any other method that's defined in B but not in A.
If this was not so, then you could break the parent's class contract at a place where the author thought it should not be broken and therefore did not allow access to it.
So since the class did not override the method, you can only reference that method the same way you'd be able to reference any method declared in B that was not in A - only through a B reference.
Why doesn't the compiler prevent you from using names of methods that are already in the parent class, then?
Well, if you get a package, and the only information you have about it is what's in the classes' contracts, as written in its Javadoc, you won't even know about the existence of that method. All of a sudden, you write a method that, as far as you know, is unique, and you get a compilation error.
There is no reason to do that. What's not visible to you should not prevent you from freely naming your own methods. Thus it is allowed.
But if you want the compiler to prevent you from making mistakes like that, use the #Override annotation whenever you are writing a method that is supposed to override a parent class's method. This way, the compiler will warn you if you are trying to override a method that is not part of the class's contract.
You're experiencing Method Shadowing. From Java Language Specification. Chapter 6. Names. 6.4. Shadowing and Obscuring. 6.4.1. Shadowing (emphasys mine):
Some declarations may be shadowed in part of their scope by another declaration of the same name, in which case a simple name cannot be used to refer to the declared entity
(...)
A declaration d is said to be visible at point p in a program if the scope of d includes p, and d is not shadowed by any other declaration at p.
(...)
A declaration d of a method named n shadows the declarations of any other methods named n that are in an enclosing scope at the point where d occurs throughout the scope of d.
Let's check if B#foo overrides A#foo. From 8.4.8.1. Overriding (by Instance Methods):
An instance method mC declared in or inherited by class C, overrides from C another method mA declared in class A, iff all of the following are true:
A is a superclass of C.
C does not inherit mA.
The signature of mC is a subsignature (§8.4.2) of the signature of mA.
One of the following is true:
mA is public. (not your case)
mA is protected. (not your case)
mA is declared with package access in the same package as C (not your case since the classes are in different packages), and either C declares mC or mA is a member of the direct superclass of C.
mA is declared with package access and mC overrides mA from some superclass of C (not your case because there should be another class between C and A that let's you override mA).
mA is declared with package access and mC overrides a method m' from C (m' distinct from mC and mA), such that m' overrides mA from some superclass of C (not your case because there should be another class between C and A that let's you override mA).
So, B#foo does not override A#foo by any mean. With this in mind, when you call obj.foo() then foo will be obtained based on the class obj is designated at compile time. The explanation of this part is explained at 15.12. Method Invocation Expressions
If you want to avoid this, mark your method with #Override annotation in the subclass to make sure you're specifically overriding the desired method and not hiding it. If you get a compiler error when annotating your method, then you will know that you're not overriding such method but shadowing it.
As a result from this, you cannot override a method with default scope from a subclass that is in a different package than the parent class. Mark the method as protected in the parent class or redesign your classes accordingly to avoid this scenario.
Given the following classes:
public abstract class Super {
protected static Object staticVar;
protected static void staticMethod() {
System.out.println( staticVar );
}
}
public class Sub extends Super {
static {
staticVar = new Object();
}
// Declaring a method with the same signature here,
// thus hiding Super.staticMethod(), avoids staticVar being null
/*
public static void staticMethod() {
Super.staticMethod();
}
*/
}
public class UserClass {
public static void main( String[] args ) {
new UserClass().method();
}
void method() {
Sub.staticMethod(); // prints "null"
}
}
I'm not targeting at answers like "Because it's specified like this in the JLS.". I know it is, since JLS, 12.4.1 When Initialization Occurs reads just:
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
...
T is a class and a static method declared by T is invoked.
...
I'm interested in whether there is a good reason why there is not a sentence like:
T is a subclass of S and a static method declared by S is invoked on T.
Be careful in your title, static fields and methods are NOT inherited. This means that when you comment staticMethod() in Sub , Sub.staticMethod() actually calls Super.staticMethod() then Sub static initializer is not executed.
However, the question is more interesting than I thought at the first sight : in my point of view, this shouldn't compile without a warning, just like when one calls a static method on an instance of the class.
EDIT: As #GeroldBroser pointed it, the first statement of this answer is wrong. Static methods are inherited as well but never overriden, simply hidden. I'm leaving the answer as is for history.
I think it has to do with this part of the jvm spec:
Each frame (§2.6) contains a reference to the run-time constant pool (§2.5.5) for the type of the current method to support dynamic linking of the method code. The class file code for a method refers to methods to be invoked and variables to be accessed via symbolic references. Dynamic linking translates these symbolic method references into concrete method references, loading classes as necessary to resolve as-yet-undefined symbols, and translates variable accesses into appropriate offsets in storage structures associated with the run-time location of these variables.
This late binding of the methods and variables makes changes in other classes that a method uses less likely to break this code.
In chapter 5 in the jvm spec they also mention:
A class or interface C may be initialized, among other things, as a result of:
The execution of any one of the Java Virtual Machine instructions new, getstatic, putstatic, or invokestatic that references C (§new, §getstatic, §putstatic, §invokestatic). These instructions reference a class or interface directly or indirectly through either a field reference or a method reference.
...
Upon execution of a getstatic, putstatic, or invokestatic instruction, the class or interface that declared the resolved field or method is initialized if it has not been initialized already.
It seems to me the first bit of documentation states that any symbolic reference is simply resolved and invoked without regard as to where it came from. This documentation about method resolution has the following to say about that:
[M]ethod resolution attempts to locate the referenced method in C and its superclasses:
If C declares exactly one method with the name specified by the method reference, and the declaration is a signature polymorphic method (§2.9), then method lookup succeeds. All the class names mentioned in the descriptor are resolved (§5.4.3.1).
The resolved method is the signature polymorphic method declaration. It is not necessary for C to declare a method with the descriptor specified by the method reference.
Otherwise, if C declares a method with the name and descriptor specified by the method reference, method lookup succeeds.
Otherwise, if C has a superclass, step 2 of method resolution is recursively invoked on the direct superclass of C.
So the fact that it's called from a subclass seems to simply be ignored. Why do it this way? In the documentation you provided they say:
The intent is that a class or interface type has a set of initializers that put it in a consistent state, and that this state is the first state that is observed by other classes.
In your example, you alter the state of Super when Sub is statically initialized. If initialization happened when you called Sub.staticMethod you would get different behavior for what the jvm considers the same method. This might be the inconsistency they were talking about avoiding.
Also, here's some of the decompiled class file code that executes staticMethod, showing use of invokestatic:
Constant pool:
...
#2 = Methodref #18.#19 // Sub.staticMethod:()V
...
Code:
stack=0, locals=1, args_size=1
0: invokestatic #2 // Method Sub.staticMethod:()V
3: return
The JLS is specifically allowing the JVM to avoid loading the Sub class, it's in the section quoted in the question:
A reference to a static field (§8.3.1.1) causes initialization of only the class or interface that actually declares it, even though it might be referred to through the name of a subclass, a subinterface, or a class that implements an interface.
The reason is to avoid having the JVM load classes unnecessarily. Initializing static variables is not an issue because they are not getting referenced anyway.
The reason is quite simple: for JVM not to do extra work prematurely (Java is lazy in its nature).
Whether you write Super.staticMethod() or Sub.staticMethod(), the same implementation is called. And this parent's implementation typically does not depend on subclasses. Static methods of Super are not supposed to access members of Sub, so what's the point in initializing Sub then?
Your example seems to be artificial and not well-designed.
Making subclass rewrite static fields of superclass does not sound like a good idea. In this case an outcome of Super's methods will depend on which class is touched first. This also makes hard to have multiple children of Super with their own behavior. To cut it short, static members are not for polymorphism - that's what OOP principles say.
According to this article, when you call static method or use static filed of a class, only that class will be initialized.
Here is the example screen shot.
for some reason jvm think that static block is no good, and its not executed
I believe, it is because you are not using any methods for subclass, so jvm sees no reason to "init" the class itself, the method call is statically bound to parent at compile time - there is late binding for static methods
http://ideone.com/pUyVj4
static {
System.out.println("init");
staticVar = new Object();
}
Add some other method, and call it before the sub
Sub.someOtherMethod();
new UsersClass().method();
or do explicit Class.forName("Sub");
Class.forName("Sub");
new UsersClass().method();
When static block is executed Static Initializers
A static initializer declared in a class is executed when the class is initialized
when you call Sub.staticMethod(); that means class in not initialized.Your are just refernce
When a class is initialized
When a Class is initialized in Java After class loading, initialization of class takes place which means initializing all static members of class. A Class is initialized in Java when :
1) an Instance of class is created using either new() keyword or using reflection using class.forName(), which may throw ClassNotFoundException in Java.
2) an static method of Class is invoked.
3) an static field of Class is assigned.
4) an static field of class is used which is not a constant variable.
5) if Class is a top level class and an assert statement lexically nested within class is executed.
When a class is loaded and initialized in JVM - Java
that's why your getting null(default value of instance variable).
public class Sub extends Super {
static {
staticVar = new Object();
}
public static void staticMethod() {
Super.staticMethod();
}
}
in this case class is initialize and you get hashcode of new object().If you do not override staticMethod() means your referring super class method
and Sub class is not initialized.
Lets say I have a class A.java,
When I will execute a constructor method of A, it will create a memory space for xyz Object.
A xyz = new A();
The reference to memory may be something like,
[xyz] ---> '0x34524'
Thats basics of OOP. Simple enough!
Now,
What happens if a class is inheriting from different parent classes? How many object space will be created in memory?
Lets say we have,
and then we create an object of class D.java,
D omg = new D();
Here as we know that D's object will call construct of C.java and so on until A.java. Does this mean that in memory we are having 4 different memory reference, because we are instantiating all of the four objects (one directly and another 3 indirectly)?
[omg] ---> '0x34525'
[C] ---> '0x34526'
[B] ---> '0x34527'
[A] ---> '0x34528'
Note :
This isn't homework question, this is just a curiosity question.
I am aware of the fact that if we have a instance variable inside an A.java then we will not create only object A but we will be creating other internal object whenever we hit new keyword.
First, a tid bit... calling the constructor of an object does not allocate it. In bytecode, the initialization new Object() is expressed as something to the effect of...
new java/lang/Object
invokespecial java/lang/Object <init>()V
The new instruction takes care of allocating the space and acquiring a reference to the yet uninitialized object, while the invokespecial handles calling the constructor itself (which is internally compiled to a void method named <init>, hence the descriptor <init>()V).
Moving on, internals of object allocation and representation on the heap are entirely JVM specific. However, as far as I know, there is only one allocated object per allocated object, no matter its number of super classes. The object itself in memory has space for the instance fields of both its own class and its super classes. It must also have space for a virtual method table, in order to do virtual dispatch when performing virtual method calls (e.g. via invokevirtual) for the object.
Internally, the Oracle HotSpot JVM manages things called oops, or ordinary object pointers. You can read more about the HotSpot memory layout here. Feel free to browse the HotSpot source repository.
JVM allocates memory for only one object (here D)
memory allocation and initialization happens bottom(here D) to top(Object)
initialization/calling constructors happens Top(Object) to Bottom(here D)
reference :
http://www.artima.com/designtechniques/initialization.html
I have not read this anywhere but its my experience.
When you call new D(), the constructor chain begins, it first creates an java.lang.Object and then extends it to an A, I mean after creating the Object (which is root of all objects), A is initialized on it, by adding memory for A's members, including fields and methods (which are a pointer to some code!). And then it extends to B and so on.
In the process of extension if a method is overriden, the method pointer in the object will point to new code.
It will be only one reference to D.