国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

網(wǎng)絡(luò)公司的名字優(yōu)化手機流暢度的軟件

網(wǎng)絡(luò)公司的名字,優(yōu)化手機流暢度的軟件,免費logo設(shè)計的網(wǎng)站,國內(nèi)推廣雙親委派模型的第一次“被破壞”是重寫自定義加載器的loadClass(),jdk不推薦。一般都只是重寫findClass(),這樣可以保持雙親委派機制.而loadClass方法加載規(guī)則由自己定義,就可以隨心所欲的加載類,典型的打破雙親委派模型的框架和中間件有tomc…
  1. 雙親委派模型的第一次“被破壞”是重寫自定義加載器的loadClass(),jdk不推薦。一般都只是重寫findClass(),這樣可以保持雙親委派機制.而loadClass方法加載規(guī)則由自己定義,就可以隨心所欲的加載類,典型的打破雙親委派模型的框架和中間件tomcatosgi

  2. 雙親委派模型的第二次“被破壞”是ServiceLoader和Thread.setContextClassLoader()。即線程上下文類加載器(contextClassLoader)。雙親委派模型很好地解決了各個類加載器的基礎(chǔ)類統(tǒng)一問題(越基礎(chǔ)的類由越上層的加載器進行加載),基礎(chǔ)類之所以被稱為“基礎(chǔ)”,是因為它們總是作為被調(diào)用代碼調(diào)用的API。但是,如果基礎(chǔ)類又要調(diào)用用戶的代碼,那該怎么辦呢?線程上下文類加載器就出現(xiàn)了。

    1. SPI。這個類加載器可以通過java.lang.Thread類的setContextClassLoader()方法進行設(shè)置,如果創(chuàng)建線程時還未設(shè)置,它將會從父線程中繼承一個;如果在應(yīng)用程序的全局范圍內(nèi)都沒有設(shè)置過,那么這個類加載器默認(rèn)就是應(yīng)用程序類加載器。了有線程上下文類加載器,JNDI服務(wù)使用這個線程上下文類加載器去加載所需要的SPI代碼,也就是父類加載器請求子類加載器去完成類加載動作,這種行為實際上就是打通了雙親委派模型的層次結(jié)構(gòu)來逆向使用類加載器,已經(jīng)違背了雙親委派模型,但這也是無可奈何的事情。Java中所有涉及SPI的加載動作基本上都采用這種方式,例如JNDI,JDBC,JCE,JAXB和JBI等。

    2. 線程上下文類加載器默認(rèn)情況下就是AppClassLoader,那為什么不直接通過getSystemClassLoader()獲取類加載器來加載classpath路徑下的類的呢?其實是可行的,但這種直接使用getSystemClassLoader()方法獲取AppClassLoader加載類有一個缺點,那就是代碼部署到不同服務(wù)時會出現(xiàn)問題,如把代碼部署到Java Web應(yīng)用服務(wù)或者EJB之類的服務(wù)將會出問題,因為這些服務(wù)使用的線程上下文類加載器并非AppClassLoader,而是Java Web應(yīng)用服自家的類加載器,類加載器不同。,所以我們應(yīng)用該少用getSystemClassLoader()。總之不同的服務(wù)使用的可能默認(rèn)ClassLoader是不同的,但使用線程上下文類加載器總能獲取到與當(dāng)前程序執(zhí)行相同的ClassLoader,從而避免不必要的問題

  3. 雙親委派模型的第三次“被破壞”是由于用戶對程序動態(tài)性的追求導(dǎo)致的,這里所說的“動態(tài)性”指的是當(dāng)前一些非?!盁衢T”的名詞:代碼熱替換、模塊熱部署等,簡答的說就是機器不用重啟,只要部署上就能用

前言
比較兩個類是否“相等”,前提是這兩個類由同一個類加載器加載,
否則,即使這兩個類來源于同一個Class 文件,被同一個虛擬機加載,
只要加載它們的類加載器不同,那么這兩個類就必定不相等。
打破雙親委派

?如下是一個自定義的類加載器TestClassLoader,并重寫了findClass和loadClass:

public class TestClassLoader extends ClassLoader {public TestClassLoader(ClassLoader parent) {super(parent);}@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {// 1、獲取class文件二進制字節(jié)數(shù)組byte[] data = null;try {System.out.println(name);String namePath = name.replaceAll("\\.", "\\\\");String classFile = "C:\\study\\myStudy\\ZooKeeperLearning\\zkops\\target\\classes\\" + namePath + ".class";ByteArrayOutputStream baos = new ByteArrayOutputStream();FileInputStream fis = new FileInputStream(new File(classFile));byte[] bytes = new byte[1024];int len = 0;while ((len = fis.read(bytes)) != -1) {baos.write(bytes, 0, len);}data = baos.toByteArray();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}// 2、字節(jié)碼加載到 JVM 的方法區(qū),// 并在 JVM 的堆區(qū)建立一個java.lang.Class對象的實例// 用來封裝 Java 類相關(guān)的數(shù)據(jù)和方法return this.defineClass(name, data, 0, data.length);}@Overridepublic Class<?> loadClass(String name) throws ClassNotFoundException{Class<?> clazz = null;// 直接自己加載clazz = this.findClass(name);if (clazz != null) {return clazz;}// 自己加載不了,再調(diào)用父類loadClass,保持雙親委托模式return super.loadClass(name);}
}

測試:初始化自定義的類加載器,需要傳入一個parent,指定其父類加載器,那就先指定為加載TestClassLoader的類加載器為TestClassLoader的父類加載器吧:

public static void main(String[] args) throws Exception {// 初始化TestClassLoader,被將加載TestClassLoader類的類加載器設(shè)置為TestClassLoader的parentTestClassLoader testClassLoader = new TestClassLoader(TestClassLoader.class.getClassLoader());System.out.println("TestClassLoader的父類加載器:" + testClassLoader.getParent());// 加載 DemoClass clazz = testClassLoader.loadClass("study.stefan.classLoader.Demo");System.out.println("Demo的類加載器:" + clazz.getClassLoader());
}

運行如下測試代碼,發(fā)現(xiàn)報錯了:
找不到java\lang\Object.class,我加載study.stefan.classLoader.Demo類和Object有什么關(guān)系呢?

轉(zhuǎn)瞬想到j(luò)ava中所有的類都隱含繼承了超類Object,加載study.stefan.classLoader.Demo,也會加載父類Object。Object和study.stefan.classLoader.Demo并不在同個目錄,那就找到Object.class的目錄(將jre/lib/rt.jar解壓),修改TestClassLoader#findClass如下:
遇到前綴為java.的就去找官方的class文件。

運行測試代碼:
還是報錯了!!!?報錯信息為:Prohibited package name: java.lang

看意思是java禁止用戶用自定義的類加載器加載java.開頭的官方類,也就是說只有啟動類加載器BootstrapClassLoader才能加載java.開頭的官方類。

得出結(jié)論,因為java中所有類都繼承了Object,而加載自定義類study.stefan.classLoader.Demo,之后還會加載其父類,而最頂級的父類Object是java官方的類,只能由BootstrapClassLoader加載

跳過AppClassLoaderExtClassLoader
既然如此,先將study.stefan.classLoader.Demo交由BootstrapClassLoader加載即可。
由于java中無法直接引用BootstrapClassLoader,所以在初始化TestClassLoader時,傳入parent為null,也就是TestClassLoader的父類加載器設(shè)置為BootstrapClassLoader:

package com.stefan.DailyTest.classLoader;public class Test {public static void main(String[] args) throws Exception {// 初始化TestClassLoader,并將加載TestClassLoader類的類加載器// 設(shè)置為TestClassLoader的parentTestClassLoader testClassLoader = new TestClassLoader(null);System.out.println("TestClassLoader的父類加載器:" + testClassLoader.getParent());// 加載 DemoClass clazz = testClassLoader.loadClass("com.stefan.DailyTest.classLoader.Demo");System.out.println("Demo的類加載器:" + clazz.getClassLoader());}
}

雙親委派的邏輯在 loadClass,由于現(xiàn)在的類加載器的關(guān)系為TestClassLoader —>BootstrapClassLoader,所以TestClassLoader中無需重寫loadClass。
運行測試代碼:

成功了,Demo類由自定義的類加載器TestClassLoader加載的,雙親委派模型被破壞了。

如果不破壞雙親委派,那么Demo類處于classpath下,就應(yīng)該是AppClassLoader加載的,所以真正破壞的是AppClassLoader這一層的雙親委派

一個比較完整的自定義類加載器

一般情況下,自定義類加載器都是繼承URLClassLoader,具有如下類關(guān)系圖:

tomcat是如何打破雙親委派的

Tomcat中可以部署多個web項目,為了保證每個web項目互相獨立,所以不能都由AppClassLoader加載,所以自定義了類加載器WebappClassLoader,WebappClassLoader繼承自URLClassLoader,重寫了findClass和loadClass,并且WebappClassLoader的父類加載器設(shè)置為AppClassLoader。
WebappClassLoader.loadClass中會先在緩存中查看類是否加載過,沒有加載,就交給ExtClassLoader,ExtClassLoader再交給BootstrapClassLoader加載;都加載不了,才自己加載;自己也加載不了,就遵循原始的雙親委派,交由AppClassLoader遞歸加載。

Web應(yīng)用默認(rèn)的類加載順序是(打破了雙親委派規(guī)則):

先從JVM的BootStrapClassLoader中加載。
加載Web應(yīng)用下/WEB-INF/classes中的類。
加載Web應(yīng)用下/WEB-INF/lib/*.jap中的jar包中的類。
加載上面定義的System路徑下面的類。
加載上面定義的Common路徑下面的類。


如果在配置文件中配置了``,那么就是遵循雙親委派規(guī)則,加載順序如下:

先從JVM的BootStrapClassLoader中加載。
加載上面定義的System路徑下面的類。
加載上面定義的Common路徑下面的類。
加載Web應(yīng)用下/WEB-INF/classes中的類。
加載Web應(yīng)用下/WEB-INF/lib/*.jap中的jar包中的類。


1 Tomcat對用戶類庫與類加載器的規(guī)劃
在其目錄結(jié)構(gòu)下有三組目錄(“/common/”、“/server/”、“/shared/”)可以存放Java類庫,另外還可以加上Web應(yīng)用程序本身的目錄“/WEB-INF/”,一共4組,把Java類庫放置在這些目錄中的含義分別如下:

放置在/commom目錄中:類庫可被Tomcat和所有的Web應(yīng)用程序共同使用
放置在/server目錄中:類庫可被Tomcat使用,對所有的Web應(yīng)用程序都不可見
放置在/shared目錄中:類庫可被所有的Web應(yīng)用程序所共同使用,但對Tomcat自己不可見
放置在/WebApp/WEB-INF目錄中:類庫僅僅可以被此Web應(yīng)用程序使用,對Tomcat和其他Web應(yīng)用程序都不可見
為了支持這套目錄結(jié)構(gòu),并對目錄里面的類庫進行加載和隔離,Tomcat自定義了多個類加載器,這些類加載器按照經(jīng)典的雙親委派模型來實現(xiàn),所下圖:

最上面的三個類加載器是JDK默認(rèn)提供的類加載器,這三個加載器的的作用之前也說過,這里不再贅述了,而CommonClassLoader、CatalinaClassLoader、SharedClassLoader和WebAppClassLoader則是Tomcat自己定義的類加載器,他們分別加載/common/、/server/、/shared/和/WebApp/WEB-INF/中的Java類庫。其中WebApp類加載器和jsp類加載器通常會存在多個實例每一個Web應(yīng)用程序?qū)?yīng)一個WebApp類加載器,每一個jsp文件對應(yīng)一個Jsp類加載器

從上圖的委派關(guān)系可以看出,CommonClassLoader能加載的類都可以被CatalinaClassLoader和SharedClassLoader使用,而CatalinaClassLoader和SharedClassLoader自己能加載的類則與對方相互隔離。WebAppClassLoader可以使用SharedClassLoader加載到的類,但各個WebAppClassLoader實例之間相互隔離。而JasperLoader的加載范圍僅僅是這個JSP文件所編譯出來的哪一個Class,它出現(xiàn)的目的就是為了被丟棄:當(dāng)服務(wù)器檢測到JSP文件被修改時,會替換掉目前的JasperLoader的實例,并通過在建立一個新的Jsp類加載器來實現(xiàn)JSP文件的HotSwap功能

tomcat對于不同應(yīng)用需要有不同的隔離環(huán)境。
tomcat給每個應(yīng)用都創(chuàng)建了一個WebApp ClassLoader類加載器
重寫了load方法:不再向上查找,而是在本類查找不到后再向上。對于其他的需要共享的例如Redis,可以在上層Share ClassLoader中共享。

OSGI是如何打破雙親委派的

既然說到OSGI,就要來解釋一下OSGi是什么,以及它的作用

OSGi(Open Service Gateway Initiative):是OSGi聯(lián)盟指定的一個基于Java語言的動態(tài)模塊化規(guī)范,這個規(guī)范最初是由Sun、IBM、愛立信等公司聯(lián)合發(fā)起,目的是使服務(wù)提供商通過住宅網(wǎng)管為各種家用智能設(shè)備提供各種服務(wù),后來這個規(guī)范在Java的其他技術(shù)領(lǐng)域也有不錯的發(fā)展,現(xiàn)在已經(jīng)成為Java世界中的“事實上”的模塊化標(biāo)準(zhǔn),并且已經(jīng)有了Equinox、Felix等成熟的實現(xiàn)。OSGi在Java程序員中最著名的應(yīng)用案例就是Eclipse IDE

OSGi中的每一個模塊(稱為Bundle)與普通的Java類庫區(qū)別并不大,兩者一般都以JAR格式進行封裝,并且內(nèi)部存儲的都是Java Package和Class。但是一個Bundle可以聲明它所依賴的Java Package(通過Import-Package描述),也可以聲明他允許導(dǎo)出發(fā)布的Java Package(通過Export-Package描述)。在OSGi里面,Bundle之間的依賴關(guān)系從傳統(tǒng)的上層模塊依賴底層模塊轉(zhuǎn)變?yōu)?strong>平級模塊之間的依賴(至少外觀上如此),而且類庫的可見性能得到精確的控制,一個模塊里只有被Export過的Package才可能由外界訪問,其他的Package和Class將會隱藏起來。除了更精確的模塊劃分和可見性控制外,引入OSGi的另外一個重要理由是,基于OSGi的程序很可能可以實現(xiàn)模塊級的熱插拔功能,當(dāng)程序升級更新或調(diào)試除錯時,可以只停用、重新安裝然后啟動程序的其中一部分,這對企業(yè)級程序開發(fā)來說是一個非常有誘惑性的特性

OSGi之所以能有上述“誘人”的特點,要歸功于它靈活的類加載器架構(gòu)。OSGi的Bundle類加載器之間只有規(guī)則,沒有固定的委派關(guān)系。例如,某個Bundle聲明了一個它依賴的Package,如果有其他的Bundle聲明發(fā)布了這個Package,那么所有對這個Package的類加載動作都會為派給發(fā)布他的Bundle類加載器去完成。不涉及某個具體的Package時,各個Bundle加載器是平級關(guān)系,只有具體使用某個Package和Class的時候,才會根據(jù)Package導(dǎo)入導(dǎo)出定義來構(gòu)造Bundle間的委派和依賴

另外,一個Bundle類加載器為其他Bundle提供服務(wù)時,會根據(jù)Export-Package列表嚴(yán)格控制訪問范圍。如果一個類存在于Bundle的類庫中但是沒有被Export,那么這個Bundle的類加載器能找到這個類,但不會提供給其他Bundle使用,而且OSGi平臺也不會把其他Bundle的類加載請求分配給這個Bundle來處理

一個例子:假設(shè)存在BundleA、BundleB、BundleC三個模塊,并且這三個Bundle定義的依賴關(guān)系如下:

BundleA:聲明發(fā)布了packageA,依賴了java.*的包
BundleB:聲明依賴了packageA和packageC,同時也依賴了Java.*的包
BundleC:聲明發(fā)布了packageC,依賴了packageA
那么,這三個Bundle之間的類加載器及父類加載器之間的關(guān)系如下圖:

由于沒有涉及到具體的OSGi實現(xiàn),所以上圖中的類加載器沒有指明具體的加載器實現(xiàn),只是一個體現(xiàn)了加載器之間關(guān)系的概念模型,并且只是體現(xiàn)了OSGi中最簡單的加載器委派關(guān)系。一般來說,在OSGi中,加載一個類可能發(fā)生的查找行為委派關(guān)系會比上圖中顯示的復(fù)雜,類加載時的查找規(guī)則如下:

以java.*開頭的類,委派給父類加載器加載
否則,委派列表名單內(nèi)的類,委派給父類加載器加載
否則,Import列表中的類,委派給Export這個類的Bundle的類加載器加載
否則,查找當(dāng)前Bundle的ClassPath,使用自己的類加載器加載
否則,查找是否在自己的Fragment Bundle中,如果是,則委派給Fragment bundle的類加載器加載
否則,查找Dynamic Import列表的Bundle,委派給對應(yīng)Bundle的類加載器加載
否則,查找失敗
從之前的圖可以看出,在OSGi里面,加載器的關(guān)系不再是雙親委派模型的樹形架構(gòu),而是已經(jīng)進一步發(fā)展成了一種更復(fù)雜的、運行時才能確定的網(wǎng)狀結(jié)構(gòu)

相關(guān)面試題:一個類的靜態(tài)塊是否可能被執(zhí)行兩次

一個自于網(wǎng)易面試官的一個問題,一個類的靜態(tài)塊是否可能被執(zhí)行兩次。

答案:如果一個類,被兩個 osgi的bundle加載, 然后又有實例被初始化,其靜態(tài)塊會被執(zhí)行兩次

什么是SPI 機制

Spi 機制加載第三方擴展的jar包類初始化。
mysql, dubbo rpc


SPi機制的原理:
java SPI全稱Service Provider Interface 。是java 提供的一套用來被第三方實現(xiàn)的API,他可以用來啟用框架擴展和替換組件。實際上是基于接口編程+策略模式+配置文件 組合實現(xiàn)的動態(tài)加載機制

JDBC

原本的JDBC: Class.forName(“DriverName”) 是通過調(diào)用Driver中靜態(tài)代碼塊中的將Driver注冊

public class Driver extends NonRegisteringDriver implements java.sql.Driver {public Driver() throws SQLException {}static {try {DriverManager.registerDriver(new Driver());} catch (SQLException var1) {throw new RuntimeException("Can't register driver!");}}
}

使用SPI的JDBC:
在mysql的jar包中的META-INF/services/java.sql.Driver 文件中指明當(dāng)前使用的Driver,然后可以直接調(diào)用

Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb?characterEncoding=GBK", "root", "");

問題是 :一個類的加載器和調(diào)用他的加載器相同
這里調(diào)用的是 bootstrap類加載器,無法加載到子類廠商中的類


方法:使用線程上下文加載器

public class DriverManager {static {loadInitialDrivers();println("JDBC DriverManager initialized");}private static void loadInitialDrivers() {//省略代碼//這里就是查找各個sql廠商在自己的jar包中通過spi注冊的驅(qū)動ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);Iterator<Driver> driversIterator = loadedDrivers.iterator();try{while(driversIterator.hasNext()) {driversIterator.next();}} catch(Throwable t) {// Do nothing}//省略代碼}
}

使用Thread類的 getContextClassLoader

    public static <S> ServiceLoader<S> load(Class<S> service) {ClassLoader cl = Thread.currentThread().getContextClassLoader();return ServiceLoader.load(service, cl);}public static <S> ServiceLoader<S> load(Class<S> service,ClassLoader loader){return new ServiceLoader<>(service, loader);}

整個mysql的驅(qū)動加載過程:

第一,獲取線程上下文類加載器,從而也就獲得了應(yīng)用程序類加載器(也可能是自定義的類加載器)
第二,從META-INF/services/java.sql.Driver文件中獲取具體的實現(xiàn)類名“com.mysql.jdbc.Driver”
第三,通過線程上下文類加載器去加載這個Driver類,從而避開了雙親委派模型的弊端

?SPI參考:39 如何破壞雙親委派機制原則 - 簡書

知識來源:

JVM問題(一) -- 如何打破雙親委派模型_如何打破雙親委派機制_leo_messi94的博客-CSDN博客

打破雙親委派的幾種辦法_破壞雙親委派_hhpub的博客-CSDN博客

http://aloenet.com.cn/news/46105.html

相關(guān)文章:

  • 網(wǎng)店代運營怎么做廣東seo網(wǎng)站設(shè)計
  • 網(wǎng)站開發(fā)女生可以做嗎淘寶指數(shù)網(wǎng)站
  • 京東商城網(wǎng)站地址是多少今日最新的新聞
  • 旅游信息網(wǎng)站開發(fā)背景站內(nèi)關(guān)鍵詞排名優(yōu)化軟件
  • 建設(shè)部網(wǎng)站1667號北京seo外包平臺
  • 網(wǎng)站點擊率多少正常怎樣在百度做廣告宣傳
  • 湖北移動網(wǎng)站建設(shè)互聯(lián)網(wǎng)營銷的五個手段
  • 網(wǎng)站怎么做推廣和優(yōu)化seo推廣知識
  • 泰州網(wǎng)站建設(shè)多少錢北京環(huán)球影城每日客流怎么看
  • 做網(wǎng)站建設(shè)價格網(wǎng)絡(luò)軟文營銷案例3篇
  • 網(wǎng)站建設(shè)需要多少錢小江網(wǎng)頁設(shè)計seo網(wǎng)絡(luò)推廣外包公司
  • 網(wǎng)站開發(fā)需求書接推廣一般多少錢
  • 昆明房產(chǎn)網(wǎng)站建設(shè)seo全網(wǎng)營銷
  • 建設(shè)網(wǎng)站公司 優(yōu)幫云網(wǎng)站排名優(yōu)化專業(yè)定制
  • 哪些網(wǎng)站可以做調(diào)查賺錢廣告關(guān)鍵詞有哪些類型
  • 政府網(wǎng)站用的什么cms系統(tǒng)常州seo排名收費
  • 泉州seo-泉州網(wǎng)站建設(shè)公司正規(guī)推廣平臺有哪些
  • 外貿(mào)網(wǎng)站銷售方式好用搜索引擎排名
  • dw制作網(wǎng)站站長聯(lián)盟
  • 做網(wǎng)站違法嘛萬能軟文模板
  • 做免費網(wǎng)站怎么賺錢品牌推廣方案
  • 周杰倫做的廣告網(wǎng)站英文外鏈代發(fā)
  • 贛州曬房網(wǎng)百度seo排名360
  • 合肥網(wǎng)站 技術(shù)支持 上誠科技餐飲營銷方案
  • 成都個人建網(wǎng)站關(guān)鍵詞優(yōu)化哪家強
  • 中國最新軍事新聞 新聞seo外鏈發(fā)布軟件
  • 免費網(wǎng)站下載軟件免費個人網(wǎng)頁制作
  • 我做的網(wǎng)站服務(wù)器別人沒法左鍵點擊下載呢寧波谷歌seo
  • 有賬號和密碼怎么進公司網(wǎng)站后臺百度seo如何做
  • ??诰W(wǎng)站建設(shè)解決方案云南疫情最新數(shù)據(jù)消息中高風(fēng)險地區(qū)