class A { void F() { System.out.println("a"); }}
class B extends A { void F() { System.out.println("b"); }}
public class X {
public static void main(String[] args) {
A objA = new B();
objA.F();
}
}
Here, F() is being invoked dynamically, isn't it?
This article says:
... the Java bytecode doesn’t support
dynamic method invocation. There are
three supported invocations modes :
invokestatic, invokespecial,
invokeinterface or invokevirtual.
These modes allows to call methods
with known signature. We talk of
strongly typed language. This allows
to to make some checks directly at
compile time.
On the other side, the dynamic
languages use dynamic types. So we can
call a method unknown at the compile
time, but that’s completely impossible
with the Java bytecode.
What am I missing?
You are confusing dynamic invocation with dynamic binding..
The first one allows the type checker to accept programs in which you are not sure if a method will be present on an object at run-time, while dynamic binding just chooses the right implementation according to the runtime type of the object but maintaining the statically type checking.
What does it mean?
It means that in your example, Java will call the implementation on object B because the runtime type of the objA variable is B; and it will compile because it knows that a B is a A so the method invocation won't fail at runtime (objA will have a F implementation for sure).
With dynamic invocation instead it won't check at compile time that the type of the object on which you are calling F contains that method, of course it will raise an exception if during execution the method won't be available on specified object.
Just for trivia: the invokedynamic feature will be added with Java7 because many scripting languages have been written to work on top of JVM and the lack of a dynamic invocation feature forced the developers of these languages to add a middle layer between the script and the real JVM that cares about dynamic invocation using the reflection. Of course this approach causes a lot of overhead (think about Grovvy's MetaClass), that's why Sun decided to give them a help..
In your example the correct method is called because polymorphically the instance of B appears like an instance of A. The method can be located by examining the runtime type of the object; that is, B; as opposed to the compile-time type of the object reference, A. The other important part is the signature of method - these must always match (polymorphically of course).
This differs from dynamic languages because in those there is essentially no compile-time for the object - and everything must be resolved at runtime.
In fact, what you're missing is that this is the part of 'invokevirtual' which is explained in the article.
You're simply overriding the method and that uses a virtual method table to invoke the correct method.
I wouldn't call your example "dynamic", rather virtual. Because at compile time the method name and signature is known (and its existence is checked by the compiler). The only that is resolved at runtime is the concrete implementation to be used for that method.
A more proper example of "dynamic" method invocation would involve reflection, (see the Method class ). In that way, methods whose existence are unkown at compile type can be invoked in runtime (this is extensively used by frameworks, not so much by application code).
The article you mention seems a little misleading in that respect. But it's true that the signature of the methods you explicitly call must be known/checked in compile time, and so, in that sense, Java is not dynamic.
You can make functional interfaces.
class Logger {
private BiConsumer<Object, Integer> logger = null;
// ...
private Logger(Object logger) {
this.akkaLogger = (LoggingAdapter) logger;
this.logger = (message, level) -> {
switch (level) {
case INFO: akkaInfo(message);
break;
case DEBUG: akkaDebug(message);
break;
case ERROR: akkaError(message);
break;
case WARN: akkaWarn(message);
break;
}
};
}
private Logger() {
this.logger = (message, level) -> System.out.println(message);
}
// ...
}
Related
There are too many associated names: Early and Late Binding, Static and Dynamic Dispatch, Runtime vs. Compile-time Polymorphism, etc. that I don't understand the difference.
I found a clear explanation, but is it correct? I'll paraphrase JustinC:
Binding: is determining the type of a variable (object?). If it's done at compile time, its early binding. If it's done at run time, it's late binding.
Dispatch: is determining which method matches the method call. Static Dispatch is computing methods at compile time, whereas dynamic dispatch is doing it at run time.
Is Binding matching up primitive and reference variables with primitive values and objects respectively?
Edit: Please give me some clear reference material so I can read more about this.
I believe the confusion typically comes from how overloaded these terms are.
We program our programs in a high level language, and either a compiler or an interpreter must transform that into something a machine actually understands.
In coarse terms, you can picture a compiler transforming our method code into some form of machine code. If the compiler knew at that point exactly where in the memory that method would reside when we run our program later, then it could safely go and find every method invocation of this compiled method and replace it with a jump to this address where the compiled code resides, right?.
Well, materializing this relationship is what I understand as binding. This binding, though, could happen at different moments, for example at compile time, linking time, load time, or at run time depending on the design of the language.
The terms static and dynamic are generally used to refer to things bound before run time and at run time, respectively.
Later binding times are associated with greater flexibility, earlier binding times are associated with greater efficiency. Language designers have to balance these two aspects when they're creating a language.
Most object-oriented programming languages support subtype polymorphism. In these languages, virtual methods are bound at runtime depending on the dynamic type of the object at that point. In other words, virtual method invocations are dispatched to the appropriate implementation at runtime based on the dynamic type of the object implementation involved and not based solely on its static type reference.
So, in my opinion, you must first bind the method invocation to a specific implementation or execution address, and then you can dispatch an invocation to it.
I had answered a very similar question in the past in which I demonstrate with examples how this happens in Java.
I would also recommend reading the book Programming Language Pragmatics. It is a great reference to learn all this kind of stuff from a theoretical standpoint.
When you're looking for "low level" definitions, probably the only legitimate source is our old friend - the JLS. Though it does not give a clear definition in this case, the context in which it uses each term might be enough.
Dispatch
This term is indeed mentioned in procedures of determining which method to call.
15.12.2. Compile-Time Step 2: Determine Method Signature
The second step searches the type determined in the previous step for
member methods. This step uses the name of the method and the argument
expressions to locate methods that are both accessible and applicable,
that is, declarations that can be correctly invoked on the given
arguments.
There may be more than one such method, in which case the
most specific one is chosen. The descriptor (signature plus return
type) of the most specific method is the one used at run time to
perform the method dispatch. A method is applicable if it is
applicable by one of strict invocation
The elaboration on what is the "most specific" method is done in 15.12.2.5 Choosing the Most Specific Method.
As for "dynamic dispatch",
JLS 12.5. Creation of New Class Instances:
Unlike C++, the Java programming language does not specify altered
rules for method dispatch during the creation of a new class instance.
If methods are invoked that are overridden in subclasses in the object
being initialized, then these overriding methods are used, even before
the new object is completely initialized.
It includes
Example 12.5-2. Dynamic Dispatch During Instance Creation
class Super {
Super() {
printThree();
}
void printThree() {
System.out.println("three");
}
}
class Test extends Super {
int three = 3;
void printThree() {
System.out.println(three);
}
public static void main(String[] args) {
Test t = new Test();
t.printThree();
}
}
Output:
0
3
This happens because during the constructor call chain, Super's constructor calls printThree, but due to dynamic dispatch the method in Test is called, and that is before the field is initialized.
Binding
This term is used in contexts of class member access.
Example 15.11.1-1. Static Binding for Field Access demonstrates early and late bindings. I will summarize the examples given there for the lazy of us:
class S {
int x = 0;
int z() { return x; }
}
class T extends S {
int x = 1;
int z() { return x; }
}
public class Test1 {
public static void main(String[] args) {
S s = new T();
System.out.println("s.x=" + s.x);
System.out.println("s.x=" + s.z());
}
}
Output:
s.x=0
s.x=1
Showing that the field uses "early binding", while the instance method uses "late binding":
This lack of dynamic lookup for field accesses allows programs to be run efficiently with
straightforward implementations. The power of late binding and overriding is available, but
only when instance methods are used.
Binding is also used in regards to determining the type of a generic,
8. Classes
Classes may be generic (§8.1.2), that is, they may declare type variables whose bindings may differ among different instances of the class.
Meaning that if you create 2 instances of List<String>, the bindings of String in both instances are different from each other.
This also applies to raw types:
4.8. Raw Types
class Outer<T>{
T t;
class Inner {
T setOuterT(T t1) { t = t1; return t; }
}
}
The type of the member(s) of Inner depends on the type parameter of Outer. If Outer is raw, Inner must be treated as raw as well, as there is no valid binding for T.
Meaning that declaring Outer outer (this will generate a raw type warning) does not allow to determine the type of T (obviously - it wasn't defined in the declaration).
These are general terms, you can summarize it in this way: when some thing(method or object) is static/early it means that thing is configured in compile-time and there is no ambiguity in run time for example in the following code:
class A {
void methodX() {
System.out.print("i am A");
}
}
If we create an instance of A and call methodX(), nothing is ambitious and everythin is configured at compile time but if we have the following code
class B extends A {
void methodX() {
System.out.print("i am B");
}
}
....
A objX= new B();
objX.methodX();
Out put of method x is not known until runtime, so this method is dynamically binded/dispatched (we can use the term dispatched instead of bind for methods link).
I am a bit confused when inheritance and type casting is mixed. I want to understand the rules which java compiler follows when choosing correct methods and variables in inheritance.
I have read something like
Variables are bound at compile time and methods are bound at run time.
The second one is from stackoverflow (#John Skeet)
Overload resolution (which method signature is called) is determined at compile-time, based on the compile-time types of both the method target and the argument expressions
The implementation of that method signature (overriding) is based on the actual type of the target object at execution time.
But the problem is that they are explanations of specific situations and do not give the general process to be followed when other factors (like exception handling) are taken into consideration.
This may be bad practice but assume that both methods and variables are overridden(hidden in case of static variables).
Now if java compiler has to choose at compile time which method/variable needs to be invoked then what algorithm will it follow? Similarly at run time what is the algorithm that java compiler will use(based on the actual type of the object whose reference is being used)?
All method signatures and variables are verified during compile-time but the actual method calls are done / resolved during run-time.
For example :
class A {
int i=5;
public void doSomething(){
//print "in A"
}
}
class B extends A{
int i=10;
public void doSomething(){
// print "in B"
}
public static void main(String[] args){
A a = new B();
a.doSomething();
}
}
Now, when you call a.doSomething(); , during compilation, the compiler just checks whether doSomething() is defined for class A (lhs reference). It is not even bothered about whether the method is also defined for class B. Even if the method were not present in B, the program would compile fine.
Next, during runtime, the JVM dynamically decides which method to call based on type of Object (B in your case.).
So, "in B" is printed.
Now, coming back to fields. Access to fields are resolved during compile time. So, if a field doesn't exist during compile-time, then the compilation fails. The fields are called based on the reference type. So, a.i will print 5 (A's value of i) because the field was resolved during compile-time. Thus, the difference is, method calls are resolved during runtime, their signatures are needed / checked during compile-time where-as fields are checked / resolved during compile-time.
I have searched through all the similar questions on late binding on stack overflow, and I would severely disagree with anyone who marks this question as a duplicate. First off, i found this example on another question, but I do not understand how I am supposed to know when something is decided during compile time and when something is decided during run time. Basically, the crux of my question boils down to two things:
What in this example must bring me to the logical conclusion that one method is late binding and another is early binding
How do I know when the decision about which version of a method to execute is decided during run-time or compile time in Java
Code:
class A
{
public void foo()
{
System.out.println("Class A");
}
}
class B extends A
{
public void foo()
{
System.out.println("Class B");
}
}
public class C
{
public static void main(String [] args)
{
A a=new A();
B b=new B();
A ref=null;
/*
early binding --- calls method foo() of class A and
decided at compile time
*/
a.foo();
/* early binding --- calls method foo() of class B and
decided at compile time
*/
b.foo();
/* late binding --- --- calls method foo() of class B and
decided at Run time
*/
ref=b;
ref.foo(); }
}
Wrong on all counts. The method to be called is decided at runtime, in every case here, based on the runtime type of the object. The only decisions made at compile time are for calls to final, private, or static methods, or choices among a set of overloaded methods (which could still lead to runtime choices if the overloaded methods are not final, private, or static.)
Java uses late binding for all non-final, non-private instance methods. This is how polymorphism is implemented. All of the calls you commented on are determined at run time.
In
A a=new A();
a.foo();
a is referencing an A object so A's implementation will be found, bound and used.
In
B b=new B();
b.foo();
b is referencing a B object so B's implementation will be found, bound, and used.
In
ref=b;
ref.foo();
ref is referencing a B object so B's implementation will be found, bound, and used.
The static (declared) type of the variable is only used by the compiler to verify that such a method is accessible on that type.
Related:
What is early and late binding?
All the answers here are mostly correct, but there is one key point missing regarding late binding in Java.
Java does not perform "by the book" late binding if we go by the definition of late binding.
Late binding in its book definition form means that the compiler should perform no argument checks, no type checks on a method call and should leave it all to the runtime - because possibly the compiler does not have access to the method implementation code (for example in COM programming).
Java however at compile time does verify, even in a polymorphic scenario, that the method being called and the method signature does exist somewhere in the type hierarchy of the expression that qualifies the method. So for example, lets say I call a method foo1 on ref that does not exist in either A or B:
A ref=null;
ref=new B();
ref.foo1();
//This will not compile in Java, because java will check at compile time
//for the method foo1 in the type hierarchy of A, which is the type of the
// variable ref at compile time.
//In pure late binding, however this would pass compilation and
//throw an error at runtime.
In a pure late binding scenario, the determination of whether the method foo1() exists or not with the right number of arguments is made purely at runtime.
However in Java, there is some level of checking done at compile time, to ensure that the method with the right number of arguments does exist somewhere in the type hierarchy.
The only time that I think Java does perform pure late binding is if one uses reflection to call a method.
What Java does is better termed as dynamic dispatch rather than late binding, but everyone calls it late binding in Java and hence there is confusion.
Consider the statement
A ref; //reference of A
ref = new B();//Object of B
ref.f2();
Here ref is a reference of class A and it has address of object of class B f2() is a overridden method.
When compiler detects such a statement then it doesn't bind the function call with any definition. It only validates the call.
Binding of such calls is left for the runtime environment. At program runtime system identifies the datatype of the object and binds the function call with the function definition provided by the class of object. This type of binding between the function call and function defination is called as "late binding" or "runtime binding" or "runtime polymorphism" or "dynamic method dispatch".
go through this question and read my answer example is also given there.
When you call a method on any object, always remember in inheritance "least modified version" of method will be called. This is nothing but dynamically picking the method version from the hierarchy.
While studying Java tutorials, Reflection and Late Binding have confused me. In some tutorials, they have written that they are both the same, and that there isn't any difference between Reflection and Late Binding. But other tutorials say that there is a difference.
I am confused, so can someone please explain what Reflection and Late Binding are in Java, and if posible, please give me some real world examples of both.
Thanks..
Java uses late-binding to support polymorphism; which means the decision of which of the many methods should be used is deferred until runtime.
Take the case of N classes implementing an abstract method of an interface (or an abstract class, fwiw).
public interface IMyInterface {
public void doSomething();
}
public class MyClassA implements IMyInterface {
public void doSomething(){ ... }
}
public class MyClassB implements IMyInterface {
public void doSomething(){ ... }
}
public class Caller {
public void doCall(IMyInterface i){
// which implementation of doSomething is called?
// it depends on the type of i: this is late binding
i.doSomething();
}
}
Reflection is used instead to describe code which is able to inspect other code, ie. to know which methods or attributes are available in a class, to call a method (or load a class) by name, and doing a lot of very interesting things at runtime.
A very nice explaination of reflection is here: What is reflection and why is it useful?
Late binding (also known as dynamic dispatch) does not need reflection -- it still needs to know which member to dynamically bind to at compile-time (i.e. the signature of the member is known at compile-time), even though the binding to overridden members happens at run-time.
When doing reflection, you don't even know which member you're using (not even the name is known at compile-time, let alone the signature) -- everything happens at run-time, so it's a lot slower.
Real world examples:
If you build your project with jdesktop 0.8, but ship with jdesktop 0.9, your code will still use the 0.9 features, because it takes advantage of late binding, i.e. the code that your code calls is the version that is loaded by the class loader, irrespective of the version that it was compiled against. (This is as opposed to linkers, which embed the compile-time version of the called code into the application.)
For reflection, let's say you are trying to target Java 1.5 and 1.6, but want to use tab components in 1.6 if they are available, then you'll check for their presence by using reflection on the JTabbedPane class to find the setTabComponentAt method. In this case you're building against Java 1.5, which doesn't have those features at all, so you can't call them directly or the compile will fail. However if on the end-user's system you find yourself running against 1.6 (late binding comes into play here) you can use reflection to call methods that didn't exist in 1.5.
They are related; many uses of reflection rely on late binding to be useful, but they are fundamentally different aspects of the language and its implementation.
One important issue which is addressed by "Late Binding" is the polymorphism, i.e. that the call of the proper overriden method along your class hierachy is determined during the run-time, not during compilation. Reflection is the feature to gather and manipulate information about your objects during run-time. E.g. you can get all attributes or method names of an object using its 'Class' attribute during the runtime and call those methods or manipulate its attributes.
In following code you can dynamically create a new object by the means of reflection (see how the constructor is retrieved and accessed using a Class, instead of using simply something like object obj = new MyClass( "MyInstance" ) ). In a similar way it is possible to access other constructor forms, methods and attributes. For more information about reflection in java visit: http://java.sun.com/developer/technicalArticles/ALT/Reflection/
... in some method of some class ...
Class c = getClass();
Constructor ctor = c.getConstructor( String.class );
Object obj = ctor.newInstance( "MyInstance" );
I have to disagree with most of the responses here -
Everyone calls what Java does in terms of zeroing in on a method implementation at runtime as late binding, but in my opinion its not correct to use the term late binding for what java does.
Late binding implies absolutely no checks on a method call at compile time and no compilation errors if the method does not exist.
Java however will throw a compile error if the method does not exist somewhere in the type hierarchy of the type qualifying the method call (being somewhat approximate when describing the behavior here). This is not pure traditional late binding.
What Java does in a normal non private non final non static method call would be better termed as dynamic dispatch.
However if we use reflection in Java, then Java does perform pure late binding as the compiler simply cannot verify if the called method exists or not.
Here is an example:
class A
{
public void foo()
{
System.out.println("Foo from A");
}
}
class B extends A
{
public void foo()
{
System.out.println("Foo from B");
}
}
public class C
{
public static void main(String [] args)
{
A a=new A();
B b=new B();
A ref=null;
Class ref1 = null;
ref1 = b.getClass();
ref.foo1();//will not compile because Java in this normal method
//call does some compile time checks for method and method
//signature existence. NOT late binding in its pure form.
try {
ref1.getMethod("foo1").invoke(null); //will throw a
//NoSuchMethodException at runtime, but compiles perfectly even
//though foo1 does not exist. This is pure late binding.
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Consider this simple Java class:
class MyClass {
public void bar(MyClass c) {
c.foo();
}
}
I want to discuss what happens on the line c.foo().
Original, Misleading Question
Note: Not all of this actually happens with each individual invokevirtual opcode. Hint: If you want to understand Java method invocation, don't read just the documentation for invokevirtual!
At the bytecode level, the meat of c.foo() will be the invokevirtual opcode, and, according to the documentation for invokevirtual, more or less the following will happen:
Look up the foo method defined in compile-time class MyClass. (This involves first resolving MyClass.)
Do some checks, including: Verify that c is not an initialization method, and verify that calling MyClass.foo wouldn't violate any protected modifiers.
Figure out which method to actually call. In particular, look up c's runtime type. If that type has foo(), call that method and return. If not, look up c's runtime type's superclass; if that type has foo, call that method and return. If not, look up c's runtime type's superclass's superclass; if that type has foo, call that method and return. Etc.. If no suitable method can be found, then error.
Step #3 alone seems adequate for figuring out which method to call and verifying that said method has the correct argument/return types. So my question is why step #1 gets performed in the first place. Possible answers seem to be:
You don't have enough information to perform step #3 until step #1 is complete. (This seems implausible at first glance, so please explain.)
The linking or access modifier checks done in #1 and #2 are essential to prevent certain bad things from happening, and those checks must be performed based on the compile-time type, rather than the run-time type hierarchy. (Please explain.)
Revised Question
The core of the javac compiler output for the line c.foo() will be an instruction like this:
invokevirtual i
where i is an index to MyClass' runtime constant pool. That constant pool entry will be of type CONSTANT_Methodref_info, and will indicate (maybe indirectly) A) the name of the method called (i.e. foo), B) the method signature, and C) the name of compile time class that the method is called on (i.e. MyClass).
The question is, why is the reference to the compile-time type (MyClass) needed? Since invokevirtual is going to do dynamic dispatch on the runtime type of c, isn't it redundant to store the reference to the compile-time class?
It is all about performance. When by figuring out the compile-time type (aka: static type) the JVM can compute the index of the invoked method in the virtual function table of the runtime type (aka: dynamic type). Using this index step 3 simply becomes an access into an array which can be accomplished in constant time. No looping is needed.
Example:
class A {
void foo() { }
void bar() { }
}
class B extends A {
void foo() { } // Overrides A.foo()
}
By default, A extends Object which defines these methods (final methods omitted as they are invoked via invokespecial):
class Object {
public int hashCode() { ... }
public boolean equals(Object o) { ... }
public String toString() { ... }
protected void finalize() { ... }
protected Object clone() { ... }
}
Now, consider this invocation:
A x = ...;
x.foo();
By figuring out that x's static type is A the JVM can also figure out the list of methods that are available at this call site: hashCode, equals, toString, finalize, clone, foo, bar. In this list, foo is the 6th entry (hashCode is 1st, equals is 2nd, etc.). This calculation of the index is performed once - when the JVM loads the classfile.
After that, whenever the JVM processes x.foo() is just needs to access the 6th entry in the list of methods that x offers, equivalent to x.getClass().getMethods[5], (which points at A.foo() if x's dynamic type is A) and invoke that method. No need to exhaustively search this array of methods.
Note that the method's index, remains the same regardless of the dynamic type of x. That is: even if x points to an instance of B, the 6th methods is still foo (although this time it will point at B.foo()).
Update
[In light of your update]: You're right. In order to perform a virtual method dispatch all the JVM needs is the name+signature of the method (or the offset within the vtable). However, the JVM does not execute things blindly. It first checks that the cassfiles loaded into it are correct in a process called verification (see also here).
Verification expresses one of the design principles of the JVM: It does not rely on the compiler to produce correct code. It checks the code itself before it allows it to be executed. In particular, the verifier checks that every invoked virtual method is actually defined by the static type of the receiver object. Obviously, the static type of the receiver is needed to perform such a check.
That's not the way I understand it after reading the documentation. I think you have steps 2 and 3 transposed, which would make the whole series of events more logical.
Presumably, #1 and #2 have already happened by the compiler. I suspect that at least part of the purpose is to make sure that the they still hold with the version of the class in the runtime environment, which may be different from the version the code was compiled against.
I haven't digested the invokevirtual documentation to verify your summary, though, so Rob Heiser could be right.
I'm guessing answer "B".
The linking or access modifier checks done in #1 and #2 are essential to prevent certain bad things from happening, and those checks must be performed based on the compile-time type, rather than the run-time type hierarchy. (Please explain.)
#1 is described by 5.4.3.3 Method Resolution, which makes some important checks. For example, #1 checks the accessibility of the method in the compile-time type and may return an IllegalAccessError if it is not:
...Otherwise, if the referenced method is not accessible (§5.4.4) to D, method resolution throws an IllegalAccessError. ...
If you only checked the run-time type (via #3), then the run-time type could illegally widen the accessibility of the overridden method (a.k.a. a "bad thing"). Its true that the compiler should prevent such a case, but the JVM is nevertheless protecting itself from rogue code (e.g. manually-constructed malevolent code).
To totally understand this stuff, you need to understand how method resolution works in Java. If you're looking for an in-depth explanation, I suggest looking at the book, "Inside the Java Virtual Machine". The following sections from Chapter 8, "The Linking Model", are available online and seem particularly relevant:
Chapter introduction
Resolution of CONSTANT_Methodref_info Entries
Direct References
(CONSTANT_Methodref_info entries are entries in the class file header that describe the methods called by that class.)
Thanks to Itay for inspiring me to do the Googling required to find this.