`
haiyupeter
  • 浏览: 427417 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

invokevirtual,invokespecial,invokestatic,invokein

    博客分类:
  • Java
阅读更多

 invokevirtual,invokespecial,invokestatic,invokeinterface

invokevirtual  调用类实例方法,方法引用
        栈:
        前:。。。,objectref,[arg1,[arg2......]]
        后:。。。
invlkestatic 调用类方法,不需要建新建类实例,此时操作数栈只要保存留参数即可
        栈:
        前:。。。,[arg1,[arg2.....]]
        后:。。。
invokespecial 使用对私有方法,超类方法和实例初始化方法的特殊处理来调用实例方法。
        栈:
        前:。。。,objectref,[arg1,[arg2......]]
        后:。。。
invokeinterface 调用接口方法
        栈:
        前:。。。,objectref,[arg1,[arg2......]]
        后:。。。



程序如下:

package yhs.test;

public interface Iface {
    public void test();
}

package yhs.test;

public class Impl
  implements Iface {

    public void test() {
    }

    public static void testStatic() {
    }

    private void testPrivate() {
    }

    //--------------------------------------------------------------------------
    //--------------------------------------------------------------------------
    public static void main(String[] args) {
        Impl impl = new Impl();
        Iface iface = impl;

        //热身
        int count = 10000000;
        for (int i = 0; i < count; i++) {
            impl.test();
            impl.testPrivate();
            Impl.testStatic();
            iface.test();
        }

        //开始测试
        count = 100000000;

        long t1 = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            impl.test();
        }
        System.out.println("invokevirtual:   " +
                           (System.currentTimeMillis() - t1));

        t1 = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            impl.testPrivate();
        }
        System.out.println("invokespecial:   " +
                           (System.currentTimeMillis() - t1));

        t1 = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            Impl.testStatic();
        }
        System.out.println("invokestatic:    " +
                           (System.currentTimeMillis() - t1));

        t1 = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            iface.test();
        }
        System.out.println("invokeinterface: " +
                           (System.currentTimeMillis() - t1));
    }
}
 



反汇编Impl.class产生的字节码如下:

public class yhs.test.Impl extends java.lang.Object implements yhs.test.Iface{
public yhs.test.Impl();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."":()V
   4:   return

public void test();
  Code:
   0:   return

public static void testStatic();
  Code:
   0:   return

public static void main(java.lang.String[]);
  Code:
   0:   new     #2; //class Impl
   3:   dup
   4:   invokespecial   #3; //Method "":()V
   7:   astore_1
   8:   aload_1
   9:   astore_2
   //---------------------------------------------------------------------------------------------
   10:  ldc     #4; //int 10000000
   12:  istore_3
   13:  iconst_0
   14:  istore  4
   16:  goto    39
   19:  aload_1
   20:  invokevirtual   #5; //Method test:()V
   23:  aload_1
   24:  invokespecial   #6; //Method testPrivate:()V
   27:  invokestatic    #7; //Method testStatic:()V
   30:  aload_2
   31:  invokeinterface #8,  1; //InterfaceMethod yhs/test/Iface.test:()V
   36:  iinc    4, 1
   39:  iload   4
   41:  iload_3
   42:  if_icmplt       19
   //---------------------------------------------------------------------------------------------
   45:  ldc     #9; //int 100000000
   47:  istore_3
   48:  invokestatic    #10; //Method java/lang/System.currentTimeMillis:()J
   51:  lstore  5
   53:  iconst_0
   54:  istore  7
   56:  goto    66
   59:  aload_1
   60:  invokevirtual   #5; //Method test:()V
   63:  iinc    7, 1
   66:  iload   7
   68:  iload_3
   69:  if_icmplt       59
   72:  getstatic       #11; //Field java/lang/System.out:Ljava/io/PrintStream;
   75:  new     #12; //class StringBuffer
   78:  dup
   79:  invokespecial   #13; //Method java/lang/StringBuffer."":()V
   82:  ldc     #14; //String invokevirtual:
   84:  invokevirtual   #15; //Method java/lang/StringBuffer.append:(Ljava/lang/
String;)Ljava/lang/StringBuffer;
   87:  invokestatic    #10; //Method java/lang/System.currentTimeMillis:()J
   90:  lload   5
   92:  lsub
   93:  invokevirtual   #16; //Method java/lang/StringBuffer.append:(J)Ljava/lan
g/StringBuffer;
   96:  invokevirtual   #17; //Method java/lang/StringBuffer.toString:()Ljava/la
ng/String;
   99:  invokevirtual   #18; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
   //---------------------------------------------------------------------------------------------
   102: invokestatic    #10; //Method java/lang/System.currentTimeMillis:()J
   105: lstore  5
   107: iconst_0
   108: istore  8
   110: goto    120
   113: aload_1
   114: invokespecial   #6; //Method testPrivate:()V
   117: iinc    8, 1
   120: iload   8
   122: iload_3
   123: if_icmplt       113
   126: getstatic       #11; //Field java/lang/System.out:Ljava/io/PrintStream;
   129: new     #12; //class StringBuffer
   132: dup
   133: invokespecial   #13; //Method java/lang/StringBuffer."":()V
   136: ldc     #19; //String invokespecial:
   138: invokevirtual   #15; //Method java/lang/StringBuffer.append:(Ljava/lang/
String;)Ljava/lang/StringBuffer;
   141: invokestatic    #10; //Method java/lang/System.currentTimeMillis:()J
   144: lload   5
   146: lsub
   147: invokevirtual   #16; //Method java/lang/StringBuffer.append:(J)Ljava/lan
g/StringBuffer;
   150: invokevirtual   #17; //Method java/lang/StringBuffer.toString:()Ljava/la
ng/String;
   153: invokevirtual   #18; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
   //---------------------------------------------------------------------------------------------
   156: invokestatic    #10; //Method java/lang/System.currentTimeMillis:()J
   159: lstore  5
   161: iconst_0
   162: istore  9
   164: goto    173
   167: invokestatic    #7; //Method testStatic:()V
   170: iinc    9, 1
   173: iload   9
   175: iload_3
   176: if_icmplt       167
   179: getstatic       #11; //Field java/lang/System.out:Ljava/io/PrintStream;
   182: new     #12; //class StringBuffer
   185: dup
   186: invokespecial   #13; //Method java/lang/StringBuffer."":()V
   189: ldc     #20; //String invokestatic:
   191: invokevirtual   #15; //Method java/lang/StringBuffer.append:(Ljava/lang/
String;)Ljava/lang/StringBuffer;
   194: invokestatic    #10; //Method java/lang/System.currentTimeMillis:()J
   197: lload   5
   199: lsub
   200: invokevirtual   #16; //Method java/lang/StringBuffer.append:(J)Ljava/lan
g/StringBuffer;
   203: invokevirtual   #17; //Method java/lang/StringBuffer.toString:()Ljava/la
ng/String;
   206: invokevirtual   #18; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
   //---------------------------------------------------------------------------------------------
   209: invokestatic    #10; //Method java/lang/System.currentTimeMillis:()J
   212: lstore  5
   214: iconst_0
   215: istore  10
   217: goto    229
   220: aload_2
   221: invokeinterface #8,  1; //InterfaceMethod yhs/test/Iface.test:()V
   226: iinc    10, 1
   229: iload   10
   231: iload_3
   232: if_icmplt       220
   235: getstatic       #11; //Field java/lang/System.out:Ljava/io/PrintStream;
   238: new     #12; //class StringBuffer
   241: dup
   242: invokespecial   #13; //Method java/lang/StringBuffer."":()V
   245: ldc     #21; //String invokeinterface:
   247: invokevirtual   #15; //Method java/lang/StringBuffer.append:(Ljava/lang/
String;)Ljava/lang/StringBuffer;
   250: invokestatic    #10; //Method java/lang/System.currentTimeMillis:()J
   253: lload   5
   255: lsub
   256: invokevirtual   #16; //Method java/lang/StringBuffer.append:(J)Ljava/lan
g/StringBuffer;
   259: invokevirtual   #17; //Method java/lang/StringBuffer.toString:()Ljava/la
ng/String;
   262: invokevirtual   #18; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
   //---------------------------------------------------------------------------------------------
   265: return

}

测试得到类似如下的一组结果:

#1

invokevirtual:   250

invokespecial:   219

invokestatic:    125

invokeinterface: 1062

 

#2

invokevirtual:   281

invokespecial:   250

invokestatic:    141

invokeinterface: 1078
...
可以看出,静态方法调用最快,而通过接口调用方法最慢(比invokevirtual慢了3-4倍),调用private的方法比调用一般的方法稍快。

调用超类(在现在的jvm spec中与以前的有所不同,不是通过invokespecial来调用)的方法不是很好测试,再想想看。

分享到:
评论
2 楼 haiyupeter 2011-03-07  
嗯,其实Java还是有很多很好玩的东西。
1 楼 yeshaoting 2011-03-04  
好!!现在才知道Java也能反编译出类似汇编的指令信息.

相关推荐

    深入JVM---JVM命令---invokespecial

    然而,`invokespecial`与`invokevirtual`、`invokestatic`和`invokeinterface`等其他方法调用指令有所不同。`invokevirtual`用于调用非私有实例方法,`invokestatic`用于调用静态方法,而`invokeinterface`则用于...

    java虚拟机_JVM高级特性与实践最新版

    - 方法调用优化:涵盖静态绑定与动态绑定的区别,以及invokevirtual、invokespecial、invokestatic等指令的运用。 - JIT编译器:介绍即时编译器如何将热点代码转换为机器码,提升执行效率。 4. **运行时数据区** ...

    JVM工作原理及内存管理机制

    在执行方法时JVM提供了invokestatic、invokevirtual、invokeinterface和invokespecial四种指令来执行 (1)invokestatic:调用类的static方法 (2)invokevirtual:调用对象实例的方法 (3)invokeinterface:将属性...

    自己动手写Java虚拟机 (Java核心技术系列)

    6. **方法调用**:讲解动态链接与方法调用的实现,包括虚方法表、invoke系列指令和 invokevirtual / invokespecial / invokestatic / invokeinterface 等。 7. **异常处理**:探讨JVM如何处理异常,包括异常表、try...

    JVM调用Lambda的表达式实现方法原理详解.docx

    这里主要讨论的是`invokestatic`、`invokespecial`、`invokevirtual`、`invokeinterface`和`invokedynamic`这五种指令。 1. `invokestatic`: 这个指令用于调用静态方法,它不需要任何特定的对象实例,因为静态方法...

    Java虚拟机(字节码介绍)1

    invokevirtual、invokeinterface、invokespecial和invokestatic分别处理虚拟方法调用、接口方法调用、特殊方法调用(如构造器、私有方法)和静态方法调用。ireturn、lreturn等返回指令则根据方法返回值的类型决定...

    08JVM是怎么实现invokedynamic的?(上)1

    在 Java 中,方法调用会被编译为 invokestatic、invokespecial、invokevirtual 以及 invokeinterface 四种指令。这些指令与包含目标方法类名、方法名以及方法描述符的符号引用捆绑。在实际运行之前,Java 虚拟机将...

    [inside hotspot] java方法调用的StubCode1

    在 Java 虚拟机 (JVM) 的实现中,HotSpot 是一个广泛使用的虚拟机实现,它支持多种方法调用指令,如 `invokestatic`、`invokedynamic`、`invokespecial` 和 `invokevirtual`。这些指令负责执行方法调用的不同方面,...

    JVM指令手册(Java)

    `invokevirtual`、`invokespecial`、`invokestatic`、`invokeinterface`指令用于调用方法,它们根据方法的特性(虚拟、特殊、静态、接口)来区分。`return`指令则用于结束方法执行并返回结果。 5. 类加载与初始化...

    Java分布式应用学习笔记-谈JVM.doc

    例如,JVM通过不同的指令(如Invokestatic、invokevirtual、invokeinterface和invokespecial)来调用静态方法、实例方法、接口方法以及private方法或构造器。 **总结** 在Java分布式应用中,理解JVM的运作机制能够...

    JVM指令手册_jvm指令手册_

    5. **对象创建与访问指令**:`new`用于创建一个新的对象实例,`aload`和`astore`用于对象引用的加载和存储,`getfield`和`putfield`用于读写对象字段,`invokevirtual`、`invokespecial`、`invokestatic`、`invoke...

    JVM.rar_jvm_虚拟机

    `invokevirtual`、`invokespecial`、`invokestatic`和`invokeinterface`用于调用方法。 6. **类和数组操作指令**:`checkcast`用于类型检查转换,`instanceof`检查对象是否是特定类或其子类的实例。` anewarray`...

    java字节码指令集.docx

    - `invokevirtual`、`invokespecial`、`invokestatic`、`invokeinterface`:调用方法的指令,根据方法调用的类型执行。 Java字节码指令集的设计使得JVM可以高效地解释和执行代码,同时提供了跨平台兼容性。理解...

    jvm指令手册

    10. **方法调用与返回**:`invokevirtual`、`invokespecial`、`invokestatic` 和 `invokeinterface` 指令用于调用方法,`return` 指令结束方法执行并返回结果。 11. **异常处理**:JVM提供了异常处理框架,通过 `a...

    JVM指令查询手册.pdf

    对象操作指令涉及创建对象(如`new`),访问和调用方法(如`invokevirtual`,`invokespecial`),以及字段访问(如`getfield`, `putfield`)。数组操作指令如`iaload`加载数组中的int元素,`iastore`存储int元素到...

    InvokeDynamic

    在Java虚拟机(JVM)层面,它是一个字节码指令,与`invokestatic`, `invokevirtual`, `invokespecial`等其他方法调用指令并列。 InvokeDynamic机制的核心在于两个概念:Bootstrap Methods(引导方法)和Call Sites...

    JVM指令手册.pdf

    - `invokevirtual`、`invokespecial`、`invokestatic`、`invokeinterface` 用于调用方法。 JVM指令集是Java字节码的基础,理解这些指令的含义和作用,对于优化Java代码、调试程序以及深入理解JVM的工作原理至关...

    多态的实现原理.docx

    调用方法的指令主要有三种:invokestatic用于调用静态方法,invokespecial用于调用私有方法和构造器,而invokevirtual和invokeinterface分别用于调用实例方法和接口方法。 在多态调用时,如果一个对象声明为父类...

    jvm-java字节码规则.pdf

    `invokevirtual`、`invokespecial`、`invokestatic`、`invokeinterface`是JVM用于调用方法的指令集,分别对应虚拟方法调用、特殊方法调用、静态方法调用和接口方法调用。 控制流指令如`ifeq`、`ifne`、`ifle`等用于...

    执行篇:解析JDK 7的动态类型语言支持

    在Java SE 6及以前,JVM主要使用invokestatic、invokevirtual、invokeinterface和invokespecial等指令来调用方法。然而,这些指令在处理动态绑定时效率较低,因为它们在编译期间就确定了方法调用的目标。...

Global site tag (gtag.js) - Google Analytics