方法调用相关的jvm子令集主要有一下四种:
invokestatic ------------------------------->调用类方法(静态绑定,速度快)
invokevirtual ------------------------------>调用实例方法(动态绑定)
invokespecial ----------------------------->调用实例方法(静态绑定,速度快)
invokeinterface --------------------------->调用引用类型为interface的实例方法(动态绑定)
invokedynamic --------------------------->JDK 7引入的,主要是为了支持动态语言的方法调用。可参考
New JDK 7 Feature: Support for Dynamically Typed Languages in the Java Virtual Machine
操作码 操作数 说明
invokestatic indexbyte1,indexbyte2 把args从stack中弹出,调用constant pool索引指向的实例方法
invokevirtual indexbyte1,indexbyte2 把objectref和args从stack中弹出,调用constant pool索引指向的实例方法
invokespecial indexbyte1,indexbyte2 把objectref和args从stack中弹出,调用constant pool索引指向的实例方法
invokeinterface indexbyte1,indexbyte2 把objectref和args从stack中弹出,调用constant pool索引指向的实例方法
//-----------------------------------------------举例浅析区别----------------------------------------------------------------
invokevirtual和invokespecial的区别在于:invokespecial通常根据引用的类型选择方法,而不是对象的类来选择!即它使用静态绑定而不是动态绑定。
使用invokespecial指令分为下面三种情况:
1. 实例初始化方法(<init>())方法
2. 私有方法
3. 使用super关键字调用的方法
invokespecial and Private Methods
看下面一个例子:
- 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();
- }
- }
Here are the bytecodes for the main() method of class Subclass:
- 0: new #5; //class Subclass
- 3: dup
- 4: invokespecial #6; //Method "<init>":()V
- 7: astore_1
- 8: aload_1
- 9: invokevirtual #7; //Method exampleMethod:()V
- 12: return
Subclass从Superclass处继承了exampleMethod()方法。当Subclass的me对象调用exampleMethod()时使用的是invokevirtual。JVM会创建一个新的栈帧并将其压入栈,然后执行exampleMethod()的bytecode。下面是exampleMethod()的bytecode:
- 0: aload_0
- 1: invokespecial #5; //Method interestingMethod:()V
- 4: return
exampleMethod()首先将赋给局部变量0的reference压入stack(隐含参数this被传入给所有的实例方法),然后使用invokespecial指令通过这个引用调用interestingMethod()。
尽管这里的对象时Subclass的实例,而且Subclass类中的interestingMethod()方法也是能够访问的,但是JVM最终还是调用了Superclass类中的interestingMethod()方法。
程序的正确输出为:"Superclass's interesting method",因为这里生成的bytecode中调用的interestingMethod()使用的是invokespecial指令,而调用invokespecial指令时,JVM会按照你reference type来choice调用的method。
//-----------------------------------------------------------------指令调用和速度PK-------------------------------------------------------
可想而知,调用接口引用方法可能要比调用类引用方法慢。因为,当JVM遇到invokevirtual指令时,它把实例方法的符号引用解析为直接引用,所以生成的直接引用很可能是方法表中的一个偏移量,而且从此往后都可以使用同样的偏移量。但对于invokeinterface指令来说,虚拟机每一次遇到invokeinterface指令,都不能不重新搜寻一遍方法表,因为虚拟机不能够假设这一次的偏移量与上一次的偏移量相同。
最快的指令莫过于invokespecial和invokestatic,因为这些指令调用的都是静态绑定的,即在编译器确定了!所以当JVM为这些指令解析符号引用时,将符号引用转换成为直接饮用,所生成的直接引用将包含一个指向实际操作码的指针。
以上内容参考《深入Java虚拟机》
文章来源:http://boy00fly.iteye.com/blog/1158854
分享到:
相关推荐
- **Method Handle**:表示方法的引用,可以通过`java.lang.invoke.MethodHandles`和`java.lang.invoke.MethodHandle`类来创建和操作。 - **Dynamic Call Site**:`invokedynamic`指令所在的字节码位置,它与引导...
5. **资源访问**:Java通过类库直接访问资源,Smali则通过特定指令如`invoke-direct`调用Android框架方法。 学习Smali对于Android开发者来说,尤其是在进行应用安全分析、调试和优化时,具有很大的价值。它可以让你...
- Java代码调用:在Java中使用`System.loadLibrary`或`java.lang.reflect.Method.invoke`加载本地库,并通过`native`关键字定义的方法调用本地代码。 2. **二维码打印机驱动**: - 驱动程序是操作系统与硬件设备...
例如,理解方法定义(`.method`)、字段定义(`.field`)、指令(如`invoke-*`)等基本元素,能够更好地理解转换过程。 总的来说,Smali2JavaUI是Android逆向工程领域的一个实用工具,它使得开发者能更高效地探索和...
而在Smali代码中,我们会看到对应的函数定义,如`.method`和`.end method`,以及具体的指令序列,如`invoke-virtual`用于调用其他方法,`iput`用于设置对象的字段值,`iget`用于获取字段值。 对比Java和Smali,有...
- **方法调用指令**:JVM提供了四种方法调用指令,分别为`invokestatic`(静态绑定)、`invokespecial`(用于私有方法、构造函数和父类方法)、`invokevirtual`(动态绑定)和`invokeinterface`(接口方法调用)。...
它的作用是记录当前线程执行的字节码指令的地址,如果线程正在执行的是 Java 方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是 Native 方法,这个计数器值则为空(Undefined)。 2. ...
3. **方法调用**:反射可以动态调用类的方法,`Method`类提供了`invoke()`方法,传入对象和参数即可执行对应的方法。 4. **字段访问**:可以使用`Field`类来获取和修改类的私有字段,`Field.get()`和`Field.set()`...
5. **使用JDK 1.7的动态语言支持时**,如果`java.lang.invoke.MethodHandle`实例最后的解析结果是`REF_getStatic`、`REF_putStatic`、`REF_invokeStatic`的方法句柄,并且这个方法句柄对应的类没有初始化,则需要先...
3. JVM对反射的支持:JVM提供了相应的API来支持反射操作,如`invoke`指令用于调用方法,`getfield`和`putfield`用于访问字段。 七、Java反射的应用 反射广泛应用于以下场景: - 插件系统:允许加载未知的插件类并...
method.invoke(object, new Object[]{}); } } ``` 这段代码展示了如何在运行时通过反射检查方法是否被特定的注解标记,以及如何获取和使用注解的值。在实际开发中,注解的用途广泛,如用于框架的配置、代码生成、...
这是通过`Method`类提供的`invoke()`方法实现的。 #### 总结 以上是Java面试中常见的一些知识点和问题解答。这些内容不仅涵盖了Java的基础知识,还包括了高级特性和编程实践。深入理解这些概念和技术可以帮助...
通常,这会涉及到`java.lang.invoke.MethodHandle`和`java.lang.invoke.MethodHandles`等类。这些类提供了创建和操作调用点的方法,而引导方法则可以通过`java.lang.invoke.CallSite`接口和相关的`LambdaMetafactory...
2. 调用本地方法:Java代码通过`java.lang.reflect.Method`的`invoke`方法或`Native`关键字定义的方法名来调用本地方法。 3. 本地方法执行:在本地方法中,JNI提供了多种函数,如`JNIEnv`指针,用于访问Java对象、...
在 Java 中,方法调用会被编译为 invokestatic、invokespecial、invokevirtual 以及 invokeinterface 四种指令。这些指令与包含目标方法类名、方法名以及方法描述符的符号引用捆绑。在实际运行之前,Java 虚拟机将...
5. **调用方法**:通过`Method`对象的`invoke()`方法,我们可以调用对象的任意方法,包括参数和重载方法。 6. **处理泛型**:虽然反射无法直接获取泛型信息,但可以通过方法签名或字段类型间接获取。 7. **安全性...
- 动态调用:Method对象的invoke()方法,用于运行时动态调用方法。 - 构造器:Constructor类,newInstance()方法创建对象。 8. **泛型** - 泛型类、泛型方法和通配符:约束类型参数,提高代码安全性和复用性。 ...
- **Method.invoke()**:调用方法。 #### 6. 实现 Java 反射的类 - **Class**:表示一个类。 - **Field**:表示类的成员变量。 - **Method**:表示类的方法。 - **Constructor**:表示类的构造函数。 #### 7. 反射...
SMALI指令集包含许多指令,如`invoke`用于调用方法,`move`用于变量间的数据移动,`add`、`sub`等用于算术运算,`if`、`goto`等用于流程控制。每个指令都有特定的格式和参数,理解这些指令对于解析SMALI至关重要。 ...
method.invoke(instanceOfSomeClass); } } ``` #### 三、输入输出流 1. **文件操作**: - **File类**: 提供了基本的文件和目录管理功能。 - **创建文件**: `File file = new File("path/to/file");` - **...