18. java虚拟机总结-JVM介绍(二)

JVM 就是Java虚拟机(Java Runtime Machine),能够识别.class后缀的文件,解析他的指令,最终调用操作系统上的函数,完成我们需要的操作。

JVM 和操作系统的关系

Java 程序使用 javac 编译成 .class 文件之后,还需要使用 Java 命令去主动执行它,否则操作系统无法识别这些 .class 文件,Java 虚拟机就是一个中间层的角色,承担了解析.class文件的责任,它能够解析.class的指令,最终调用操作系统上的函数。

一句话概括 JVM 与操作系统之间的关系:JVM 上承开发语言,下接操作系统,是一个中间商的角色,有了它就可以实现跨平台了。

Java为什么不像c++一样直接在操作系统上运行编译后的二进制文件,而非要做一个处于中间层的JVM出来?因为Java是一个抽象度特别高的语言,提供了自动内存管理等一系列特性,这些无法通过操作系统实现,所以需要JVM做转换

jvm和操作系统的关系.png

JVM、JRE、JDK的关系

上边说了JVM是用来处理.class文件的,.class就是JVM的输入原料,所以仅仅是 JVM,是无法完成一次编译,处处运行的,.class从何而来?它需要一个基本的类库,比如怎么操作文件、怎么连接网络等,这些JVM 运行所需的类库就是通过JRE提供的

1.JRE : Java Runtime Environment = 类库+JVM

JVM 标准加上实现的一大堆基础类库,就组成了 Java 的运行时环境---JRE(Java Runtime Environment)。有了 JRE 之后,Java 程序便可以运行了。可以看一下安装的 Java 目录,如果是只需要执行一些 Java 程序,只需要一个 JRE 就足够了

2.JDK : Java Development Kit = JRE+工具

JDK包含JRE,除此之外还提供了一些非常好用的小工具,比如 javac、java、jar 等,是 Java 开发的核心

JVM : Java Runtime Machine

JDK JRE JVM的关系.png

Java 虚拟机规范和 Java 语言规范的关系

Java 虚拟机规范,其实就是为输入和执行字节码提供一个运行环境,Java 语言规范,指的是我们开发Java程序中编码时需要注意的规范。Java程序被最终编译成字节码,输入到Java虚拟机中进行解析执行,二者的联系就是字节码


Java虚拟机规范和Java语言规范.png

Java 代码是如何被运行起来的

public class HelloWorld{
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

我们把上边代码反编译,命令: javap -c HelloWorld.class c表示对代码进行反编译

public class HelloWorld {
  public HelloWorld();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #3                  // String Hello World
       5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return
}

Java虚拟机采用基于栈的架构,其指令由操作码和操作数组成。这些字节码指令,就叫作opcode。其中,getstatic、ldc、invokevirtual、return等,就是opcode

使用 hexdump 看一下main方法中字节码的二进制内容。与以上字节码对应的二进制,就是下面这几个数字(可以搜索一下)。

b2 00 02 12 03 b6 00 04 b1

看一下它们的对应关系。

0xb2   getstatic   获取静态字段的值
0x12    ldc   常量池中的常量值入栈
0xb6   invokevirtual   运行时方法绑定调用
0xb1    return           void 函数返回

opcode 有一个字节的长度(0~255),意味着指令集的操作码个数不能操作 256 条。而紧跟在 opcode 后面的是被操作数。比如 b2 00 02,就代表了 getstatic #2

JVM靠解析这些opcode和操作数来运行程序,我们使用Java命令运行.class文件就相当于启动了一个JVM进程,然后JVM会翻译这些字节码,通过两种方式,1.解释执行(解析模式),将opcode和操作数解析成机器代码,或者2.JIT(即时编译,编译模式),它会在一定条件下将字节码编译成机器码之后再执行。这些.class文件会被加载、存放到metaspace中,等待被调用,这里会有一个类加载器的概念。而JVM的程序运行,都是在栈上完成的,这和其他普通程序的执行是类似的,同样分为堆和栈。比如我们现在运行到了 main 方法,就会给它分配一个栈帧。当退出方法体时,会弹出相应的栈帧。你会发现,大多数字节码指令,就是不断的对栈帧进行操作。而其他大块数据,是存放在堆上的。


java程序运行过程.png

解释模式、编译模式、混合模式

jvm中的及时编译器 JIT 有三种编译模式:解释执行模式、编译执行模式、混合执行模式。(编译执行模式效率远远高于解释执行模式)

// mixed mode 表示是混合执行模式
C:\Users\Administrator>java -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) Client VM (build 25.144-b01, mixed mode, sharing)

可以通过命令切换为编译执行模式:java -Xcomp -version。该模式会将函数体编译成机器码,每次函数执行只执行编译好的机器码,效率很高。
编译执行的缺点是不加筛选的将全部代码编译成机器码而不考虑其执行频率是否由编译的价值,在程序有响应时间的限制下,编译器没法采用耗时较高的优化技术(因为JIT的编译是首次运行或启动的时候进行的),所以纯编译模式下Java程序的执行效率和c c++相比仍有差距

C:\Users\Administrator>java -Xcomp -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) Client VM (build 25.144-b01, compiled mode, sharing)

通过命令切换为解析模式:java -Xint -version,该模式不经过jit直接由解释器解释执行所有字节码,效率低于编译模式

C:\Users\Administrator>java -Xint -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) Client VM (build 25.144-b01, interpreted mode, sharing)

通过命令切换为混合模式(默认都是混合模式):java -Xmixed -version,该模式是混合使用解析模式和编译模式,执行时会判断执行函数调用频率,若频率高则是热点代码,使用编译模式执行,否则则使用解析模式执行

C:\Users\Administrator>java -Xmixed -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) Client VM (build 25.144-b01, mixed mode)

三个问题。

为什么 Java 研发系统需要 JVM?

JVM 解释的是类似于汇编语言的字节码,需要一个抽象的运行时环境。同时,这个虚拟环境也需要解决字节码加载、自动垃圾回收、并发等一系列问题。JVM 其实是一个规范,定义了 .class 文件的结构、加载机制、数据存储、运行时栈等诸多内容,最常用的 JVM 实现就是 Hotspot。

对你 JVM 的运行原理了解多少?

JVM 的生命周期是和 Java 程序的运行一样的,当程序运行结束,JVM 实例也跟着消失了。JVM 处于整个体系中的核心位置,关于其具体运行原理,我们在下面的课时中详细介绍。

我们写的 Java 代码到底是如何运行起来的?

一个 Java 程序,首先经过 javac 编译成 .class 文件,然后 JVM 将其加载到元数据区,执行引擎将会通过混合模式执行这些字节码。执行时,会翻译成操作系统相关的函数。JVM 作为 .class 文件的黑盒存在,输入字节码,调用操作系统函数。

过程如下:Java 文件->编译器>字节码->JVM->机器码。

选用的JVM版本

JVM 只是一个虚拟机规范,有非常多的实现。最流行的要数 Oracle 的 HotSpot。目前,最新的版本是 Java13(注意最新的LTS版本是11)。以 13 版本的 Java 为基准,来了解发生在 JVM 上的那些事儿。

我们所说的JVM,狭义上指的就HotSpot。如非特殊说明,我们都以HotSpot为准。我们了解到,Java之所以成为跨平台,就是由于JVM的存在。Java的字节码,是沟通 Java 语言与 JVM 的桥梁,同时也是沟通 JVM 与操作系统的桥梁。

Java 虚拟机采用基于栈的架构,有比较丰富的 opcode。这些字节码可以解释执行,也可以编译成机器码,运行在底层硬件上,可以说 JVM 是一种混合执行的策略。

总结:

一个Java程序,首先经过javac编译成.class文件,然后JVM将其加载到元数据区,执行引擎将会执行这些字节码。执行时,会翻译成操作系统相关的函数。JVM 作为 .class 文件的黑盒存在,输入字节码,调用操作系统函数。过程如下:Java 文件->编译器>字节码->JVM->机器码。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容