JVM類加載器ClassLoader的源碼分析

1、ClassLoader與現有類加載器的關系

ClassLoader與現有類加載器的關系:

image-20231203232034068

ClassLoader是一個抽象類。如果我們給定了一個類的二進制名稱,類加載器應嘗試去定位或生成構成定義類的數據。一種典型的策略是將給定的二進制名稱轉換為文件名,然后去文件系統中讀取這個文件名所對應的class文件。

2、ClassLoader的主要方法

抽象類ClassLoader的主要方法:(內部沒有抽象方法)

public final ClassLoader getParent() 
//返回該類加載器的超類加載器
public Class<?> loadClass(String name) throws ClassNotFoundException
加載名稱為name的類,返回結果為java.lang.Class類的實例。

如果找不到類,則返回 ClassNotFoundException 異常。該方法中的邏輯就是雙親委派模式的實現。

protected Class<?> findClass(String name) throws ClassNotFoundException
// 查找二進制名稱為name的類,返回結果為java.lang.Class類的實例。這是一個受保護的方法,JVM鼓勵我們重寫此方法,需要自定義加載器遵循雙親委托機制,該方法會在檢查完父類加載器之后被loadClass()方法調用。

在JDK1.2之前,在自定義類加載時,總會去繼承ClassLoader類并重寫loadClass方法,從而實現自定義的類加載類。但是在JDK1.2之后已不再建議用戶去覆蓋loadClass()方法,而是建議把自定義的類加載邏輯寫在findClass()方法中,從前面的分析可知,findClass()方法是在loadClass()方法中被調用的,當loadClass()方法中父加載器加載失敗后,則會調用自己的findClass()方法來完成類加載,這樣就可以保證自定義的類加載器也符合雙親委托模式。

需要注意的是ClassLoader類中并沒有實現findClass()方法的具體代碼邏輯,取而代之的是拋出ClassNotFoundException異常,同時應該知道的是findClass方法通常是和defineClass方法一起使用的。一般情況下,在自定義類加載器時,會直接覆蓋ClassLoader的findClass()方法并編寫加載規則,取得要加載類的字節碼后轉換成流,然后調用defineClass()方法生成類的Class對象。

protected final Class<?> defineClass(String name, byte[] b, int off, int len)
//根據給定的字節數組b轉換為Class的實例,off和len參數表示實際Class信息在byte數組中的位置和長度,其中byte數組b是ClassLoader從外部獲取的。這是受保護的方法,只有在自定義ClassLoader子類中可以使用。

defineClass()方法是用來將byte字節流解析成JVM能夠識別的Class對象(ClassLoader中已實現該方法邏輯),通過這個方法不僅能夠通過class文件實例化class對象,也可以通過其他方式實例化class對象,如通過網絡接收一個類的字節碼,然后轉換為byte字節流創建對應的Class對象。
defineClass()方法通常與findClass()方法一起使用,一般情況下,在自定義類加載器時,會直接覆蓋ClassLoader的findClass()方法并編寫加載規則,取得要加載類的字節碼后轉換成流,然后調用defineClass()方法生成類的Class對象

例如:

protected Class<?> findClass(String name) throws ClassNotFoundException {// 獲取類的字節數組byte[] classData = getClassData(name);if (classData == null) {throw new ClassNotFoundException();} else {//使用defineClass生成class對象return defineClass(name, classData, 0, classData.length);}
}
protected final void resolveClass(Class<?> c)
// 鏈接指定的一個Java類。使用該方法可以使用類的Class對象創建完成的同時也被解析。前面我們說鏈接階段主要是對字節碼進行驗證,為類變量分配內存并設置初始值同時將字節碼文件中的符號引用轉換為直接引用。
protected final Class<?> findLoadedClass(String name)
//查找名稱為name的已經被加載過的類,返回結果為java.lang.Class類的實例。這個方法是final方法,無法被修改。
private final ClassLoader parent;
//它也是一個ClassLoader的實例,這個字段所表示的ClassLoader也稱為這個ClassLoader的雙親。在類加載的過程中,ClassLoader可能會將某些請求交予自己的雙親處理。

loadClass()的剖析

ClassLoader.getSystemClassLoader().loadClass("com.atguig.java.User");
//測試代碼

涉及到對如下方法的調用:

protected Class<?> loadClass(String name, boolean resolve) //resolve:true-加載class的同時進行解析操作。throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) { //同步操作,保證只能加載一次。//首先,在緩存中判斷是否已經加載同名的類。Class<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {//獲取當前類加載器的父類加載器。if (parent != null) {//如果存在父類加載器,則調用父類加載器進行類的加載c = parent.loadClass(name, false);} else { //parent為null:父類加載器是引導類加載器c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c == null) { //當前類的加載器的父類加載器未加載此類 or 當前類的加載器未加載此類// 調用當前ClassLoader的findClass()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;}
}

在這里插入圖片描述

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

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

相關文章

C語言--實現一個函數把一個整數轉為它對應的十六進制的字符串

一.題目描述 實現一個函數把一個整數轉為它對應的十六進制的字符串。 比如&#xff1a;輸入數字1234 輸出&#xff1a;4D2 二.思路分析 用一個sprintf函數可以解決問題&#xff0c;輸出相對應的字符串 要注意的問題就是&#xff1a;函數結束后要繼續使用的內存&#xff08;比如…

Carla自動駕駛仿真六:pygame多個車輛攝像頭畫面拼接

此文章主要介紹carla前后左右攝像頭畫面拼接到pygame上 文章目錄 前言一、要點分析二、完整代碼三、拼接效果四、總結 前言 1、使用carla做仿真測試或者開發時&#xff0c;如果能夠將車輛周邊的畫面拼接并渲染&#xff0c;可以直觀地查看周圍地環境&#xff0c;便于調試。本文…

Spring Boot 工廠模式 + 抽象類 + 泛型干掉重復代碼

業務場景&#xff1a;N個Excel導入&#xff0c;實現動態加載&#xff0c;只需要定義Excel實體&#xff0c;即可實現功能開發&#xff0c; 核心代碼 import cn.afterturn.easypoi.excel.annotation.ExcelTarget; import cn.hutool.core.annotation.AnnotationUtil; import cn.h…

刪除Windows系統中無用的隱藏設備

一些即插即用設備會占用一些隱藏的系統資源&#xff0c;比如USB轉串口的設備會占用COM號碼&#xff0c;網卡會占用靜態IP地址等等。 通常我們使用設備管理器的顯示隱藏設備功能&#xff0c;來刪除這些設備。但是設備管理器每次只允許刪除一個設備&#xff0c;如果設備太多了&a…

【算法集訓】基礎數據結構:四、棧

棧理解了兩天&#xff0c;所以遲了一天發。 一、棧的概念 棧是一個容器&#xff0c;是一個先進后出的線性表&#xff0c;類似與日常生活中的電梯、杯子等。 僅限在表尾部進行插入和刪除操作。 使用鏈表來模擬棧&#xff1a; typedef int DataType; 相當于給int起一個別名 st…

Go 協程基礎:輕松入門并發編程,解析 Goroutines 的奧秘

一、協程基本使用 1、啟動一個協程 主線程中每個100毫秒打印一次&#xff0c;總共打印2次另外開啟一個協程&#xff0c;打印10次情況一&#xff1a;打印是交替&#xff0c;證明是并行的情況二&#xff1a;開啟的協程打印2次&#xff0c;就退出了&#xff08;因為主線程退出了…

做題筆記:SQL Sever 方式做牛客SQL的題目--SQL157

----SQL157 平均播放進度大于60%的視頻類別 計算各類視頻的平均播放進度&#xff0c;將進度大于60%的類別輸出。 注&#xff1a; 播放進度播放時長視頻時長*100%&#xff0c;當播放時長大于視頻時長時&#xff0c;播放進度均記為100%。 結果保留兩位小數&#xff0c;并按播放進…

基于ssm的學生公寓管理中心系統的設計與實現論文

摘 要 現代經濟快節奏發展以及不斷完善升級的信息化技術&#xff0c;讓傳統數據信息的管理升級為軟件存儲&#xff0c;歸納&#xff0c;集中處理數據信息的管理方式。本學生公寓管理中心系統就是在這樣的大環境下誕生&#xff0c;其可以幫助管理者在短時間內處理完畢龐大的數據…

[報錯]記錄IDEA遠程開發報錯:java: Cannot run program.....

報錯內容 IDEA在進行遠程開發的時候報錯&#xff0c;內容如下&#xff1a; java: Cannot run program "/usr/lib/jvm/java-1.8.0-openjdk-amd64/bin/java" (in directory "/home/jim/.cache/JetBrains/RemoteDev-IU/_home_jim_DevCodes_Github_zfile/compile-…

redis主從復制【面試必看】

在分布式系統中&#xff0c;希望使用多個服務器來部署redis&#xff0c;存在以下幾種redis的部署方式 主從模式主從哨兵集群模式 主從模式 在若干個redis節點中&#xff0c;有的是主節點&#xff0c;有的是從節點 假設有三個物理服務器&#xff08;稱為是三個節點&#xff…

(JSP)EL——優化登錄界面,獲取對象,獲取數據

EL優化登錄界面 <% page language"java" import"java.util.*" pageEncoding"UTF-8"%> <% String path request.getContextPath(); String basePath request.getScheme()"://"request.getServerName()":"reques…

生產工序(oj題)

很有趣的一道題 關鍵在于固定工序的整合 看樣例是固定工序中間是不能插入其他工序的&#xff08;也不講清楚&#xff09;&#xff0c;如果可以的話&#xff0c;只能說可能會更麻煩 注意固定工序是按照固定工序中的第一個工序進行排序的 整合完之后&#xff0c;就是遞歸列出…

Java中的IO流①——IO流的體系、字節流、try...catch異常處理

概述 IO流的分類 IO流的體系 這四個類都是抽象類&#xff0c;所以需要實現類對象才能使用---> 字節流 FileInputStream--> 書寫細節 代碼示范 此時文件a.txt內容為abcde 使用char強轉和read方法調用五次read方法--> public static void main(String[] args) throws IO…

mysql 語言學習

整理了一下 mysql 操作語言&#xff0c;不是很全&#xff0c;部分地方也許需要修改&#xff0c;先放上來&#xff0c;有時間再慢慢完善。 一、數據庫操作 連接數據庫 $ sudo mysql [-h ip] -u root -p [-P 3306] 初始化數據庫 $ mysql_secure_installation備份數據庫 # 備…

初出茅廬的小李博客之TobudOS移植到EVB_AIoT開發板

本博客參考教程&#xff1a; https://atomgit.com/OpenAtomFoundation/TobudOS/blob/master/doc/TobudOS_EVB_AIoT_STM32_Guide.md 介紹一下EVB_AIoT開發板 這個開發板是由TobudOS開源社區聯合意法半導體、南京厚德物聯網設計的一款高性能IoT開發平臺&#xff0c;主控芯片是S…

SystemVerilog學習(0)——目錄與傳送門

一、驗證導論 SystemVerilog學習&#xff08;1&#xff09;——驗證導論-CSDN博客文章瀏覽閱讀403次。SystemVerilog自學&#xff0c;驗證系統概述&#xff0c;什么是SVhttps://blog.csdn.net/apple_53311083/article/details/133953016 二、數據類型 SystemVerilog學習&…

含掩膜mask的單通道灰度圖轉化為COCO數據集格式標簽的json文件(python)

輸入&#xff1a;單通道的灰度圖&#xff0c;灰度圖內含掩膜mask 目標&#xff1a;把灰度圖中的語義mask轉換為COCO數據集格式的json文件 輸出&#xff1a;COCO數據集格式的json文件 期間遇到的問題&#xff1a; 發現有的掩膜內部存在其他類別的掩膜&#xff0c;即mask內部還套…

枚舉類簡單使用

1、創建一個枚舉 public enum DemoEnum {// 引號里面存放的是下面所創建的屬性&#xff0c;如果不創建屬性則不能輸入引號里的值的NORMAL("正常"),DESTORY("廢棄");private String label;private DemoEnum(String label){this.label label;}public Strin…

使用.net core MVC實現圖片上傳下載

今天閑來無事&#xff0c;復習復習 1、上傳 上傳界面 <div class"text-center"><h1 class"display-4">Welcome</h1><form method"post" enctype"multipart/form-data" asp-controller"Home" asp-ac…

<HarmonyOS主題課>三方庫【課后考核】

【習題】三方庫 判斷題 三方組件是開發者在系統能力的基礎上進行了一層具體功能的封裝&#xff0c;對其能力進行拓展的工具 。 正確(True) 可以通過ohpm uninstall 指令下載指定的三方庫 錯誤(False) lottie使用loadAnimation方法加載動畫。 正確(True) 單選題 通過ohpm安…