JVM學習--編譯過程和類加載機制

JVM學習–編譯過程和類加載機制

本章學習java中類的編譯過程和加載機制。部分內容參考Oracle官網以及咕泡學院教材。分析版本爲jdk1.8。

/**
 * jvm學習測試使用對象
 * @author: to-be-continued
 * @Date: 2020/6/12 18:11
 */
@Data
public class Person implements Serializable {

    private Long id;


    private String name;


    public static void main(String[] args) {
        System.out.println(new Person());
    }

}

編譯:javac Person.java 得到Person.class文件

運行:java Person.class

java中,虛擬機要運行這段代碼,需要經過源碼的編譯過程->類加載->運行main方法。編譯後生成class文件,然後通過java運行class文件。下面以Person對象爲例介紹java編譯過程。

編譯過程

從上面可以看到,在經過javac Person.java之後,生成了一個Person.class文件,這中間是經過java編譯器的編譯過程得到的。過程如下:

Person.java -> 詞法分析器 ->tokens流 -> 語法分析器 -> 語法樹/抽象語法樹 -> 語義分析器 -> 註解抽象語法樹 -> 字節碼生成器 -> Person.class

打開class文件是一大串看不懂的字節碼,不是人能看懂的。如下所示:

CA FE BA BE 00 00 00 34  00 58 0A 00 1D 00 39 07
00 3A 0A 00 02 00 39 09  00 1C 00 3B 09 00 1C 00
3C 0B 00 3D 00 3E 0A 00  02 00 3F 0A 00 02 00 40
0A 00 02 00 3E 07 00 41  0A 00 42 00 43 07 00 44
0A 00 0A 00 45 0A 00 46  00 47 0B 00 3D 00 3F 06
40 00 00 00 00 00 00 00  06 40 08 00 00 00 00 00
00 06 40 10 00 00 00 00  00 00 06 40 14 00 00 00
00 00 00 06 40 18 00 00  00 00 00 00 06 40 1C 00
00 00 00 00 00 07 00 48  07 00 49 01 00 12 71 75
6F 74 65 53 74 61 74 75  73 57 65 69 67 68 74 73
01 00 0F 4C 6A 61 76 61  2F 75 74 69 6C 2F 4D 61
70 3B 01 00 09 53 69 67  6E 61 74 75 72 65 01 00
36 4C 6A 61 76 61 2F 75  74 69 6C 2F 4D 61 70 3C
4C 6A 61 76 61 2F 6C 61  6E 67 2F 49 6E 74 65 67
65 72 3B 4C 6A 61 76 61  2F 6C 61 6E 67 2F 44 

這個時候可以參考一下官網的介紹。自此得到class文件後,可以開始運行class文件了。

The class File Format

類加載機制

類的加載過程經過Loading(加載)、Linking(鏈接)和Initializing(初始化),在Oracle官網中提供了對於加載、鏈接、初始化的定義。參見:

Loading、Linking、Initializing

The Java Virtual Machine dynamically loads, links and initializes classes and interfaces. Loading is the process of finding the binary representation of a class or interface type with a particular name and creating a class or interface from that binary representation. Linking is the process of taking a class or interface and combining it into the run-time state of the Java Virtual Machine so that it can be executed. Initialization of a class or interface consists of executing the class or interface initialization method <clinit> (§2.9).

In this chapter, §5.1 describes how the Java Virtual Machine derives symbolic references from the binary representation of a class or interface. §5.2 explains how the processes of loading, linking, and initialization are first initiated by the Java Virtual Machine. §5.3 specifies how binary representations of classes and interfaces are loaded by class loaders and how classes and interfaces are created. Linking is described in §5.4. §5.5 details how classes and interfaces are initialized. §5.6 introduces the notion of binding native methods. Finally, §5.7 describes when a Java Virtual Machine exits.

直譯:Java虛擬機動態加載、鏈接和初始化類和接口。加載是查找具有特定名稱的類或接口類型的二進制表示,並從該二進制表示創建類或接口的過程。鏈接是獲取類或接口並將其結合到Java虛擬機的運行時狀態以便執行的過程。類或接口的初始化由執行類或接口的初始化方法組成。(§2.9)。

在這一章中,§5.1描述了Java虛擬機如何從類或接口的二進制表示中獲取符號引用。§5.2解釋了Java虛擬機是如何首先啓動加載、鏈接和初始化過程的。§5.3指定類裝入器如何裝入類和接口的二進制表示,以及類和接口如何創建。鏈接在§5.4中進行了描述。5.5詳細說明了類和接口是如何初始化的。5.6介紹了綁定本機方法的概念。最後,§5.7描述了Java虛擬機何時退出

加載(Loading)

查找和導入class文件

(1)通過類的全限定名獲取定義此類的二進制字節流

(2)將字節流所代表的靜態結構轉化爲方法區的運行時數據結構

(3)在java堆中生成此類的class對象,作爲對方法區中這些數據的訪問入口

鏈接(Linking)

Linking a class or interface involves verifying and preparing that class or interface, its direct superclass, its direct superinterfaces, and its element type (if it is an array type), if necessary. Resolution of symbolic references in the class or interface is an optional part of linking.

This specification allows an implementation flexibility as to when linking activities (and, because of recursion, loading) take place, provided that all of the following properties are maintained:

  • A class or interface is completely loaded before it is linked.
  • A class or interface is completely verified and prepared before it is initialized.
  • Errors detected during linkage are thrown at a point in the program where some action is taken by the program that might, directly or indirectly, require linkage to the class or interface involved in the error.

For example, a Java Virtual Machine implementation may choose to resolve each symbolic reference in a class or interface individually when it is used (“lazy” or “late” resolution), or to resolve them all at once when the class is being verified (“eager” or “static” resolution). This means that the resolution process may continue, in some implementations, after a class or interface has been initialized. Whichever strategy is followed, any error detected during resolution must be thrown at a point in the program that (directly or indirectly) uses a symbolic reference to the class or interface.

從官網介紹得出,鏈接一個類或者接口需要經過驗證、準備、解析過程。

驗證(Verification)

保證類加載的正確性

  • 文件格式驗證
  • 元數據驗證
  • 字節碼驗證
  • 符號引用驗證
準備(Preparation)

爲類的靜態變量分配內存,將其初始化爲默認值

解析(Resolution)

把類中的符號引用轉換爲直接引用

初始化(Initializing)

對類中存在的靜態變量、靜態代碼塊執行初始化操作

加載過程圖解

在這裏插入圖片描述

類加載器

ClassLoader爲加載階段用來裝載class文件的。

分類

1)Bootstrap ClassLoader 負責加載JAVAHOMEjre/lib/rt.jarclassXbootclassoathjarC++ClassLoader2ExtensionClassLoaderjavajarJAVA_HOME中 jre/lib/rt.jar 裏所有的class或 Xbootclassoath選項指定的jar包。由C++實現,不是ClassLoader子類。 2)Extension ClassLoader 負責加載java平臺中擴展功能的一些jar包,包括JAVA_HOME中
jre/lib/*.jar 或 -Djava.ext.dirs指定目錄下的jar包。
3)App ClassLoader 負責加載classpath中指定的jar包及 Djava.class.path 所指定目錄下的類和
jar包。
4)Custom ClassLoader 通過java.lang.ClassLoader的子類自定義加載class,屬於應用程序根據
自身需要自定義的ClassLoader,如tomcat、jboss都會根據j2ee規範自行實現ClassLoader。

加載原則

檢查某個類是否已經加載:順序是自底向上,從Custom ClassLoader到BootStrap ClassLoader逐層檢
查,只要某個Classloader已加載,就視爲已加載此類,保證此類只所有ClassLoader加載一次。
加載的順序:加載的順序是自頂向下,也就是由上層來逐層嘗試加載此類。

擴展:這裏用到了雙親委派機制來實現。

雙親委派機制
定義:如果一個類加載器在接到加載類的請求時,它首先不會自己嘗試去加載這個類,而是把
這個請求任務委託給父類加載器去完成,依次遞歸,如果父類加載器可以完成類加載任務,就
成功返回;只有父類加載器無法完成此加載任務時,才自己去加載。
優勢:Java類隨着加載它的類加載器一起具備了一種帶有優先級的層次關係。比如,Java中的
Object類,它存放在rt.jar之中,無論哪一個類加載器要加載這個類,最終都是委派給處於模型
最頂端的啓動類加載器進行加載,因此Object在各種類加載環境中都是同一個類。如果不採用
雙親委派模型,那麼由各個類加載器自己取加載的話,那麼系統中會存在多種不同的Object
類。
破壞:可以繼承ClassLoader類,然後重寫其中的loadClass方法,其他方式大家可以自己瞭解
拓展一下。

引用自咕泡學院教材

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章