成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java Class Loader?

開發 后端
類加載器(class loader)用來加載 Java 類到 Java 虛擬機中。Java 源程序(.java 文件)在經過 Java 編譯器編譯之后就被轉換成 Java 字節代碼(.class 文件)。類加載器負責讀取 Java 字節代碼,并轉換成 java.lang.Class 類的一個實例。

1. ClassLoader

類加載器(class loader)用來加載 Java 類到 Java 虛擬機中。Java 源程序(.java 文件)在經過 Java 編譯器編譯之后就被轉換成 Java 字節代碼(.class 文件)。類加載器負責讀取 Java 字節代碼,并轉換成 java.lang.Class 類的一個實例。

2. ClassLoader Hierarchy

JVM在加載類時,使用的是雙親委托模式(delegation model),也就是說除了Bootstrap ClassLoader之外,每個ClassLoader都有一個Parent ClassLoader。ClassLoader是按需進行加載class文件。當ClassLoader試圖加載一個類時,首先檢查本地緩沖,查看類是否已被加載,如果類沒有被加載,嘗試委托給父ClassLoader進行加載,如果父ClassLoader加載失敗,才會由該ClassLoader進行加載,從而避免了重復加載的問題。一下為類裝載器層次圖:

 

 

Bootstrap ClassLoader:負責加載java_home/lib目錄下的核心類或- Xbootclasspath指定目錄下的類。

Extension ClassLoader:負責加載java_home/lib/ext目錄下的擴展類或 -Djava.ext.dirs 指定目錄下的類。

System ClassLoader:負責加載-classpath/-Djava.class.path所指的目錄下的類。

如果類App1在本地緩沖中沒有class文件(沒有被加載),那么它會自底向上依次查找是否已經加載了類,如果已經加載,則直接返回該類實例的引用。如果BootstrapClassLoader也未成功加載該類,那么會拋出異常,然后自頂向下依次嘗試加載,如果到App1 ClassLoader還沒有加載成功,那么會拋出ClassNotFoundException異常給調用者。

Java代碼

  1. public static void main(String[] args) {     
  2.         ClassLoader cl = ClassLoader.getSystemClassLoader();     
  3.         while(cl != null){     
  4.             System.out.println(cl);     
  5.             System.out.println("parent class loader: " + cl.getParent());     
  6.             cl = cl.getParent();     
  7.         }     
  8.     }  

 

Java代碼

  1. sun.misc.Launcher$AppClassLoader@19821f    
  2. parent class loader: sun.misc.Launcher$ExtClassLoader@addbf1    
  3. sun.misc.Launcher$ExtClassLoader@addbf1    
  4. parent class loader: null   

 

我們看到,當前系統類裝載器為AppClassLoader,AppClassLoader的父類裝載器是ExtClassLoader,ExtClassLoader的父裝載器為null,表示為BootstrapClassLoader。BootstrapClassLoader由JVM采用本地代碼實現,因此沒有對應的Java類,所以ExtClassLoader的getParent()返回null。

ClassLoader的職責之一是保護系統名字空間。以下為ClassLoader類部分代碼:

Java代碼

  1. private ProtectionDomain preDefineClass(String name,     
  2.                         ProtectionDomain protectionDomain)     
  3.     {     
  4.     if (!checkName(name))     
  5.         throw new NoClassDefFoundError("IllegalName: " + name);     
  6.     
  7.     if ((name != null) && name.startsWith("java.")) {     
  8.         throw new SecurityException("Prohibited package name: " +     
  9.                     name.substring(0, name.lastIndexOf('.')));     
  10.     }     
  11.     if (protectionDomain == null) {     
  12.         protectionDomain = getDefaultDomain();     
  13.     }     
  14.     
  15.     if (name != null)     
  16.         checkCerts(name, protectionDomain.getCodeSource());     
  17.     
  18.     return protectionDomain;     
  19.     } 

 

那么,當我們定義如下類Foo,雖然能夠通過編譯,但是會報java.lang.SecurityException: Prohibited package name: java.lang異常,因為我們試圖將Foo類寫入到java.lang包下。

Java代碼

  1. package java.lang;     
  2.     
  3. public class Foo {     
  4.          
  5.     public static void main(String args[]) throws Exception {     
  6.         Foo f = new Foo();     
  7.         System.out.println(f.toString());     
  8.     }     
  9. }   

 

3. 定制ClassLoader

Java自帶的ClassLoader類的定義為:

Java代碼

  1. public abstract class ClassLoader{      

 

啟動類加載器是JVM通過調用ClassLoader.loadClass()方法。

Java代碼

  1. public Class loadClass(String name) throws ClassNotFoundException {     
  2.     return loadClass(name, false);     
  3.     }     
  4.     
  5. protected synchronized Class loadClass(String name, boolean resolve)     
  6.     throws ClassNotFoundException     
  7.     {     
  8.     // First, check if the class has already been loaded     
  9.     Class c = findLoadedClass(name);     
  10.     if (c == null) {     
  11.         try {     
  12.         if (parent != null) {     
  13.             c = parent.loadClass(name, false);     
  14.         } else {     
  15.             c = findBootstrapClass0(name);     
  16.         }     
  17.         } catch (ClassNotFoundException e) {     
  18.             // If still not found, then invoke findClass in order     
  19.             // to find the class.     
  20.             c = findClass(name);     
  21.         }     
  22.     }     
  23.     if (resolve) {     
  24.         resolveClass(c);     
  25.     }     
  26.     return c;     
  27.     }     
  28.     
  29. protected Class findClass(String name) throws ClassNotFoundException {     
  30.     throw new ClassNotFoundException(name);     
  31.     }    

 

loadClass(String name, boolean resolve)方法中的resolve如果為true,表示分析這個Class對象,包括檢查Class Loader是否已經初始化等。loadClass(String name) 在加載類之后不會對該類進行初始化,直到***次使用該類時,才會對該類進行初始化。

那么,我們在定制ClassLoader的時候,通常只需要覆寫findClass(String name)方法。在findClass(String name)方法內,我們可以通過文件、網絡(URL)等形式獲取字節碼。以下為獲取字節碼的方法:

Java代碼

  1. public InputStream getResourceAsStream(String name);     
  2. public URL getResource(String name);     
  3. public InputStream getResourceAsStream(String name);     
  4. public Enumeration getResources(String name) throws IOException;   

 

在取得字節碼后,需要調用defineClass()方法將字節數組轉換成Class對象,該方法簽名如下:

Java代碼

  1. protected final Class defineClass(String name, byte[] b, int off, int len,     
  2.                      ProtectionDomain protectionDomain)     
  3.     throws ClassFormatError  

 

對于相同的類,JVM最多會載入一次。如果同一個class文件被不同的ClassLoader載入(定義),那么載入后的兩個類是完全不同的。

Java代碼

  1. public class Foo{     
  2.     //     
  3.     private static final AtomicInteger COUNTER = new AtomicInteger(0);     
  4.     
  5.     public Foo() {     
  6.         System.out.println("counter: " + COUNTER.incrementAndGet());     
  7.     }     
  8.          
  9.     public static void main(String args[]) throws Exception {     
  10.         URL urls[] = new URL[]{new URL("file:/c:/")};     
  11.         URLClassLoader ucl1 = new URLClassLoader(urls);     
  12.         URLClassLoader ucl2 = new URLClassLoader(urls);     
  13.         Class c1 = ucl1.loadClass("Foo");     
  14.         Class c2 = ucl2.loadClass("Foo");     
  15.         System.out.println(c1 == c2);     
  16.         c1.newInstance();     
  17.         c2.newInstance();     
  18.     }     
  19. }   

 

以上程序需要保證Foo.class文件不在classpath路徑下。從而使AppClassLoader無法加載Foo.class。

輸出結果:

Java代碼

  1. false    
  2. counter: 1    
  3. counter: 1 

 

4. Web應用的ClassLoader

絕大多數的EJB容器,Servlet容器等都會提供定制的ClassLoader,來實現特定的功能。但是通常情況下,所有的servlet和filter使用一個ClassLoader。每個jsp都使用一個獨立的ClassLoader。

5. 隱式(implicit)和顯示(explicit)的加載

隱式加載:我們使用new關鍵字實例化一個類,就是隱身的加載了類。

顯示加載分為兩種:

java.lang.Class的forName()方法;

java.lang.ClassLoader的loadClass()方法。

Class.forName()方法有兩個重載的版本:

Java代碼

  1. public static Class forName(String className)      
  2.                 throws ClassNotFoundException {     
  3.         return forName0(className, true, ClassLoader.getCallerClassLoader());     
  4.     }     
  5.     
  6. public static Class forName(String name, boolean initialize,     
  7.                    ClassLoader loader)     
  8.         throws ClassNotFoundException   

 

可以看出,forName(String className)默認以true和ClassLoader.getCallerClassLoader()調用了三參數的重載方法。ClassLoader.getCallerClassLoader()表示以caller class loader加載類,并會初始化類(即靜態變量會被初始化,靜態初始化塊中的代碼也會被執行)。如果以false和ClassLoader.getCallerClassLoader()調用三參數的重載方法,表示加載后的類不會被初始化。

ClassLoader.loadClass()方法在類加載后,也同樣不會初始化類。

6. 兩個異常(exception)

NoClassDefFoundError: 當java源文件已編譯成.class文件,但是ClassLoader在運行期間搜尋路徑load某個類時,沒有找到.class文件則拋出這個異常。

ClassNotFoundException: 試圖通過一個String變量來創建一個Class類時不成功則拋出這個異常

【編輯推薦】

  1. 解答WebLogic與JVM六大疑問
  2. 解決JVM***內存設置問題
  3. 調用weblogic設置jvmheap大小
  4. 詳解Tomcat配置JVM參數步驟
  5. 深入學習JVM內存設置原理和調優
責任編輯:金賀 來源: ITEYE博客
相關推薦

2017-01-11 19:05:45

AndroidAndroid Loa詳解

2012-02-09 10:18:55

Java

2021-05-31 05:36:43

WebpackJavaScript 前端

2021-04-30 08:28:15

WebpackLoaderPlugin

2022-05-29 17:37:39

LinuxUbuntuPHP

2013-07-02 14:33:35

JavaClass

2012-11-06 10:02:04

JavaJadEclipse

2014-11-03 15:44:07

2020-11-17 09:55:48

Java

2022-04-29 14:38:49

class文件結構分析

2017-11-28 15:36:25

換扶技術Android資源

2010-03-17 17:20:15

Java class線

2012-03-05 11:09:01

JavaClass

2021-06-22 10:43:03

Webpack loader plugin

2021-08-12 09:48:21

Webpack Loa工具Webpack

2021-11-30 11:17:23

自定義配置插件

2010-01-06 10:08:16

Boot Loader

2017-02-07 09:54:43

JVMJavaClass

2020-10-30 15:04:16

開發技能代碼

2025-03-07 02:00:00

webpackPlugin開發
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 一区二区三区视频在线 | 日本视频免费观看 | 久久久久无码国产精品一区 | 九九综合 | 国产亚洲精品久久19p | 国产精品99久久久久久久久久久久 | 99在线播放 | 国产在线视频三区 | 美女福利视频一区 | 欧美一区二区三区在线观看视频 | 日本中文在线视频 | 久久天天躁狠狠躁夜夜躁2014 | 久草免费电影 | 日韩午夜影院 | 午夜影院毛片 | 99精品一区二区三区 | 中文字幕 欧美 日韩 | 最新中文字幕在线 | 日韩av一区二区在线观看 | 成人午夜精品 | 国产精品久久 | 亚洲三区视频 | 亚洲午夜精品一区二区三区他趣 | 欧美日韩国产三级 | 国产91丝袜在线播放 | 999免费网站 | 国产美女视频黄a视频免费 国产精品福利视频 | 91视频网址 | 久久国产精品视频 | 九九激情视频 | 久久三级影院 | 国产午夜av片 | 狠狠操狠狠 | 亚洲免费在线 | 中文字幕日韩一区 | 日韩在线成人 | 成人久久久久久久久 | 午夜在线| 91国内外精品自在线播放 | 欧美一区免费 | 三级视频久久 |