`
sslaowan
  • 浏览: 374242 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JVM方法调用指令

    博客分类:
  • JVM
阅读更多

     终于把Inside JVM这本看完了,好久没这么细致的看一本书了。

     好多人都写了文章讨论jvm如何实现多态的,我只是简单做个笔记。

     类的字节码结构有个常量池,其中就存放了这个类中调用的方法的符号引用,这些符号引用实际上是放在一些特殊类型(CONSTANT_NameAndType_info)的常量池入口中,调用方法有四个指令,invoke_static,invoke_special,invoke_virtual,invoke_interface。jvm指令是调用某个栈上的变量的方法,因此这个变量就有可能指向的是对象或者接口。

刚才提到直接引用,这个在常量池解析时,会将符号引用替换为直接引用。而对于不同情况,直接引用代表的东东是不同的。对于静态类变量,方法指的是本地指针,对于实例方法,指的就是方法表偏移量。

     对于类继承关系而言,从Object开始,所有类的方法的描述的方法在方法表中的索引(也就是在方法表中的位置的偏移量)都是一样的,比如toString方法,无论是在Object,还是在它的子类里,子类的子类里,这个偏移量都是一样的,因此如果栈上的那个变量指向的是一个类实例而不是一个接口,那么就可以替换这个方法调用的常量池入口的符号引用为这个偏移量,真正在运行时调用这个方法时,直接找到那个对象对应的类的方法表,用那个偏移量一下子就可以定位到具体的方法了。

      方法表是类基本信息的一部分,这个可以理解成一个中间表,将偏移量这个逻辑的index与方法真实的本地指针关联了起来(指向方法区,这个区是跟堆一样,所有线程共享的)。

      可以看到,如果是调用静态编译的方法,那么调用时,直接就可以找到本地指针去执行那个方法,如果是指向类的变量调用实例方法,那么就拿放在常量池中的偏移量到类方法表中去查到那个本地指针,再去执行那个方法。

      jvm还有一些指令,加了quick后缀,对于上面两种情况,在常量池解析后,实际上就会直接将原来的指令换为quick版本,将直接引用直接作为指令的操作数,这样就不用跑到常量池中去查一次了。

      那么对于栈中的变量是指向接口的情况怎么办。如果两个毫不相干的类都实现了某个接口,那么对于接口中的一个方法,在两个类的方法表中的偏移量就有可能是不同的,这个时候,在运行时,就只能用方法描述去到类的方法表中现去匹配,当然虚拟机在实现时,会有各种方法提高这个匹配的速度,比如预先分配一个数据结构做索引,或者是把成功匹配到的方法的偏移量做个mapping表,下次再访问时就可以快速找到了。

 

     另外,每调用一个方法时,当前线程就会创建一个frame,然后把它放到当前stack中,每个frame都包括局部变量区,操作数栈和frame变量区。那么一个方法里调用了另一个方法怎么办呢?那就再创建一个frame,去执行那个frame里所有的指令,执行完了再返回刚才那个frame继续执行。因此调用另一个方法是比较耗时的,这才有了方法内联这个优化。在编译类的时候,每个方法占多大内存都是计算好的,运行时中的方法区里保存了这些元数据,创建frame时就根据方法区的内容去创建就好了。

分享到:
评论

相关推荐

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

    Java中方法的调用对应字节码有5条指令: invokestatic:用于调用静态方法。 invokespecial:用于调用实例构造器方法、私有方法和父类中的方法。 invokevirtual:用于调用所有的虚方法。 invokeinterface:...

    JVM执行子系统原理

    详细介绍了JVM执行子系统的工作原理,包括类文件结构与字节码指令(Class类文件结构、JVM字节码指令简介)、JVM类加载机制(类加载器、类加载时机、类加载过程)、字节码执行引擎(运行时候的栈结构、方法调用、方法...

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

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

    深入理解JVM内存结构及运行原理全套视频加资料.txt

     第83讲 方法调用和返回指令 00:06:37  第84讲 异常处理指令 00:09:44  第85讲 同步指令 00:07:34  第86讲 类加载机制概述 00:07:26  第87讲 类加载时机 00:13:15  第88讲 类加载的过程-加载 00:15:15 ...

    sunjava虚拟机(jvm)v1.6官方安装版java(TM)6Update4

    JVM:Java Virtual Machine(JAVA虚拟机)。JVM是JRE的一部分,它是一个...JVM 的主要工作是解释自己的指令集(即字节码)并映射到本地的 CPU 的指令集或 OS 的系统调用。Java语言是跨平台运行的,其实就是不同的操作系统

    【读书笔记】【图解JVM】ppt

    JVM内在结构的图解文档,visio格式 1.编译过程 2.内存结构 3.对象与类的结构 4.类结构信息 5.对象建立过程 6.收集器 7.方法调用 8.垃圾回收 9.JIT 10.指令 11.线程

    深入理解Java虚拟机视频教程(jvm性能调优+内存模型+虚拟机原理)视频教程

    第83节方法调用和返回指令00:06:37分钟 | 第84节异常处理指令00:09:44分钟 | 第85节同步指令00:07:34分钟 | 第86节类加载机制概述00:07:26分钟 | 第87节类加载时机00:13:15分钟 | 第88节类加载的过程-加载00:15...

    精简版JVM总结.pdf

    每个线程都有独自的虚拟机栈,并且在栈中的结构是栈帧,当调用一个方法时,会为这个方法 创建一个栈帧,每个方法对应的是入栈、出栈的过程 栈帧中包括局部变量表、操作数栈、动态链接、方法出口等信息 线程请求的栈...

    【读书笔记】【图解JVM】

    JVM内在结构的图解文档,visio格式 1.编译过程 2.内存结构 3.对象与类的结构 4.类结构信息 5.对象建立过程 6.收集器 7.方法调用 8.垃圾回收 9.JIT 10.指令 11.线程

    sys rucaja-Rust通过JNI调用Java-Rust开发

    用法JNI调用比常规JVM指令慢大约10到20倍。 建议Rucaja(Rust称为Java)通过JNI从Rust调用JVM代码。 用法JNI调用比常规JVM指令慢大约10到20倍。 建议调用尽可能少的函数来完成尽可能多的工作。 创建一个平面Java包装...

    该仓库为Java进阶部分课堂同步代码.rar

    在VM字节码层面并没有任何特别的指令来实现被synchronized修饰的方法,而是在Class文件的方法表中将该方法的access_flags字段中的synchronized标志位置1,表示该方法是同步方法并使用调用该方法的对象或该方法所属的...

    深入理解_Java_虚拟机 JVM_高级特性与最佳实践

    / 199 8.2.2 操作数栈 / 204 8.2.3 动态连接 / 206 8.2.4 方法返回地址 / 206 8.2.5 附加信息 / 207 8.3 方法调用 / 207 8.3.1 解析 / 207 8.3.2 分派 / 209 8.4 基于栈的字节码解释执行引擎 / 221 8.4.1 ...

    Java虚拟机.docx

    3.本地方法栈:当Java去调用一些本地的C/C++方法时使用的栈,native关键字修饰的方法是间接去调用本地的底层方法。 4.堆:通过new关键字,创建对象都会使用到堆内存,堆属于线程共享的,需要考虑线程安全的问题,有...

    java虚拟机详解.docx

    而每个线程创建的时候,都会拥有自己的程序计数器和 Java栈,其中程序计数器中的值指向下一条即将被执行的指令,线程的Java栈则存储为该线程调用Java方法的状态;本地方法调用的状态被存储在本地方法栈,该方法栈...

    组装:将WebAssembly编译为JVM和其他WASM工具

    WASM解释器(一次可逐步执行的指令) WASM二进制,WASM文本和WASM AST之间的转换实用程序 上面所有程序的JVM库(用Kotlin编写) 示出了如何使用其他语言在经由WASM的JVM(例如生锈) 快速开始 WebAssembly本身...

    JVM内存模型及垃圾回收

    通俗的来讲,jvm主要分为5个部分 程序计数器、虚拟机枝、本地方法枝、 Java 堆、 方法区, 引用大佬总结的概括程序计数器用于存放下一条运行的指令,虚拟机栈和本地方法栈用于存放函数调用堆栈信息, Java 堆用于...

    深入Java虚拟机(原书第2版).pdf【附光盘内容】

    19.3.1 指令invokespecial和[init]()方法 19.3.2 指令invokespecial和私有方法 19.3.3 指令invokespecial和super关键字 19.4 指令invokeinterface 19.5 指令的调用和速度 19.6 方法调用的实例 19.7 ...

    09JVM是怎么实现invokedynamic的?(下)1

    在第一次执行 invokedynamic 指令时,Java 虚拟机会调用该指令所对应的启动方法(BootStrapMethod),来生成前面提到的调用点,并且将

    java7rt.jar源码-Java_JVM:这是我的JavaJVM学习笔记

    Runtime或System类调用exit()方法或Runtime调用half()方法 JVM的框架: 执行引擎: (字节)解释器 + JIT(java即时编译器) 前者是用 PC计数器 来依次编译每一行代码解释为本地机器指令; 后者是通过 寻找热点代码 进行...

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

    引入了一条新的指令invokedynamic。该指令的调用机制抽象出调用点这一个概念,并允许应用程序将调用点链接至任意符合条件的方法上。// 加载一个任意对象1

Global site tag (gtag.js) - Google Analytics