JVM—类加载器
原文作者:Java技術大聯盟
原文地址:JVM真香系列:.java文件到.class文件
目錄
什么是JVM
認識JDK
JDK、JRE、JVM的關系
".java"文件到".class"文件
編譯過程
javap查看class文件內容
什么是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是使用者最多的版本。從JDK9之后,Oracle采用了新的發布周期:每6個月發布一個版本,每3年發布一個LTS版本。JDK14是繼JDK9之后發布的第四個版本, 該版本為非LTS版本,最新的LTS版本為JDK11。下面是JDK版本情況:
這個混個眼熟就行,隨時關注JDK版本更新和新特性。官網地址:https://www.oracle.com/java/
JDK、JRE、JVM的關系
上面已經說過JDK和JVM的相關概念,JRE全程Java Runtime Environment,是運行基于Java語言編寫的程序所不可缺少的運行環境。也是通過它,Java的開發者才得以將自己開發的程序發布到用戶手中,讓用戶使用。三者到底是什么關系呢?關于三者關系請看官網https://docs.oracle.com/javase/8/docs/index.html
JDK中包含JRE,也包括JDK,而JRE也包括JDK。范圍關系:JDK>JRE>JVM
".java"文件到".class"文件
1)`javac`命令:編寫一個HelloWorld.java文件,內容就是一個Java入門
public?class?HelloWorld?{public?static?void?main(String[]?args)?{System.out.println("Hello?world");} }2)打開CMD,進入當前目錄,使用命令
javac?HelloWorld.java3)就編譯出HelloWorld.class
?
編譯過程
這個javac命令過程到底干了些什么呢?javac背后大致做了這些操作
使用十六進制查看class文件內容,我只用的是Notepad++,選中文本→插件→Converter→ASCII->HEX
class文件的開頭就是CAFEBABE,想要學習這里的十六進制的字節碼的含義可以參考:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html
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.classLast?modified?2020-11-5;?size?441?bytesMD5?checksum?2fa72d3f53bd9f138e0bfae82aba67e3Compiled?from?"User.java" public?class?com.tian.demo.test.Userminor?version:?0major?version:?52flags:?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:?()Vflags:?ACC_PUBLICCode:stack=2,?locals=1,?args_size=10:?aload_01:?invokespecial?#1??????????????????//?Method?java/lang/Object."<init>":()V4:?aload_05:?bipush????????227:?putfield??????#2??????????????????//?Field?age:I10:?aload_011:?ldc???????????#3??????????????????//?String?tian13:?putfield??????#4??????????????????//?Field?name:Ljava/lang/String;16:?returnLineNumberTable:line?3:?0line?4:?4line?5:?10public?int?addAge();descriptor:?()Iflags:?ACC_PUBLICCode:stack=3,?locals=1,?args_size=10:?aload_01:?aload_02:?getfield??????#2??????????????????//?Field?age:I5:?iconst_16:?iadd7:?dup_x18:?putfield??????#2??????????????????//?Field?age:I11:?ireturnLineNumberTable:line?8:?0public?static?void?main(java.lang.String[]);descriptor:?([Ljava/lang/String;)Vflags:?ACC_PUBLIC,?ACC_STATICCode:stack=0,?locals=1,?args_size=10:?returnLineNumberTable:line?13:?0 } SourceFile:?"User.java"魔數與class文件版本
常量池
訪問標志
類索引、父類索引、接口索引
字段表集合
方法表集合
屬性表集合
然后JVM就可以讀取這個User.class文件進行解析等一系列的操作。
?
總結
- 上一篇: JVM—学习路线
- 下一篇: JVM—垃圾回收与算法