最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中JVM的類加載器詳解

 更新時(shí)間:2023年07月31日 11:41:42   作者:兔老大RabbitMQ  
這篇文章主要介紹了Java中的類加載器詳解,從概念上來(lái)講, 自定義類加載器一般指的是程序中由開發(fā)人員自定義的類加載器,但是Java虛擬機(jī)規(guī)范卻沒(méi)有這么定義,而是將所有派生于抽象類ClassLoader的類加載器都劃分為自定義類加載器,需要的朋友可以參考下

類加載過(guò)程

加載->連接->初始化。

連接過(guò)程又可分為三步:驗(yàn)證->準(zhǔn)備->解析。

類加載器分類

JVM 中內(nèi)置了三個(gè)重要的 ClassLoader,除了 BootstrapClassLoader 其他類加載器均由 Java 實(shí)現(xiàn)且全部繼承自java.lang.ClassLoader

  1. 啟動(dòng)類加載器(Bootstrap ClassLoader)
    此類加載器負(fù)責(zé)將存放在 <JRE_HOME>\lib 目錄中的,或者被 -Xbootclasspath 參數(shù)所指定的路徑中的,并且是虛擬機(jī)識(shí)別的(僅按照文件名識(shí)別,如 rt.jar,名字不符合的類庫(kù)即使放在 lib 目錄中也不會(huì)被加載)類庫(kù)加載到虛擬機(jī)內(nèi)存中。啟動(dòng)類加載器無(wú)法被 Java 程序直接引用,用戶在編寫自定義類加載器時(shí),如果需要把加載請(qǐng)求委派給啟動(dòng)類加載器,直接使用 null 代替即可。
  2. 擴(kuò)展類加載器(Extension ClassLoader)
    這個(gè)類加載器是由 ExtClassLoader(sun.misc.Launcher$ExtClassLoader)實(shí)現(xiàn)的。它負(fù)責(zé)將 <JAVA_HOME>/lib/ext 或者被 java.ext.dir 系統(tǒng)變量所指定路徑中的所有類庫(kù)加載到內(nèi)存中,開發(fā)者可以直接使用擴(kuò)展類加載器。
  3. 應(yīng)用程序類加載器(Application ClassLoader)
    這個(gè)類加載器是由 AppClassLoader(sun.misc.Launcher$AppClassLoader)實(shí)現(xiàn)的。由于這個(gè)類加載器是 ClassLoader 中的 getSystemClassLoader() 方法的返回值,因此一般稱為系統(tǒng)類加載器。它負(fù)責(zé)加載用戶類路徑(ClassPath)上所指定的類庫(kù),開發(fā)者可以直接使用這個(gè)類加載器,如果應(yīng)用程序中沒(méi)有自定義過(guò)自己的類加載器,一般情況下這個(gè)就是程序中默認(rèn)的類加載器。

雙親委派模型

每一個(gè)類都有一個(gè)對(duì)應(yīng)它的類加載器。系統(tǒng)中的 ClassLoder 在協(xié)同工作的時(shí)候會(huì)默認(rèn)使用 雙親委派模型 。

1、在類加載的時(shí)候,系統(tǒng)會(huì)首先判斷當(dāng)前類是否被加載過(guò)。已經(jīng)被加載的類會(huì)直接返回,否則才會(huì)嘗試加載。

2、加載的時(shí)候,首先會(huì)把該請(qǐng)求委派該父類加載器的 loadClass() 處理,因此所有的請(qǐng)求最終都應(yīng)該傳送到頂層的啟動(dòng)類加載器 BootstrapClassLoader 中。當(dāng)父類加載器無(wú)法處理時(shí),才由自己來(lái)處理。

3、當(dāng)父類加載器為null時(shí),會(huì)使用啟動(dòng)類加載器 BootstrapClassLoader 作為父類加載器。

好處

使得 Java 類隨著它的類加載器一起具有一種帶有優(yōu)先級(jí)的層次關(guān)系,從而使得基礎(chǔ)類得到統(tǒng)一。

例如 java.lang.Object 存放在 rt.jar 中,如果編寫另外一個(gè) java.lang.Object 并放到 ClassPath 中,程序可以編譯通過(guò)。

由于雙親委派模型的存在,所以在 rt.jar 中的 Object 比在 ClassPath 中的 Object 優(yōu)先級(jí)更高,這是因?yàn)?rt.jar 中的 Object 使用的是啟動(dòng)類加載器,而 ClassPath 中的 Object 使用的是應(yīng)用程序類加載器。rt.jar 中的 Object 優(yōu)先級(jí)更高,那么程序中所有的 Object 都是這個(gè) Object。

保證了Java程序的穩(wěn)定運(yùn)行,可以避免類的重復(fù)加載(JVM 區(qū)分不同類的方式不僅僅根據(jù)類名,相同的類文件被不同的類加載器加載產(chǎn)生的是兩個(gè)不同的類),也保證了 Java 的核心 API 不被篡改。

如果沒(méi)有使用雙親委派模型,而是每個(gè)類加載器加載自己的話就會(huì)出現(xiàn)一些問(wèn)題,比如我們編寫一個(gè)稱為 java.lang.Object 類的話,那么程序運(yùn)行的時(shí)候,系統(tǒng)就會(huì)出現(xiàn)多個(gè)不同的 Object 類。

注意

這個(gè)雙親翻譯的容易讓人誤解,一般理解雙親都是父母,這里的雙親表達(dá)的是“父母一輩”的人,并不是說(shuō)真的有一個(gè) Mother ClassLoader 和一個(gè) Father ClassLoader 。另外,類加載器之間的“父子”關(guān)系也不是通過(guò)繼承來(lái)體現(xiàn)的,是由“優(yōu)先級(jí)”來(lái)決定。官方API文檔對(duì)這部分的描述如下:

The Java platform uses a delegation model for loading classes. The basic idea is that every class loader has a "parent" class loader. When loading a class, a class loader first "delegates" the search for the class to its parent class loader before attempting to find the class itself.

 源碼分析

private final ClassLoader parent; 
protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // 首先檢查請(qǐng)求的類是否已經(jīng)被加載過(guò)
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        //父加載器不為空,調(diào)用父加載器loadClass()方法處理
                        c = parent.loadClass(name, false);
                    } else {
                        //父加載器為空,使用啟動(dòng)類加載器 BootstrapClassLoader 加載
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                   //父類加載器無(wú)法完成加載請(qǐng)求
                }
                if (c == null) {
                    long t1 = System.nanoTime();
                    //自己嘗試加載
                    c = findClass(name);
                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

自定義加載器

除了 BootstrapClassLoader 其他類加載器均由 Java 實(shí)現(xiàn)且全部繼承自java.lang.ClassLoader。

如果我們要自定義自己的類加載器,很明顯需要繼承 ClassLoader

示例:自定義一個(gè)NetworkClassLoader,用于加載網(wǎng)絡(luò)上的class文件

package classloader;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;
/**
 * 加載網(wǎng)絡(luò)class的ClassLoader
 */
public class NetworkClassLoader extends ClassLoader {
	private String rootUrl;
	public NetworkClassLoader(String rootUrl) {
		this.rootUrl = rootUrl;
	}
	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		Class clazz = null;//this.findLoadedClass(name); // 父類已加載	
		//if (clazz == null) {	//檢查該類是否已被加載過(guò)
			byte[] classData = getClassData(name);	//根據(jù)類的二進(jìn)制名稱,獲得該class文件的字節(jié)碼數(shù)組
			if (classData == null) {
				throw new ClassNotFoundException();
			}
			clazz = defineClass(name, classData, 0, classData.length);	//將class的字節(jié)碼數(shù)組轉(zhuǎn)換成Class類的實(shí)例
		//} 
		return clazz;
	}
	private byte[] getClassData(String name) {
		InputStream is = null;
		try {
			String path = classNameToPath(name);
			URL url = new URL(path);
			byte[] buff = new byte[1024*4];
			int len = -1;
			is = url.openStream();
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			while((len = is.read(buff)) != -1) {
				baos.write(buff,0,len);
			}
			return baos.toByteArray();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (is != null) {
			   try {
			      is.close();
			   } catch(IOException e) {
			      e.printStackTrace();
			   }
			}
		}
		return null;
	}
	private String classNameToPath(String name) {
		return rootUrl + "/" + name.replace(".", "/") + ".class";
	}
}

到此這篇關(guān)于Java中JVM的類加載器詳解的文章就介紹到這了,更多相關(guān)JVM類加載器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中字符串與日期轉(zhuǎn)換常見(jiàn)方法總結(jié)

    Java中字符串與日期轉(zhuǎn)換常見(jiàn)方法總結(jié)

    這篇文章主要給大家介紹了關(guān)于Java中字符串與日期轉(zhuǎn)換常見(jiàn)方法的相關(guān)資料,在Java編程中經(jīng)常需要將字符串表示的日期轉(zhuǎn)換為日期對(duì)象進(jìn)行處理,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-11-11
  • Java使用POI導(dǎo)出Excel(二):多個(gè)sheet

    Java使用POI導(dǎo)出Excel(二):多個(gè)sheet

    這篇文章介紹了Java使用POI導(dǎo)出Excel的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-10-10
  • Java基于ip2region.xdb數(shù)據(jù)庫(kù)從IP獲取到屬地解析的全攻略

    Java基于ip2region.xdb數(shù)據(jù)庫(kù)從IP獲取到屬地解析的全攻略

    在日常的Java開發(fā)中,IP地址相關(guān)的操作是非常常見(jiàn)的需求,無(wú)論是用戶行為分析、地域化服務(wù),還是安全防護(hù),都需要精準(zhǔn)地獲取和解析IP信息,本文將詳細(xì)介紹一個(gè)功能完善的Java IP工具類,需要的朋友可以參考下
    2026-02-02
  • sentinel整合ribbon與fallback流程分步講解

    sentinel整合ribbon與fallback流程分步講解

    這篇文章主要介紹了sentinel整合ribbon與fallback分步流程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • Java InheritableThreadLocal用法詳細(xì)介紹

    Java InheritableThreadLocal用法詳細(xì)介紹

    InheritableThreadLocal繼承了ThreadLocal,此類擴(kuò)展了ThreadLocal以提供從父線程到子線程的值的繼承:當(dāng)創(chuàng)建子線程時(shí),子線程接收父線程具有的所有可繼承線程局部變量的初始值。 通常子線程的值與父線程的值是一致的
    2022-09-09
  • Spring Boot中的SpringSecurity基礎(chǔ)教程

    Spring Boot中的SpringSecurity基礎(chǔ)教程

    Spring Security是一個(gè)功能強(qiáng)大且高度可定制的身份驗(yàn)證和訪問(wèn)控制框架。它實(shí)際上是保護(hù)基于spring的應(yīng)用程序的標(biāo)準(zhǔn)Spring Security是一個(gè)框架,側(cè)重于為Java應(yīng)用程序提供身份驗(yàn)證和授權(quán),這篇文章主要介紹了Spring Boot中的SpringSecurity學(xué)習(xí),需要的朋友可以參考下
    2023-01-01
  • java實(shí)現(xiàn)上傳文件到oss(阿里云)功能示例

    java實(shí)現(xiàn)上傳文件到oss(阿里云)功能示例

    這篇文章主要介紹了java實(shí)現(xiàn)上傳文件到oss(阿里云)功能,結(jié)合實(shí)例形式詳細(xì)分析了java上傳文件到阿里云的具體步驟、配置及相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2019-11-11
  • java基于JDBC連接Oracle 11g Release2實(shí)例分析

    java基于JDBC連接Oracle 11g Release2實(shí)例分析

    這篇文章主要介紹了java基于JDBC連接Oracle 11g Release2的方法,實(shí)例分析了JDBC連接Oracle 11g Release2容易出現(xiàn)的異常與解決方法,需要的朋友可以參考下
    2015-06-06
  • java中的DDD思想指的是什么及在Java中的體現(xiàn)詳解

    java中的DDD思想指的是什么及在Java中的體現(xiàn)詳解

    領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(簡(jiǎn)稱DDD)是一種軟件開發(fā)方法,旨在通過(guò)對(duì)業(yè)務(wù)領(lǐng)域的深入理解,構(gòu)建高內(nèi)聚、低耦合的系統(tǒng),這篇文章主要介紹了java中的DDD思想指的是什么及在Java中體現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2025-11-11
  • mybatis配置Mapper.xml文件時(shí)遇到的問(wèn)題及解決

    mybatis配置Mapper.xml文件時(shí)遇到的問(wèn)題及解決

    這篇文章主要介紹了mybatis配置Mapper.xml文件時(shí)遇到的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01

最新評(píng)論

庄河市| 林州市| 敦煌市| 山西省| 嘉义市| 沅江市| 罗山县| 镇赉县| 呼伦贝尔市| 桐梓县| 眉山市| 安宁市| 玉田县| 乾安县| 会泽县| 保亭| 盐源县| 博白县| 长武县| 乐昌市| 如皋市| 壤塘县| 瓦房店市| 洪洞县| 巢湖市| 青田县| 双流县| 加查县| 明水县| 麻栗坡县| 吉木萨尔县| 鹿泉市| 巴林右旗| 抚顺市| 襄汾县| 洱源县| 重庆市| 胶州市| 原阳县| 阜康市| 当涂县|