Java 類載入機制 ClassLoader Class.forName 記憶體管理 垃圾回收GC
為了弄清楚這個問題,首先還要看看System類的API doc文件。
1、Bootstrap Loader(啟動類載入器):載入System.getProperty("sun.boot.class.path")所指定的路徑或jar。 2、Extended Loader(標準擴充套件類載入器ExtClassLoader):載入System.getProperty("java.ext.dirs")所指定的路徑或jar。在使用Java執行程式時,也可以指定其搜尋路徑,例如:java -Djava.ext.dirs=d:/projects/testproj/classes HelloWorld 3、AppClass Loader(系統類載入器AppClassLoader):載入System.getProperty("java.class.path")所指定的路徑或jar。在使用Java執行程式時,也可以加上-cp來覆蓋原有的Classpath設定,例如: java -cp ./lavasoft/classes HelloWorld ExtClassLoader和AppClassLoader在JVM啟動後,會在JVM中儲存一份,並且在程式執行中無法改變其搜尋路徑。如果想在執行時從其他搜尋路徑載入類,就要產生新的類載入器。 三、類載入器的特點3、Bootstrap Loader(啟動類載入器)是最頂級的類載入器了,其父載入器為null. 四、類載入器的獲取 很容易,看下面例子 public class HelloWorld {
public static void main(String[] args) {
HelloWorld hello = new HelloWorld();
Class c = hello.getClass();
ClassLoader loader = c.getClassLoader();
System.out.println(loader);
System.out.println(loader.getParent());
System.out.println(loader.getParent().getParent());
}
} 列印結果:
[email protected]
null
Process finished with exit code 0 從上面的結果可以看出,並沒有獲取到ExtClassLoader的父Loader,原因是Bootstrap Loader(啟動類載入器)是用C語言實現的,找不到一個確定的返回父Loader的方式,於是就返回null。 五、類的載入 類載入有三種方式: 1、命令列啟動應用時候由JVM初始化載入 2、通過Class.forName()方法動態載入 3、通過ClassLoader.loadClass()方法動態載入 三種方式區別比較大,看個例子就明白了: public class HelloWorld {
public static void main(String[] args) throws ClassNotFoundException {
ClassLoader loader = HelloWorld. class.getClassLoader();
System.out.println(loader);
//使用ClassLoader.loadClass()來載入類,不會執行初始化塊
loader.loadClass( "Test2");
//使用Class.forName()來載入類,預設會執行初始化塊
// Class.forName("Test2");
//使用Class.forName()來載入類,並指定ClassLoader,初始化時不執行靜態塊
// Class.forName("Test2", false, loader);
}
} public class Test2 {
static {
System.out.println( "靜態初始化塊執行了!");
}
} 分別切換載入方式,會有不同的輸出結果。 六、自定義ClassLoader 為了說明問題,先看例子: package test;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
/**
* 自定義ClassLoader
*
* @author leizhimin 2009-7-29 22:05:48
*/
public class MyClassLoader {
public static void main(String[] args) throws MalformedURLException, ClassNotFoundException, IllegalAccessException, InstantiationException {
URL url = new URL( "file:/E://projects//testScanner//out//production//testScanner");
ClassLoader myloader = new URLClassLoader( new URL[]{url});
Class c = myloader.loadClass( "test.Test3");
System.out.println( "----------");
Test3 t3 = (Test3) c.newInstance();
}
} public class Test3 {
static {
System.out.println( "Test3的靜態初始化塊執行了!");
}
} 執行後: ----------
Test3的靜態初始化塊執行了!
Process finished with exit code 0 可以看出自定義了ClassLoader myloader = new URLClassLoader(new URL[]{url});已經成功將類Test3載入到記憶體了,並通過預設構造方法構造了物件Test3 t3 = (Test3) c.newInstance(); 有關ClassLoader還有很重要一點: 同一個ClassLoader載入的類檔案,只有一個Class例項。但是,如果同一個類檔案被不同的ClassLoader載入,則會有兩份不同的ClassLoader例項(前提是著兩個類載入器不能用相同的父類載入器)。
在java.lang包裡有個ClassLoader類,ClassLoader 的基本目標是對類的請求提供服務,按需動態裝載類和資
源,只有當一個類要使用(使用new 關鍵字來例項化一個類)的時候,類載入器才會載入這個類並初始化。
一個Java應用程式可以使用不同型別的類載入器。例如Web Application Server中,Servlet的載入使用開發
商自定義的類載入器, java.lang.String在使用JVM系統載入器,Bootstrap Class Loader,開發商定義的其他類
則由AppClassLoader載入。在JVM裡由類名和類載入器區別不同的Java型別。因此,JVM允許我們使用不同
的載入器載入相同namespace的java類,而實際上這些相同namespace的java類可以是完全不同的類。這種
機制可以保證JDK自帶的java.lang.String是唯一的。
2. 載入類的兩種方式:
(1) 隱式方式
使用new關鍵字讓類載入器按需求載入所需的類
(2) 顯式方式
由 java.lang.Class的forName()方法載入
public static Class forName(String className)
public static Class forName(String className, boolean initialize,ClassLoader loader)
引數說明:
className - 所需類的完全限定名
initialize - 是否必須初始化類(靜態程式碼塊的初始化)
loader - 用於載入類的類載入器
呼叫只有一個引數的forName()方法等效於 Class.forName(className, true, loader)。
這兩個方法,最後都要連線到原生方法forName0(),其定義如下:
private static native Class forName0(String name, boolean initialize,ClassLoader loader)
throws ClassNotFoundException;
只有一個引數的forName()方法,最後呼叫的是:
forName0(className, true, ClassLoader.getCallerClassLoader());
而三個引數的forName(),最後呼叫的是:
forName0(name, initialize, loader);
所以,不管使用的是new 來例項化某個類、或是使用只有一個引數的Class.forName()方法,內部都隱含
了“載入類 + 執行靜態程式碼塊”的步驟。而使用具有三個引數的Class.forName()方法時,如果第二個引數
為false,那麼類載入器只會載入類,而不會初始化靜態程式碼塊,只有當例項化這個類的時候,靜態程式碼塊
才會被初始化,靜態程式碼塊是在類第一次例項化的時候才初始化的。
直接使用類載入器
獲得物件所屬的類 : getClass()方法
獲得該類的類載入器 : getClassLoader()方法
3.執行java XXX.class的過程
找到JRE——》找到jvm.dll——》啟動JVM並進行初始化——》產生Bootstrap Loader——》
載入ExtClassLoader——》載入AppClassLoader——》執行java XXX.class
ClassLoader是用來處理類載入的類,它管理著具體類的執行時上下文。
1.ClassLoader存在的模組意義:
1)從java的package定義出發:
classloader是通過分層的關聯方式來管理執行中使用的類,不同的classloader中管理的類是不相同的,或者即便兩個類毫無二致(除了路徑)也是不同的兩個類,在進行強制轉換時也會丟擲ClassCastException。所以,通過classloader的限制,我們可以建立不同的package路徑以區別不同的類(注意這裡的“不同”是指,命名和實現完全一致,但是有不同的包路徑。)。那麼也是因為有特定的classloader,我們可以實現具體模組的載入,而不影響jvm中其他類,即發生類載入的衝突。
2)但是,如果兩個在不同路徑下的類(我們假定,這兩個類定義中,不存在package宣告,完全一樣的兩個類),經過不同的classloader載入,這兩個類在jvm中產生的例項可以相互轉換嗎?
答案是否定的。即便這兩個類除了存在位置不同之外,都完全一樣。經由不同classloader載入的兩個類依然是不同的兩個物件。通過Class.newInstance()或者Class.getConstructor().newInstance()產生的物件是完全不同的例項。
以上兩種情況,package可以使得我們的軟體架構清晰,但那不是最終作用,如果跟classloader結合起來理解,效果更好。
2.ClassLoader的類載入機制:
ClassLoader作為java的一個預設抽象類,給我們帶來了極大的方便,如果我們要自己實現相應的類載入演算法的話。
每個類都有一個對應的class與之繫結,並且可以通過MyClass.class方式來獲取這個Class物件。通過Class物件,我們就能獲取載入這個類的classloader。但是,我們現在要研究的是,一個類,是如何通過classloader載入到jvm中的。
其中有幾個關鍵方法,值得我們瞭解一番:
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException;
我們可以假設一個例項在建立時,例如通過new方式,是經由如此步驟實現:ClassLoader.loadClass("classname",false).newInstance()。
接下來需要考慮的是loadClass方法為我們做了哪些工作?如何跟對應的.class檔案結合,如何將對應的檔案變成我們的Class物件,如何獲得我們需要的類?
在ClassLoader類中,已經有了loadClass預設實現。我們結合原始碼說明一下:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
相關推薦Java 類載入機制 ClassLoader Class.forName 記憶體管理 垃圾回收GC類載入是Java程式執行的第一步,研究類的載入有助於瞭解JVM執行過程,並指導開發者採取更有效的措施配合程式執行。 研究類載入機制的第二個目的是讓程式能動態的控制類載入,比如熱部署等,提高程式的靈活性和適應性。 一、簡單過程 Java 【正文】Java類載入器( CLassLoader ) 死磕 4: 神祕的雙親委託機制【正文】Java類載入器( CLassLoader ) 死磕4: 神祕的雙親委託機制 本小節目錄 4.1. 每個類載入器都有一個parent父載入器 4.2. 類載入器之間的層次關係 4.3. 類的載入次序 4.4 雙親委託機制原理與沙箱機制 4.5. forName方法和load jvm之java類載入機制和類載入器(ClassLoader)的詳解當程式主動使用某個類時,如果該類還未被載入到記憶體中,則JVM會通過載入、連線、初始化3個步驟來對該類進行初始化。如果沒有意外,JVM將會連續完成3個步驟,所以有時也把這個3個步驟統稱為類載入或類初始化。 java類載入器——ClassLoaderweb rac rgb 好的 全盤負責機制 安全 trac 字節 如何 Java的設計初衷是主要面向嵌入式領域,對於自己定義的一些類,考慮使用依需求載入原則。即在程序使用到時才載入類,節省內存消耗,這時就可以通過類載入器來動態載入。 假設你平時僅僅是做web開發,那應該 Java類載入器 ClassLoader的解析index html dir obj ble body 6.4 odin 普通 //參考 : http://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 類載入器基本概念 類載 從阿里巴巴面試題到java類載入機制首先很經典的阿里巴巴面試題 加上我自己的一些疑惑程式碼 public class Text { public static int k = 0; public final int k1 = 3; //自己加的 public static Text t1 = new Text(" Java類載入器( CLassLoader ) 死磕9: 上下文載入器原理和案例【正文】Java類載入器( CLassLoader ) 死磕9: 上下文載入器原理和案例 本小節目錄 9.1. 父載入器不能訪問子載入器的類 9.2. 一個寵物工廠介面 9.3. 一個寵物工廠管理類 9.4 APPClassLoader不能訪問子載入器中的類 9.5. 執行緒上下文 Java類載入器( CLassLoader ) 死磕 6: 自定義網路類載入器【正文】Java類載入器( CLassLoader ) 死磕 6: 自定義網路類載入器 本小節目錄 6.1. 自定義網路類載入器的類設計 6.2. 檔案傳輸Server端的原始碼 6.3. 檔案傳輸Client端的原始碼 6. 4 自定義載入器SocketClassLoader的原始 Java類載入器( CLassLoader ) 死磕8: 使用ASM,和類載入器實現AOP【正文】Java類載入器( CLassLoader ) 死磕8: 使用ASM,和類載入器實現AOP 本小節目錄 8.1. ASM位元組碼操作框架簡介 8.2. ASM和訪問者模式 8.3. 用於增強位元組碼的事務類 8.4 通過ASM訪問註解 8.5. 通過ASM注入AOP事務程式 Java類載入器( CLassLoader ) 死磕7: 基於加密的自定義網路載入器 本小節目錄【正文】Java類載入器( CLassLoader ) 死磕7: 基於加密的自定義網路載入器 本小節目錄 7.1. 加密傳輸Server端的原始碼 7.2. 加密傳輸Client端的原始碼 7.3. 使用亦或實現簡單加密和解密演算法 7. 網路加密SafeClassLoader的原 Java類載入器( CLassLoader ) 死磕5: 自定義一個檔案系統的classLoader【正文】Java類載入器( CLassLoader ) 死磕5: 自定義一個檔案系統classLoader 本小節目錄 5.1. 自定義類載入器的基本流程 5.2. 入門案例:自定義檔案系統類載入器 5.3. 案例的環境配置 5.4 FileClassLoader 案例實現步驟 5 Java類載入器( CLassLoader ) 死磕 3: 揭祕 ClassLoader抽象基類【正文】Java類載入器( CLassLoader ) 死磕 3: 揭祕 ClassLoader抽象基類 (1)一個載入器的parent是誰? (2)為什麼優先從parent載入,而不是從自己的地盤載入?欲知後事如何,請看下回分解。 原始碼: 程式碼工程: class Java類載入器( CLassLoader ) 死磕 1、2: 匯入 & 分類JAVA類載入器 死磕系列 目錄 by 瘋狂創客圈 1.匯入1.1. 從class檔案的載入開始1.2. 什麼是類載入器2. JAVA類載入器分類2.1. 作業系統的環境變數2.2. Bootstrap ClassLoader(啟動類載入器)2.3. Extention ClassL java類載入機制和自定義類載入器類載入順序 上圖所示的是類載入的順序,按照大的順序可以分為載入、連結、初始化 其中連結又可以分成驗證、準備、解析三個步驟 載入 1.將類的class檔案讀入到記憶體中 載入類檔案的方式有: 1. 本機檔案載入 2.jar包載入 3.網路載入 4.原始檔動態編譯載入 淺談Java類載入機制最近在學習 Tomcat 架構,其中很重要的一個模組是類載入器,因為以前學習的不夠深入,所以趁這個機會好好把類載入機制搞明白。 概述 類載入器主要分為兩類,一類是 JDK 預設提供的,一類是使用者自定義的。 JDK 預設提供三種類載入器 Bootstrap ClassLo 深入理解Java類載入機制(一)1 前言: 在上一篇文章一文讓你明白 Java 位元組碼中, 我們瞭解了java位元組碼的解析過程,那麼在接下來的內容中,我們來了解一下類的載入機制。 2 題外話 Java的核心是什麼?當然是JVM了,所以說了解並熟悉JVM對於我們理解Java語言非常重要,不管你是做Java還是Andr Java 類載入機制詳解一、類載入器 類載入器(ClassLoader),顧名思義,即載入類的東西。在我們使用一個類之前,JVM需要先將該類的位元組碼檔案(.class檔案)從磁碟、網路或其他來源載入到記憶體中,並對位元組碼進行解析生成對應的Class物件,這就是類載入器的功能。我們可以利用類載入器,實現類的動態載入。 二、類的 Java類載入機制類載入機制 概念 類載入器把class檔案中的二進位制資料讀入到記憶體中,存放在方法區,然後在堆區建立一個java.lang.Class物件,用來封裝類在方法區內的資料結構。 1、載入: 查詢並載入類的二進位制資料(把class檔案裡面的資訊載入到記憶體裡面) 2 JVM——Java類載入機制class Singleton{ private static Singleton singleton = new Singleton(); public static int value1; public static int valu JAVA 類載入機制學習筆記JAVA 類生命週期 如上圖所示,Java類的生命週期如圖所示,分別為載入、驗證、準備、解析、初始化、使用、解除安裝。其中驗證、準備、解析這三個步驟統稱為連結。 載入:JVM根據全限定名來獲取一段二進位制位元組流,將二進位制流轉化為方法區的執行時資料結構,在記憶體中生成一個代表 |