摘要:當一個文件是通過網絡傳輸并且可能會進行相應的加密操作時,需要先對文件進行相應的解密后再加載到內存中,這種情況下也需要編寫自定義的并實現相應的邏輯
Java虛擬機中的類加載有三大步驟:,鏈接,初始化.其中加載是指查找字節流(也就是由Java編譯器生成的class文件)并據此創建類的過程,這中間我們需要借助類加載器來查找字節流.
Java虛擬機默認類加載器Java虛擬機提供了3種類加載器,啟動(Bootstrap)類加載器、擴展(Extension)類加載器、應用(Application)類加載器.除了啟動類加載器外,其他的類加載器都是java.lang.ClassLoader的子類.啟動類加載器由C++語言實現,沒有對應的Java對象,它負責將
注意這里面的父子類加載器并不是繼承的關系,只是ClassLoader類中的parent屬性.我們來看Launcher類中創建擴展類加載器的代碼:
public ExtClassLoader(File[] var1) throws IOException { super(getExtURLs(var1), (ClassLoader)null, Launcher.factory); SharedSecrets.getJavaNetAccess().getURLClassPath(this).initLookupCache(this); }
這里設置了其父加載器為null.
雙親委派機制Java虛擬機在加載類時默認采用的是雙親委派機制,即當一個類加載器接收到加載請求時,會將請求轉發到父類加載器,如果父類加載器在路徑下沒有找到該類,才會交給子類加載器去加載.我們來看ClassLoader中laodClass方法:
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 { //調用Bootstrap Classloader c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { long t1 = System.nanoTime(); //到自己指定類加載路徑下查找是否有class字節碼 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; } }
通過這種層級我們可以避免類的重復加載,當父親已經加載了該類時,就沒有必要子類加載器再加載一次。其次也考慮到安全因素,比如我們自己寫一個java.lang.String的類,通過雙親委派機制傳遞到啟動類加載器,而啟動類加載器在核心Java API發現這個名字的類,發現該類已被加載,并不會重新加載我們新寫的java.lang.String,而直接返回已加載過的String.class,這樣保證生成的對象是同一種類型.
自定義類加載器除了jvm自身提供的類加載器,我們還可以自定義類加載器,我們先寫一個Person類
public class Person { private int age; private String name; //省略getter/setter方法 }
我們先看他是由哪個類加載器加載的.
public class TestJava { public static void main(String[] args) throws Exception { Person person = new Person(); System.out.println("person是由" + person.getClass().getClassLoader() + "加載的"); } }
運行結果如下:
我們把Person.class放置在其他目錄下
再運行會發生什么,在上面的loadClass方法中其實已經有了答案,會拋出ClassNotFoundException,因為在指定路徑下查找不到字節碼.
我們現在寫一個自定義的類加載器,讓他能夠去加載person類,很簡單,我們只需要繼承ClassLoader并重寫findClass方法,這里面寫查找字節碼的邏輯.
public class PersonCustomClassLoader extends ClassLoader { private String classPath; public PersonCustomClassLoader(String classPath) { this.classPath = classPath; } private byte[] loadByte(String name) throws Exception { name = name.replaceAll(".", "/"); FileInputStream fis = new FileInputStream(classPath + "/" + name + ".class"); int len = fis.available(); byte[] data = new byte[len]; fis.read(data); fis.close(); return data; } protected Class> findClass(String name) throws ClassNotFoundException { try { byte[] data = loadByte(name); return defineClass(name, data, 0, data.length); } catch (Exception e) { e.printStackTrace(); throw new ClassNotFoundException(); } } }
我們來測試一下:
public class TestJava { public static void main(String[] args) throws Exception { PersonCustomClassLoader classLoader = new PersonCustomClassLoader("/home/shenxinjian"); Class> pClass = classLoader.loadClass("me.shenxinjian.algorithm.Person"); System.out.println("person是由" + pClass.getClassLoader() + "類加載器加載的"); } }
測試結果如下:
當class文件不在classPath路徑下,如上面那種情況,默認系統類加載器無法找到該class文件,在這種情況下我們需要實現一個自定義的classLoader來加載特定路徑下的class文件來生成class對象。
當一個class文件是通過網絡傳輸并且可能會進行相應的加密操作時,需要先對class文件進行相應的解密后再加載到JVM內存中,這種情況下也需要編寫自定義的ClassLoader并實現相應的邏輯
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/73405.html
摘要:它負責將的字節碼形式轉換成內存形式的對象。先使用工具對字節碼文件進行加密,運行時使用定制的先解密文件內容再加載這些解密后的字節碼。的方法是需要子類來覆蓋的,不同的加載器將使用不同的邏輯來獲取目標類的字節碼。 ClassLoader 詳解 ClassLoader 做什么的? 延遲加載 各司其職 ClassLoader 傳遞性 雙親委派 Class.forName 自定義加載器 Clas...
摘要:加載器種類啟動類加載器在中用來加載自身需要的類,實現,用來加載。那么就能保證的類會被優先加載,限制了使用者對系統的影響。這種方式下就完成類加載器的雙親委派機制此處會將作為參數傳入進去實際上是調用了方法 Class 文件的裝載流程 (類加載過程) 加載 -> 連接 (驗證 -> 準備 -> 解析) -> 初始化 -> 使用 -> 卸載 加載 加載階段,jvm 會通過類名獲取到此類的字節碼...
摘要:如問到是否使用某框架,實際是是問該框架的使用場景,有什么特點,和同類可框架對比一系列的問題。這兩個方向的區分點在于工作方向的側重點不同。 [TOC] 這是一份來自嗶哩嗶哩的Java面試Java面試 32個核心必考點完全解析(完) 課程預習 1.1 課程內容分為三個模塊 基礎模塊: 技術崗位與面試 計算機基礎 JVM原理 多線程 設計模式 數據結構與算法 應用模塊: 常用工具集 ...
摘要:反射機制的應用實例在泛型為的中存放一個類型的對象。工廠模式可以參考現在我們利用反射機制實現工廠模式,可以在不修改工廠類的情況下添加任意多個子類。 學習交流群:669823128java 反射 定義 功能 示例概要:Java反射機制詳解| |目錄 1反射機制是什么 2反射機制能做什么 3反射機制的相關API 通過一個對象獲得完整的包名和類名 實例化Class類對象 獲取一個對象的父類與...
摘要:再附一部分架構面試視頻講解本文已被開源項目學習筆記總結移動架構視頻大廠面試真題項目實戰源碼收錄 Java反射(一)Java反射(二)Java反射(三)Java注解Java IO(一)Java IO(二)RandomAccessFileJava NIOJava異常詳解Java抽象類和接口的區別Java深拷貝和淺拷...
閱讀 649·2021-11-25 09:43
閱讀 1668·2021-11-18 10:02
閱讀 1041·2021-10-15 09:39
閱讀 1890·2021-10-12 10:18
閱讀 2122·2021-09-22 15:43
閱讀 773·2021-09-22 15:10
閱讀 2088·2019-08-30 15:53
閱讀 988·2019-08-30 13:00