关注“Java 后端技术全栈”
回复“000”获取大量电子书
意识 JVM
什么是 JVM
JVM
全称 Java Virtual Machine,也就是咱们耳熟能详的 Java 虚拟机。它能辨认 .class 后缀的文件,并且可能解析它的指令,最终调用操作系统上的函数,实现咱们想要的操作。
可能有局部小伙伴学习过 C ++,C++ 开发进去的程序,编译成二进制文件后,就能够间接执行了,操作系统是可能辨认的。
然而咱们开的的 Java 程序就不一样了,应用 javac
命令编译进去的的.class 文件之后,操作系统是不能辨认的,须要对应 JVM
去做一个转换后,操作系统能力辨认。
咱们为什么不能像 C++ 一样,间接在操作系统上运行编译后的二进制文件呢?而非要搞一个处于程序与操作系统中间层的虚拟机呢?
这就是 JVM
的过人之处了。大家都晓得,Java 是一门形象水平特地高的语言,提供了主动内存治理等一系列的个性。这些个性间接在操作系统上实现是不太可能的,所以就须要JVM
进行做一系列的转换。
大家一开始学 Java 的时候,就晓得有个 Write Once, Run Everywhere。就是咱们编写了一个 java 文件通过编译成.class 文件后,能够在各种零碎中进行运行。
其实这里是有个前提的,咱们须要在对应操作系统中装置对应的JVM
,而后咱们的.class 文件就能运行了。
比方:Windows 操作系统有对应的 JDK
装置版本、Linux 也有对应的 JDK
装置版本等。
意识 JDK
Java Development Kit (JDK
) 是 Sun 公司(已被 Oracle 收买)针对 Java 开发员的软件开发工具包。自从 Java 推出以来,JDK
曾经成为应用最宽泛的 Java SDK
(Software development kit)。
经非官方考察,目前 JDK8
是使用者最多的版本。
JDK14
将在 4 月和 7 月收到安全更新,而后由 9 月到期的非 LTS 版本的 JDK 15
取代。JDK14
包含 16 项新性能,例如 JDK Flight Recorder
事件流,模式匹配和开关表达式等特色。
从 JDK9
之后,Oracle 采纳了新的公布周期:每 6 个月公布一个版本,每 3 年公布一个 LTS
版本。JDK14
是继 JDK9
之后公布的第四个版本,该版本为非 LTS
版本,最新的 LTS
版本为JDK11
。
上面是 JDK
版本状况
这个混个眼生就行,随时关注 JDK
版本更新和新个性。
官网地址:https://www.oracle.com/java/
对于 JDK
装置这里就省略。
JDK、JRE、JVM 的关系
下面曾经说过 JDK
和JVM
的相干概念,
JRE
全程 Java Runtime Environment,是运行基于 Java 语言编写的程序所不可短少的运行环境。也是通过它,Java 的开发者才得以将本人开发的程序公布到用户手中,让用户应用。
三者到底是什么关系呢?
对于三者关系请看官网
https://docs.oracle.com/javas…
JDK
中蕴含 JRE
,也包含JDK
,而JRE
也包含JDK
。范畴关系:JDK
>JRE
>JVM
“.java” 文件到 ”.class” 文件
javac
命令
编写一个 HelloWorld.java
文件
内容就是一个 Java
入门
public class HelloWorld {public static void main(String[] args) {System.out.println("Hello world");
}
}
关上CMD
,进入当前目录,应用命令
javac HelloWorld.java
就编译出HelloWorld.class
编译过程
这个 javac命令过程到底干了些什么呢?
javac
背地大抵做了这些操作
这个流程
1、词法剖析
读取源代码,一个字节一个字节的读取,找出其中咱们定义好的关键字(如 Java
中的 if、else、for、while 等关键词,辨认哪些 if 是非法的关键词,哪些不是),这就是词法分析器进行词法剖析的过程,其后果是从源代码中找出规范化的 Token 流。
2、语法分析
通过语法分析器对词法剖析后 Token 流进行语法分析,这一步查看这些关键字组合再一次是否合乎 Java
语言标准(如在 if 前面是不是紧跟着一个布尔判断表达式),词法剖析的后果是造成一个合乎 Java
语言标准的形象语法树。
3、语义剖析
通过语义分析器进行语义剖析。语音剖析次要是将一些难懂的、简单的语法转化成更加简略的语法,后果造成最简略的语法(如将 foreach
转换成 for 循环,好有注解等),最初造成一个注解过后的形象语法树,这个语法树更为靠近目标语言的语法规定。
4、生成字节码
通过字节码生产器生成字节码,依据通过注解的语法形象树生成字节码,也就是将一个数据结构转化为另一个数据结构。最初生成咱们想要的.class 文件。
应用十六进制查看 class 文件内容
我只用的是 Notepad++,选中文本→插件→Converter→ASCII->HEX
class 文件的结尾就是
CAFEBABE
想要学习这里的十六进制的字节码的含意能够参考
https://docs.oracle.com/javas…
–
javap 查看 class 文件内容
javap
是 Java class 文件分解器,能够反编译(即对 javac
编译的文件进行反编译),也能够查看 java
编译器生成的字节码。
新建一个 User.java
源文件,通过 javac
编译后,生成User.classs
。
package com.tian.demo.test;
public class User {
private int age = 22;
private String name = "tian";
public int addAge() {return age = age + 1;}
public static void main(String[] args) {}}
应用 javap
命令
javap -v User.class >log.txt
关上log.txt
Classfile /D:/workspace/new/demo/src/main/java/com/tian/demo/test/User.class
Last modified 2020-11-5; size 441 bytes
MD5 checksum 2fa72d3f53bd9f138e0bfae82aba67e3
Compiled from "User.java"
public class com.tian.demo.test.User
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #6.#21 // java/lang/Object."<init>":()V
#2 = Fieldref #5.#22 // com/tian/demo/test/User.age:I
#3 = String #23 // tian
#4 = Fieldref #5.#24 // com/tian/demo/test/User.name:Ljava/lang/String;
#5 = Class #25 // com/tian/demo/test/User
#6 = Class #26 // java/lang/Object
#7 = Utf8 age
#8 = Utf8 I
#9 = Utf8 name
#10 = Utf8 Ljava/lang/String;
#11 = Utf8 <init>
#12 = Utf8 ()V
#13 = Utf8 Code
#14 = Utf8 LineNumberTable
#15 = Utf8 addAge
#16 = Utf8 ()I
#17 = Utf8 main
#18 = Utf8 ([Ljava/lang/String;)V
#19 = Utf8 SourceFile
#20 = Utf8 User.java
#21 = NameAndType #11:#12 // "<init>":()V
#22 = NameAndType #7:#8 // age:I
#23 = Utf8 tian
#24 = NameAndType #9:#10 // name:Ljava/lang/String;
#25 = Utf8 com/tian/demo/test/User
#26 = Utf8 java/lang/Object
{public com.tian.demo.test.User();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 22
7: putfield #2 // Field age:I
10: aload_0
11: ldc #3 // String tian
13: putfield #4 // Field name:Ljava/lang/String;
16: return
LineNumberTable:
line 3: 0
line 4: 4
line 5: 10
public int addAge();
descriptor: ()I
flags: ACC_PUBLIC
Code:
stack=3, locals=1, args_size=1
0: aload_0
1: aload_0
2: getfield #2 // Field age:I
5: iconst_1
6: iadd
7: dup_x1
8: putfield #2 // Field age:I
11: ireturn
LineNumberTable:
line 8: 0
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=0, locals=1, args_size=1
0: return
LineNumberTable:
line 13: 0
}
SourceFile: "User.java"
魔数与 class 文件版本
常量池
拜访标记
类索引、父类索引、接口索引
字段表汇合
办法表汇合
属性表汇合
而后 JVM
就能够读取这个 User.class
文件进行解析等一系列的操作。
以上就是咱们的 Java
文件到 class 文件。
后续还会更新一系列 JVM 相干文章,敬请期待~
举荐浏览:
《Java Web 企业我的项目实战》.pdf
《MySQL 开发者 SQL 权威指南》.pdf
关注公众号“Java 后端技术全栈”
收费获取 500G 最新学习材料