Why invokeSpecial is needed when invokeVirtual exists

JavaJvmBytecode

Java Problem Overview


There are three opcodes to invoke Java methods. It is clear that invokeStatic is just for static method invocation.

As far as I know invokespecial is used when invoking constructor and private methods. So, do we need to differenticate private and public method invocation at run time? It could be invoked with same opcode say invokevirtual?

Does JVM deals with private and public method definition? As far as I know public and private keywords is just needed at development phase for encapsulation?

Java Solutions


Solution 1 - Java

From this site

>The answer can be easily found if one reads the Java VM Spec carefully: > >>The difference between the invokespecial and the invokevirtual instructions is that invokevirtual invokes a method based on the class of the object. The invokespecial instruction is used to invoke instance initialization methods as well as private methods and methods of a superclass of the current class. > >In other words, invokespecial is used to call methods without concern for dynamic binding, in order to invoke the particular class’ version of a method.

Solution 2 - Java

http://www.artima.com/underthehood/invocationP.html The link above gives valuable examples clearly which addresing my question.

class Superclass {

    private void interestingMethod() {
        System.out.println("Superclass's interesting method.");
    }

    void exampleMethod() {
        interestingMethod();
    }
}

class Subclass extends Superclass {

    void interestingMethod() {
        System.out.println("Subclass's interesting method.");
    }

    public static void main(String args[]) {
        Subclass me = new Subclass();
        me.exampleMethod();
    }
}

When you invoke main() in Subclass as defined above, it must print "Superclass's interesting method." If invokevirtual were used, it would print "Subclass's interesting method." Why? Because the virtual machine would choose the interestingMethod() to call based on the actual class of the object, which is Subclass. So it will use Subclass's interestingMethod(). On the other hand, with invokespecial the virtual machine will select the method based on the type of the reference, so Superclass's version of interestingMethod() will be invoked.

Solution 3 - Java

Thanks for reading out that explanation: Please don't forget to upvote if it helps you out to identify assembly instruction creation during method call Here I am explaining static vs dynamic binding.

First of all I am going to tell you that invokeStatic, invokeSpecial, invokeVirtual, invokeInterface etc are the assembly instructions which are generate by the compiler after compilation process. As we all knows that we got a .class file format after compilation and we can't read it out. But java provide a tool for that named "javap".

We can read out our .class file assembly instructions by using javap command. By default we can't see private method assembly instructions so we need to use -private with it. Below are the commands to see java compiler generated assembly instructions:

  1. Imaging you have A.java class

    class A { public void printValue() { System.out.println("Inside A"); }

    public static void callMethod(A a) { a.printValue(); } }

  2. open cmd prompt and go to the folder which contains that java file A.java.

  3. run javac A.java.

  4. Now A.class file is generated which contains assembly instructions but you can't read it.

  5. Now run javap -c A

  6. You can see assembly generation for your method call --> a.printValue();

  7. If printValue( ) method is private you need to use javap -c -private A .

  8. You can make your printValue( ) private / static / public / private static both.

  9. One more thing to keep in mind that first compiler check the object on which the method is getting called. Then find its Class Type and found that method in that class if available or not.

Note : Now keep in mind that if our calling method is static then invokeStatic assembly is generated, if its private then invokeSpecial assembly instruction is generated and if its public then invokeVirtual instruction is generated. public method never mean that every time invokeVirtual instruction is generated. In case of super.printValue() call from the subclass of A is exceptional case. i.e. if A is parent class for B and B contains the same method printValue() then it will generate invokeVirtual(dynamic) but if printValue() in B have super.printValue() as its first statement then invokeStatic is generated even if printValue() of A is public.

Let's try this too:

class B extends A
{
public void printValue()
{
super.printValue();// invokeStatic
System.out.println("Inside B");
}

}

public class Test
{
public static void main(String[] arr)
{
	A a = new A();
	B b = new B();
	A.callMethod(a);// invokeVirtual
	A.callMethod(b);// invokeVirtual
}
}

--> save it by Test.java --> run javac Test.java --> javap -c -private Test

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAhmet KarakayaView Question on Stackoverflow
Solution 1 - JavaTim PoteView Answer on Stackoverflow
Solution 2 - JavaAhmet KarakayaView Answer on Stackoverflow
Solution 3 - JavaMaddyView Answer on Stackoverflow