本文目錄一覽:
- 1、怎樣實現java代碼的動態載入
- 2、java 類載入機制有什麼用
- 3、java動態載入類的時候求硬碟、堆、棧、方法區之間的工作原理,最好有個圖什麼的能更形象的表現出來。
- 4、Java類載入機制?
- 5、java中類的動態載入到底有什麼作用,直接導入包在獲取該類的實例不是一樣嗎
怎樣實現java代碼的動態載入
1.將你這段字元串輸出到一個文件里,用Java類文件的方式命名。
2.調用外部javac命令將該文件編譯。
3.用類載入器(ClassLoad)動態載入新的class文件並用Class.forName()註冊該類,然後就可以正常使用了。
上面的每一步都能在baidu中找到實現方法,自己發揮吧。
java 類載入機制有什麼用
AVA類載入機制詳解
「代碼編譯的結果從本地機器碼轉變為位元組碼,是存儲格式發展的一小步,卻是變成語言發展的一大步」,這句話出自《深入理解JAVA虛擬機》一書,後面關於jvm的系列文章主要都是參考這本書。
JAVA源碼編譯由三個過程組成:
1、源碼編譯機制。
2、類載入機制
3、類執行機制
我們這裡主要介紹編譯和類載入這兩種機制。
一、源碼編譯
代碼編譯由JAVA源碼編譯器來完成。主要是將源碼編譯成位元組碼文件(class文件)。位元組碼文件格式主要分為兩部分:常量池和方法位元組碼。
二、類載入
類的生命周期是從被載入到虛擬機內存中開始,到卸載出內存結束。過程共有七個階段,其中到初始化之前的都是屬於類載入的部分
載入—-驗證—-準備—-解析—–初始化—-使用—–卸載
系統可能在第一次使用某個類時載入該類,也可能採用預載入機制來載入某個類,當運行某個java程序時,會啟動一個java虛擬機進程,兩次運行的java程序處於兩個不同的JVM進程中,兩個jvm之間並不會共享數據。
1、載入階段
這個流程中的載入是類載入機制中的一個階段,這兩個概念不要混淆,這個階段需要完成的事情有:
1)通過一個類的全限定名來獲取定義此類的二進位位元組流。
2)將這個位元組流所代表的靜態存儲結構轉化為方法區的運行時數據結構。
3)在java堆中生成一個代表這個類的Class對象,作為訪問方法區中這些數據的入口。
由於第一點沒有指明從哪裡獲取以及怎樣獲取類的二進位位元組流,所以這一塊區域留給我開發者很大的發揮空間。這個我在後面的類載入器中在進行介紹。
2、準備階段
這個階段正式為類變數(被static修飾的變數)分配內存並設置類變數初始值,這個內存分配是發生在方法區中。
1、注意這裡並沒有對實例變數進行內存分配,實例變數將會在對象實例化時隨著對象一起分配在JAVA堆中。
2、這裡設置的初始值,通常是指數據類型的零值。
private static int a = 3;
這個類變數a在準備階段後的值是0,將3賦值給變數a是發生在初始化階段。
3、初始化階段
初始化是類載入機制的最後一步,這個時候才正真開始執行類中定義的JAVA程序代碼。在前面準備階段,類變數已經賦過一次系統要求的初始值,在初始化階段最重要的事情就是對類變數進行初始化,關注的重點是父子類之間各類資源初始化的順序。
java類中對類變數指定初始值有兩種方式:1、聲明類變數時指定初始值;2、使用靜態初始化塊為類變數指定初始值。
初始化的時機
1)創建類實例的時候,分別有:1、使用new關鍵字創建實例;2、通過反射創建實例;3、通過反序列化方式創建實例。
new Test();
Class.forName(「com.mengdd.Test」);
2)調用某個類的類方法(靜態方法)
Test.doSomething();
3)訪問某個類或介面的類變數,或為該類變數賦值。
int b=Test.a;
Test.a=b;
4)初始化某個類的子類。當初始化子類的時候,該子類的所有父類都會被初始化。
5)直接使用java.exe命令來運行某個主類。
除了上面幾種方式會自動初始化一個類,其他訪問類的方式都稱不會觸發類的初始化,稱為被動引用。
1、子類引用父類的靜態變數,不會導致子類初始化。
public class SupClass
{ public static int a = 123;
static
{
System.out.println(“supclass init”);
}
}public class SubClass extends SupClass
{ static
{
System.out.println(“subclass init”);
}
}public class Test
{ public static void main(String[] args)
{
System.out.println(SubClass.a);
}
}
執行結果:
supclass init123
2、通過數組定義引用類,不會觸發此類的初始化
public class SupClass
{ public static int a = 123;
static
{
System.out.println(“supclass init”);
}
}public class Test
{ public static void main(String[] args)
{
SupClass[] spc = new SupClass[10];
}
}
執行結果:
3、引用常量時,不會觸發該類的初始化
public class ConstClass
{ public static final String A= “MIGU”;
static
{
System.out.println(“ConstCLass init”);
}
}public class TestMain
{ public static void main(String[] args)
{
System.out.println(ConstClass.A);
}
}
執行結果:
MIGU
用final修飾某個類變數時,它的值在編譯時就已經確定好放入常量池了,所以在訪問該類變數時,等於直接從常量池中獲取,並沒有初始化該類。
初始化的步驟
1、如果該類還沒有載入和連接,則程序先載入該類並連接。
2、如果該類的直接父類沒有載入,則先初始化其直接父類。
3、如果類中有初始化語句,則系統依次執行這些初始化語句。
在第二個步驟中,如果直接父類又有直接父類,則系統會再次重複這三個步驟來初始化這個父類,依次類推,JVM最先初始化的總是java.lang.Object類。當程序主動使用任何一個類時,系統會保證該類以及所有的父類都會被初始化。
java動態載入類的時候求硬碟、堆、棧、方法區之間的工作原理,最好有個圖什麼的能更形象的表現出來。
方法區(非堆):是各個線程共享的內存區域,它用於存儲已被虛擬機載入的類信息、常量、靜態變數、即時編譯器編譯後的代碼等數據。
java堆:是虛擬機中所管理的內存中區域最大的一塊,是被所有線程共享的一塊內存區域,在虛擬機啟動時創建。此內存區域的唯一目的就是存放對象實例,幾乎所有的對象實例都在這裡分配內存。java堆是垃圾收集器管理的主要區域。
java虛擬機棧:線程私有的,它的生命周期與線程相同。每個方法被執行的時候都會同時創建一個棧幀,用於存儲局部變數表、操作數棧、動態鏈接、方法出口等信息。每個方法被調用直至執行完成的過程,就對應著一個棧幀在虛擬機中從入棧到出棧的過程。
Java類載入機制?
1,類的載入
每個開發人員對java.lang.ClassNotFoundExcetpion這個異常肯定都不陌生,這背後就涉及到了java技術體系中的類載入。Java的類載入機制是技術體系中比較核心的部分,雖然和大部分開發人員直接打交道不多,但是對其背後的機理有一定理解有助於排查程序中出現的類載入失敗等技術問題,對理解java虛擬機的連接模型和java語言的動態性都有很大幫助。
那麼什麼是類的載入?
類的載入指的是將類的.class文件中的二進位數據讀入到內存中,將其放在運行時數據區的方法區內,然後在堆區創建一個java.lang.Class對象,用來封裝類在方法區內的數據結構。類的載入的最終產品是位於堆區中的Class對象,Class對象封裝了類在方法區內的數據結構,並且向Java程序員提供了訪問方法區內的數據結構的介面。
類載入器是Java語言的一個創新,也是Java語言流行的重要原因之一。它使得Java類可以被動態載入到Java虛擬機中並執行。類載入器從JDK1.0就出現了,最初是為了滿足JavaApplet的需要而開發出來的。JavaApplet需要從遠程下載Java類文件到瀏覽器中並執行。現在類載入器在Web容器和OSGi中得到了廣泛的使用,而類載入器並不需要等到某個類被「首次主動使用」時再載入它,JVM規範允許類載入器在預料某個類將要被使用時就預先載入它,如果在預先載入的過程中遇到了.class文件缺失或存在錯誤,類載入器必須在程序首次主動使用該類時才報告錯誤(LinkageError錯誤)如果這個類一直沒有被程序主動使用,那麼類載入器就不會報告錯誤。
2,類的生命周期
類載入的過程中包括有載入,驗證,準備,解析,初始化五個階段。而需要注意的是在這五個階段中,載入、驗證、準備和初始化這四個階段發生的順序是確定的,而解析階段則不一定,它在某些情況下可以在初始化階段之後開始,這是為了支持Java語言的運行時綁定(也成為動態綁定或晚期綁定)。另外注意這裡的幾個階段是按順序開始,而不是按順序進行或完成,因為這些階段通常都是互相交叉地混合進行的,通常在一個階段執行的過程中調用或激活另一個階段。
載入:查找並載入類的二進位數據
載入時類載入過程的第一個階段,在載入階段,虛擬機需要完成以下三件事情:
1、通過一個類的全限定名來獲取其定義的二進位位元組流。(並沒有指明要從一個Class文件中獲取,可以從其他渠道,譬如:網路、動態生成、資料庫等)
2、將這個位元組流所代表的靜態存儲結構轉化為方法區的運行時數據結構。
3、在Java堆中生成一個代表這個類的java.lang.Class對象,作為對方法區中這些數據的訪問入口。
相對於類載入的其他階段而言,載入階段(準確地說,是載入階段獲取類的二進位位元組流的動作)是可控性最強的階段,電腦培訓發現因為開發人員既可以使用系統提供的類載入器來完成載入,也可以自定義自己的類載入器來完成載入。
java中類的動態載入到底有什麼作用,直接導入包在獲取該類的實例不是一樣嗎
當然不一樣啊,這樣維護成本太高了,如果是動態載入只需要配置文件修改一下類庫位置就可以了,假如有100個類需要引用這個第三方包那麼就需要重新打開程序一個一個import嗎?不符合開閉原則,不利於維護
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/184387.html