成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

JVM真香系列:Java文件到.Class文件

開發(fā) 后端
JVM 全稱 Java Virtual Machine,也就是我們耳熟能詳?shù)?Java 虛擬機(jī)。它能識別 .class后綴的文件,并且能夠解析它的指令,最終調(diào)用操作系統(tǒng)上的函數(shù),完成我們想要的操作。

 [[352624]]

什么是JVM

JVM 全稱 Java Virtual Machine,也就是我們耳熟能詳?shù)?Java 虛擬機(jī)。它能識別 .class后綴的文件,并且能夠解析它的指令,最終調(diào)用操作系統(tǒng)上的函數(shù),完成我們想要的操作。

可能有部分小伙伴學(xué)習(xí)過C++,C++開發(fā)出來的程序,編譯成二進(jìn)制文件后,就可以直接執(zhí)行了,操作系統(tǒng)是能夠識別的。

但是咱們開的的Java程序就不一樣了,使用javac命令編譯出來的的.class文件之后,操作系統(tǒng)是不能識別的,需要對應(yīng)JVM去做一個轉(zhuǎn)換后,操作系統(tǒng)才能識別。

我們?yōu)槭裁床荒芟?C++ 一樣,直接在操作系統(tǒng)上運(yùn)行編譯后的二進(jìn)制文件呢?而非要搞一個處于程序與操作系統(tǒng)中間層的虛擬機(jī)呢?

這就是 JVM的過人之處了。大家都知道,Java 是一門抽象程度特別高的語言,提供了自動內(nèi)存管理等一系列的特性。這些特性直接在操作系統(tǒng)上實(shí)現(xiàn)是不太可能的,所以就需要JVM 進(jìn)行做一系列的轉(zhuǎn)換。

大家一開始學(xué)Java的時候,就知道有個Write Once, Run Everywhere。就是我們編寫了一個java文件經(jīng)過編譯成.class文件后,可以在各種系統(tǒng)中進(jìn)行運(yùn)行。

其實(shí)這里是有個前提的,我們需要在對應(yīng)操作系統(tǒng)中安裝對應(yīng)的JVM,然后我們的.class文件就能運(yùn)行了。

比如:Windows操作系統(tǒng)有對應(yīng)的JDK安裝版本、Linux也有對應(yīng)的JDK安裝版本等。

認(rèn)識JDK

Java Development Kit (JDK) 是Sun公司(已被Oracle收購)針對Java開發(fā)員的軟件開發(fā)工具包。自從Java推出以來,JDK已經(jīng)成為使用最廣泛的Java SDK(Software development kit)。

經(jīng)非官方調(diào)查,目前JDK8是使用者最多的版本。

JDK14將在4月和7月收到安全更新,然后由9月到期的非LTS版本的JDK 15取代。JDK14包括16項(xiàng)新功能,例如JDK Flight Recorder事件流,模式匹配和開關(guān)表達(dá)式等特征。

從JDK9之后,Oracle采用了新的發(fā)布周期:每6個月發(fā)布一個版本,每3年發(fā)布一個LTS版本。JDK14是繼JDK9之后發(fā)布的第四個版本, 該版本為非LTS版本,最新的LTS版本為JDK11。

下面是JDK版本情況


這個混個眼熟就行,隨時關(guān)注JDK版本更新和新特性。

官網(wǎng)地址:https://www.oracle.com/java/

關(guān)于JDK安裝這里就省略。

JDK、JRE、JVM的關(guān)系

上面已經(jīng)說過JDK和JVM的相關(guān)概念,

JRE全程Java Runtime Environment,是運(yùn)行基于Java語言編寫的程序所不可缺少的運(yùn)行環(huán)境。也是通過它,Java的開發(fā)者才得以將自己開發(fā)的程序發(fā)布到用戶手中,讓用戶使用。

三者到底是什么關(guān)系呢?

關(guān)于三者關(guān)系請看官網(wǎng)

https://docs.oracle.com/javase/8/docs/index.html

JDK中包含JRE,也包括JDK,而JRE也包括JDK。范圍關(guān)系:JDK>JRE>JVM

".java"文件到".class"文件

`javac`命令

編寫一個HelloWorld.java文件

內(nèi)容就是一個Java入門

  1. public class HelloWorld { 
  2.     public static void main(String[] args) { 
  3.         System.out.println("Hello world"); 
  4.     } 

 打開CMD,進(jìn)入當(dāng)前目錄,使用命令

  1. javac HelloWorld.java 

就編譯出HelloWorld.class

編譯過程

這個javac命令過程到底干了些什么呢?

javac背后大致做了這些操作


這個流程

 

 

1、詞法分析

讀取源代碼,一個字節(jié)一個字節(jié)的讀取,找出其中我們定義好的關(guān)鍵字(如Java中的if、else、for、while等關(guān)鍵詞,識別哪些if是合法的關(guān)鍵詞,哪些不是),這就是詞法分析器進(jìn)行詞法分析的過程,其結(jié)果是從源代碼中找出規(guī)范化的Token流。

2、語法分析

通過語法分析器對詞法分析后Token流進(jìn)行語法分析,這一步檢查這些關(guān)鍵字組合再一次是否符合Java語言規(guī)范(如在if后面是不是緊跟著一個布爾判斷表達(dá)式),詞法分析的結(jié)果是形成一個符合Java語言規(guī)范的抽象語法樹。

3、語義分析

通過語義分析器進(jìn)行語義分析。語音分析主要是將一些難懂的、復(fù)雜的語法轉(zhuǎn)化成更加簡單的語法,結(jié)果形成最簡單的語法(如將foreach轉(zhuǎn)換成for循環(huán) ,好有注解等),最后形成一個注解過后的抽象語法樹,這個語法樹更為接近目標(biāo)語言的語法規(guī)則。

4、生成字節(jié)碼

通過字節(jié)碼生產(chǎn)器生成字節(jié)碼,根據(jù)經(jīng)過注解的語法抽象樹生成字節(jié)碼,也就是將一個數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)化為另一個數(shù)據(jù)結(jié)構(gòu)。最后生成我們想要的.class文件。

使用十六進(jìn)制查看class文件內(nèi)容

我只用的是Notepad++,選中文本→插件→Converter→ASCII->HEX

 

class文件的開頭就是

CAFEBABE

想要學(xué)習(xí)這里的十六進(jìn)制的字節(jié)碼的含義可以參考

https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html

javap查看class文件內(nèi)容

javap是 Java class文件分解器,可以反編譯(即對javac編譯的文件進(jìn)行反編譯),也可以查看java編譯器生成的字節(jié)碼。

新建一個User.java源文件,經(jīng)過javac編譯后,生成User.classs。 

  1. package com.tian.demo.test; 
  2.  
  3. public class User { 
  4.     private int age = 22; 
  5.     private String name = "tian"
  6.  
  7.     public int addAge() { 
  8.         return age = age + 1; 
  9.     } 
  10.  
  11.     public static void main(String[] args) { 
  12.  
  13.     } 

 

使用javap命令

  1. javap -v User.class >log.txt 

打開log.txt

  1. Classfile /D:/workspace/new/demo/src/main/java/com/tian/demo/test/User.class 
  2.   Last modified 2020-11-5; size 441 bytes 
  3.   MD5 checksum 2fa72d3f53bd9f138e0bfae82aba67e3 
  4.   Compiled from "User.java" 
  5. public class com.tian.demo.test.User 
  6.   minor version: 0 
  7.   major version: 52 
  8.   flags: ACC_PUBLIC, ACC_SUPER 
  9. Constant pool: 
  10.    #1 = Methodref          #6.#21         // java/lang/Object."<init>":()V 
  11.    #2 = Fieldref           #5.#22         // com/tian/demo/test/User.age:I 
  12.    #3 = String             #23            // tian 
  13.    #4 = Fieldref           #5.#24         // com/tian/demo/test/User.name:Ljava/lang/String; 
  14.    #5 = Class              #25            // com/tian/demo/test/User 
  15.    #6 = Class              #26            // java/lang/Object 
  16.    #7 = Utf8               age 
  17.    #8 = Utf8               I 
  18.    #9 = Utf8               name 
  19.   #10 = Utf8               Ljava/lang/String; 
  20.   #11 = Utf8               <init> 
  21.   #12 = Utf8               ()V 
  22.   #13 = Utf8               Code 
  23.   #14 = Utf8               LineNumberTable 
  24.   #15 = Utf8               addAge 
  25.   #16 = Utf8               ()I 
  26.   #17 = Utf8               main 
  27.   #18 = Utf8               ([Ljava/lang/String;)V 
  28.   #19 = Utf8               SourceFile 
  29.   #20 = Utf8               User.java 
  30.   #21 = NameAndType        #11:#12        // "<init>":()V 
  31.   #22 = NameAndType        #7:#8          // age:I 
  32.   #23 = Utf8               tian 
  33.   #24 = NameAndType        #9:#10         // name:Ljava/lang/String; 
  34.   #25 = Utf8               com/tian/demo/test/User 
  35.   #26 = Utf8               java/lang/Object 
  36.   public com.tian.demo.test.User(); 
  37.     descriptor: ()V 
  38.     flags: ACC_PUBLIC 
  39.     Code: 
  40.       stack=2, locals=1, args_size=1 
  41.          0: aload_0 
  42.          1: invokespecial #1                  // Method java/lang/Object."<init>":()V 
  43.          4: aload_0 
  44.          5: bipush        22 
  45.          7: putfield      #2                  // Field age:I 
  46.         10: aload_0 
  47.         11: ldc           #3                  // String tian 
  48.         13: putfield      #4                  // Field name:Ljava/lang/String; 
  49.         16: return 
  50.       LineNumberTable: 
  51.         line 3: 0 
  52.         line 4: 4 
  53.         line 5: 10 
  54.  
  55.   public int addAge(); 
  56.     descriptor: ()I 
  57.     flags: ACC_PUBLIC 
  58.     Code: 
  59.       stack=3, locals=1, args_size=1 
  60.          0: aload_0 
  61.          1: aload_0 
  62.          2: getfield      #2                  // Field age:I 
  63.          5: iconst_1 
  64.          6: iadd 
  65.          7: dup_x1 
  66.          8: putfield      #2                  // Field age:I 
  67.         11: ireturn 
  68.       LineNumberTable: 
  69.         line 8: 0 
  70.  
  71.   public static void main(java.lang.String[]); 
  72.     descriptor: ([Ljava/lang/String;)V 
  73.     flags: ACC_PUBLIC, ACC_STATIC 
  74.     Code: 
  75.       stack=0, locals=1, args_size=1 
  76.          0: return 
  77.       LineNumberTable: 
  78.         line 13: 0 
  79. SourceFile: "User.java" 
 
  • 魔數(shù)與class文件版本
  • 常量池
  • 訪問標(biāo)志
  • 類索引、父類索引、接口索引
  • 字段表集合
  • 方法表集合
  • 屬性表集合

然后JVM就可以讀取這個User.class文件進(jìn)行解析等一系列的操作。

 以上就是我們的Java文件到class文件。

IT技術(shù)分享社區(qū)

個人博客網(wǎng)站:https://programmerblog.xyz認(rèn)識JVM

什么是JVM

JVM 全稱 Java Virtual Machine,也就是我們耳熟能詳?shù)?Java 虛擬機(jī)。它能識別 .class后綴的文件,并且能夠解析它的指令,最終調(diào)用操作系統(tǒng)上的函數(shù),完成我們想要的操作。

可能有部分小伙伴學(xué)習(xí)過C++,C++開發(fā)出來的程序,編譯成二進(jìn)制文件后,就可以直接執(zhí)行了,操作系統(tǒng)是能夠識別的。

但是咱們開的的Java程序就不一樣了,使用javac命令編譯出來的的.class文件之后,操作系統(tǒng)是不能識別的,需要對應(yīng)JVM去做一個轉(zhuǎn)換后,操作系統(tǒng)才能識別。

我們?yōu)槭裁床荒芟?C++ 一樣,直接在操作系統(tǒng)上運(yùn)行編譯后的二進(jìn)制文件呢?而非要搞一個處于程序與操作系統(tǒng)中間層的虛擬機(jī)呢?

這就是 JVM的過人之處了。大家都知道,Java 是一門抽象程度特別高的語言,提供了自動內(nèi)存管理等一系列的特性。這些特性直接在操作系統(tǒng)上實(shí)現(xiàn)是不太可能的,所以就需要JVM 進(jìn)行做一系列的轉(zhuǎn)換。

大家一開始學(xué)Java的時候,就知道有個Write Once, Run Everywhere。就是我們編寫了一個java文件經(jīng)過編譯成.class文件后,可以在各種系統(tǒng)中進(jìn)行運(yùn)行。

其實(shí)這里是有個前提的,我們需要在對應(yīng)操作系統(tǒng)中安裝對應(yīng)的JVM,然后我們的.class文件就能運(yùn)行了。

比如:Windows操作系統(tǒng)有對應(yīng)的JDK安裝版本、Linux也有對應(yīng)的JDK安裝版本等。


認(rèn)識JDK

Java Development Kit (JDK) 是Sun公司(已被Oracle收購)針對Java開發(fā)員的軟件開發(fā)工具包。自從Java推出以來,JDK已經(jīng)成為使用最廣泛的Java SDK(Software development kit)。

經(jīng)非官方調(diào)查,目前JDK8是使用者最多的版本。

JDK14將在4月和7月收到安全更新,然后由9月到期的非LTS版本的JDK 15取代。JDK14包括16項(xiàng)新功能,例如JDK Flight Recorder事件流,模式匹配和開關(guān)表達(dá)式等特征。

從JDK9之后,Oracle采用了新的發(fā)布周期:每6個月發(fā)布一個版本,每3年發(fā)布一個LTS版本。JDK14是繼JDK9之后發(fā)布的第四個版本, 該版本為非LTS版本,最新的LTS版本為JDK11。

下面是JDK版本情況


這個混個眼熟就行,隨時關(guān)注JDK版本更新和新特性。

官網(wǎng)地址:https://www.oracle.com/java/

關(guān)于JDK安裝這里就省略。

JDK、JRE、JVM的關(guān)系

上面已經(jīng)說過JDK和JVM的相關(guān)概念,

JRE全程Java Runtime Environment,是運(yùn)行基于Java語言編寫的程序所不可缺少的運(yùn)行環(huán)境。也是通過它,Java的開發(fā)者才得以將自己開發(fā)的程序發(fā)布到用戶手中,讓用戶使用。

三者到底是什么關(guān)系呢?

關(guān)于三者關(guān)系請看官網(wǎng)

https://docs.oracle.com/javase/8/docs/index.html


JDK中包含JRE,也包括JDK,而JRE也包括JDK。范圍關(guān)系:JDK>JRE>JVM

".java"文件到".class"文件

`javac`命令

編寫一個HelloWorld.java文件


內(nèi)容就是一個Java入門

  1. public class HelloWorld { 
  2.     public static void main(String[] args) { 
  3.         System.out.println("Hello world"); 
  4.     } 

 打開CMD,進(jìn)入當(dāng)前目錄,使用命令 

  1. javac HelloWorld.java 

就編譯出HelloWorld.class

編譯過程

這個javac命令過程到底干了些什么呢?

javac背后大致做了這些操作 


這個流程


1、詞法分析

讀取源代碼,一個字節(jié)一個字節(jié)的讀取,找出其中我們定義好的關(guān)鍵字(如Java中的if、else、for、while等關(guān)鍵詞,識別哪些if是合法的關(guān)鍵詞,哪些不是),這就是詞法分析器進(jìn)行詞法分析的過程,其結(jié)果是從源代碼中找出規(guī)范化的Token流。

2、語法分析

通過語法分析器對詞法分析后Token流進(jìn)行語法分析,這一步檢查這些關(guān)鍵字組合再一次是否符合Java語言規(guī)范(如在if后面是不是緊跟著一個布爾判斷表達(dá)式),詞法分析的結(jié)果是形成一個符合Java語言規(guī)范的抽象語法樹。

3、語義分析

通過語義分析器進(jìn)行語義分析。語音分析主要是將一些難懂的、復(fù)雜的語法轉(zhuǎn)化成更加簡單的語法,結(jié)果形成最簡單的語法(如將foreach轉(zhuǎn)換成for循環(huán) ,好有注解等),最后形成一個注解過后的抽象語法樹,這個語法樹更為接近目標(biāo)語言的語法規(guī)則。

4、生成字節(jié)碼

通過字節(jié)碼生產(chǎn)器生成字節(jié)碼,根據(jù)經(jīng)過注解的語法抽象樹生成字節(jié)碼,也就是將一個數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)化為另一個數(shù)據(jù)結(jié)構(gòu)。最后生成我們想要的.class文件。

使用十六進(jìn)制查看class文件內(nèi)容

我只用的是Notepad++,選中文本→插件→Converter→ASCII->HEX


class文件的開頭就是

CAFEBABE

想要學(xué)習(xí)這里的十六進(jìn)制的字節(jié)碼的含義可以參考

https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html

javap查看class文件內(nèi)容

javap是 Java class文件分解器,可以反編譯(即對javac編譯的文件進(jìn)行反編譯),也可以查看java編譯器生成的字節(jié)碼。

新建一個User.java源文件,經(jīng)過javac編譯后,生成User.classs。

  1. package com.tian.demo.test; 
  2.  
  3. public class User { 
  4.     private int age = 22; 
  5.     private String name = "tian"
  6.  
  7.     public int addAge() { 
  8.         return age = age + 1; 
  9.     } 
  10.  
  11.     public static void main(String[] args) { 
  12.  
  13.     } 

 

使用javap命令

  1. javap -v User.class >log.txt 

打開log.txt

  1. Classfile /D:/workspace/new/demo/src/main/java/com/tian/demo/test/User.class 
  2.   Last modified 2020-11-5; size 441 bytes 
  3.   MD5 checksum 2fa72d3f53bd9f138e0bfae82aba67e3 
  4.   Compiled from "User.java" 
  5. public class com.tian.demo.test.User 
  6.   minor version: 0 
  7.   major version: 52 
  8.   flags: ACC_PUBLIC, ACC_SUPER 
  9. Constant pool: 
  10.    #1 = Methodref          #6.#21         // java/lang/Object."<init>":()V 
  11.    #2 = Fieldref           #5.#22         // com/tian/demo/test/User.age:I 
  12.    #3 = String             #23            // tian 
  13.    #4 = Fieldref           #5.#24         // com/tian/demo/test/User.name:Ljava/lang/String; 
  14.    #5 = Class              #25            // com/tian/demo/test/User 
  15.    #6 = Class              #26            // java/lang/Object 
  16.    #7 = Utf8               age 
  17.    #8 = Utf8               I 
  18.    #9 = Utf8               name 
  19.   #10 = Utf8               Ljava/lang/String; 
  20.   #11 = Utf8               <init> 
  21.   #12 = Utf8               ()V 
  22.   #13 = Utf8               Code 
  23.   #14 = Utf8               LineNumberTable 
  24.   #15 = Utf8               addAge 
  25.   #16 = Utf8               ()I 
  26.   #17 = Utf8               main 
  27.   #18 = Utf8               ([Ljava/lang/String;)V 
  28.   #19 = Utf8               SourceFile 
  29.   #20 = Utf8               User.java 
  30.   #21 = NameAndType        #11:#12        // "<init>":()V 
  31.   #22 = NameAndType        #7:#8          // age:I 
  32.   #23 = Utf8               tian 
  33.   #24 = NameAndType        #9:#10         // name:Ljava/lang/String; 
  34.   #25 = Utf8               com/tian/demo/test/User 
  35.   #26 = Utf8               java/lang/Object 
  36.   public com.tian.demo.test.User(); 
  37.     descriptor: ()V 
  38.     flags: ACC_PUBLIC 
  39.     Code: 
  40.       stack=2, locals=1, args_size=1 
  41.          0: aload_0 
  42.          1: invokespecial #1                  // Method java/lang/Object."<init>":()V 
  43.          4: aload_0 
  44.          5: bipush        22 
  45.          7: putfield      #2                  // Field age:I 
  46.         10: aload_0 
  47.         11: ldc           #3                  // String tian 
  48.         13: putfield      #4                  // Field name:Ljava/lang/String; 
  49.         16: return 
  50.       LineNumberTable: 
  51.         line 3: 0 
  52.         line 4: 4 
  53.         line 5: 10 
  54.  
  55.   public int addAge(); 
  56.     descriptor: ()I 
  57.     flags: ACC_PUBLIC 
  58.     Code: 
  59.       stack=3, locals=1, args_size=1 
  60.          0: aload_0 
  61.          1: aload_0 
  62.          2: getfield      #2                  // Field age:I 
  63.          5: iconst_1 
  64.          6: iadd 
  65.          7: dup_x1 
  66.          8: putfield      #2                  // Field age:I 
  67.         11: ireturn 
  68.       LineNumberTable: 
  69.         line 8: 0 
  70.  
  71.   public static void main(java.lang.String[]); 
  72.     descriptor: ([Ljava/lang/String;)V 
  73.     flags: ACC_PUBLIC, ACC_STATIC 
  74.     Code: 
  75.       stack=0, locals=1, args_size=1 
  76.          0: return 
  77.       LineNumberTable: 
  78.         line 13: 0 
  79. SourceFile: "User.java" 
  •  魔數(shù)與class文件版本
  • 常量池
  • 訪問標(biāo)志
  • 類索引、父類索引、接口索引
  • 字段表集合
  • 方法表集合
  • 屬性表集合

然后JVM就可以讀取這個User.class文件進(jìn)行解析等一系列的操作。


以上就是我們的Java文件到class文件。

 

責(zé)任編輯:姜華 來源: 今日頭條
相關(guān)推薦

2020-10-19 09:09:46

Class文件加載過程

2017-02-07 09:54:43

JVMJavaClass

2009-07-08 11:01:40

Servlet源文件

2020-07-10 16:00:57

dumpJava內(nèi)存

2013-07-02 14:33:35

JavaClass

2017-09-26 16:32:03

JavaGC分析

2017-09-20 08:48:09

JVM內(nèi)存結(jié)構(gòu)

2020-09-10 14:52:01

JVMJava算法

2012-03-05 11:09:01

JavaClass

2010-09-17 13:28:10

JVM.dll

2017-11-01 15:38:54

jvm知識點(diǎn)總覽

2017-10-17 14:02:30

jvm調(diào)優(yōu)工具

2017-09-22 15:15:23

jvm調(diào)優(yōu)命令

2022-03-30 14:07:47

Harmony操作系統(tǒng)鴻蒙

2011-11-30 14:12:05

JavaJVM虛擬機(jī)

2017-11-08 15:23:57

Java GC優(yōu)化jvm

2023-07-03 08:11:48

java字節(jié)碼字段

2017-09-20 08:07:32

java加載機(jī)制

2021-10-11 19:54:04

JVM面試虛擬機(jī)

2011-06-21 11:02:15

JavaJboss
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 国产一区二区在线免费观看 | 高清视频一区二区三区 | 伊人一二三 | 欧美日韩在线播放 | 久久精品色欧美aⅴ一区二区 | 精品日韩| 99精品在线免费观看 | 日韩黄色小视频 | 天天玩夜夜操 | 亚洲午夜精品 | 天天干夜夜操 | 天天干天天干 | 久久一二三区 | 亚洲精品2区 | 99精品99| 成人av片在线观看 | 黄色免费网站在线看 | 91在线精品视频 | 99re视频在线观看 | 久热国产精品视频 | 韩国av网站在线观看 | 中文字幕在线观看第一页 | 午夜激情免费 | 日韩国产在线观看 | 国产精品天堂 | 欧美日韩在线一区二区三区 | 视频二区 | 欧美日韩中文在线 | 亚洲国产网址 | 亚洲精品中文字幕在线观看 | 中文字幕第十页 | 欧美成年人 | 操操日 | 国产精品久久久久久久久免费软件 | 人人干视频在线 | 久久aⅴ乱码一区二区三区 亚洲欧美综合精品另类天天更新 | 国内精品久久久久 | 亚洲视频欧美视频 | 美女久久久| 日韩中文字幕在线观看 | 国产精品日韩欧美一区二区三区 |