Java虚拟机

前面写了几篇关于Java虚拟机和字节码的文章,由于没有进行系统的整理,导致在阅读的过程中很难有一个清晰的框架和思路,今天就在回顾的基础上以及加上新的理解,统一整理如下。

一、Java虚拟机的概念

Java虚拟机(Java Virtual Machine,JVM),一种能够运行Java字节码的虚拟机。作为一种编程语言的虚拟机,实际上不只是专用于Java语言,只要生成的编译文件匹配JVM对加载编译文件格式要求,任何语言都可以由JVM编译运行,比如Kotlin、Groovy等。

在这里可以看出Java虚拟机提供了两个很重要的特性:平台无关性、语言无关性

平台无关性是指:Java字节码是运行在Java虚拟机上而不是具体的操作系统,然后虚拟机运行在操作系统上。这样的好处就是在编写程序时无需考虑各种系统的差异,只要编译后的字节码遵循Java虚拟机的规范,就可以运行在各个系统上。

语言无关性是指:Java虚拟机直接运行的是字节码文件,但字节码是用什么语言编译而来Java虚拟机不在乎,可以是Java语言、Groovy语言等。

二、Java虚拟机的基本结构

JVM由三个主要的子系统构成:类加载子系统、运行时数据区(内存结构)、执行引擎,如下图:

下面分别对这三个部分进行讲解

1、类加载子系统

该篇文章已经做过详细的介绍:虚拟机类加载机制

2、运行时数据区(内存结构)

该篇文章已经做过详细的介绍:Java虚拟机内存划分

3、执行引擎

“虚拟机”是一个相对于“物理机”的概念,这两种机器都有代码执行的能力,其区别是物理机的执行引擎是直接建立在处理器、硬件、指令集和操作系统层面的,而虚拟机的执行引擎是由自己实现的,因此可以自行制定指令集与执行引擎的结构体系,并且能够执行那些不被硬件直接支持的指令集格式。

下面通过一个简单的实例来看执行引擎是如何执行程序的

JvmDemo.java源码:

package cn.yxz;

public class JvmDemo {

    public int math() {
        int a = 1;
        int b = 2;
        int c = (a + b) * 10;
        return c;
    }

    public static void main(String[] args) {
        JvmDemo demo = new JvmDemo();
        demo.math();
    }

}

通过javap -c JvmDemo.class反编译后的内容如下:

在分析这段指令前,首先介绍下面要用到的几个概念:

1、operand stack:操作数栈,是一个栈结构,只做临时存储作用。它位于local variable(局部变量表)和CPU中间,存到局部变量表里的值必须从操作数栈获取,CPU需要运算的值也从里面获取,并且这个获取操作是出栈操作,即操作后该值不再存在在栈中。

2、local variable:局部变量表。局部变量表是一种数组结构,单位是32位即4个字节,像64位的long和double类型需要占两个单位。

下面主要分析一下math方法,命令参考链接

1、iconst_1:push int 1 constant onto the operand stack,将1推送到操作数栈中
2、istore_1:store int from operand stack into local variable at index 1,将操作数栈中的值出栈并存放在局部变量表的下标为1的位置
3、iconst_2:push int 2 constant onto the operand stack,同1,将2推送到操作数栈中
4、istore_2:store int from operand stack into local variable at index 2,同2,将操作数栈中的值出栈并存放在局部变量表的下标为2的位置
5、iload_1:load int from local variable at index 1 and push onto operand stack ,与istore_1对应,将局部变量表中下标为1的值复制一份存入到操作数栈中,注意:这时是复制,因为后面可能还需要用到
6、iload_2:load int from local variable at index 2 and push onto operand stack    ,同5
7、iadd:pop the first 2 ints from the operand stack, add them and place the int result onto the operand stack,将最上面的两个值出栈并送去CPU执行加法,然后将值存到操作数栈
8、bipush:convert index byte (signed 8-bit integer) to an int and push it onto the operand stack,将索引字节(带符号的8位整数)转换为int并将其推送到操作数堆栈上
9、imul:pop the first 2 ints from the operand stack, multiply them and place the integer result onto the operand stack,将最上面的两个值出栈并送去CPU执行乘法,然后将值存到操作数栈
10、istore_3,同2
11、iload_3,同5
12、ireturn:pop int from operand stack of the current frame (= method) and push onto the operand stack of the frame of the invoker,将当前栈帧的栈顶的值出栈并推送到调用者的栈真的操作数栈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值