亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java中JVM的類加載器詳解

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

類加載過程

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

連接過程又可分為三步:驗(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,名字不符合的類庫即使放在 lib 目錄中也不會(huì)被加載)類庫加載到虛擬機(jī)內(nèi)存中。啟動(dòng)類加載器無法被 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)變量所指定路徑中的所有類庫加載到內(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)上所指定的類庫,開發(fā)者可以直接使用這個(gè)類加載器,如果應(yīng)用程序中沒有自定義過自己的類加載器,一般情況下這個(gè)就是程序中默認(rèn)的類加載器。

雙親委派模型

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

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

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

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 中,程序可以編譯通過。

由于雙親委派模型的存在,所以在 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 不被篡改。

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

注意

這個(gè)雙親翻譯的容易讓人誤解,一般理解雙親都是父母,這里的雙親表達(dá)的是“父母一輩”的人,并不是說真的有一個(gè) Mother ClassLoader 和一個(gè) Father ClassLoader 。另外,類加載器之間的“父子”關(guān)系也不是通過繼承來體現(xiàn)的,是由“優(yōu)先級(jí)”來決定。官方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)被加載過
            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) {
                   //父類加載器無法完成加載請(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) {	//檢查該類是否已被加載過
			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實(shí)現(xiàn)簡單聊天軟件

    java實(shí)現(xiàn)簡單聊天軟件

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡單的聊天軟件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • Java使用Semaphore對(duì)單接口進(jìn)行限流

    Java使用Semaphore對(duì)單接口進(jìn)行限流

    本篇主要講如何使用Semaphore對(duì)單接口進(jìn)行限流,主要有三種方式,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • Java?中的5個(gè)代碼性能提升技巧

    Java?中的5個(gè)代碼性能提升技巧

    這篇文章主要給大家分享了Java的5個(gè)代碼性能提升的技巧,雖然大多數(shù)情況下極致優(yōu)化代碼是沒有必要的,但是作為一名技術(shù)開發(fā)者,我們還是想追求代碼的更小、更快,更強(qiáng)。如果哪天發(fā)現(xiàn)程序的運(yùn)行速度不盡人意,就需要這樣的文章了,需要的朋友可以參考一下
    2021-12-12
  • java實(shí)現(xiàn)Base64加密解密算法

    java實(shí)現(xiàn)Base64加密解密算法

    Base64用來將非ASCII字符的數(shù)據(jù)轉(zhuǎn)換成ASCII字符的一種方法,這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)Base64加密解密算法,感興趣的小伙伴們可以參考一下
    2016-04-04
  • 將Java的List結(jié)構(gòu)通過GSON庫轉(zhuǎn)換為JSON的方法示例

    將Java的List結(jié)構(gòu)通過GSON庫轉(zhuǎn)換為JSON的方法示例

    GONS是Google在GitHub上開源的Java類庫,提供各種Java對(duì)象和JSON格式對(duì)象之間的轉(zhuǎn)換功能,將Java的List結(jié)構(gòu)通過GSON庫轉(zhuǎn)換為JSON的方法示例
    2016-06-06
  • spring boot實(shí)現(xiàn)profiles動(dòng)態(tài)切換的示例

    spring boot實(shí)現(xiàn)profiles動(dòng)態(tài)切換的示例

    Spring Boot支持在不同的環(huán)境下使用不同的配置文件,該技術(shù)非常有利于持續(xù)集成,在構(gòu)建項(xiàng)目的時(shí)候只需要使用不同的構(gòu)建命令就可以生成不同運(yùn)行環(huán)境下war包,而不需要手動(dòng)切換配置文件。
    2020-10-10
  • SpringBoot讀取配置優(yōu)先級(jí)順序的方法詳解

    SpringBoot讀取配置優(yōu)先級(jí)順序的方法詳解

    Spring Boot作為一種輕量級(jí)的Java應(yīng)用程序框架,以其開箱即用、快速搭建新項(xiàng)目的特性贏得了廣大開發(fā)者的青睞,在Spring Boot生態(tài)系統(tǒng)中,配置屬性可以從各種來源獲取,本文將深入探討Spring Boot加載外部配置屬性的優(yōu)先級(jí)規(guī)則,需要的朋友可以參考下
    2024-05-05
  • 詳解Java中final的用法

    詳解Java中final的用法

    本文主要介紹了Java中final的使用方法,final是java的關(guān)鍵字,本文就詳細(xì)說明一下它的使用方法,需要的朋友可以參考下
    2015-08-08
  • 解決mybatis批量更新(update foreach)失敗的問題

    解決mybatis批量更新(update foreach)失敗的問題

    這篇文章主要介紹了解決mybatis批量更新(update foreach)失敗的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • Spring Cloud Gateway實(shí)現(xiàn)灰度發(fā)布方案

    Spring Cloud Gateway實(shí)現(xiàn)灰度發(fā)布方案

    灰度發(fā)布是在微服務(wù)中的表現(xiàn)為同一服務(wù)同時(shí)上線不同版本,讓一部分用戶使用新版本來驗(yàn)證新特性,如果驗(yàn)證沒有問題,則將所有用戶都遷移到新版本上,本文就來介紹一下如何實(shí)現(xiàn),感興趣的可以了解一下
    2023-12-12

最新評(píng)論