1. 程式人生 > >Java提高篇——JVM載入class檔案的原理機制

Java提高篇——JVM載入class檔案的原理機制

  在面試java工程師的時候,這道題經常被問到,故需特別注意。

1、JVM 簡介

  JVM 是我們Javaer 的最基本功底了,剛開始學Java 的時候,一般都是從“Hello World ”開始的,然後會寫個複雜點class ,然後再找一些開源框架,比如Spring ,Hibernate 等等,再然後就開發企業級的應用,比如網站、企業內部應用、實時交易系統等等,直到某一天突然發現做的系統咋就這麼慢呢,而且時不時還來個記憶體溢位什麼的,今天是交易系統報了StackOverflowError ,明天是網站系統報了個OutOfMemoryError ,這種錯誤又很難重現,只有分析Javacore 和dump 檔案,運氣好點還能分析出個結果,執行遭的點,就直接去廟裡燒香吧!每天接客戶的電話都是戰戰兢兢的,生怕再出什麼么蛾子了。我想Java 做的久一點的都有這樣的經歷,那這些問題的最終根結是在哪呢?—— JVM 。

  JVM 全稱是Java Virtual Machine ,Java 虛擬機器,也就是在計算機上再虛擬一個計算機,這和我們使用 VMWare不一樣,那個虛擬的東西你是可以看到的,這個JVM 你是看不到的,它存在記憶體中。我們知道計算機的基本構成是:運算器、控制器、儲存器、輸入和輸出裝置,那這個JVM 也是有這成套的元素,運算器是當然是交給硬體CPU 還處理了,只是為了適應“一次編譯,隨處執行”的情況,需要做一個翻譯動作,於是就用了JVM 自己的命令集,這與彙編的命令集有點類似,每一種彙編命令集針對一個系列的CPU ,比如8086 系列的彙編也是可以用在8088 上的,但是就不能跑在8051 上,而JVM 的命令集則是可以到處執行的,因為JVM 做了翻譯,根據不同的CPU ,翻譯成不同的機器語言。

  JVM 中我們最需要深入理解的就是它的儲存部分,儲存?硬碟?NO ,NO , JVM 是一個記憶體中的虛擬機器,那它的儲存就是記憶體了,我們寫的所有類、常量、變數、方法都在記憶體中,這決定著我們程式執行的是否健壯、是否高效,接下來的部分就是重點介紹之。

2、JVM 的組成部分

我們先把JVM 這個虛擬機器畫出來,如下圖所示:

 

從這個圖中可以看到,JVM 是執行在作業系統之上的,它與硬體沒有直接的互動。我們再來看下JVM 有哪些組成部分,如下圖所示:

該圖參考了網上廣為流傳的JVM 構成圖,大家看這個圖,整個JVM 分為四部分:

## Class Loader 類載入器 

類載入器的作用是載入類檔案到記憶體,比如編寫一個HelloWord.java 程式,然後通過javac 編譯成class 檔案,那怎麼才能載入到記憶體中被執行呢?Class Loader 承擔的就是這個責任,那不可能隨便建立一個.class 檔案就能被載入的,Class Loader 載入的class 檔案是有格式要求,在《JVM Specification 》中式這樣定義Class 檔案的結構:

  ClassFile {
      u4 magic;
      u2 minor_version;
       u2 major_version;
      u2 constant_pool_count;
      cp_info constant_pool[constant_pool_count-1];
      u2 access_flags;
      u2 this_class;
      u2 super_class;
      u2 interfaces_count;
      u2 interfaces[interfaces_count];
      u2 fields_count;
      field_info fields[fields_count];
      u2 methods_count;
      method_info methods[methods_count];
      u2 attributes_count;
      attribute_info attributes[attributes_count];
    }

需要詳細瞭解的話,可以仔細閱讀《JVM Specification 》的第四章“The class File Format ”,這裡不再詳細說明。

友情提示:Class Loader 只管載入,只要符合檔案結構就載入,至於說能不能執行,則不是它負責的,那是由Execution Engine 負責的。

## Execution Engine 執行引擎 

執行引擎也叫做直譯器(Interpreter) ,負責解釋命令,提交作業系統執行。

## Native Interface 本地介面

本地介面的作用是融合不同的程式語言為Java 所用,它的初衷是融合C/C++ 程式,Java 誕生的時候是C/C++ 橫行的時候,要想立足,必須有一個聰明的、睿智的呼叫C/C++ 程式,於是就在記憶體中專門開闢了一塊區域處理標記為native 的程式碼,它的具體做法是Native Method Stack 中登記native 方法,在Execution Engine 執行時載入native libraies 。目前該方法使用的是越來越少了,除非是與硬體有關的應用,比如通過Java 程式驅動印表機,或者Java 系統管理生產裝置,在企業級應用中已經比較少見,因為現在的異構領域間的通訊很發達,比如可以使用Socket 通訊,也可以使用Web Service 等等,不多做介紹。

## Runtime data area 執行資料區 

執行資料區是整個JVM 的重點。我們所有寫的程式都被載入到這裡,之後才開始執行,Java 生態系統如此的繁榮,得益於該區域的優良自治。

整個JVM 框架由載入器載入檔案,然後執行器在記憶體中處理資料,需要與異構系統互動是可以通過本地介面進行,瞧,一個完整的系統誕生了!

3、JVM載入class檔案的原理機制 

   Java中的所有類,都需要由類載入器裝載到JVM中才能執行。類載入器本身也是一個類,而它的工作就是把class檔案從硬碟讀取到記憶體中。在寫程式的時候,我們幾乎不需要關心類的載入,因為這些都是隱式裝載的,除非我們有特殊的用法,像是反射,就需要顯式的載入所需要的類。

  類裝載方式,有兩種 
      1.隱式裝載, 程式在執行過程中當碰到通過new 等方式生成物件時,隱式呼叫類裝載器載入對應的類到jvm中,
      2.顯式裝載, 通過class.forname()等方法,顯式載入需要的類 
    隱式載入與顯式載入的區別:兩者本質是一樣? 

     Java類的載入是動態的,它並不會一次性將所有類全部載入後再執行,而是保證程式執行的基礎類(像是基類)完全載入到jvm中,至於其他類,則在需要的時候才載入。這當然就是為了節省記憶體開銷。

   Java的類載入器有三個,對應Java的三種類:(java中的類大致分為三種:   1.系統類   2.擴充套件類 3.由程式設計師自定義的類 )

     Bootstrap Loader  // 負責載入系統類 (指的是內建類,像是String,對應於C#中的System類和C/C++標準庫中的類)
            | 
          - - ExtClassLoader   // 負責載入擴充套件類(就是繼承類和實現類)
                          | 
                      - - AppClassLoader   // 負責載入應用類(程式設計師自定義的類)

 三個載入器各自完成自己的工作,但它們是如何協調工作呢?哪一個類該由哪個類載入器完成呢?為了解決這個問題,Java採用了委託模型機制。

委託模型機制的工作原理很簡單:當類載入器需要載入類的時候,先請示其Parent(即上一層載入器)在其搜尋路徑載入,如果找不到,才在自己的搜尋路徑搜尋該類。這樣的順序其實就是載入器層次上自頂而下的搜尋,因為載入器必須保證基礎類的載入。之所以是這種機制,還有一個安全上的考慮:如果某人將一個惡意的基礎類載入到jvm,委託模型機制會搜尋其父類載入器,顯然是不可能找到的,自然就不會將該類載入進來。

      我們可以通過這樣的程式碼來獲取類載入器:

ClassLoader loader = ClassName.class.getClassLoader();
ClassLoader ParentLoader = loader.getParent();

注意一個很重要的問題,就是Java在邏輯上並不存在BootstrapKLoader的實體!因為它是用C++編寫的,所以列印其內容將會得到null。
      

前面是對類載入器的簡單介紹,它的原理機制非常簡單,就是下面幾個步驟:

1.裝載:查詢和匯入class檔案;

2.連線:

      (1)檢查:檢查載入的class檔案資料的正確性;

      (2)準備:為類的靜態變數分配儲存空間;

      (3)解析:將符號引用轉換成直接引用(這一步是可選的)

3.初始化:初始化靜態變數,靜態程式碼塊。

      這樣的過程在程式呼叫類的靜態成員的時候開始執行,所以靜態方法main()才會成為一般程式的入口方法。類的構造器也會引發該動作。

相關推薦

Java提高——JVM載入class檔案原理機制

  在面試java工程師的時候,這道題經常被問到,故需特別注意。 1、JVM 簡介   JVM 是我們Javaer 的最基本功底了,剛開始學Java 的時候,一般都是從“Hello World ”開始的,然後會寫個複雜點class ,然後再找一些開源框架,比如Spring ,Hibernate 等等,再然

Java進階——JVM載入class檔案原理機制

  在面試java工程師的時候,這道題經常被問到,故需特別注意。回到頂部1、JVM 簡介  JVM 是我們Javaer 的最基本功底了,剛開始學Java 的時候,一般都是從“Hello World ”開始的,然後會寫個複雜點class ,然後再找一些開源框架,比如Spring ,Hibernate 等等,再然

Java中的基礎----JVM載入class檔案原理

Java是一種解釋型語言,class檔案只有被載入到JVM中才能執行。當執行指定程式時,JVM會將編譯生成的.class檔案按一定的規則(從硬碟)載入到記憶體中(由類載入器classLoader和它的子類來完成)。 有以下兩種載入方式: 1)隱式載入: 程式使用new等方式

JAVA面試常備題、JVM載入class檔案原理機制

Java中的所有類,都需要由類載入器裝載到JVM中才能執行。類載入器本身也是一個類,而它的工作就是把class檔案從硬碟讀取到記憶體中。在寫程式的時候,我們幾乎不需要關心類的載入,因為這些都是隱式裝載的,除非我們有特殊的用法,像是反射,就需要顯式的載入所需要的類。 Ja

JVM載入class檔案原理機制

Java語言是一種具有動態性的解釋型語言,類(class)只有被載入到JVM中後才能執行。當執行指定程式時,JVM會將編譯生成的.class檔案按照需求和一定的規則載入到記憶體中,並組織成為一個完整的Java應用程式。這個載入過程是由類載入器來完成的,具體來說,就是由Clas

JVM載入class檔案原理

原始檔:編寫Java原始檔(我們也稱之為原始碼檔案),它的副檔名為.java; 編譯:然後通過編譯器把原始檔編譯成位元組碼檔案,位元組碼副檔名為.class; 執行:最後使用直譯器來執行位元組碼檔案。 類載入的主要步驟: 當程式要使用某個類時,如果該類還未被載入到記

jvm載入class檔案原理機制分析

案例分析 A、B類中均包含靜態程式碼塊,非靜態程式碼塊以及構造器,A類是B類的父類。 public class A { static { System.out.print("A中靜態程式碼塊>>>"); }

JVM載入class檔案原理機制簡單總結

Java中的所有類,必須被裝載到jvm中才能執行,這個裝載工作是由jvm中的類裝載器完成的,類裝載器所做的工作實質是把類檔案從硬碟讀取到記憶體中 java中的類大致分為三種:     1).系統類      2).擴充套件類      3).由程式設計師自定義的類類裝載方式

JVM載入class檔案原理機制是什麼?類載入器的工作原理

Java語言是一種具有動態性的解釋型語言,類(class)只有被載入到JVM中後才能執行。當執行指定程式時,JVM會將編譯生成的.class檔案按照需求和一定的規則載入到記憶體中,並組織成為一個完整的Java應用程式。這個載入過程是由類載入器來完成的,具體來說,就是由Cla

描述一下JVM載入class檔案原理機制

JVM中類的裝載是由類載入器(ClassLoader)和它的子類來實現的,Java中的類載入器是一個重要的Java執行時系統元件,它負責在執行時查詢和裝入類檔案中的類。    由於Java的跨平臺性,經過編譯的Java源程式並不是一個可執行程式,而是一個或多個類檔案。當J

描述一下JVM 載入class檔案原理機制?

JVM中類的裝載是由ClassLoader和它的子類來實現的,Java ClassLoader 是一個重要的Java執行時系統元件。它負責在執行時查詢和裝入類檔案的類。 當Java編譯器編譯好.class檔案之後,我們需要使用JVM來執行這個class檔案。那

【轉】JVM載入class檔案原理機制

JVM載入class檔案的原理機制 收藏 1.Java中的所有類,必須被裝載到jvm中才能執行,這個裝載工作是由jvm中的類裝載器完成的, 類裝載器所做的工作實質是把類檔案從硬碟讀取到記憶體中 2.java中的類大致分為三種: 1.系統類 2.擴充套件類

JVM載入Class檔案原理機制

1.java中的所以類,必須被載入到JVM中才能執行,這個載入是由類載入器完成的,類載入器所做的工作實質上是把類檔案從硬碟讀取到記憶體中 2.java中的類大致分為三種: 1、系統類 2、擴充套件類 3、程式設計師自定義的類 3.類載入的方式,兩種 1、隱式裝載,程式在執行

21、描述一下JVM載入class檔案原理機制

答:JVM中類的裝載是由類載入器(ClassLoader)和它的子類來實現的,Java中的類載入器是一個重要的Java執行時系統元件,它負責在執行時查詢和裝入類檔案中的類。 由於Java的跨平臺性,經過編譯的Java源程式並不是一個可執行程式,而是一個或多個類檔案。當Ja

jvm載入class檔案機制j

1、載入類檔案      a、讀取class檔案,從jar包、war包、class檔案、jsp檔案等處都可以。           a.1、採用雙親委派機制載入類,由classLoader和其子類完成,支援自定義

JVM載入class檔案的一些理解

Java是一種動態解釋型語言,類(class)只有被載入到JVM中後才能執行。每當一個Java程式執行時,都會有一個對應的JVM例項,只有當程式執行結束後,這個JVM才會退出。JVM例項通過呼叫類的main()方法來啟動一個Java程式。當執行指定程式時,JVM將編譯生成的.class檔案按照需求和一定的規則

Java基礎(JVM)——Class物件

Class物件   這篇文章算是補充的一點東西,主要看一看Class物件的相關知識。 主要關心的有以下幾個點: Class物件是什麼? Class物件和反射 Class物件如何使用 Class物件是什麼 可以簡單這麼說:Class物件就是位元組碼檔案儲存的內容。所以將位元組

java載入class檔案(類載入機制)

一概述:在編譯期,所有的*.java檔案被編譯成.class檔案。在執行期,class檔案只有被載入到jvm記憶體中才能執行。這個裝載工作是由類裝載器完成的。實質就是把class檔案從硬碟讀取到記憶體中,並對資料進行校驗,轉化解析和初始化,最終形成可以被jvm直接使用的ja

JVM的啟動和載入class檔案流程

載入主類的class檔案 Java執行方式有兩種:jar方式和class方式。 + 裝載:查詢和匯入class檔案; 連線: (1)檢查:檢查載入的class檔案資料的正確性; (2)準備:為類的靜態變數分配儲存空間; (3)解析:將符號引用轉換成

如何載入Class檔案JVM

如下圖所示,是ClassLoader載入一個class檔案到JVM時需要經過的步驟: 第一階段是找到.class檔案並把這個檔案包含的位元組碼載入到記憶體中。 第二階段又可以分為三個步驟,分別是位元組碼驗證、Class類資料結構分析及相應的記憶體分配和最