手记

图解JVM系列-JVM入门指南:基础、转换流程

大家好,我是大圣,很高兴又和大家见面。

我打算写一个图解JVM 的系列,从 JVM 最基础的知识讲起,一直到最后JVM调优。

目前规划是这个系列是八篇文章,一星期更新四篇。今天是第一篇,大纲如下:

前言

为什么要学习JVM

JVM 可以说是 Java 工程师和大数据工程师必须掌握的一个技能。

因为 Java 代码是跑在 JVM 平台上面的,如果你写的代码在 JVM 运行的时候出现内存溢出或者GC 严重的时候,这个时候就需要你对 JVM 有一定的了解了。

大数据方向的话,Spark、Flink 的内存模型都是在 JVM 模型上进行了二次改造,而且基本上现在大数据主流的框架底层都是 Java 编写的,也是跑在 JVM 上面的,在对这些框架调优的时候 JVM 也是避不开的一个知识。

内容预告

这一篇文章注意说 JVM的核心作用、代码到JVM上的过程、Java的跨平台优势 三个问题。

通过这三个问题,大家可以对 JVM 有一个直观的认识,然后为接下来的文章打下一个基础。

JVM的核心作用

程序到底是怎么执行的

不知道大家有没有想过,我们天天写的 Java、C++、Python 程序最后是怎么上 CPU 执行的。

其实是这样的,我给大家先说一个专业的解释,然后举一个通俗易懂的例子。

专业解释

编译

编译器将你的高级语言代码(如C++或Java)转换为低级的机器代码或字节码。对于像Java这样的语言,它首先编译为字节码,然后由JVM进一步处理。

JVM处理:

对于Java这样的语言,JVM会将字节码转换为机器码。这通常是通过JIT(即时编译器)完成的,它在运行时将字节码转换为特定于平台的机器码。

加载到内存:

编译后的代码(机器码)被加载到计算机的内存中,准备执行。

CPU执行指令:

CPU从内存中读取指令,这些指令是二进制形式的,对应于CPU的指令集架构。

CPU根据指令执行操作,这可能包括算术运算、数据传输、条件分支等。

指令通常会操作CPU的寄存器和内存中的数据。

CPU通过其控制单元解析并执行这些指令,而算术逻辑单元(ALU)负责执行数学和逻辑操作。

与其他硬件组件交互:

CPU执行的指令可能涉及与计算机的其他部分交互,如读写内存、发送数据到输出设备或从输入设备接收数据。

举例说明

大家可以先看下面这个图:

想象一下你是一名厨师,想要做一道菜:

编译

这就像是你有一本食谱(源代码),但这本食谱是用你不太熟悉的外语写的。所以你需要一个翻译(编译器)来将这个食谱翻译成你能理解的语言。对于Java来说,这个“翻译”过程就是将Java代码转换成字节码。

JVM处理

如果你是用Java做的这道菜,你现在有了字节码版本的食谱。但这还不是你可以直接使用的。你需要一个专门的厨师助手(JVM),他能够理解这个字节码食谱,并且知道如何将其转换成实际的烹饪步骤(即时编译器将字节码转换为机器码)。

加载到内存

现在你的助手已经知道要做什么了,他开始准备食材(将机器码加载到计算机内存中)。

CPU执行指令

现在开始烹饪(CPU执行指令)。CPU就像是厨房的炉子和工具,根据食谱上的指示(机器码指令)进行烹饪。这包括切东西、搅拌、加热等操作(算术运算、数据传输、条件分支等)。

与其他硬件组件交互

在烹饪过程中,你可能需要使用冰箱(内存)来取出或存放食材,或者把成品放到餐盘上(输出设备)供人品尝。

小结

总的来说,就像厨师按照翻译后的食谱准备和烹饪食物一样,计算机程序也是经过一系列的转换和处理步骤,最终由CPU以机器码的形式执行。

大家可以直观的认为 JVM 就是把 Java 编译成的字节码翻译成CPU 所需要的机器码。

可能有小伙伴对 Java 编译成的字节码不太了解,下面咱们就来说一下这个字节码。

代码到JVM上的过程

专业解释

当写一个.java文件中的Java程序时,该程序需要经过编译过程才能变成可以被 JVM 执行的形式。这个过程如下:

编写源代码

使用Java语言编写程序,这些代码被保存在一个或多个.java文件中。

调用Java编译器

使用Java编译器(通常是javac),将.java文件中的源代码编译成Java字节码。
编译器检查源代码的语法错误,如果发现错误,编译过程会停止,并提示错误信息。

生成字节码

如果源代码没有错误,编译器将每个.java文件转换成一个对应的.class文件。
这些.class文件包含Java字节码,这是一种中间形式的代码,不是人类可读的源代码,也不是特定于某种处理器的机器代码。
字节码的特点:

Java字节码是一种中间级别的代码,它更接近于机器码,但仍然保留了高级语言的一些特性。
字节码设计成可在任何实现了Java虚拟机的系统上运行,实现了Java的“一次编写,到处运行”(Write Once, Run Anywhere)的理念。

准备执行:

生成的.class文件现在可以被Java虚拟机加载和执行。JVM会进一步将字节码转换为特定平台的机器码。

举例说明

如下图:

想象一下你是一名剧本作家(程序员):

编写剧本(编写源代码):

你用一种特定的语言(Java语言)写一个故事(程序)。这个故事被记录在多个文档(.java文件)中。

剧本审核(调用Java编译器):

你把剧本交给一位编辑(Java编译器),他负责检查剧本的语法和结构是否正确。如果剧本中有任何语法错误,编辑会通知你,并指出需要修改的地方。

转换成剧本剧情大纲(生成字节码):

如果剧本没有错误,编辑会将其转换成一个剧情大纲(.class文件)。这个大纲不像完整的剧本那样详细,但包含了故事的所有关键元素(Java字节码)。

剧本剧情大纲的特点(字节码的特点):

这个大纲是一个标准格式,可以被任何剧院(JVM)理解。它不是具体的演出指南,但包含足够的信息让不同的剧院可以根据自己的方式来演绎这个故事。

准备上演(准备执行):

这个剧情大纲现在可以被不同的剧院(不同平台上的JVM)拿去演绎。剧院会根据大纲把故事转换成实际的舞台表演(JVM将字节码转换为机器码),并最终呈现给观众。

小结

这个剧情大纲现在可以被不同的剧院(不同平台上的JVM)拿去演绎。剧院会根据大纲把故事转换成实际的舞台表演(JVM将字节码转换为机器码),并最终呈现给观众。

Java的跨平台优势

为什么我们要装不同系统的 JDK

前面我们说了,JVM 就是把我们编译的.class 的字节码拿来执行一下翻译成操作系统所需要的机器指令。

那我们为什么要装不同系统的JDK 呢? 这是因为一方面 JDK 里面包含了 JVM,另一方面是因为不同操作系统的 CPU 指令集是有差别的。

比如window 系统和Linux 系统,它底层的CPU 指令集是有差别的,所以我们JVM 在不同操作系统把.class 字节码翻译成的机器指令也是有差别的。

Java 为什么能够跨平台

这就是因为Java程序不是直接编译成特定操作系统或硬件平台的机器码,而是编译成一个中间形式——Java字节码(.class文件)。

这种字节码不依赖于任何特定的硬件或操作系统

由于Java程序是编译成平台无关的字节码,因此,同一个Java程序(不考虑特定平台的API调用)可以在任何安装了相应JVM的操作系统上面执行。

总结

内容说明

这篇文章就说了 JVM的核心作用、代码到JVM上的过程、Java的跨平台优势 三个知识 ,让大家可以直观的感受到 JVM 的一些作用。

补充

可能有小伙伴们会说,你这个文章说的太粗糙,而且 .class 字节码这个知识点,就一笔带过了,也没给大家说一下.class 字节码的文件格式,一些注意点等等细节。

其实我想说,如果我们学JVM一上来就钻到这种 .class 字节码的这种细节里面,这里面有很多专业名词,很快就会把你劝退的,我被劝退过很多次,这是我学 JVM 的亲身体验。

并且 .class 字节码这个知识点在 JVM 这个知识体系里面是很小的一个知识点,重要的知识点在运行时数据区,垃圾回收器,GC日志,DUMP 日志 这些东西,这些我都会详细说的。

小结

JVM的核心作用、代码到JVM上的过程、Java的跨平台优势 三个知识点。

JVM的核心作用:就是把.class 文件拿来跑跑翻译成机器指令

代码到JVM上的过程:Java 代码会被编译成 .class 文件

Java的跨平台优势:Java字节码(.class文件)和 JVM 提供了跨平台

0人推荐
随时随地看视频
慕课网APP