电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

淺談Java自定義類加載器及JVM自帶的類加載器之間的交互關系

瀏覽:21日期:2022-08-16 13:54:20
JVM自帶的類加載器:

淺談Java自定義類加載器及JVM自帶的類加載器之間的交互關系

其關系如下:

淺談Java自定義類加載器及JVM自帶的類加載器之間的交互關系

其中,類加載器在加載類的時候是使用了所謂的“父委托”機制。其中,除了根類加載器以外,其他的類加載器都有且只有一個父類加載器。

關于父委托機制的說明:

淺談Java自定義類加載器及JVM自帶的類加載器之間的交互關系

當生成 一個自定義的類加載器實例時,如果沒有指定它的父加載器,那么系統類加載器將成為該類加載器的父類加載器

下面,自定義類加載器。自定義的類加載器必須繼承java.lang.ClassLoader類

import java.io.*;public class MyClassLoader extends ClassLoader { private String name; //類加載器的名字 private String path; //加載類的路徑 private final String fileType = '.class'; //class文件的擴展名 public MyClassLoader(String name){ super(); //讓系統類加載器成為該類加載器的父 類加載器,該句可省略不寫 this.name = name; } public MyClassLoader(ClassLoader parent,String name){ super(parent); //顯示指定該類加載器的父 類加載器 this.name = name; } @Override public String toString() { return this.name; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } //實現自定義的類加載器必須重寫findClass方法,否則ClassLoader類中的findClass()方法是拋出了異常 @Override public Class findClass(String name)throws ClassNotFoundException{ byte[] data = this.loadClassData(name); return this.defineClass(name,data,0,data.length); } private byte[] loadClassData(String name){ InputStream is = null; byte[] data = null; ByteArrayOutputStream baos = null; try { this.name = this.name.replace('.',''); //com.dream.it---->comdreamit is = new FileInputStream(new File(path + name + fileType)); int ch; while(-1 != (ch = is.read())){baos.write(ch); //將數據寫入到字節數組輸出流對象中去 } data = baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); }finally { try {is.close();baos.close(); } catch (IOException e) {e.printStackTrace(); } } return data; } public static void main(String[] args) throws Exception { MyClassLoader loader1 = new MyClassLoader('loader1'); loader1.setPath('d:/myapp/serverlib/'); MyClassLoader loader2 = new MyClassLoader(loader1,'loader2'); //loader1作為loader2的父 類加載器 loader2.setPath('d:/myapp/clientlib'); MyClassLoader loader3 = new MyClassLoader(null,'loader3');//父類加載器為null,表明其父類加載器為根類加載器 loader3.setPath('d:/myapp/otherlib'); test(loader2); test(loader3); } public static void test(ClassLoader cl) throws Exception { Class clazz = cl.loadClass('Sample'); Object object = clazz.newInstance(); }}附上findClass()方法的JDK說明

protected Class<?> findClass(String name) throws ClassNotFoundExceptionFinds the class with the specified binary name. This method should be overridden by class loaderimplementations that follow the delegation model for loading classes, and will be invoked by the loadClass method after checking the parent classloader for the requested class. The default implementation throws a ClassNotFoundException.

大致說明一下意思:通過指定的name來查找類。該方法應該被類加載器的實現類重寫,從而能夠保證在加載類的時候可以遵循委托機制模型。在loadClass()方法(該方法是由JVM調用的)中,檢查其父類加載器之后,該方法再被調用去加載請求的類。默認該方法的實現是拋出了一個ClassNotFoundException異常。

其實,所謂的加載類,無非就是讀取.class文件到內存中,所以在findClass()方法中,loadClassData()方法用于讀取.class文件的數據,并返回一個字節數組。然后利用ClassLoader類的defineClass()方法將字節數組轉換為Class對象。

上述自定義的類加載器loader1,loader2,loader3及JVM自帶的類加載器之間的關系如下:

淺談Java自定義類加載器及JVM自帶的類加載器之間的交互關系

對于各個類加載器,系統的類加載器是從環境變量classpath中讀取.class文件實現類的加載;loader1是從目錄d:/myapp/serverlib/下讀取.class文件;loader2是從目錄d:/myapp/clientlib/下讀取.class文件,loader3是從目錄d:/myapp/otherlib/下讀取.class文件

執行結果:

淺談Java自定義類加載器及JVM自帶的類加載器之間的交互關系

此處我們分析一下出現這種執行結果的原因:

當執行loader2.loadClass(“Sample”)時先由它上層的所有父類加載器嘗試加載Sample類。

loader1從D:myappserverliv目錄下成功加載了Sample類,所以loader1是Sample類的定義類加載器,loader1和loader2是Sample類的初始類加載器。

當執行loader3.loadClass(“Sample”)時,先由它上層的所有父類加載器嘗試加載Sample類。

loader3的父加載器為根類加載器,它無法加載Sample類,接著loader3從D:myappotherlib目錄下成功加載Sample類,所以loader3是Sample類的定義類加載器及初始類加載器。

在Sample類中主動使用了Dog類(new Dog()),當執行Sample類的構造方法中的new Dog()語句時,JVM需要先加載Dog類,到底用哪個類加載器家在呢?

從上述的打印結果中可以看出,加載Sample類的loader1還加載了Dog類,JVM會用Sample類的定義類加載器去加載Dog類,加載過程中也同樣采用了父親委托機制。

為了驗證這一點,可以吧D:myappserverlib目錄下Dog.class文件刪除,然后在D:myappsyslib目錄下存放一個Dog.class文件,此時打印結果如下:

Sample:loader1Dog:sun.misc.Launcher$AppClassLoader@1b84c92Sample:loader3Dog:loader3

由此可見,當由loader1加載的Sample類首次主動使用Dog類時,Dog類由系統類加載器加載,如果把D:myappserverlib和D:myappsyslib目錄下的Dog.class文件都刪除,然后在D:myappclient目錄下存放一個Dog.class文件。

此時文件結構如下圖所示:

淺談Java自定義類加載器及JVM自帶的類加載器之間的交互關系

當Loader1加載Sample類首次主動使用Dog類時,由于loader1及其父類加載器都無法加載Dog類,因此test(loader2)會拋出ClassNotFoundExcption.

這又是因為什么原因呢?

這又牽扯到命名空間的問題。

同一個命名空間內的類時相互可見的。

子加載器的命名空間包含所有父類加載器的命名空間,因此由子加載器加載的類能看見父類加載器加載的類。例如系統類加載器加載的類能看見根類加載器加載的類。由父加載器加載的類不能看見子加載器加載的類。

如果兩個加載器之間沒有直接或間接的父子關系,那么它們各自加載的類相互不可見。

對于上述問題,loader1可以加載Sample類,而Dog類只能由loader2加載Dog類,loader1是Loader2的父類加載器,父加載器loader1加載的類Sample不能看見子加載器loader2加載的類Dog,所以會拋出異常。

對于上述實例中的main方法,我們不調用test方法,換成如下代碼

Class clazz = loader1.loadClass('Sample');Object obj = clazz.newInstance();Sample sample = (Sample)obj;System.out.println(sample.v1);

MyClassLoader類由系統類加載器加載,而Sample類由loader1類加載器加載,所以MyClassLoader類看不見Sample類。在MyClassLoader類的main方法中使用Sample類,會導致NoClassFoundError錯誤。

當兩個不同命名空間內的類相互不可見時,可采用Java反射機制來訪問對象實例的屬性和方法。

將上述代碼修改:

Class clazz = loader1.loadClass('Sample');Object obj = clazz.newInstance();Field field = clazz.getField('v1');int v1 = field.getInt(obj);System.out.println(v1);

此時,可以獲取到對象中的v1屬性值。利用反射機制,我們可以跨越這種命名空間的限制。

補充:

命名空間:

淺談Java自定義類加載器及JVM自帶的類加載器之間的交互關系

運行時包:

淺談Java自定義類加載器及JVM自帶的類加載器之間的交互關系

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持好吧啦網。如有錯誤或未考慮完全的地方,望不吝賜教。

標簽: Java
相關文章:
主站蜘蛛池模板: 蔬菜配送公司|蔬菜配送中心|食材配送|饭堂配送|食堂配送-首宏公司 | 合肥仿石砖_合肥pc砖厂家_合肥PC仿石砖_安徽旭坤建材有限公司 | 手持式浮游菌采样器-全排二级生物安全柜-浙江孚夏医疗科技有限公司 | 大数据营销公司_舆情监测软件_上海SEO公司-文军营销官网 | 滁州高低温冲击试验箱厂家_安徽高低温试验箱价格|安徽希尔伯特 | 过滤器_自清洗过滤器_气体过滤器_苏州华凯过滤技术有限公司 | 广东青藤环境科技有限公司-水质检测 | 无锡网站建设_企业网站定制-网站制作公司-阿凡达网络 | 首页-浙江橙树网络技术有限公司 石磨面粉机|石磨面粉机械|石磨面粉机组|石磨面粉成套设备-河南成立粮油机械有限公司 | 聚氨酯保温钢管_聚氨酯直埋保温管道_聚氨酯发泡保温管厂家-沧州万荣防腐保温管道有限公司 | 洛阳防爆合格证办理-洛阳防爆认证机构-洛阳申请国家防爆合格证-洛阳本安防爆认证代办-洛阳沪南抚防爆电气技术服务有限公司 | 车充外壳,车载充电器外壳,车载点烟器外壳,点烟器连接头,旅行充充电器外壳,手机充电器外壳,深圳市华科达塑胶五金有限公司 | 安全,主动,被动,柔性,山体滑坡,sns,钢丝绳,边坡,防护网,护栏网,围栏,栏杆,栅栏,厂家 - 护栏网防护网生产厂家 | 英国雷迪地下管线探测仪-雷迪RD8100管线仪-多功能数字听漏仪-北京迪瑞进创科技有限公司 | 恒温恒湿试验箱厂家-高低温试验箱维修价格_东莞环仪仪器_东莞环仪仪器 | 食品级焦亚硫酸钠_工业级焦亚硫酸钠_焦亚硫酸钠-潍坊邦华化工有限公司 | 皮带机-带式输送机价格-固定式胶带机生产厂家-河南坤威机械 | 紧急切断阀_气动切断阀_不锈钢阀门_截止阀_球阀_蝶阀_闸阀-上海上兆阀门制造有限公司 | 铸铁平台,大理石平台专业生产厂家_河北-北重机械 | 瑞典Blueair空气净化器租赁服务中心-专注新装修办公室除醛去异味服务! | 不锈钢拉手厂家|浴室门拉手厂家|江门市蓬江区金志翔五金制品有限公司 | 恒温振荡混匀器-微孔板振荡器厂家-多管涡旋混匀器厂家-合肥艾本森(www.17world.net) | 聚合氯化铝价格_聚合氯化铝厂家_pac絮凝剂-唐达净水官网 | 交变/复合盐雾试验箱-高低温冲击试验箱_安奈设备产品供应杭州/江苏南京/安徽马鞍山合肥等全国各地 | 香港新时代国际美容美发化妆美甲培训学校-26年培训经验,值得信赖! | 杭州画室_十大画室_白墙画室_杭州美术培训_国美附中培训_附中考前培训_升学率高的画室_美术中考集训美术高考集训基地 | 物流之家新闻网-最新物流新闻|物流资讯|物流政策|物流网-匡匡奈斯物流科技 | 首页 - 张店继勇软件开发工作室| 衬塑设备,衬四氟设备,衬氟设备-淄博鲲鹏防腐设备有限公司 | 成都租车_成都租车公司_成都租车网_众行宝| 高压互感器,电流互感器,电压互感器-上海鄂互电气科技有限公司 | 传动滚筒,改向滚筒-淄博建凯机械科技有限公司 | 合肥活动房_安徽活动板房_集成打包箱房厂家-安徽玉强钢结构集成房屋有限公司 | 武汉不干胶印刷_标签设计印刷_不干胶标签印刷厂 - 武汉不干胶标签印刷厂家 | 蜂窝块状沸石分子筛-吸附脱硫分子筛-萍乡市捷龙环保科技有限公司 | 扬尘在线监测系统_工地噪声扬尘检测仪_扬尘监测系统_贝塔射线扬尘监测设备「风途物联网科技」 | SMC-SMC电磁阀-日本SMC气缸-SMC气动元件展示网 | 标准品网_标准品信息网_【中检计量】 | 陕西安玻璃自动感应门-自动重叠门-磁悬浮平开门厂家【捷申达门业】 | 消泡剂_水处理消泡剂_切削液消泡剂_涂料消泡剂_有机硅消泡剂_广州中万新材料生产厂家 | 紫外可见光分光度计-紫外分光度计-分光光度仪-屹谱仪器制造(上海)有限公司 |