JVM——類加載器

回顧一下類加載過程

類加載過程:加載->連接->初始化。連接過程又可分為三步:驗證->準備->解析

在這里插入圖片描述

一個非數組類的加載階段(加載階段獲取類的二進制字節流的動作)是可控性最強的階段,這一步我們可以去完成還可以自定義類加載器去控制字節流的獲取方式(重寫一個類加載器的 loadClass() 方法)。數組類型不通過類加載器創建,它由 Java 虛擬機直接創建。

所有的類都由類加載器加載,加載的作用就是將 .class文件加載到內存。

類加載器總結

JVM 中內置了三個重要的 ClassLoader,除了 BootstrapClassLoader 其他類加載器均由 Java 實現且全部繼承自java.lang.ClassLoader

  1. BootstrapClassLoader(啟動類加載器) :最頂層的加載類,由C++實現,負責加載 %JAVA_HOME%/lib目錄下的jar包和類或者或被 -Xbootclasspath參數指定的路徑中的所有類。
  2. ExtensionClassLoader(擴展類加載器) :主要負責加載目錄 %JRE_HOME%/lib/ext 目錄下的jar包和類,或被 java.ext.dirs 系統變量所指定的路徑下的jar包。
  3. AppClassLoader(應用程序類加載器) :面向我們用戶的加載器,負責加載當前應用classpath下的所有jar包和類。

雙親委派模型

雙親委派模型介紹

每一個類都有一個對應它的類加載器。系統中的 ClassLoder 在協同工作的時候會默認使用 雙親委派模型 。即在類加載的時候,系統會首先判斷當前類是否被加載過。已經被加載的類會直接返回,否則才會嘗試加載。加載的時候,首先會把該請求委派該父類加載器的 loadClass() 處理,因此所有的請求最終都應該傳送到頂層的啟動類加載器 BootstrapClassLoader 中。當父類加載器無法處理時,才由自己來處理。當父類加載器為null時,會使用啟動類加載器 BootstrapClassLoader 作為父類加載器。
在這里插入圖片描述

每個類加載都有一個父類加載器,我們通過下面的程序來驗證。

public class ClassLoaderDemo {public static void main(String[] args) {System.out.println("ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader());System.out.println("The Parent of ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader().getParent());System.out.println("The GrandParent of ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader().getParent().getParent());}
}

Output

ClassLodarDemo's ClassLoader is sun.misc.Launcher$AppClassLoader@18b4aac2
The Parent of ClassLodarDemo's ClassLoader is sun.misc.Launcher$ExtClassLoader@1b6d3586
The GrandParent of ClassLodarDemo's ClassLoader is null

AppClassLoader的父類加載器為ExtClassLoader
ExtClassLoader的父類加載器為null,null并不代表ExtClassLoader沒有父類加載器,而是 BootstrapClassLoader

其實這個雙親翻譯的容易讓別人誤解,我們一般理解的雙親都是父母,這里的雙親更多地表達的是“父母這一輩”的人而已,并不是說真的有一個 Mother ClassLoader 和一個 Father ClassLoader 。另外,類加載器之間的“父子”關系也不是通過繼承來體現的,是由“優先級”來決定。官方API文檔對這部分的描述如下:

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.

雙親委派模型實現源碼分析

雙親委派模型的實現代碼非常簡單,邏輯非常清晰,都集中在 java.lang.ClassLoaderloadClass() 中,相關代碼如下所示。

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

雙親委派模型的好處

雙親委派模型保證了Java程序的穩定運行,可以避免類的重復加載(JVM 區分不同類的方式不僅僅根據類名,相同的類文件被不同的類加載器加載產生的是兩個不同的類),也保證了 Java 的核心 API 不被篡改。如果沒有使用雙親委派模型,而是每個類加載器加載自己的話就會出現一些問題,比如我們編寫一個稱為 java.lang.Object 類的話,那么程序運行的時候,系統就會出現多個不同的 Object 類。

如果我們不想用雙親委派模型怎么辦?

自定義加載器的話,需要繼承 ClassLoader 。如果我們不想打破雙親委派模型,就重寫 ClassLoader 類中的 findClass() 方法即可,無法被父類加載器加載的類最終會通過這個方法被加載。但是,如果想打破雙親委派模型則需要重寫 loadClass() 方法

自定義類加載器

除了 BootstrapClassLoader 其他類加載器均由 Java 實現且全部繼承自java.lang.ClassLoader。如果我們要自定義自己的類加載器,很明顯需要繼承 ClassLoader

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/41006.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/41006.shtml
英文地址,請注明出處:http://en.pswp.cn/news/41006.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【計算機網絡篇】UDP協議

?作者簡介&#xff1a;大家好&#xff0c;我是小楊 &#x1f4c3;個人主頁&#xff1a;「小楊」的csdn博客 &#x1f433;希望大家多多支持&#x1f970;一起進步呀&#xff01; UDP協議 1&#xff0c;UDP 簡介 UDP&#xff08;User Datagram Protocol&#xff09;是一種無連…

Flink學習筆記(一)

流處理 批處理應用于有界數據流的處理&#xff0c;流處理則應用于無界數據流的處理。 有界數據流&#xff1a;輸入數據有明確的開始和結束。 無界數據流&#xff1a;輸入數據沒有明確的開始和結束&#xff0c;或者說數據是無限的&#xff0c;數據通常會隨著時間變化而更新。 在…

Kaptcha的基本應用

Kaptcha Kaptcha 是一個用于生成和驗證驗證碼的 Java 庫&#xff0c;提供了豐富的生成和驗證功能&#xff0c;并支持自定義配置。它可以用于增加應用程序的安全性&#xff0c;防止機器人和惡意攻擊。 Kaptcha 可以生成各種類型的驗證碼&#xff0c;包括數字、字母、數字字母組…

KDD 2023 獲獎論文公布,港中文、港科大等獲最佳論文獎

ACM SIGKDD&#xff08;國際數據挖掘與知識發現大會&#xff0c;KDD&#xff09;是數據挖掘領域歷史最悠久、規模最大的國際頂級學術會議&#xff0c;也是首個引入大數據、數據科學、預測分析、眾包等概念的會議。 今年&#xff0c;第29屆 KDD 大會于上周在美國加州長灘圓滿結…

HTTP--Request詳解

請求消息數據格式 請求行 請求方式 請求url 請求協議/版本 GET /login.html HTTP/1.1 請求頭 客戶端瀏覽器告訴服務器一些信息 請求頭名稱: 請求頭值 常見的請求頭&#xff1a; User-Agent&#xff1a;瀏覽器告訴服務器&#xff0c;我訪問你使用的瀏覽器版本信息 可…

藍橋杯每日N題 (消滅老鼠)

大家好 我是寸鐵 希望這篇題解對你有用&#xff0c;麻煩動動手指點個贊或關注&#xff0c;感謝您的關注 不清楚藍橋杯考什么的點點下方&#x1f447; 考點秘籍 想背純享模版的伙伴們點點下方&#x1f447; 藍橋杯省一你一定不能錯過的模板大全(第一期) 藍橋杯省一你一定不…

【日常積累】HTTP和HTTPS的區別

背景 在運維面試中&#xff0c;經常會遇到面試官提問http和https的區別&#xff0c;今天咱們先來簡單了解一下。 超文本傳輸協議HTTP被用于在Web瀏覽器和網站服務器之間傳遞信息&#xff0c;HTTP協議以明文方式發送內容&#xff0c;不提供任何方式的數據加密&#xff0c;如果…

09- DMA(DirectMemoryAccess直接存儲器訪問)

DMA 09 、DMA(DirectMemoryAccess直接存儲器訪問)DMA配置流程 09 、DMA(DirectMemoryAccess直接存儲器訪問) DMA配置流程 dma.c文件 main.c文件 詳見《stm32中文參考手冊》表57。

tsconfig.json和jsconfig.json配置

{// 編譯選項"compilerOptions": {// 生成代碼的語言版本&#xff1a;將我們寫的 TS 代碼編譯成哪個版本的 JS 代碼// 命令行&#xff1a; tsc --target es5 11-測試TS配置文件.ts"target": "es5",// 指定要包含在編譯中的 library"lib&quo…

3年 Android 開發的面試心經(后悔當初沒有拿 N+1)

作者&#xff1a;勇闖天涯 當某人順利通過大廠面試時&#xff0c;總會有人認為這是運氣比較好罷了&#xff0c;但他們不曾得知對方之前受過多少苦和委屈&#xff0c;又付出了多少努力一步步去突破這些困境。正是因為他們的努力付出&#xff0c;在合適的時間與地點&#xff0c;用…

SSH連接工具匯總

xshell 這是個熟悉的軟件啦&#xff0c;目前我正在使用Xshell_7 鏈接&#xff1a;https://www.xshell.com/zh/xshell/ FinalShell 國產軟件&#xff0c;有windows和MAC版本&#xff1b;使用方便而且免費&#xff0c;但是軟件比較占用內存。但是都2021年了&#xff0c;筆記本…

AlphaZero能否從圍棋和國際象棋飛躍到量子計算?

一項新的研究表明&#xff0c;DeepMind驚人的游戲算法AlphaZero可以幫助釋放量子計算的力量和潛力。 自兩年多前出現以來&#xff0c;AlphaZero一再證明了其快速學習能力&#xff0c;將自己提升到圍棋&#xff0c;國際象棋和將棋&#xff08;日本象棋&#xff09;的特級大師級別…

VHDL記錄

文章目錄 使用function名稱作為“常量”numeric_std包集中使用乘法的注意項variable的使用對于entity設置屬性的方法在entity聲明中嵌入function的定義VHDL仿真讀寫文件File declaration/File handingFile readingFile writing小例子 使用函數 模塊中打印出調試信息 使用functi…

RTC實驗

一、RTC簡介 RTC(Real Time Clock)即實時時鐘&#xff0c;它是一個可以為系統提供精確的時間基準的元器件&#xff0c;RTC一般采用精度較高的晶振作為時鐘源&#xff0c;有些RTC為了在主電源掉電時還可以工作&#xff0c;需要外加電池供電BCD碼&#xff0c;四位二進制表示一位…

Java Persistence APl(JPA)——JPA是啥? SpringBoot整合JPA JPA的增刪改查 條件模糊查詢 多對一查詢

目錄 引出Jpa是啥&#xff1f;Jpa的使用創建實體類寫dao接口類寫服務類 crud增刪改查增加修改根據id刪除全查詢分頁查詢 條件查詢模糊查詢單條件查詢多條件查詢模糊查詢排序查詢 多對一查詢定義實體類auto主鍵策略下新增進行全查詢測試 全部代碼application.yml配置類pom配置文…

Java反射機制是什么?

Java反射機制是 Java 語言的一個重要特性。 在學習 Java 反射機制前&#xff0c;大家應該先了解兩個概念&#xff0c;編譯期和運行期。 編譯期是指把源碼交給編譯器編譯成計算機可以執行的文件的過程。在 Java 中也就是把 Java 代碼編成 class 文件的過程。編譯期只是做了一些…

Python學習筆記第五十二天(Pandas 安裝)

Python學習筆記第五十二天 Pandas 安裝查看安裝版本 安裝驗證后記 Pandas 安裝 安裝 pandas 需要基礎環境是 Python&#xff0c;開始前我們假定你已經安裝了 Python 和 Pip。 使用 pip 安裝 pandas: pip install pandas安裝成功后&#xff0c;我們就可以導入 pandas 包使用&…

iPhone(iPad)安裝deb文件

最簡單的方法就是把deb相關的文件拖入手機對應的目錄&#xff0c;一般是DynamicLibraries文件夾 參考&#xff1a;探討手機越獄和安裝deb文件的幾種方式研究 1、在 Mac 上安裝 dpkg 命令 打包 deb 教程之在 Mac 上安裝 dpkg 命令_xcode打包root權限deb_qq_34810996的博客-CS…

神經網絡基礎-神經網絡補充概念-26-前向和反向傳播

簡單比較 前向傳播&#xff08;Forward Propagation&#xff09;&#xff1a; 前向傳播是神經網絡中的正向計算過程&#xff0c;用于從輸入數據開始&#xff0c;逐層計算每個神經元的輸出值&#xff0c;直到得到最終的預測值。在前向傳播過程中&#xff0c;我們按以下步驟進行…

驅動DAY4 字符設備驅動分步注冊和ioctl函數點亮LED燈

頭文件 #ifndef __HEAD_H__ #define __HEAD_H__ typedef struct{unsigned int MODER;unsigned int OTYPER;unsigned int OSPEEDR;unsigned int PUPDR;unsigned int IDR;unsigned int ODR; }gpio_t; #define PHY_LED1_ADDR 0X50006000 #define PHY_LED2_ADDR 0X50007000 #d…