How "Super" is implemented by Java?

A

anup

Hi,

Can anybody point to some resource which explains how a call to the
"super" is resolved/implemented in java (or for that matter any OO
language?

I am a bit confused as to when an object of any subclass is
instantiated does an object of the super class also get created? The
answer is probably NO as only one object gets created in the memory
and the fact is documented almost in every inheritance tutorial.

But then the point is - how does "super" work, which is supposed to
act as a reference to an object of the parent class? Is there any
demarcation in the memory for the members (data/methods) of the parent
class?

Any resource on the control flow during memory allocation while
instantiating an inherited object (indicating both the function as
well as data) shall be great.

thanks and regards,
anup
 
S

Silvio Bierman

anup said:
Hi,

Can anybody point to some resource which explains how a call to the
"super" is resolved/implemented in java (or for that matter any OO
language?

I am a bit confused as to when an object of any subclass is
instantiated does an object of the super class also get created? The
answer is probably NO as only one object gets created in the memory
and the fact is documented almost in every inheritance tutorial.

A class extends its superclass and therefore an object of class X (which
extends, say Y) is also an Y. Once it is instantiated as an X it's
implicit Y exists as part of it.
But then the point is - how does "super" work, which is supposed to
act as a reference to an object of the parent class? Is there any
demarcation in the memory for the members (data/methods) of the parent
class?

The 'super' notion is not so much a reference to the "parent" object as
it is a deterministic/non-virtual way to refer to methods defined in the
base class.

Let's assume class Y contains a (non-final) method f(). If X would
override this method and wanted to call f() as it was defined in Y then
the syntax for that call inside X's f() would be super.f(). Note that
this will call Y's f() circumventing the "virtual" calling mechanism
which that would resolve to X's y() and therefore cause infinite
recursive calls of X's f().

C++ has a similar notion, be it slightly more powerful and expressive.
In C++ X's f() (called X::f() in that language) would call the method
Y::f(). Only calls not prefixed by a class specification are virtually
resolved.
Any resource on the control flow during memory allocation while
instantiating an inherited object (indicating both the function as
well as data) shall be great.

Basically quite simple: the object is created as a byte sequence large
enough to hold Y's fields plus X's fields in addition. Then Y's
constructor is called as the first action inside X's constructor.

There are some more details to it but for they are not relevant in this
context.

Regards,

Silvio
 
J

Joshua Cranmer

anup said:
Hi,

Can anybody point to some resource which explains how a call to the
"super" is resolved/implemented in java (or for that matter any OO
language?

The short way to explain this is in the difference between virtual
method calls and nonvirtual method calls. A virtual method call finds
the method that it actually invokes starting from the actual class
instance and working up. Nonvirtual method calls will only look at calls
defined in the class it is called upon (or higher).

In Java, all methods except private methods and constructors are
generally called virtually (this is not the case in, say, C++, where
virtual methods have to be explicitly noted as such). Calls using super
use a nonvirtual method call.
I am a bit confused as to when an object of any subclass is
instantiated does an object of the super class also get created? The
answer is probably NO as only one object gets created in the memory
and the fact is documented almost in every inheritance tutorial.

I'm going to step back and assume single inheritance here because
multiple inheritance breaks some basic assumptions and identities in
non-trivial ways.

Suppose we have an instance of type Object. Object has its data fields,
etc., laid out in memory in some fashion:

+---------------+
| Object fields |
+---------------+

Now we have an instance of type String, which extends Object. It too has
its own data fields, which need memory to lay out.

+---------------+
| String fields |
+---------------+

But, since it extends Object, it needs the fields from Object somewhere
in the list somewhere. Things work out if we put these fields at the
beginning.

+-----------------+
| STRING OBJECT: |
|+---------------+|
|| Object fields ||
|+---------------+|
|| String fields ||
|+---------------+|
+-----------------+

A pointer to the object will generally point to offset 0, or to the
Object fields. If we don't know of the existance of the String fields,
we have a reference to only an Object object at the same place. A String
object is therefore nothing more than an Object object with a little
more data.

In answer to your question, instantiating a String instance will also
instantiate an Object instance--the same instance, in fact. Only one
object is being created, true, but the same object is being
instantiated, first as an Object, then as a String.
But then the point is - how does "super" work, which is supposed to
act as a reference to an object of the parent class? Is there any
demarcation in the memory for the members (data/methods) of the parent
class?

An object of the subclass is merely an object of the parent class with
some extra stuff tacked in on the end. The location of this data is
almost always (assuming single inheritance) at the beginning of the
object to avoid having to fiddle with offsets.

Note that I've been talking about fields; methods are a different story.
I know how g++ does virtual methods, but I haven't looked into how JVM
does the same thing.
Any resource on the control flow during memory allocation while
instantiating an inherited object (indicating both the function as
well as data) shall be great.

The JLS includes a section on how object initialization must occur in
terms of what must be done when:
<http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.9>.

The JVM discusses this topic from a much lower level, but is more
explicit on (say) which method to be invoked. I can't point to any one
spot in this reference, so here's the ToC:
<http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html>.
 
A

anup

The short way to explain this is in the difference between virtual
method calls and nonvirtual method calls. A virtual method call finds
the method that it actually invokes starting from the actual class
instance and working up. Nonvirtual method calls will only look at calls
defined in the class it is called upon (or higher).

In Java, all methods except private methods and constructors are
generally called virtually (this is not the case in, say, C++, where
virtual methods have to be explicitly noted as such). Calls using super
use a nonvirtual method call.


I'm going to step back and assume single inheritance here because
multiple inheritance breaks some basic assumptions and identities in
non-trivial ways.

Suppose we have an instance of type Object. Object has its data fields,
etc., laid out in memory in some fashion:

+---------------+
| Object fields |
+---------------+

Now we have an instance of type String, which extends Object. It too has
its own data fields, which need memory to lay out.

+---------------+
| String fields |
+---------------+

But, since it extends Object, it needs the fields from Object somewhere
in the list somewhere. Things work out if we put these fields at the
beginning.

+-----------------+
|  STRING OBJECT: |
|+---------------+|
|| Object fields ||
|+---------------+|
|| String fields ||
|+---------------+|
+-----------------+

A pointer to the object will generally point to offset 0, or to the
Object fields. If we don't know of the existance of the String fields,
we have a reference to only an Object object at the same place. A String
object is therefore nothing more than an Object object with a little
more data.

In answer to your question, instantiating a String instance will also
instantiate an Object instance--the same instance, in fact. Only one
object is being created, true, but the same object is being
instantiated, first as an Object, then as a String.


An object of the subclass is merely an object of the parent class with
some extra stuff tacked in on the end. The location of this data is
almost always (assuming single inheritance) at the beginning of the
object to avoid having to fiddle with offsets.

Note that I've been talking about fields; methods are a different story.
I know how g++ does virtual methods, but I haven't looked into how JVM
does the same thing.


The JLS includes a section on how object initialization must occur in
terms of what must be done when:
<http://java.sun.com/docs/books/jls/third_edition/html/expressions.htm...>.

The JVM discusses this topic from a much lower level, but is more
explicit on (say) which method to be invoked. I can't point to any one
spot in this reference, so here's the ToC:
<http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc...>.

Thanks Silvio and Joshua for your answers.

Silvio, what you say does not answer my question of how a call to
"super" is implemented by the JVM. The notion of virtual methods is
well understood and there is no confusion there. Still your effort is
very much appreciated.

How "super" knows that it has to fetch the "hidden/overridden" members
from the parent class was point in question. Does the JVM hardcode
this fetching when it sees the "super" keyword? Just thinking out
loud.

Anyways, Joshua I think your answer is leading me to the solution. I
believe I should go through the links and dig down the VM specs to get
the answer. Thanks a ton for the reply.
 
M

Mark Space

anup said:
How "super" knows that it has to fetch the "hidden/overridden" members
from the parent class was point in question. Does the JVM hardcode
this fetching when it sees the "super" keyword? Just thinking out
loud.
> Does that mean that the JVM uses some sort of "if then else" blocks to
> fetch the members (hidden/over-ridden also) of the parent class when
> referencing through the "super" keyword and without it? Fetching data


You can think of it as a series of if-then statements, but I believe
it's a bit better to think of it as a linked list.

What the JVM or compiler does is search the linked list. If it doesn't
find a method name or data field in the current object, it gets the next
item on the list (superclass) and searchers there.

MyClass SuperClass Object
+--------+ +--------+ +--------+
+ parent |---->| parent |---->| parent |----> null
+--------+ +--------+ +--------+
| | | | | |
| other | | other | | other |
| member | | member | | member |
| data...| | data...| | data...|
| | | | | |
+--------+ +--------+ +--------+

So the JVM just searches this list. If it gets to the end (sees null)
without finding the method or field you asked for, then that class does
not implement that method.

Thus, if you call wait() on MyClass, the list is searched and eventually
ends up in Object, which does implement wait() and so the call resolves
there, calling that method.

If you call "super()" or "super.method()" then the first item in the
list is skipped (in this case MyClass) and the search starts off with
the parent class immediately. (Obviously, if SuperClass uses the super
keyword, then that class is skipped and the search starts off with Object.)

So really it's more of a for(;;) loop than a series of if-then's.

Again, let's see if any net-denizens see fit to correct this simple model.
 
M

Mike Schilling

anup said:
Hi,

Can anybody point to some resource which explains how a call to the
"super" is resolved/implemented in java (or for that matter any OO
language?

I am a bit confused as to when an object of any subclass is
instantiated does an object of the super class also get created? The
answer is probably NO as only one object gets created in the memory
and the fact is documented almost in every inheritance tutorial.

But then the point is - how does "super" work, which is supposed to
act as a reference to an object of the parent class?

That's not quite right. "super" means "If 'this' were an instance of its
superclass, how would it resolve this method or field name? OK, use that
one." Since the superclass has been loaded (even if no instances of it have
been created), that question can always be answered.
 
M

Mike Schilling

anup said:
How "super" knows that it has to fetch the "hidden/overridden" members
from the parent class was point in question. Does the JVM hardcode
this fetching when it sees the "super" keyword? Just thinking out
loud.

There's a different IL instruction generated for "super" calls:

class Super
{
public void method()
{
String s = this.toString();
String t = super.toString();
}
}

public void method();
Code:
0: aload_0
1: invokevirtual #2; //Method
java/lang/Object.toString:()Ljava/lang/String;
4: astore_1
5: aload_0
6: invokespecial #2; //Method
java/lang/Object.toString:()Ljava/lang/String;
9: astore_2
10: return

How the JVM implements invokespecial will, of course, differ between JVM
implementations.
 
A

anup

anupwrote:


There's a different IL instruction generated for "super" calls:

classSuper
{
    public void method()
    {
        String s = this.toString();
        String t =super.toString();
    }

}

public void method();
  Code:
   0:   aload_0
   1:   invokevirtual   #2; //Method
java/lang/Object.toString:()Ljava/lang/String;
   4:   astore_1
   5:   aload_0
   6:   invokespecial   #2; //Method
java/lang/Object.toString:()Ljava/lang/String;
   9:   astore_2
   10:  return

How the JVM implements invokespecial will, of course, differ between JVM
implementations.

Thanks Mike. Shall look into the implementation of involespecial. I
believe that answers it.
 
R

Roedy Green

I am a bit confused as to when an object of any subclass is
instantiated does an object of the super class also get created

A composite object gets created, with superclass files and subclass
fields, contiguously.

So super really does not have much to do.

I puzzled for years how to add that subclassing to my own language in
an efficient way. I eventually learned the trick. It is simple, and
so obvious once you see it. Stroustrup explains it either in his C++
reference book or the design and evolution of C++ book. The trick is
VTBLs.

I congratulated Stroustrup on the elegance of VTBLs. He apparently
had no problem at all coming up with it. He is brilliant at such low
level stuff. My complaints were always with the simplicity and
elegance of the higher levels of the C++ language, e.g. overloading >>
for I/O. I think he wished he could kill me at one point.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top