关注“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的关系

下面曾经说过JDKJVM的相干概念,

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_SUPERConstant 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最新学习材料

同步该文章