How are VTBLs implemented in Java?
Running this code:
class A {
public int x;
public A() {
function();
}
public void function() {
this.x = 20;
}
public void printhey() { System.out.println("Hey"); }
}
class B extends A {
public B() {
super();
printhey();
}
public void function() {
this.x = 50;
} 开发者_如何学C
}
public class tmp {
public static void main(String[] args) {
System.out.println((new B()).x);
}
}
prints out:
Hey
50
Who sets up the VTBL? in A
's constructor, function
is already set to be B. But in B
's constructor, printhey
is set up to be A's.
"VTBL"s are an artifact of languages that deal in Storage Structures. That is, in C++, you can deduce with a fair degree of accuracy exactly how a class will map in RAM.
Java doesn't deal with Storage Structures, it deals with Data Structures. You can easily use a Storage Structure as a Data Structure, but the reverse isn't as trivial. If you happen to have a copy of BYTE magazine from back in early 1991, you can even find the article where I extolled the virtues of mapping C++ data structures onto the storage structures used by the Commodore Amiga OS ROM Kernel (Exec). Back then, in fact, the term "data structure" was used as a sort of catch-all, since we still worried about how things would fit precisely into memory.
Data Structures are generally used by algorithms. Storage Structures are more closely related to internal implementations and serialized forms. Actual program execution requires a little bit of both, but the Storage Structures underlying a Java Data Structure are supposed to be opaque. It's a large part of what makes Java "Write Once, Run Anywhere". If you don't have to worry about the size and byte orientation of things, you don't have to load down your app with "swabbers" and memory-offset calculators.
Some programming languages don't like forward and circular references. Java would be hard put to do without them. However, there's a difference between a hard reference to code and a reference to a method signature that's bound to a bytecode and which will (possibly) eventually be JIT-compiled to machine code. Or even re-optimized and recompiled, in some of the more advanced JVMS. What it all boils down to is that you have, in effect, multiple passes over the class, where one establishes the dictionary and another plugs in the linkages. Including automatic inlining, if appropriate.
There is no concept of a VTBL in Java; ergo, there is no VTBL.
The object created is a new B(), and B has (by then) a function (defined in B, since it overrides A's) and printhey (inherited from A). So X gets assigned to 50 - A's constructor, invoked via B's constructor, does the set operation by calling 'function' (from B). We then invoke 'printhey' (line after super() in B) which calls the inherited fn. Then, we return the instance, from which X is obtained, so you see 50.
The simple answer is, 'The JVM, of course'. By the time B is loaded, the JVM has complete knowledge of the class hierarchy, and has resolved all the references. It's not like C++. Of course, I'm interpreting you as using the term VTBL metaphorically. There's no actual data structure much like a VTBL in any serious JRE.
精彩评论