类加载机制-深入理解jvm
一.目標:
1.什么是類的加載?
2.類的生命周期?
3.類加載器是什么?
4.雙親委派機制是什么?
二.原理 (類的加載過程及其最終產品):
JVM將class文件字節碼文件加載到內存中, 并將這些靜態數據轉換成方法區中的運行時數據結構,在堆(并不一定在堆中,HotSpot在方法區中)中生成一個代表這個類的java.lang.Class 對象,作為方法區類數據的訪問入口。
三.過程(類的生命周期):
JVM類加載機制分為五個部分:加載,驗證,準備,解析,初始化,下面我們就分別來看一下這五個過程。其中加載、檢驗、準備、初始化和卸載這個五個階段的順序是固定的,而解析則未必。為了支持動態綁定,解析這個過程可以發生在初始化階段之后。
加載:
加載過程主要完成三件事情:
這個過程主要就是類加載器完成。
校驗:
此階段主要確保Class文件的字節流中包含的信息符合當前虛擬機的要求,并且不會危害虛擬機的自身安全。
準備:
為類變量分配內存,并將其初始化為默認值。(此時為默認值,在初始化的時候才會給變量賦值)即在方法區中分配這些變量所使用的內存空間。例如:
?
public static int value = 123;此時在準備階段過后的初始值為0而不是123;將value賦值為123的putstatic指令是程序被編譯后,存放于類構造器<client>方法之中.特例:
?
public static final int value = 123;此時value的值在準備階段過后就是123。
解析:
把類型中的符號引用轉換為直接引用。
- 符號引用與虛擬機實現的布局無關,引用的目標并不一定要已經加載到內存中。各種虛擬機實現的內存布局可以各不相同,但是它們能接受的符號引用必須是一致的,因為符號引用的字面量形式明確定義在Java虛擬機規范的Class文件格式中。
- 直接引用可以是指向目標的指針,相對偏移量或是一個能間接定位到目標的句柄。如果有了直接引用,那引用的目標必定已經在內存中存在
主要有以下四種:
初始化:
初始化階段是執行類構造器<client>方法的過程。<client>方法是由編譯器自動收集類中的類變量的賦值操作和靜態語句塊中的語句合并而成的。虛擬機會保證<client>方法執行之前,父類的<client>方法已經執行完畢。如果一個類中沒有對靜態變量賦值也沒有靜態語句塊,那么編譯器可以不為這個類生成<client>()方法。
java中,對于初始化階段,有且只有以下五種情況才會對要求類立刻“初始化”(加載,驗證,準備,自然需要在此之前開始):
四.類加載器:
把類加載階段的“通過一個類的全限定名來獲取描述此類的二進制字節流”這個動作交給虛擬機之外的類加載器來完成。這樣的好處在于,我們可以自行實現類加載器來加載其他格式的類,只要是二進制字節流就行,這就大大增強了加載器靈活性。系統自帶的類加載器分為三種:
四.雙親委派機制:
雙親委派機制工作過程:
如果一個類加載器收到了類加載器的請求.它首先不會自己去嘗試加載這個類.而是把這個請求委派給父加載器去完成.每個層次的類加載器都是如此.因此所有的加載請求最終都會傳送到Bootstrap類加載器(啟動類加載器)中.只有父類加載反饋自己無法加載這個請求(它的搜索范圍中沒有找到所需的類)時.子加載器才會嘗試自己去加載。
雙親委派模型的優點:java類隨著它的加載器一起具備了一種帶有優先級的層次關系.
例如類java.lang.Object,它存放在rt.jart之中.無論哪一個類加載器都要加載這個類.最終都是雙親委派模型最頂端的Bootstrap類加載器去加載.因此Object類在程序的各種類加載器環境中都是同一個類.相反.如果沒有使用雙親委派模型.由各個類加載器自行去加載的話.如果用戶編寫了一個稱為“java.lang.Object”的類.并存放在程序的ClassPath中.那系統中將會出現多個不同的Object類.java類型體系中最基礎的行為也就無法保證.應用程序也將會一片混亂.
?
?
總結
以上是生活随笔為你收集整理的类加载机制-深入理解jvm的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 线程的 5 种状态
- 下一篇: 垃圾回收,和面试官扯皮没问题了