日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java类加载器、双亲委派、沙箱安全机制全都让你整明白(三万字,收藏慢慢啃)

發(fā)布時(shí)間:2025/3/19 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java类加载器、双亲委派、沙箱安全机制全都让你整明白(三万字,收藏慢慢啃) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

?

一、概述

1、類加載的分類

2、類加載器的必要性

3、命名空間

4、類加載機(jī)制的基本特征

二、類加載器的分類

1、引導(dǎo)類加載器

2、擴(kuò)展類加載器

3、系統(tǒng)類加載器

4、用戶自定義類加載器

三、測試不同的類加載器

四、ClassLoader源碼解析

1、抽象類ClassLoader的主要方法:(內(nèi)部沒有抽象方法)

(1)public final ClassLoader getParent()

(2)public Class loadClass(String name) throws ClassNotFoundException

(3)protected Class findClass(String name) throws ClassNotFoundException

(4)protected final Class defineClass(byte[] b, int off, int len)

(5)protected final void resolveClass(Class c)

(6)protected final Class findLoadedClass(String name)

(7)private?final?ClassLoader?parent;

2、SecureClassLoader?與?URLClassLoader

3、ExtClassLoader?與?AppClassLoader

4、Class.forName()?與ClassLoader.loadClass()

五、雙親委派模型

1、定義與本質(zhì)

2、優(yōu)勢與劣勢

(1)雙親委派機(jī)制優(yōu)勢

(2)代碼支持

(3)舉例

(4)思考

(5)雙親委托模式的弊端

(6)結(jié)論

3、破壞雙親委派機(jī)制

(1)破壞雙親委派機(jī)制1

(2)破壞雙親委派機(jī)制2

(3)破壞雙親委派機(jī)制3

4、熱替換的實(shí)現(xiàn)

六、沙箱安全機(jī)制

1、JDK1.0時(shí)期

2、JDK1.1時(shí)期

3、JDK1.2時(shí)期

4、JDK1.6時(shí)期

七、自定義類的加載器

1、為什么要自定義類加載器?

(1)隔離加載類

(2)修改類加載的方式

(3)擴(kuò)展加載源

(4)防止源碼泄漏

2、常見的場景

3、注意

4、實(shí)現(xiàn)方式

(1)實(shí)現(xiàn)方式

(2)對比

八、java9新特性


一、概述

? ? 類加載器是JVM執(zhí)行類加載機(jī)制的前提。

ClassLoader的作用:

? ? ClassLoader是Java的核心組件,所有的Class都是由ClassLoader進(jìn)行加載的,ClassLoader負(fù)責(zé)通過各種方式將Class信息的二進(jìn)制數(shù)據(jù)流讀入JVM內(nèi)部,轉(zhuǎn)換為一個(gè)與目標(biāo)類對應(yīng)的java.lang.Class對象實(shí)例。然后交給Java虛擬機(jī)進(jìn)行鏈接、初始化等操作。因此,ClassLoader在整個(gè)裝載階段,只能影響到類的加載,而無法通過ClassLoader去改變類的鏈接和初始化行為。至于它是否可以運(yùn)行,則由Execution?Engine決定。

? ? 類加載器最早出現(xiàn)在Java1.0版本中,那個(gè)時(shí)候只是單純地為了滿足Java?Applet應(yīng)用而被研發(fā)出來。但如今類加載器卻在OSGi(熱部署)、字節(jié)碼加解密領(lǐng)域大放異彩。這主要?dú)w功于Java虛擬機(jī)的設(shè)計(jì)者們當(dāng)初在設(shè)計(jì)類加載器的時(shí)候,并沒有考慮將它綁定在JVM內(nèi)部,這樣做的好處就是能夠更加靈活和動態(tài)地執(zhí)行類的加載操作。

1、類加載的分類

?? ?類的加載分類:顯式加載vs隱式加載

?? ?class文件的顯式加載與隱式加載的方式是指JVM加載class文件到內(nèi)存的方式。

?? ?①?顯式加載指的是在代碼中通過調(diào)用ClassLoader加載class對象,如直接使用Class.forName(name)或this.getClass().getClassLoader().loadClass()加載class對象。

?? ?②?隱式加載則是不直接在代碼中調(diào)用ClassLoader的方法加載class對象,而是通過虛擬機(jī)自動加載到內(nèi)存中,如在加載某個(gè)類的class文件時(shí),該類的class文件中引用了另外一個(gè)類的對象,此時(shí)額外引用的類將通過JVM自動加載到內(nèi)存中。(User u = new User(); //?隱式加載User類)

?? ?在日常開發(fā)以上兩種方式一般會混合使用。

2、類加載器的必要性

? ? 一般情況下,Java開發(fā)人員并不需要在程序中顯式地使用類加載器,但是了解類加載器的加載機(jī)制卻顯得至關(guān)重要。從以下幾個(gè)方面說:

? ? ①?避免在開發(fā)中遇到j(luò)ava.lang.ClassNotFoundException異常或java.lang.NoClassDefFoundError異常時(shí),手足無措。只有了解類加載器的加載機(jī)制才能夠在出現(xiàn)異常的時(shí)候快速地根據(jù)錯誤異常日志定位問題和解決問題。

? ? ②?需要支持類的動態(tài)加載或需要對編譯后的字節(jié)碼文件進(jìn)行加解密操作時(shí),就需要與類加載器打交道了。

? ? ③?開發(fā)人員可以在程序中編寫自定義類加載器來重新定義類的加載規(guī)則,以便實(shí)現(xiàn)一些自定義的處理邏輯。

3、命名空間

(1)何為類的唯一性?

? ? 對于任意一個(gè)類,都需要由加載它的類加載器和這個(gè)類本身一同確認(rèn)其在Java虛擬機(jī)中的唯一性。每一個(gè)類加載器,都擁有一個(gè)獨(dú)立的類名稱空間:比較兩個(gè)類是否相等,只有在這兩個(gè)類是由同一個(gè)類加載器加載的前提下才有意義。否則,即使這兩個(gè)類源自同一個(gè)Class文件,被同一個(gè)虛擬機(jī)加載,只要加載他們的類加載器不同,那這兩個(gè)類就必定不相等。

//創(chuàng)建自定義類加載器1 UserClassLoader loader1 = new UserClassLoader(); Class clazz1 = loader1.findClass("com.xiang.java.User"); //創(chuàng)建自定義類加載器2 UserClassLoader loader2 = new UserClassLoader(); Class clazz2 = loader2.findClass("com.xiang.java.User");System.out.println(clazz1 == clazz2); // false clazz1與clazz2對應(yīng)了不同的類模板結(jié)構(gòu) System.out.println(clazz1.getClassLoader()); System.out.println(clazz1.getClassLoader()); // 這兩個(gè)ClassLoader的地址是不一樣的// 使用系統(tǒng)類加載器加載 Class clazz3 = ClassLoader.getSystemClassLoader().loadClass("com.xiang.java.User"); System.out.println(clazz3.getClassLoader());

(2)命名空間

? ? ①?每個(gè)類加載器都有自己的命名空間,命名空間由該加載器及所有的父加載器所加載的類組成。

? ? ②?在同一命名空間中,不會出現(xiàn)類的完整名字(包括類的包名)相同的兩個(gè)類。

? ? ③?在不同的命名空間中,有可能會出現(xiàn)類的完整名字(包括類的包名)相同的兩個(gè)類。

? ? 在大型應(yīng)用中,我們往往借助這一特性,來運(yùn)行同一個(gè)類的不同版本。

4、類加載機(jī)制的基本特征

? ? 通常類加載機(jī)制有三個(gè)基本特征:

? ? ①?雙親委派模型。但不是所有類加載都遵守這個(gè)模型,有的時(shí)候,啟動類加載器所加載的類型,是可能要加載用戶代碼的,比如JDK內(nèi)部的ServiceProvider/ServiceLoader機(jī)制,用戶可以在標(biāo)準(zhǔn)API框架上,提供自己的實(shí)現(xiàn),JDK也需要提供些默認(rèn)的參考實(shí)現(xiàn)。例如,Java中JNDI、JDBC、文件系統(tǒng)、Cipher等很多方面,都是利用的這種機(jī)制,這種情況就不會用雙親委派模型去加載,而是利用所謂的上下文加載器。

? ? ②?可見性,子類加載器可以訪問父加載器加載的類型,但是反過來是不允許的。不然,因?yàn)槿鄙俦匾母綦x,我們就沒有辦法利用類加載器去實(shí)現(xiàn)容器的邏輯。

? ? ③?單一性,由于父加載器的類型對于子加載器是可見的,所以父加載器加載過的類型,就不會在子加載器中重復(fù)加載。但是注意,類加載器“鄰居”間,同一類型仍然可以被加載多次,因?yàn)榛ハ嗖⒉豢梢姟?/p>

二、類加載器的分類

? ? JVM支持兩種類型的類加載器,分別為引導(dǎo)類加載器(Bootstrap?ClassLoader)和自定義類加載器(User-Defined?ClassLoader)。

? ? 從概念上來講,自定義類加載器一般指的是程序中由開發(fā)人員自定義的一類類加載器,但是Java虛擬機(jī)規(guī)范卻沒有這么定義,而是將所有派生于抽象類ClassLoader的類加載器都劃分為自定義類加載器。無論類加載器的類型如何劃分,在程序中我們最常見的類加載器結(jié)構(gòu)主要是如下情況:

? ? ·?除了頂層的啟動類加載器外,其余的類加載器都應(yīng)當(dāng)由自己的“父類”加載器。

? ? ·?不同類加載器看似是繼承(Inheritance)關(guān)系,實(shí)際上是包含關(guān)系。在下層加載器中,包含著上層加載器的引用。

class ClassLoader {ClassLoader parent; // 父類加載器public ClassLoader(ClassLoader parent) {this.parent = parent;} }class ParentClassLoader extends ClassLoader {public ParentClassLoader(ClassLoader parent) {super(parent);} }class ChildClassLoader extends ClassLoader {public ChildClassLoader(ClassLoader parent) { // parent = new ParentClassLoader();super(parent);} }

1、引導(dǎo)類加載器

啟動類加載器(引導(dǎo)類加載器,Bootstrap?ClassLoader)

·?這個(gè)類加載使用C/C++語言實(shí)現(xiàn)的,嵌套在JVM內(nèi)部。

·?它用來加載Java的核心庫(JAVA_HOME/jre/lib/rt.jar或sun.boot.class.path路徑下的內(nèi)容)。用于提供JVM自身需要的類。

·?并不繼承自java.lang.ClassLoader,沒有父加載器。

·?出于安全考慮,Bootstrap啟動類加載器只加載包名為java、javax、sun等開頭的類。

·?加載擴(kuò)展類和應(yīng)用程序類加載器,并指定為他們的父類加載器。

使用-XX:+TraceClassLoading參數(shù)得到:

2、擴(kuò)展類加載器

擴(kuò)展類加載器(Extension?ClassLoader)

·?Java語言編寫,由sun.misc.Launcher$ExtClassLoader實(shí)現(xiàn)。

·?繼承于ClassLoader類。

·?父類加載器為啟動類加載器。

·?從java.ext.dirs系統(tǒng)屬性所指定的目錄中加載類庫,或從JDK的安裝目錄的jre/lib/ext子目錄下加載類庫。如果用戶創(chuàng)建的JAR放在此目錄下,也會自動由擴(kuò)展類加載器加載。

// 獲取啟動類加載器、擴(kuò)展類加載器加載的路徑 import sun.misc.Launcher; import sun.security.ec.CurveDB; import java.net.URL; import java.security.Provider;public class ClassLoaderTest {public static void main(String[] args) {System.out.println("*****************啟動類加載器*****************");// 獲取BootstrapClassLoader能夠加載的api的路徑URL[] urls = Launcher.getBootstrapClassPath().getURLs();for (URL element : urls) {System.out.println(element.toExternalForm());}//從上面路徑中隨意選擇一個(gè)類,來看看他的類加載器是什么:引導(dǎo)類加載器ClassLoader classLoader = Provider.class.getClassLoader();System.out.println(classLoader); // null 為引導(dǎo)類加載器System.out.println("*****************擴(kuò)展類加載器*****************");String extDirs = System.getProperty("java.ext.dirs");for (String path : extDirs.split(";")) {System.out.println(path);}//從上面路徑中隨意選擇一個(gè)類,來看看他的類加載器是什么:擴(kuò)展類加載器ClassLoader classLoader1 = CurveDB.class.getClassLoader();System.out.println(classLoader1); // sun.misc.Launcher$ExtClassLoader@532760d8} }*****************啟動類加載器***************** file:/F:/Java/jdk1.8.0_131/jre/lib/resources.jar file:/F:/Java/jdk1.8.0_131/jre/lib/rt.jar file:/F:/Java/jdk1.8.0_131/jre/lib/sunrsasign.jar file:/F:/Java/jdk1.8.0_131/jre/lib/jsse.jar file:/F:/Java/jdk1.8.0_131/jre/lib/jce.jar file:/F:/Java/jdk1.8.0_131/jre/lib/charsets.jar file:/F:/Java/jdk1.8.0_131/jre/lib/jfr.jar file:/F:/Java/jdk1.8.0_131/jre/classes null *****************擴(kuò)展類加載器***************** F:\Java\jdk1.8.0_131\jre\lib\ext C:\Windows\Sun\Java\lib\ext sun.misc.Launcher$ExtClassLoader@532760d8

3、系統(tǒng)類加載器

應(yīng)用程序類加載器(系統(tǒng)類加載器,AppClassLoader

·?Java語言編寫,由sun.misc.Launcher$AppClassLoader實(shí)現(xiàn)。

·?繼承于ClassLoader類。

·?父類加載器為擴(kuò)展類加載器。

·?它負(fù)責(zé)加載環(huán)境變量classpath或系統(tǒng)屬性java.class.path指定路徑下的類庫。

·?應(yīng)用程序中的類加載器默認(rèn)是系統(tǒng)類加載器。

·?它是用戶自定義類加載器的默認(rèn)父加載器。

·?通過ClassLoader的getSystemClassLoader()方法可以獲取到該類加載器。

4、用戶自定義類加載器

·?在Java的日常應(yīng)用程序開發(fā)中,類的加載幾乎是由上述3種類加載器相互配合執(zhí)行的。在必要時(shí),我們還可以自定義類加載器,來定制類的加載方式。

·?體現(xiàn)Java語言強(qiáng)大生命力和巨大魅力的關(guān)鍵因素之一便是,Java開發(fā)者可以自定義類加載器來實(shí)現(xiàn)類庫的動態(tài)加載,加載源是可以本地的JAR包,也可以是網(wǎng)絡(luò)上的遠(yuǎn)程資源。

·?通過類加載器可以實(shí)現(xiàn)非常絕妙的插件機(jī)制,這方面的實(shí)際應(yīng)用案例舉不勝舉。例如,著名的OSGI組件框架,再如Eclipse的插件機(jī)制。類加載器為應(yīng)用程序提供了一種動態(tài)增加新功能的機(jī)制,這種機(jī)制無須重新打包發(fā)布應(yīng)用程序就能實(shí)現(xiàn)。

·?同時(shí),自定義加載器能夠?qū)崿F(xiàn)應(yīng)用隔離,例如?Tomcat,Spring等中間件和組件框架都在內(nèi)部實(shí)現(xiàn)了自定義的加載器,并通過自定義加載器隔離不同的組件模塊。這種機(jī)制比C/C++程序要好太多,想不修改C/C++程序就能為其新增功能,幾乎是不可能的,僅僅一個(gè)兼容性便能阻擋住所有美好的設(shè)想。

·?自定義類加載器通常需要繼承于ClassLoader。

三、測試不同的類加載器

?? ?每個(gè)Class對象都會包含一個(gè)定義它的ClassLoader的一個(gè)引用。

?? ?獲取ClassLoader的途徑:

? ? ·?獲得當(dāng)前類的ClassLoader:clazz.getClassLoader()

? ? ·?獲得當(dāng)前線程上下文的ClassLoader:Thread.currentThread().getContextClassLoader()

? ? ·?獲得系統(tǒng)的ClassLoader:ClassLoader.getSystemClassLoader()

說明:

? ? 站在程序的角度看,引導(dǎo)類加載器與另外兩種類加載器(系統(tǒng)類加載器和擴(kuò)展類加載器)并不是同一個(gè)層次意義上的加載器,引導(dǎo)類加載器是使用C++語言編寫而成的,而另外兩種類加載器則是使用Java語言編寫而成的。由于引導(dǎo)類加載器壓根兒就不是一個(gè)Java類,因此在Java程序中只能打印出空值。

? ? 數(shù)組類的Class對象,不是由類加載器去創(chuàng)建的,而是在Java運(yùn)行期JVM根據(jù)需要自動創(chuàng)建的。對于數(shù)組類的類加載器來說,是通過Class.getClassLoader()返回的,與數(shù)組當(dāng)中元素類型的類加載器是一樣的;如果數(shù)組當(dāng)中的元素類型是基本數(shù)據(jù)類型,數(shù)組類是沒有類加載器的。

public class ClassLoaderTest1 {public static void main(String[] args) throws ClassNotFoundException {// 獲取系統(tǒng)類加載器ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();System.out.println(systemClassLoader); // sun.misc.Launcher$AppClassLoader@18b4aac2// 獲取擴(kuò)展類加載器ClassLoader extClassLoader = systemClassLoader.getParent();System.out.println(extClassLoader); // sun.misc.Launcher$ExtClassLoader@277c0f21// 獲取引導(dǎo)類加載器ClassLoader bootstrapClassLoader = extClassLoader.getParent();System.out.println(bootstrapClassLoader); // null// 獲取指定類的加載器ClassLoader classLoader = Class.forName("java.lang.String").getClassLoader();System.out.println(classLoader); // null// 自定義的類默認(rèn)是系統(tǒng)類加載器ClassLoader classLoader1 = ClassLoaderTest1.class.getClassLoader();System.out.println(classLoader1); // sun.misc.Launcher$AppClassLoader@18b4aac2// 關(guān)于數(shù)組的加載,與數(shù)組當(dāng)中元素類型的類加載器是一樣的String[] arrStr = new String[10];System.out.println(arrStr.getClass()); // class [Ljava.lang.String;System.out.println(arrStr.getClass().getClassLoader()); // null,表示使用的是引導(dǎo)類加載器ClassLoaderTest1[] arr1 = new ClassLoaderTest1[10];System.out.println(arr1.getClass().getClassLoader()); // sun.misc.Launcher$AppClassLoader@18b4aac2//基本數(shù)據(jù)類型,不需要加載的,這個(gè)null并不是用了引導(dǎo)類加載器,而是沒有類加載器int[] arr2 = new int[10];System.out.println(arr2.getClass().getClassLoader());// null// 線程上下文的類加載器System.out.println(Thread.currentThread().getContextClassLoader());// sun.misc.Launcher$AppClassLoader@18b4aac2} }

四、ClassLoader源碼解析

ClassLoader與現(xiàn)有類加載器的關(guān)系:

? ? 除了以上虛擬機(jī)自帶的加載器外,用戶還可以定制自己的類加載器。Java提供了抽象類java.lang.ClassLoader,所有用戶自定義的類加載器都應(yīng)該繼承ClassLoader類。

?

?

1、抽象類ClassLoader的主要方法:(內(nèi)部沒有抽象方法)

(1)public final ClassLoader getParent()

? ? 返回該類加載器的超類加載器。

(2)public Class<?> loadClass(String name) throws ClassNotFoundException

? ? 加載名稱為name的類,返回結(jié)果為java.lang.Class類的實(shí)例。如果找不到類,則返回ClassNotFoundException異常。該方法中的邏輯就是雙親委派模式的實(shí)現(xiàn)。

protected Class<?> loadClass(String name, boolean resolve) // resolve為true時(shí),加載class的同時(shí)進(jìn)行解析操作,默認(rèn)為falsethrows ClassNotFoundException {synchronized (getClassLoadingLock(name)) { // 同步操作,保證只能加載一次// 首先,在緩存中判斷是否已經(jīng)加載同名的類。Class<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {// 獲取當(dāng)前類加載器的父類加載器if (parent != null) {// 如果存在父類加載器,則調(diào)用父類加載器,進(jìn)行類加載(進(jìn)行遞歸)。(雙親委派機(jī)制)c = parent.loadClass(name, false);} else { // parent == null ,父類加載器是引導(dǎo)類加載器c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c == null) { // 當(dāng)前類的加載器的父類加載器未加載此類 or 當(dāng)前類的加載器未加載此類// 調(diào)用當(dāng)前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) { // 是否進(jìn)行解析操作resolveClass(c);}return c;} }

(3)protected Class<?> findClass(String name) throws ClassNotFoundException

? ? 查找二進(jìn)制名稱為name的類,返回結(jié)果為java.lang.Class類的實(shí)例。這是一個(gè)受保護(hù)的方法,JVM鼓勵我們重寫此方法,需要自定義加載器遵循雙親委托機(jī)制,該方法會在檢查完父類加載器之后被loadClass()方法調(diào)用。

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

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

// ClassLoader類中的findClass方法直接拋出異常。 protected Class<?> findClass(String name) throws ClassNotFoundException {throw new ClassNotFoundException(name); }// 在URLClassLoader類中重寫了findClass方法。 protected Class<?> findClass(final String name)throws ClassNotFoundException {final Class<?> result;try {result = AccessController.doPrivileged(new PrivilegedExceptionAction<Class<?>>() {public Class<?> run() throws ClassNotFoundException {String path = name.replace('.', '/').concat(".class");Resource res = ucp.getResource(path, false);if (res != null) {try {return defineClass(name, res);} catch (IOException e) {throw new ClassNotFoundException(name, e);}} else {return null;}}}, acc);} catch (java.security.PrivilegedActionException pae) {throw (ClassNotFoundException) pae.getException();}if (result == null) {throw new ClassNotFoundException(name);}return result; }

(4)protected final Class<?> defineClass(byte[] b, int off, int len)

? ? 根據(jù)給定的字節(jié)數(shù)組b轉(zhuǎn)換為Class的實(shí)例,off和len參數(shù)表示實(shí)際Class信息在byte數(shù)組中的位置和長度,其中byte數(shù)組b是ClassLoader從外部獲取的。這是受保護(hù)的方法,只有在自定義ClassLoader子類中可以使用。

? ? defineClass()方法是用來將byte字節(jié)流解析成JVM能夠識別的Class對象(ClassLoader中已實(shí)現(xiàn)該方法邏輯),通過這個(gè)方法不僅能夠通過class文件實(shí)例化class對象,也可以通過其他方式實(shí)例化class對象,如通過網(wǎng)絡(luò)接收一個(gè)類的字節(jié)碼,然后轉(zhuǎn)換為byte字節(jié)流創(chuàng)建對應(yīng)的Class對象。

? ? defineClass()方法通常與findClass()方法一起使用,一般情況下,在自定義類加載器時(shí),會直接覆蓋ClassLoader的findClass()方法并編寫加載規(guī)則,取得要加載類的字節(jié)碼后轉(zhuǎn)換成流,然后調(diào)用defineClass()方法生成類的Class對象

簡單舉例:

protected Class<?> findClass(String name) throws ClassNotFoundException {// 獲取類的字節(jié)數(shù)組byte[] classData = getClassDate(name);if(classData == null) {throw new ClassNotFoundException();} else {//使用defineClass生成class對象return defineClass(name, classData, 0, classData.length); } }

(5)protected final void resolveClass(Class<?> c)

? ? 鏈接指定的一個(gè)Java類。使用該方法可以使用類的Class對象創(chuàng)建完成的同時(shí)也被解析。前面我們說鏈接階段主要是對字節(jié)碼進(jìn)行驗(yàn)證,為類變量分配內(nèi)存并設(shè)置初始值同時(shí)將字節(jié)碼文件中的符號引用轉(zhuǎn)換為直接引用。

(6)protected final Class<?> findLoadedClass(String name)

? ? 查找名稱為name的已經(jīng)被加載過的類,返回結(jié)果為java.lang.Class類的實(shí)例。這個(gè)方法是final方法,無法被修改。

(7)private?final?ClassLoader?parent;

? ? 它也是一個(gè)ClassLoader的實(shí)例,這個(gè)字段所表示的ClassLoader也稱為這個(gè)ClassLoader的雙親。在類加載的過程中,ClassLoader可能會將某些請求交予自己的雙親處理。

2、SecureClassLoader?與?URLClassLoader

? ? 接著SecureClassLoader擴(kuò)展了ClassLoader,新增了幾個(gè)與使用相關(guān)的代碼源(對代碼源的位置及其證書的驗(yàn)證)和權(quán)限定義類驗(yàn)證(主要指對class源碼的訪問權(quán)限)的方法,一般我們不會直接跟這個(gè)類打交道,更多的是與它的子類URLClassLoader有所關(guān)聯(lián)。

? ? 前面說過,ClassLoader是一個(gè)抽象類,很多方法是空的沒有實(shí)現(xiàn),比如findClass()、findResource()等。而URLClassLoader這個(gè)實(shí)現(xiàn)類為這些方法提供了具體的實(shí)現(xiàn)。并新增了URLClassPath類協(xié)助取得Class字節(jié)碼流等功能。在編寫自定義類加載器時(shí),如果沒有太過于復(fù)雜的需求,可以直接繼承URLClassLoader類,這樣就可以避免自己去編寫findClass()方法及其獲取字節(jié)碼流的方式,使自定義類加載器編寫更加簡潔

3、ExtClassLoader?與?AppClassLoader

? ? 這兩個(gè)類都繼承自URLClassLoader,是sun.misc.Launcher的靜態(tài)內(nèi)部類。sun.misc.Launcher主要被系統(tǒng)用于啟動主應(yīng)用程序,ExtClassLoader和AppClassLoader都是由sun.misc.Launcher創(chuàng)建的,其類主要類結(jié)構(gòu)如下:

?

? ? 我們發(fā)現(xiàn)ExtClassLoader并沒有重寫loadClass()方法,這足以說明其遵循雙親委派模式,而AppClassLoader重載了loadClass()方法,但最終調(diào)用的還是父類loadClass()方法,因此依然遵守雙親委派模式。

4、Class.forName()?與ClassLoader.loadClass()

· Class.forName():是一個(gè)靜態(tài)方法,最常用的是Class.forName(String className);根據(jù)傳入的類的全限定名返回一個(gè)Class對象。該方法在將Class文件加載到內(nèi)存的同時(shí),會執(zhí)行類的初始化

·?ClassLoader.loadClass():這是一個(gè)實(shí)例方法,需要一個(gè)ClassLoader對象來調(diào)用該方法。該方法將Class文件加載到內(nèi)存時(shí),并不會執(zhí)行類的初始化,直到這個(gè)類第一次使用時(shí)才進(jìn)行初始化。該方法因?yàn)樾枰玫揭粋€(gè)ClassLoader對象,所以可以根據(jù)需要指定使用哪個(gè)類加載器。

五、雙親委派模型

1、定義與本質(zhì)

? ? 類加載器用來把類加載到Java虛擬機(jī)中。從JDK1.2版本開始,類的加載過程采用雙親委派機(jī)制,這種機(jī)制能更好地保證Java平臺的安全。

?? ?定義:如果一個(gè)類加載器在接到加載類的請求時(shí),它首先不會自己嘗試去加載這個(gè)類,而是把這個(gè)請求任務(wù)委托給父類加載器去完成,依次遞歸,如果父類加載器可以完成類加載任務(wù),就成功返回。只有父類加載器無法完成此加載任務(wù)時(shí),才自己去加載。

? ? 本質(zhì):規(guī)定了類加載的順序是:引導(dǎo)類加載器先加載,若加載不到,由擴(kuò)展類加載器加載,若還加載不到,才會由系統(tǒng)類加載器或自定義的類加載器進(jìn)行加載。

?

2、優(yōu)勢與劣勢

(1)雙親委派機(jī)制優(yōu)勢

① 避免類的重復(fù)加載,確保一個(gè)類的全局唯一性。

? ? Java類隨著它的類加載器一起具備了一種帶有優(yōu)先級的層次關(guān)系,通過這種層級關(guān)系可以避免類的重復(fù)加載,當(dāng)父親已經(jīng)加載了該類,就沒有必要子ClassLoader再加載一次

② 保護(hù)程序安全,防止核心API被隨意篡改。

(2)代碼支持

? ? 雙親委派機(jī)制在java.lang.ClassLoader.loadClass(String, boolean)方法中體現(xiàn)。該方法的邏輯如下:

①?先在當(dāng)前加載器的緩存中查找有無目標(biāo)類,如果有,直接返回。

②?判斷當(dāng)前加載器的父加載器是否為空,如果不為空,則調(diào)用parent.loadClass(name, false)方法進(jìn)行加載。

③?反之,如果當(dāng)前加載器的父類加載器為空,則調(diào)用findBootstrapClassOrNull(name)方法,讓引導(dǎo)類加載器進(jìn)行加載。

④?如果通過以上3條路徑都沒能成功加載,則調(diào)用findClass(name)方法進(jìn)行加載。該接口最終會調(diào)用java.lang.ClassLoader方法的defineClass系列的native方法加載目標(biāo)Java類。

? ? 雙親委派的模型就隱藏在這第2和第3步中。

(3)舉例

? ? 假設(shè)當(dāng)前加載的是java.lang.Object這個(gè)類,很顯然,該類屬于JDK中核心類,因此一定只能由引導(dǎo)類加載器進(jìn)行加載。

? ? 當(dāng)JVM準(zhǔn)備加載java.lang.Object時(shí),JVM默認(rèn)會使用系統(tǒng)類加載器去加載,按照上面4步加載的邏輯,在第1步從系統(tǒng)類的緩存中肯定查找不到該類,于是進(jìn)入第2步。由于系統(tǒng)類加載器的父加載器是擴(kuò)展類加載器,于是擴(kuò)展類加載器繼續(xù)從第1步開始重復(fù)。由于擴(kuò)展類加載器的緩存中也一定查找不到該類,因此進(jìn)入第2步。擴(kuò)展類的父加載器是null,因此系統(tǒng)調(diào)用findClass(String),最終通過引導(dǎo)類加載器進(jìn)行加載。

(4)思考

? ? 如果在自定義的類加載器中重寫java.lang.ClassLoader.loadClass(String)或java.lang.ClassLoader.loadClass(String, boolean)方法,抹去其中的雙親委派機(jī)制,僅保留上面這4步中的第1步與第4步,那么是不是就能夠加載核心類庫了呢?

? ? 這也不行!因?yàn)镴DK還未核心類庫提供了一層保護(hù)機(jī)制。不管是自定義的類加載器,還是系統(tǒng)類加載器亦或擴(kuò)展類加載器,最終都必須調(diào)用java.lang.ClassLoader.defineClass(String, byte[], int, int, ProtectionDomain)方法,而該方法會執(zhí)行preDefineClass()方法,該方法中提供了對JDK核心類庫的保護(hù)。

(5)雙親委托模式的弊端

? ? 檢查類是否加載的委托過程是單向的,這個(gè)方式雖然從結(jié)構(gòu)上說比較清晰,使各個(gè)ClassLoader的職責(zé)非常明確,但是同時(shí)會帶來一個(gè)問題,即頂層的ClassLoader無法訪問底層的ClassLoader所加載的類。

? ? 通常情況下,啟動類加載器中的類為系統(tǒng)核心類,包括一些重要的系統(tǒng)接口,而在應(yīng)用類加載器中,為應(yīng)用類。按照這種模式,應(yīng)用類訪問系統(tǒng)類自然是沒有問題,但是系統(tǒng)類訪問應(yīng)用類就會出現(xiàn)問題。比如在系統(tǒng)類中提供了一個(gè)接口,該接口需要在應(yīng)用類中得以實(shí)現(xiàn),該接口還綁定一個(gè)工廠方法,用于創(chuàng)建該接口的實(shí)例,而接口和工廠方法都在啟動類加載器中。這時(shí),就會出現(xiàn)該工廠方法無法創(chuàng)建由應(yīng)用類加載器加載的應(yīng)用實(shí)例的問題。

(6)結(jié)論

? ? 由于Java虛擬機(jī)規(guī)范并沒有明確要求類加載器的加載機(jī)制一定要使用雙親委派模型,知識建議采用這種方式而已

? ? 比如在Tomcat中,類加載器所采用的加載機(jī)制就和傳統(tǒng)的雙親委派模型有一定區(qū)別,當(dāng)缺省的類加載器接收到一個(gè)類的加載任務(wù)時(shí),首先會由它自行加載,當(dāng)它加載失敗時(shí),才會將類的加載任務(wù)委派給它的超類加載器去執(zhí)行,這同時(shí)也是Servlet規(guī)范推薦的一種做法。

3、破壞雙親委派機(jī)制

? ? 雙親委派模型并不是一個(gè)具有強(qiáng)制性約束的模型,而是Java設(shè)計(jì)者推薦給開發(fā)者們的類加載器實(shí)現(xiàn)方式

? ? 在Java的世界中大部分的類加載器都遵循這個(gè)模型,但也有例外的情況,直到Java模塊化出現(xiàn)為止,雙親委派模型主要出現(xiàn)過3次較大規(guī)模“被破壞”的情況。

(1)破壞雙親委派機(jī)制1

? ??

? ? 第一次破壞雙親委派機(jī)制:

? ? 雙親委派模型的第一次“被破壞”其實(shí)發(fā)生在雙親委派模型出現(xiàn)之前——即JDK1.2面世以前的“遠(yuǎn)古”時(shí)代。

? ? 由于雙親委派模型在JDK1.2之后才被引入,但是類加載器的概念和抽象類java.lang.ClassLoader則在Java的第一個(gè)版本中就已經(jīng)存在,面對已經(jīng)存在的用戶自定義類加載器的代碼,Java設(shè)計(jì)者們引入雙親委派模型時(shí)不得不作出一些妥協(xié),為了兼容這些已有代碼,無法再以技術(shù)手段避免loadClass()被子類覆蓋的可能性,只能在JDK1.2之后的java.lang.ClassLoader中添加一個(gè)新的protected方法findClass(),并引導(dǎo)用戶編寫的類加載邏輯盡可能去重寫這個(gè)方法,而不是在loadClass()中編寫代碼。上面我們已經(jīng)分析過loadClass()方法,雙親委派的具體邏輯就實(shí)現(xiàn)在這里面,按照loadClass()方法的邏輯,如果父類加載失敗,會自動調(diào)用自己的findClass()方法來完成加載,這樣既不影響用戶按照自己的意愿去加載類,又可以保證新寫出來的類加載器是符合雙親委派規(guī)則的。

(2)破壞雙親委派機(jī)制2

? ? 第二次破壞雙親委派機(jī)制:線程上下文類加載器。

? ? 雙親委派模型的第二次“被破壞”是由這個(gè)模型自身的缺陷導(dǎo)致的,雙親委派很好地解決了各個(gè)類加載器協(xié)作時(shí)基礎(chǔ)類型的一致性問題(越基礎(chǔ)的類越上層的加載器進(jìn)行加載),基礎(chǔ)類型之所以被稱為“基礎(chǔ)”,是因?yàn)樗鼈兛偸亲鳛楸挥脩舸a繼承、調(diào)用的API存在,但程序設(shè)計(jì)往往沒有絕對不變的完美規(guī)則,如果有基礎(chǔ)類型又要調(diào)用會用戶的代碼,那該怎么辦呢

? ? 這并非是不可能出現(xiàn)的事情,一個(gè)典型的例子便是JNDI服務(wù),JDNI現(xiàn)在已經(jīng)是Java的標(biāo)準(zhǔn)服務(wù),它的代碼由啟動類加載器來完成加載(在JDK1.3時(shí)加入到rt.jar的),肯定屬于Java中很基礎(chǔ)的類型了。但JNDI存在的目的就是對資源進(jìn)行查找和集中管理,它需要調(diào)用由其他廠商實(shí)現(xiàn)并部署在應(yīng)用程序的ClassPath下的JNDI服務(wù)提供接口(Service?Provider?Interface,?SPI)的代碼,現(xiàn)在問題來了,啟動類加載器是絕不可能認(rèn)識、加載這些代碼的,那該怎么辦?(SPI:在Java平臺中,通常把核心類rt.jar中提供外部服務(wù)、可由應(yīng)用層自行實(shí)現(xiàn)的接口稱為SPI)

? ? 為了解決這個(gè)困境,Java的設(shè)計(jì)團(tuán)隊(duì)只好引入了一個(gè)不太優(yōu)雅的設(shè)計(jì):線程上下文類加載器(Thread?Context?ClassLoader)。這個(gè)類加載器可以通過java.lang.Thread類的setContextClassLoader()方法進(jìn)行設(shè)置,如果創(chuàng)建線程時(shí)還未設(shè)置,它將會從父線程中繼承一個(gè),如果在應(yīng)用程序的全局范圍內(nèi)都沒有設(shè)置過的話,那這個(gè)類加載器默認(rèn)就是應(yīng)用程序類加載器。

? ? 有了線程上下文類加載器,程序就可以做一些“舞弊”的事情了。JNDI服務(wù)使用這個(gè)線程上下文類加載器去加載所需的SPI服務(wù)代碼,這是一種父類加載器去請求子類加載器完成類加載的行為,這種行為實(shí)際上是打通了雙親委派模型的層次結(jié)構(gòu)來逆向使用類加載器,已經(jīng)違背了雙親委派模型的一般性原則,但也是無可奈何的事情。Java中涉及SPI的加載基本上都采用這種方式來完成,例如JNDI、JDBC、JCE、JAXB和JBI等。不過,當(dāng)SPI的服務(wù)提供者多于一個(gè)的時(shí)候,代碼就只能根據(jù)具體提供者的類型來硬編碼判斷,為了消除這種極不優(yōu)雅的實(shí)現(xiàn)方式,在JDK6時(shí),JDK提供了java.util.ServiceLoader類,以META-INF/services中的配置信息,輔以責(zé)任鏈模式,這才算是給SPI的加載提供了一種相對合理的解決方案。

? ? 默認(rèn)上下文加載器就是應(yīng)用類加載器,這樣以上下文加載器為中介,使得啟動類加載器中的代碼也可以訪問應(yīng)用類加載器中的類。

(3)破壞雙親委派機(jī)制3

? ? 第三次破壞雙親委派機(jī)制:

? ? 雙親委派模型的第三次“被破壞”是由于用戶對程序動態(tài)性的追求而導(dǎo)致的。如:代碼熱替換(Hot?Swap)、模塊熱部署(Hot?Deployment)等

? ? IBM公司主導(dǎo)的JSR-291(即OSGi?R4.2)實(shí)現(xiàn)模塊化熱部署的關(guān)鍵是它自定義的類加載器機(jī)制的實(shí)現(xiàn),每一個(gè)程序模塊(OSGi中稱為Bundle)都有一個(gè)自己的類加載器,當(dāng)需要更換一個(gè)Bundle時(shí),就把Bundle連同類加載器一起換掉以實(shí)現(xiàn)代碼的熱替換。在OSGi環(huán)境下,類加載器不再雙親委派模型推薦的樹狀結(jié)構(gòu),而是進(jìn)一步發(fā)展為更加復(fù)雜的網(wǎng)絡(luò)結(jié)構(gòu)。

? ? 當(dāng)收到類加載請求時(shí),OSGi將按照下面的順序進(jìn)行類搜索:

①?將以java.*開頭的類,委派給父類加載器加載。

②?否則,將委派列表名單內(nèi)的類,委派給父類加載器加載。

③?否則,將Import列表中的類,委派給Export這個(gè)類的Bundle的類加載器加載。

④?否則,查找當(dāng)前Bundle的ClassPath,使用自己的類加載器加載。

⑤?否則,查找類是否在自己的Fragment?Bundle中,如果在,則委派給Fragment?Bundle的類加載器加載。

⑥?否則,查找Dynamic?Import列表的Bundle,委派給對應(yīng)的Bundle的類加載器加載。

⑦?否則,類查找失敗。

? ? 說明:只有開頭兩點(diǎn)仍然符合雙親委派模型的原則,其余的類查找都是在平級的類加載器中進(jìn)行的。

? ? 小結(jié):這里,我們使用了“被破壞”這個(gè)詞來形容上述不符合雙親委派模型原則的行為,但這里“被破壞”并不一定是帶有貶義的。只要有明確的目的和充分的理由,突破舊有原則無疑是一種創(chuàng)新

? ? 正如:OSGi中的類加載器的設(shè)計(jì)不符合傳統(tǒng)的雙親委派的類加載器架構(gòu),且業(yè)界對其為了實(shí)現(xiàn)熱部署而帶來的額外的高復(fù)雜度還存在不少爭議,但對這方面有了解的技術(shù)人員基本還是能達(dá)成一個(gè)共識,認(rèn)為OSGi中對類加載器的運(yùn)用是值得學(xué)習(xí)的,完全弄懂了OSGi的實(shí)現(xiàn),就算是掌握了類加載器的精髓

?? ?

4、熱替換的實(shí)現(xiàn)

? ? 熱替換是指在程序的運(yùn)行過程中,不停止服務(wù),只通過替換程序文件來修改程序的行為。熱替換的關(guān)鍵需求在于服務(wù)不能中斷,修改必須立即表現(xiàn)正在運(yùn)行的系統(tǒng)之中。基本上大部分腳本語言都是天生支持熱替換的,比如:PHP,只要替換了PHP源文件,這種改動就會立即生效,而無需重啟Web服務(wù)器。

? ? 但對Java來說,熱替換并非天生就支持,如果一個(gè)類已經(jīng)加載到系統(tǒng)中,通過修改類文件,并無法讓系統(tǒng)再來加載并重定義這個(gè)類。因此,在Java中實(shí)現(xiàn)這一功能的一個(gè)可行的方法就是靈活運(yùn)用ClassLoader。

? ? 注意:由不同ClassLoader加載的同名類屬于不同的類型,不能相互轉(zhuǎn)換和兼容。即兩個(gè)不同的ClassLoader加載同一個(gè)類,在虛擬機(jī)內(nèi)部,會認(rèn)為這2個(gè)類是完全不同的。

? ? 根據(jù)這個(gè)特點(diǎn),可以用來模擬熱替換的實(shí)現(xiàn),基本思路如下圖所示:

import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.WritableByteChannel; /** * 自定義類加載器 */ public class MyClassLoader extends ClassLoader {private String rootDir;public MyClassLoader(String rootDir) {this.rootDir = rootDir;}@Overrideprotected Class<?> findClass(String className) throws ClassNotFoundException {Class clazz = this.findLoadedClass(className);FileChannel fileChannel = null;WritableByteChannel outChannel = null;if(null == clazz) {try {String classFile = getClassFile(className);FileInputStream fis = new FileInputStream(classFile);fileChannel = fis.getChannel();ByteArrayOutputStream baos = new ByteArrayOutputStream();outChannel = Channels.newChannel(baos);ByteBuffer buffer = ByteBuffer.allocateDirect(1024);while (true) {int i = fileChannel.read(buffer);if(i == 0 || i == -1){break;}buffer.flip();outChannel.write(buffer);buffer.clear();}byte[] bytes = baos.toByteArray();clazz = defineClass(className, bytes, 0, bytes.length);} catch (FileNotFoundException e){e.printStackTrace();} catch (IOException e){e.printStackTrace();}try {if(outChannel != null) outChannel.close();} catch (IOException e) {e.printStackTrace();}}return clazz;}/*** 類文件的完全路徑*/private String getClassFile(String className) {return rootDir + "\\" + className.replace('.', '\\') + ".class";} }public class Demo1 {public void hot(){System.out.println("OldDemo1-- > newDemo1");} }import java.lang.reflect.Method; /** * 熱部署實(shí)例,修改Demo1之后重新編譯,就會自動調(diào)用新Demo1的方法 */ public class HotBushu {public static void main(String[] args) {while (true) {// 每隔5秒鐘獲取一次類try {// 1.創(chuàng)建自定義類加載器MyClassLoader loader = new MyClassLoader("E:\\target\\classes");// 2.加載指定的類Class clazz = loader.findClass("com.myUtils.test.classloaderTest.Demo1");// 3.創(chuàng)建運(yùn)行時(shí)類的實(shí)例Object demo = clazz.newInstance();// 4.調(diào)用hot方法Method m = clazz.getMethod("hot");m.invoke(demo);Thread.sleep(5000);} catch (Exception e) {System.out.println("not find");try {Thread.sleep(5000);} catch (InterruptedException ex) {ex.printStackTrace();}}}} }

六、沙箱安全機(jī)制

·?保證程序安全

·?保護(hù)Java原生的JDK代碼

?? ?Java安全模型的核心就是Java沙箱(sandbox)。什么是沙箱?沙箱是一個(gè)限制程序運(yùn)行的環(huán)境。

? ? 沙箱機(jī)制就是將Java代碼限定在虛擬機(jī)(JVM)特定的運(yùn)行范圍中,并且嚴(yán)格限制代碼對本地系統(tǒng)資源訪問。通過這樣的措施來保證對代碼的有限隔離,防止對本地系統(tǒng)造成破壞。

? ? 沙箱主要限制系統(tǒng)資源訪問,那系統(tǒng)資源包括什么?CPU、內(nèi)存、文件系統(tǒng)、網(wǎng)絡(luò)。不同級別的沙箱對這些資源訪問的限制也可以不一樣。

? ? 所有的Java程序運(yùn)行都可以指定沙箱,可以定制安全策略。

1、JDK1.0時(shí)期

? ? 在Java中將執(zhí)行程序分成本地代碼和遠(yuǎn)程代碼兩種,本地代碼默認(rèn)視為可信任的,而遠(yuǎn)程代碼則被看作是不受信的。對于受信的本地代碼,可以訪問一切本地資源。而對于非授信的遠(yuǎn)程代碼在早期的Java實(shí)現(xiàn)中,完全依賴于沙箱(Sandbox)機(jī)制。如下圖所示JDK1.0安全模型。

2、JDK1.1時(shí)期

? ? JDK1.0中如此嚴(yán)格的安全機(jī)制也給程序的功能擴(kuò)展帶來障礙,比如當(dāng)用戶希望遠(yuǎn)程代碼訪問本地系統(tǒng)的文件時(shí)候,就無法實(shí)現(xiàn)。

? ? 因此在后續(xù)的Java1.1版本中,針對安全機(jī)制做了改進(jìn),增加了安全策略。允許用戶指定代碼對本地資源的訪問權(quán)限。如下圖所示JDK1.1安全模型。

3、JDK1.2時(shí)期

? ? 在Java1.2版本中,再次改進(jìn)了安全機(jī)制,增加了代碼簽名。不論本地代碼或是遠(yuǎn)程代碼,都會按照用戶的安全策略設(shè)定,由類加載器加載到虛擬機(jī)中權(quán)限不同的運(yùn)行空間,來實(shí)現(xiàn)差異化的代碼執(zhí)行權(quán)限控制。如下圖所示JDK1.2安全模型。

4、JDK1.6時(shí)期

? ? 當(dāng)前最新的安全機(jī)制實(shí)現(xiàn),則引入了域(Domain)的概念。

? ? 虛擬機(jī)會把所有代碼加載到不同的系統(tǒng)域和應(yīng)用域。系統(tǒng)域部分專門負(fù)責(zé)與關(guān)鍵資源進(jìn)行交互,而各個(gè)應(yīng)用域部分則通過系統(tǒng)域的部分代理來對各種需要的資源進(jìn)行訪問。虛擬機(jī)中不同的受保護(hù)域(Protected?Domain),對應(yīng)不一樣的權(quán)限(Permission)。存在于不同域中的類文件就具有了當(dāng)前域的全部權(quán)限,如下圖所示,最新的安全模型(JDK1.6)

七、自定義類的加載器

1、為什么要自定義類加載器?

(1)隔離加載類

? ? 在某些框架內(nèi)進(jìn)行中間件與應(yīng)用的模塊隔離,把類加載到不同的環(huán)境。比如:阿里內(nèi)某容器框架通過自定義類加載器確保應(yīng)用中依賴的jar包不會影響到中間件運(yùn)行時(shí)使用的jar包。再比如:Tomcat這類Web應(yīng)用服務(wù)器,內(nèi)部自定義了好幾種類加載器,用于隔離同一個(gè)Web應(yīng)用服務(wù)器上的不同應(yīng)用程序。

(2)修改類加載的方式

? ? 類的加載模型并非強(qiáng)制,除Bootstrap外,其他的加載并非一定要引入,或者根據(jù)實(shí)際情況在某個(gè)時(shí)間點(diǎn)進(jìn)行按需進(jìn)行動態(tài)加載。

(3)擴(kuò)展加載源

? ? 比如從數(shù)據(jù)庫、網(wǎng)絡(luò)、甚至是電視機(jī)機(jī)頂盒進(jìn)行加載。

(4)防止源碼泄漏

? ? Java代碼容易被編譯和篡改,可以進(jìn)行編譯加密。那么類加載也需要自定義,還原加密的字節(jié)碼。

2、常見的場景

(1)實(shí)現(xiàn)類似進(jìn)程內(nèi)隔離,類加載器實(shí)際上用作不同的命名空間,以提供類似容器、模塊化的效果。例如,兩個(gè)模塊依賴于某個(gè)類庫的不同版本,如果分別被不同的容器加載,就可以互不干擾。這個(gè)方面的集大成者是Java?EE和OSGi、JPMS等框架。

(2)應(yīng)用需要從不同的數(shù)據(jù)源獲取類定義信息,例如網(wǎng)絡(luò)數(shù)據(jù)源,而不是本地文件系統(tǒng)。或者是需要自己操縱字節(jié)碼,動態(tài)修改或者生成類型。

3、注意

? ? 在一般情況下,使用不同的類加載器去加載不同的功能模塊,會提高應(yīng)用程序的安全性。但是,如果涉及Java類型轉(zhuǎn)換,則加載器反而容易產(chǎn)生不美好的事情。在做Java類型轉(zhuǎn)換時(shí),只有兩個(gè)類型都是由同一個(gè)加載器所加載,才能進(jìn)行類型轉(zhuǎn)換,否則轉(zhuǎn)換時(shí)會發(fā)生異常。

4、實(shí)現(xiàn)方式

?? ?用戶通過定制自己的類加載器,這樣可以重新定義類的加載規(guī)則,以便實(shí)現(xiàn)一些自定義的處理邏輯。

(1)實(shí)現(xiàn)方式

? ? Java提供了抽象類java.lang.ClassLoader,所有用戶自定義的類加載器都應(yīng)該繼承ClassLoader類。

? ? 在自定義ClassLoader的子類的時(shí)候,我們常見的會有兩種做法:

? ? ①?方式一:重寫loadClass()方法

? ? ②?方式二:重寫findClass()方法

(2)對比

? ? 這兩種方法本質(zhì)上差不多,畢竟loadClass()也會調(diào)用findClass(),但是從邏輯上講我們最好不要直接修改loadClass()的內(nèi)部邏輯。建議的做法是只在findClass()里重寫自定義類的加載方法,根據(jù)參數(shù)指定類的名字,返回對應(yīng)的Class對象的引用。

? ? loadClass()方法是實(shí)現(xiàn)雙親委派模型邏輯的地方,擅自修改這個(gè)方法會導(dǎo)致模型被破壞,容易造成問題。因此我們最好是在雙親委派模型框架內(nèi)進(jìn)行小范圍的改動,不破壞原有的穩(wěn)定結(jié)構(gòu)。同時(shí),也避免了自己重寫loadClass()方法的過程中必須寫雙親委托的重復(fù)代碼,從代碼的復(fù)用性來看,不直接修改這個(gè)方法始終是比較好的選擇。

? ? 當(dāng)編寫好自定義類加載器后,便可以在程序中調(diào)用loadClass()方法來實(shí)現(xiàn)類的加載操作。

import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException;/** * 自定義類加載器2 */ public class MyClassLoader2 extends ClassLoader {private String rootDir;public MyClassLoader2(String rootDir) {this.rootDir = rootDir;}public MyClassLoader2(ClassLoader parent, String rootDir) {super(parent);this.rootDir = rootDir;}@Overrideprotected Class<?> findClass(String className) throws ClassNotFoundException {BufferedInputStream bis = null;ByteArrayOutputStream baos = null;try {// 獲取字節(jié)碼文件的完整路徑String fileName = getClassFile(className);// 獲取輸入流bis = new BufferedInputStream(new FileInputStream(fileName));// 獲取輸出流baos = new ByteArrayOutputStream();// 具體讀入數(shù)據(jù)、寫出數(shù)據(jù)int len;byte[] data = new byte[1024];while((len = bis.read(data)) != -1) {baos.write(data, 0, len);}// 獲取內(nèi)存中完整的字節(jié)數(shù)組數(shù)據(jù)byte[] byteCodes = baos.toByteArray();// 調(diào)用defineClass,將字節(jié)數(shù)組數(shù)據(jù)轉(zhuǎn)換為Class實(shí)例return defineClass(null, byteCodes, 0, byteCodes.length);} catch (IOException e) {e.printStackTrace();} finally {try {if(baos != null) {baos.close();}if(bis != null) {bis.close();}} catch (IOException e) {e.printStackTrace();}}return null;}/*** 類文件的完全路徑*/private String getClassFile(String className) {return rootDir + "\\" + className.replace('.', '\\') + ".class";}public static void main(String[] args) throws ClassNotFoundException {MyClassLoader2 loader = new MyClassLoader2("E:\\");Class clazz = loader.findClass("com.myUtils.test.classloaderTest.Demo1");System.out.println("此class的類加載器為:" + clazz.getClassLoader());System.out.println("此class的類加載器父類為:" + clazz.getClassLoader().getParent());} }此class的類加載器為:com.myUtils.test.classloaderTest.MyClassLoader2@277c0f21 此class的類加載器父類為:sun.misc.Launcher$AppClassLoader@18b4aac2

八、java9新特性

?? ?為了保證兼容性,JDK9沒有從根本上改變?nèi)龑宇惣虞d器架構(gòu)和雙親委派模型,但為了模塊化系統(tǒng)的順利運(yùn)行,仍然發(fā)生了一些值得被注意的變動。

1、擴(kuò)展機(jī)制被移除,擴(kuò)展類加載器由于向后兼容性的原因被保留,不過被重命名為平臺類加載器(platform?class?loader)。可以通過ClassLoader的新方法getPlatformClassLoader()來獲取。

? ? JDK9時(shí)基于模塊化進(jìn)行構(gòu)建(原來的rt.jar和tools.jar被拆分成數(shù)十個(gè)JMOD文件),其中的Java類庫就已天然地滿足了可擴(kuò)展的需求,那自然無須在保留<JAVA_HOME>\lib\ext目錄,此前使用這個(gè)目錄或者java.ext.dirs系統(tǒng)變量來擴(kuò)展JDK功能的機(jī)制已經(jīng)沒有繼續(xù)存在的價(jià)值了。

2、平臺類加載器和應(yīng)用程序類加載器都不再繼承自java.net.URLClassLoader。

? ? 現(xiàn)在啟動類加載器、平臺類加載器、應(yīng)用程序類加載器全部繼承于jdk.internal.loader.BuiltinClassLoader。

? ? 如果有程序直接依賴了這種繼承關(guān)系,或者依賴了URLClassLoader類特定方法,那代碼很可能會在JDK9及更高版本的JDK中崩潰。

3、在Java9中,類加載器有了名稱。該名稱在構(gòu)造方法中指定,可以通過getName()方法來獲取。平臺類加載器的名稱是platform,應(yīng)用類加載器的名稱是app。類加載器的名稱在調(diào)試與類加載器相關(guān)的問題時(shí)會非常有用。

4、啟動類加載器現(xiàn)在是在jvm內(nèi)部和java類庫共同協(xié)作實(shí)現(xiàn)的類加載器(以前是C++實(shí)現(xiàn)),但為了與之前代碼兼容,在獲取啟動類加載器的場景中仍然會返回null,而不會得到BootClassLoader實(shí)例。

5、類加載的委派關(guān)系也發(fā)生了變動。

? ? 當(dāng)平臺及應(yīng)用程序類加載器收到類加載請求,在委派給父加載器加載前,要先判斷該類是否能夠歸屬到某一個(gè)系統(tǒng)模塊中,如果可以找到這樣的歸屬關(guān)系,就要優(yōu)先委派給負(fù)責(zé)那個(gè)模塊的加載器完成加載。

?

6、附加

? ? 在Java模塊化系統(tǒng)明確規(guī)定了三個(gè)類加載器負(fù)責(zé)各自加載的模塊:

(1)啟動類加載器負(fù)責(zé)加載的模塊

(2)平臺類加載器負(fù)責(zé)加載的模塊

(3)應(yīng)用程序類加載器負(fù)責(zé)加載的模塊

總結(jié)

以上是生活随笔為你收集整理的java类加载器、双亲委派、沙箱安全机制全都让你整明白(三万字,收藏慢慢啃)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

美女视频黄色免费 | 美女在线免费观看视频 | av一区二区在线观看中文字幕 | 免费视频色| 日日躁夜夜躁aaaaxxxx | 国产精品乱码久久久久 | 在线免费黄网站 | 在线视频日韩一区 | 91av在线免费视频 | 免费麻豆视频 | 美女国产免费 | 在线午夜 | 99在线热播精品免费99热 | 日韩在线观看电影 | 亚洲婷婷在线视频 | 色婷婷视频网 | 毛片美女网站 | 亚洲一区二区精品视频 | 天天干夜夜爱 | 99精品视频在线看 | 精品国产伦一区二区三区 | 狠狠撸电影 | 揉bbb玩bbb少妇bbb | 免费又黄又爽的视频 | 国产一区91 | 国产999精品久久久久久麻豆 | 天天操婷婷 | 久99久中文字幕在线 | 在线观看视频一区二区三区 | 国产第一二区 | 中文字幕一区二区三区四区在线视频 | 免费高清男女打扑克视频 | 久久丝袜视频 | 国产精品一二 | 午夜视频在线网站 | 五月婷婷激情综合 | 中文字幕视频播放 | 国产麻豆精品免费视频 | 国产一区二区在线播放视频 | 国产一级淫片在线观看 | 99久久久免费视频 | 91精品少妇偷拍99 | 久久久久福利视频 | 久久综合九色欧美综合狠狠 | 手机成人免费视频 | www.天天射 | 国产一级免费片 | 丁香久久 | 人人舔人人干 | 在线观看国产亚洲 | 99视频久久| 精品产品国产在线不卡 | 99热9| 欧美另类老妇 | 国产偷在线 | 免费视频久久久久久久 | 日日夜夜网| 亚洲精品久久久久久久不卡四虎 | 国产色秀视频 | 国产91区| 欧美怡红院视频 | 日韩高清一二区 | 国产精品久免费的黄网站 | 成人h电影 | 色婷婷激情电影 | 91精品国产一区二区三区 | 99精品国自产在线 | 超碰官网| 日三级在线 | 超碰在线97观看 | 日韩电影一区二区在线观看 | 国产精品福利无圣光在线一区 | 中文字幕在线观看第一区 | www.综合网.com | 在线一区电影 | 亚洲黄色在线播放 | 婷婷综合视频 | 国产成人一区二区三区久久精品 | 99热这里有精品 | 91精品国产99久久久久 | 久久精品99| 91人人澡| 欧美日韩一区二区久久 | 亚洲精品在线观 | 亚洲精品国偷拍自产在线观看蜜桃 | 久草视频资源 | 午夜久久福利影院 | 国产视频不卡一区 | av在线一二三区 | av一级二级 | 人人干人人干人人干 | 午夜精品一区二区三区在线观看 | 日免费视频 | 美女在线免费观看视频 | 一区二区三区日韩视频在线观看 | 香蕉精品视频在线观看 | 成年人黄色免费看 | 狠狠的操狠狠的干 | 国产精品毛片一区二区在线 | 99高清视频有精品视频 | 人人爽人人插 | 久久男女视频 | 色www精品视频在线观看 | 日韩精品在线免费观看 | 久久久私人影院 | 欧美日韩高清 | 中文字幕一区二区三区乱码在线 | 亚洲综合色网站 | 久久久久www | 久久这里只有精品久久 | 亚洲理论电影网 | 九九免费在线观看 | 激情综合交| 午夜精品视频免费在线观看 | 麻豆91网站 | 日韩黄色在线 | 天天射天天添 | 久久香蕉电影 | 国产在线精品视频 | 色婷婷国产精品一区在线观看 | 在线观看蜜桃视频 | 成人黄色大片 | 91精品一区二区三区蜜桃 | 国产精品一区免费观看 | 久久久国产在线视频 | 经典三级一区 | 日韩电影在线观看一区二区三区 | 国产精品va在线观看入 | 色综合久久久久综合 | 欧美另类性| 欧洲黄色片 | www.五月天 | 一区二区三区四区五区在线 | 中文字幕超清在线免费 | 国产在线免费av | 麻豆国产在线视频 | 在线观看岛国 | 亚洲在线网址 | 久久a级片 | 中文字幕在线观看一区二区 | 欧美精品xxx| 韩日电影在线观看 | 中文字幕第| 国产精品永久在线观看 | 久久精品视频3 | 激情五月五月婷婷 | av三级在线免费观看 | 久久电影色 | 日韩一区二区免费在线观看 | 日韩一区二区三区免费视频 | 天天狠狠干 | 日本激情中文字幕 | 婷婷丁香五 | 国产婷婷精品 | 免费在线观看av不卡 | 性色大片在线观看 | 伊人看片 | 黄p网站在线观看 | 国产日韩精品一区二区三区在线 | 人人爱爱人人 | 九九视频免费观看视频精品 | 精品亚洲免费 | www.久草.com | 欧美日韩二区三区 | 欧美日韩xxx | 久久激情精品 | 麻豆国产视频 | 97超碰在线人人 | 中文在线中文资源 | 国产黄色免费在线观看 | 国产精品1024| 超碰在线官网 | 激情开心网站 | 顶级bbw搡bbbb搡bbbb | 国产黄色视| 日韩成人精品在线观看 | 久久精选视频 | 欧美日韩国产欧美 | 樱空桃av| 婷婷综合电影 | 国产91综合一区在线观看 | 国产小视频在线观看 | 欧美日韩另类视频 | 91麻豆国产 | 91精品免费看 | 91网在线 | 激情图片久久 | 国产成人精品av在线观 | 天天射天天添 | 在线观看 国产 | av黄色一级片 | 日韩视频在线观看免费 | 日韩久久精品一区二区 | 九九热免费精品视频 | 欧美日一级片 | 国产视频久久久 | 久久精品免费看 | 日韩欧美久久 | 亚洲爽爽网 | 干干日日| 国产人在线成免费视频 | 精品久久久久久综合 | 国产免费不卡 | 91中文字幕网| 一区二区三区四区精品 | 在线看的av网站 | 午夜精品久久久久久久99无限制 | 亚洲国产av精品毛片鲁大师 | 日日干激情五月 | 久久综合一本 | 人人插人人草 | 亚洲国产日韩在线 | 91原创在线观看 | 亚洲综合色网站 | 91热精品 | 国产精品一区在线 | 福利网在线 | 中文国产在线观看 | 亚洲 欧洲 国产 日本 综合 | 9久久精品 | 亚洲国产操 | 国产一性一爱一乱一交 | av在线超碰| 婷婷九月激情 | 国产一级做a爱片久久毛片a | 国产麻豆精品一区 | 中文字幕综合在线 | 午夜精品福利影院 | 四虎永久免费 | 日韩中文在线播放 | 人人爱人人爽 | 91视频在线看 | 亚洲免费a| 国产99色| 日操操 | 久久五月网| 日韩精品一区二区三区不卡 | 欧亚久久 | 久久资源总站 | 涩五月婷婷 | av网站免费看 | 亚洲理论在线 | 婷婷射五月 | 国产黄色片免费在线观看 | a成人在线 | 久久夜色精品国产欧美乱极品 | 97超碰人人澡 | 亚洲资源一区 | 欧美另类美少妇69xxxx | 欧美日韩综合在线观看 | 在线免费观看黄色小说 | 午夜国产福利在线观看 | 免费看国产黄色 | www.天天射.com| www.com在线观看 | 成人中心免费视频 | 午夜私人影院 | 鲁一鲁影院| av丁香| 久久精品亚洲综合专区 | 天天看天天操 | 五月婷在线观看 | 成年人在线免费看 | 欧美a√在线 | aaaaaa毛片| 国产69久久精品成人看 | 免费成人在线网站 | 中文字幕一区在线观看视频 | 中文字幕在线有码 | 九色视频自拍 | 97人人模人人爽人人喊网 | 特黄免费av | 中文字幕网址 | 狠狠干我 | 成人资源在线 | 婷婷在线播放 | 日本高清中文字幕有码在线 | 久久久午夜精品福利内容 | 国产在线97 | 波多野结衣一区二区三区中文字幕 | 98涩涩国产露脸精品国产网 | 欧美一区二区三区免费观看 | 国产亚洲精品久久19p | 国产永久免费高清在线观看视频 | 国产区精品区 | 91一区二区三区在线观看 | av不卡在线看| 婷婷播播网 | 欧美日韩在线播放 | 91av九色| 亚洲国产黄色片 | 开心色停停 | 久久久久欠精品国产毛片国产毛生 | 久久久久激情视频 | 综合网欧美 | 91成人精品一区在线播放69 | 久久 精品一区 | 国产日韩欧美在线一区 | 亚洲视频免费视频 | 在线观看片 | 黄色成人av| 精品视频国产一区 | 国产在线va | 天天色草| 人人爽人人澡 | 精品国产午夜 | 亚洲三级网站 | 最近中文字幕视频完整版 | www.精选视频.com | 国产精品va最新国产精品视频 | 美女网站视频一区 | 久久69精品久久久久久久电影好 | av资源免费看 | 在线免费观看av网站 | 天天射天天干 | 狠狠躁夜夜躁人人爽视频 | 久青草电影| 亚洲精品久久久久久久不卡四虎 | 91精品国产综合久久福利不卡 | 天天综合网 天天 | 亚洲精品日韩在线观看 | 三级黄色欧美 | 一区二区三区四区五区在线 | 久久久九色精品国产一区二区三区 | 日韩视频专区 | 九九视频免费观看视频精品 | 人人射人人插 | 九九热免费视频在线观看 | 国产精品乱码久久久久久1区2区 | 欧美日韩精品在线 | 亚洲资源一区 | 日韩国产高清在线 | 久久久久久久久久久久久久免费看 | 免费在线观看污 | 激情 婷婷 | 99久久综合狠狠综合久久 | 成人一级在线 | 波多野结衣在线视频免费观看 | 国产精品毛片一区视频 | 亚洲一区免费在线 | 亚洲国产视频直播 | 日韩中文字幕免费在线观看 | 欧美日韩免费观看一区二区三区 | 亚洲好视频 | 99久视频 | 亚洲视频在线免费看 | 97视频免费观看 | 婷婷丁香六月天 | 中文字幕 国产视频 | 黄色成年 | 成人三级av | 一区二区在线不卡 | 精品综合久久 | 三级黄色a | 国产无套精品久久久久久 | 成人毛片在线视频 | 狠狠操狠狠操 | 激情久久久久久久久久久久久久久久 | 欧美极品少妇xbxb性爽爽视频 | 91九色丨porny丨丰满6 | 中文视频在线 | 国产精品视频在线看 | 午夜三级理论 | 国产区网址 | 黄色大片中国 | 久久久久久久久毛片精品 | 黄色网中文字幕 | 天天操天天射天天添 | 美女免费视频网站 | 免费看的黄网站 | 天操夜夜操 | 亚洲高清在线视频 | 色综合天天综合 | 91视频免费看| 亚洲综合在线视频 | 四虎成人精品在永久免费 | 国产v视频 | 国产美女免费视频 | 精品久久国产一区 | 日韩精品最新在线观看 | 亚洲免费高清视频 | 国产精品igao视频网入口 | 天堂av在线中文在线 | 久久免费国产视频 | 亚洲国产日韩欧美 | 91看片在线观看 | 久久综合久久久久88 | 中文字幕免费看 | 国产护士hd高朝护士1 | 成人黄色电影在线播放 | 欧美日本啪啪无遮挡网站 | 久久免费观看视频 | 99热精品久久 | 91在线播放国产 | 狠狠干,狠狠操 | 天天激情站 | 久久伊人精品一区二区三区 | 亚洲国产欧美在线看片xxoo | 婷婷六月天天 | 午夜久久精品 | 日本性生活免费看 | 婷婷在线视频 | 日韩.com| 在线亚洲日本 | 色在线视频 | 狠狠狠色丁香综合久久天下网 | 国产精品18久久久久久久 | 国产精品久久网站 | 一级片色播影院 | 91精品在线免费视频 | 中国一级片在线 | 国产精品免费一区二区三区在线观看 | 福利片视频区 | 日本不卡123区 | 色婷婷中文 | 中文字幕在线看 | 欧美日韩性生活 | 亚洲最新精品 | 人人看97| 久久精品女人毛片国产 | 国产a国产 | 国产视频久久久久 | 三级av片| 亚洲激情五月 | 美女啪啪图片 | 日韩一区二区三区高清在线观看 | 狠狠干夜夜爽 | 日韩高清在线不卡 | 在线看片中文字幕 | 国产精品高清一区二区三区 | 成人啊 v| 在线a人v观看视频 | 精品一区二区在线播放 | www久| 91九色视频在线播放 | av黄网站 | 国产小视频国产精品 | 99亚洲精品 | 偷拍福利视频一区二区三区 | 久久97精品 | 国产精品久久麻豆 | 国产精品美女久久久久aⅴ 干干夜夜 | 久久中文网 | 亚洲国产精品一区二区久久,亚洲午夜 | 亚洲激情在线观看 | 久久草草热国产精品直播 | 日韩成人精品 | 日韩草比 | 久久久精品 一区二区三区 国产99视频在线观看 | 蜜臀精品久久久久久蜜臀 | 久草9视频 | 久久国产精品色婷婷 | 国产精品成人免费一区久久羞羞 | 在线观看中文字幕一区二区 | 三级在线播放视频 | 久久精品超碰 | 欧美日韩二区三区 | 在线国产一区二区 | 手机看片中文字幕 | 天堂在线成人 | 亚洲午夜精品在线观看 | 日韩精品偷拍 | 久久久综合九色合综国产精品 | 激情综合亚洲精品 | 久久午夜国产精品 | 色瓜| 在线观看黄网站 | 精品久久久久久久久久岛国gif | 久久久精品午夜 | 国产精品成人品 | www.五月婷| 日韩av电影一区 | 日操操| 成人免费大片黄在线播放 | 东方av免费在线观看 | av天天草 | 亚洲91在线| 欧美日韩精品在线观看视频 | 日韩影视大全 | 天天躁日日躁狠狠 | 国产不卡av在线 | 天天色天天干天天色 | 国产精品扒开做爽爽的视频 | 国产黄色特级片 | 久久国产精品久久精品国产演员表 | 91精品国产电影 | 亚洲欧洲精品一区 | 久久精品第一页 | 久久蜜臀一区二区三区av | 伊人婷婷| 久青草影院 | 色在线视频网 | 99精品在线免费观看 | 99中文视频在线 | 国产喷水在线 | 欧美性生交大片免网 | 久久九九影视网 | 激情网站网址 | 黄色a一级视频 | 狠狠干夜夜操天天爽 | 四虎国产永久在线精品 | av怡红院 | 99精品免费在线 | 久久免费看a级毛毛片 | 亚洲一区视频在线播放 | 免费观看国产视频 | 久久精品一区二区国产 | 视频在线一区 | 狠狠色综合欧美激情 | 国产免费亚洲 | 黄色小说在线观看视频 | 992tv在线成人免费观看 | 日韩三级在线 | 91精品视频观看 | 精品人人人 | 日韩精品视频免费专区在线播放 | 国产美女精品人人做人人爽 | caobi视频| 中文字幕成人在线 | 亚洲精品视频在线免费 | 久久久久久久久久久免费视频 | 欧美日韩在线免费观看 | 婷婷福利影院 | 久草在线视频新 | jizzjizzjizz亚洲| 色婷婷国产在线 | 日日夜夜人人天天 | 麻豆一区在线观看 | 国产精品免费久久久久久久久久中文 | 99精品欧美一区二区蜜桃免费 | 99视频在线播放 | 欧美日一级片 | 亚洲黄色在线 | 日日夜日日干 | 一色av | 欧美黄污视频 | 在线成人短视频 | 不卡视频在线 | 日本成人a| 亚洲精品中文字幕视频 | 久久国产精品第一页 | 在线黄色av | 欧美成年网站 | 怡红院av久久久久久久 | 天堂av高清| 天天操天天玩 | 国产护士av | 天天综合天天做 | 91麻豆精品国产91久久久久久 | 久久久久久视频 | 天天射天天拍 | 日韩一区正在播放 | 欧美成人免费在线 | 免费av在线网 | 日日躁夜夜躁xxxxaaaa | 国产日产在线观看 | 久久艹精品 | 激情久久久久久久久久久久久久久久 | 久久亚洲在线 | 亚洲精品在线视频播放 | 中文字幕在线视频第一页 | 国产精品在线看 | 日本久久视频 | 狠狠色狠狠色综合日日92 | 国产色久 | 91视频在线免费看 | 国产麻豆精品一区二区 | 少妇bbb| 97人人网 | 国产精品国产毛片 | 亚洲精品国产综合久久 | 久久国产美女 | 亚洲最大av网站 | 婷婷综合五月 | 国产高清在线视频 | 久久久国产日韩 | 亚洲闷骚少妇在线观看网站 | 91麻豆精品一区二区三区 | 91av在线不卡 | 91精品天码美女少妇 | 国产成人一二三 | 午夜免费久久看 | 麻豆网站免费观看 | www.黄色片.com | 91视频在线看 | 亚洲国内精品视频 | 久久久久久久久爱 | 久久免费高清视频 | 日韩久久精品一区二区三区下载 | 亚州精品在线视频 | 国产一区二区三区在线免费观看 | 久久精品人人做人人综合老师 | 国产999精品久久久影片官网 | 国产原创91| 国产美女在线精品免费观看 | 国产精品久久99综合免费观看尤物 | 激情欧美一区二区三区免费看 | 婷婷久久久久 | 日韩超碰 | 激情五月婷婷综合 | 成人免费在线播放 | 日本黄色大片免费 | 中文字幕在线观看免费高清电影 | 欧美日韩中文在线观看 | 特级西西www44高清大胆图片 | 欧美一级高清片 | 亚洲精品啊啊啊 | 波多野结衣视频一区二区三区 | 亚洲毛片在线观看. | 一区二区精品在线 | 91看片淫黄大片一级在线观看 | 欧美analxxxx | 亚洲电影图片小说 | 国产一级免费观看视频 | 91最新地址永久入口 | 日韩国产精品一区 | 国产精品1区2区在线观看 | 九九视频网 | 国产精品毛片久久久久久久久久99999999 | 国产精品麻豆欧美日韩ww | 亚洲男男gⅴgay双龙 | 日韩久久精品一区 | 日韩欧美91| 日韩免费在线观看网站 | 亚洲视频 一区 | 欧美午夜视频在线 | 成人久久精品视频 | 午夜a区| 操操日日 | 婷婷丁香av | 成人毛片在线视频 | 中文字幕精品一区久久久久 | 99 色| 视频福利在线 | 国产一级黄色av | 麻豆视频一区 | 黄色影院在线播放 | 成年人免费在线 | 久久久综合精品 | 成人久久久久久久久久 | 中文一区在线观看 | 欧美激情视频一二三区 | 成人精品一区二区三区中文字幕 | 麻豆免费视频网站 | 综合激情网... | 久久久午夜精品理论片中文字幕 | 国产精品亚 | 97电影手机| 激情综合五月 | 中文字幕精品一区二区三区电影 | 中文字幕在线国产精品 | 91成人精品视频 | 伊人网av| 久久艹精品 | 婷婷视频在线观看 | 国产午夜精品免费一区二区三区视频 | 国产亚洲精品久 | 天天躁天天躁天天躁婷 | www久久 | 人人草在线视频 | 久久精品爱视频 | 日韩手机在线观看 | 天天操天天草 | 日韩在线观看第一页 | 成年人在线观看网站 | 黄色软件网站在线观看 | 久久人人爽人人爽人人片av软件 | 综合天天网| 一区二区 不卡 | 亚洲激情 欧美激情 | 99免费在线观看视频 | 97色资源| 欧美日韩性生活 | 久久天天躁 | 日韩欧美视频免费看 | 国产精品久久久久久超碰 | 6080yy午夜一二三区久久 | 亚洲午夜电影网 | 狠狠色狠狠色合久久伊人 | 国内成人精品2018免费看 | 亚洲一级免费电影 | 中文字幕在线观看完整 | 久久久激情网 | 亚洲小视频在线观看 | va视频在线| 日p视频 | 国产精品久久久久久久久久白浆 | 免费无遮挡动漫网站 | 丁香六月婷 | 精品999在线观看 | 亚洲一区不卡视频 | 成人丁香花 | 久久97久久97精品免视看 | 中文字幕av专区 | 日韩精品一区二区不卡 | 色哟哟国产精品 | 日日精品 | 国产视频精品在线 | 久久免费福利 | 国产午夜免费视频 | 国产欧美综合视频 | 狠狠躁日日躁狂躁夜夜躁 | 91av视频在线播放 | 99热最新网址| 欧美嫩草影院 | 国产精品一区二区 91 | 天天爱天天操天天爽 | 九九久久精品 | 国产护士hd高朝护士1 | 婷婷爱五月天 | 色偷偷88888欧美精品久久 | 国产成人精品亚洲日本在线观看 | 亚洲精品视频第一页 | 最近中文字幕高清字幕免费mv | 美女黄濒| 精品一区二区在线观看 | 欧美精品一区在线发布 | 婷婷视频 | 国产三级国产精品国产专区50 | 日本性生活一级片 | 午夜精品视频一区二区三区在线看 | 91一区二区三区在线观看 | 日韩视频一二三区 | 91黄色视屏 | 免费在线观看不卡av | 97超碰人人澡人人爱学生 | 欧美色图一区 | 在线观看香蕉视频 | 色婷婷综合久色 | 免费在线| av一级片网站 | 国产美女无遮挡永久免费 | 国产裸体永久免费视频网站 | 丝袜美腿亚洲综合 | 国产精品久久久久免费观看 | 精品一区三区 | 欧美激情xxxx性bbbb | 久久精品毛片基地 | 日日夜精品 | 中文字幕在线中文 | 日韩在线一区二区免费 | 亚洲专区视频在线观看 | 天海翼一区二区三区免费 | 国内精品久久久久影院日本资源 | 国产在线播放一区二区三区 | a黄色片在线观看 | 日韩在线视频二区 | 成人在线小视频 | 91欧美国产 | 五月亚洲| 91视频久久久久 | 精品久久免费 | 国产视频不卡一区 | 国产午夜三级一区二区三桃花影视 | 中文字幕无吗 | 91麻豆精品国产91久久久久久久久 | 国产伦理久久精品久久久久_ | 久久综合99| 综合网天天射 | 日韩欧美精品一区二区三区经典 | 91夜夜夜 | 亚洲精品激情 | 亚洲涩涩色 | 五月开心婷婷网 | 亚洲精品乱码久久久久v最新版 | 91精品啪啪 | 亚洲日本精品 | 97福利在线| 亚洲免费观看在线视频 | 亚洲精品乱码久久久久 | 久久人人精| 精品你懂的 | 亚洲成人资源 | 精品视频免费观看 | 精品久久综合 | 狠色在线| 亚洲黄电影 | 六月婷操 | 中国一级片在线观看 | 亚洲最大激情中文字幕 | 国产精品精品国产 | 91免费网站在线观看 | 国内精品在线观看视频 | 人人玩人人添人人澡超碰 | 一本大道久久精品懂色aⅴ 五月婷社区 | 亚洲综合激情 | 天天操偷偷干 | 久久久久99精品成人片三人毛片 | 国产字幕在线看 | 日本不卡一区二区 | 日韩欧美有码在线 | 丰满少妇对白在线偷拍 | 97视频免费播放 | 香蕉视频4aa| 超碰国产在线播放 | 在线亚洲午夜片av大片 | 一区在线观看 | 中文字幕中文字幕中文字幕 | 亚洲成人精品久久 | 国产一区二区免费 | 久久久久久久久久久久久久av | 国产手机视频在线播放 | www.狠狠插.com| 最新国产精品拍自在线播放 | 狠狠干夜夜爱 | 视频精品一区二区三区 | 精品国产黄色片 | 国产高清无线码2021 | 国产91在线 | 美洲 | 亚洲天堂精品 | 国产黄色一级大片 | 一级一级一片免费 | 99久久婷婷国产一区二区三区 | 国产婷婷精品av在线 | 国产精品对白一区二区三区 | 草草草影院 | av丝袜天堂| 精品国产欧美一区二区 | 天天操天天玩 | 天天操天天干天天操天天干 | 在线 高清 中文字幕 | 日韩欧美视频在线观看免费 | 2019中文字幕第一页 | 日韩深夜在线观看 | 精品国产一区在线观看 | 91在线视频| 天堂av免费观看 | 天天操天天操天天 | 中国一级片在线 | 国产精品一区专区欧美日韩 | 99热精品国产一区二区在线观看 | 国产精品中文久久久久久久 | 日韩电影一区二区三区在线观看 | 在线草| 国产精品精品国产婷婷这里av | 亚州免费视频 | 九九精品视频在线 | 在线播放亚洲 | 91精品国产麻豆国产自产影视 | 天天操天天干天天操天天干 | 天堂av在线免费观看 | 亚洲va韩国va欧美va精四季 | 欧美一进一出抽搐大尺度视频 | 色偷偷中文字幕 | 国产一级片免费播放 | 日韩最新av在线 | 免费观看一区二区三区视频 | 中文字幕国产精品 | 色av男人的天堂免费在线 | 蜜臀一区二区三区精品免费视频 | 日韩综合在线观看 | 九九热国产视频 | 黄色网www| 97av视频 | 麻豆视频免费看 | 视频一区二区在线 | 日韩中文字幕国产精品 | 天堂视频中文在线 | 久久官网 | 久久手机视频 | 亚洲欧美视频一区二区三区 | 欧美日韩精品电影 | 久久综合丁香 | 狠狠干网址 | 午夜av免费在线观看 | 久久国产剧场电影 | 成人在线观看资源 | 91成年人网站 | av在线a | 综合精品久久久 | 一级成人网 | 国产精品一区电影 | 日韩欧美在线免费观看 | 黄色亚洲大片免费在线观看 | 2019中文字幕第一页 | 中文字幕在线一区观看 | 九九免费在线视频 | 超碰国产在线 | 国内精品久久久久影院一蜜桃 | 精品久久网 | 亚洲精品一区二区精华 | 超碰97人 | 91精品国产高清自在线观看 | 日韩毛片久久久 | 日日天天狠狠 | 免费人成在线观看网站 | 好看的国产精品视频 | 亚洲欧美怡红院 | 色婷婷免费 | 亚洲午夜精品久久久久久久久 | 免费视频网 | 久草精品资源 | 日本久久久久久久久久 | 欧美日韩精品在线一区二区 | 日韩免费电影网 | 色婷婷在线视频 | 成人av教育 | 国产精品久久一卡二卡 | 国产成人久久精品 | 久久久久久久国产精品视频 | 欧美久久综合 | 精品在线一区二区 | 日韩激情一二三区 | 在线免费av播放 | av在线成人 | 欧美国产一区二区 | 国产美女视频免费观看的网站 | 国产精品成人在线观看 | 2019天天干天天色 | 国产精品女视频 | 国产一二三精品 | 精品久久久久一区二区国产 | 亚洲日本一区二区在线 | 成人午夜免费剧场 | 国产精品美女久久久 | www.av免费 | 美女在线免费观看视频 | 免费网站黄 | 国产成人精品免费在线观看 | 91探花系列在线播放 | 久久99亚洲精品久久久久 | 亚洲成av片人久久久 | 免费观看mv大片高清 | 国产精品久久久久久久毛片 | 午夜精品久久久久久久99 | 深夜免费小视频 | 亚洲一二三久久 | 色噜噜色噜噜 | 免费日韩在线 | 久草在线资源观看 | 欧美久久久久久久久 | 国产护士hd高朝护士1 | 麻豆久久| 97视频一区 | 九九亚洲视频 | 午夜色影院 | 中文字幕乱码日本亚洲一区二区 | 香蕉视频在线免费看 | 97精产国品一二三产区在线 | 婷婷六月综合亚洲 | 国产成人在线网站 | 美女视频是黄的免费观看 | 国产精品原创在线 | 天天曰视频| 在线观看mv的中文字幕网站 | 国产又粗又猛又爽又黄的视频免费 | 日韩精品免费 | 日韩mv欧美mv国产精品 | 亚洲日本三级 | 亚洲精品欧美视频 | 国产成人亚洲在线观看 | 美女久久久 | 亚洲精品视频在线观看免费视频 | 日韩欧美69 | 国产高清免费视频 | 特级免费毛片 | 免费国产在线视频 | 欧女人精69xxxxxx| 中文字幕在线字幕中文 | 97视频久久久 | 免费看黄视频 | 超黄视频网站 | 天天操操 | 日本黄色片一区二区 | 激情丁香婷婷 | 九九三级毛片 | 亚洲九九影院 | a视频免费看 | 黄色亚洲在线 | 玖玖在线资源 | 亚洲精品国内 | 天堂av色婷婷一区二区三区 | 国产精品高潮在线观看 | 久久人网| 免费欧美| 久久综合亚洲鲁鲁五月久久 | 成人免费网视频 | 久久精品免视看 | wwwww.国产| 亚洲黄色成人 | 久久婷婷一区二区三区 | 国产亚洲精品久久久久久 | 69人人| 精品一区二区在线观看 | 久久永久免费视频 | 国产精品中文久久久久久久 | 亚洲精品成人在线 | 97在线观看免费观看高清 | 7777xxxx | 天天操天天爱天天爽 | 久久久国产精品一区二区中文 | 日韩大片在线 | av在线小说 | 欧美在线99| 欧美精品中文字幕亚洲专区 | 在线视频欧美精品 | 不卡的一区二区三区 | 欧美成年黄网站色视频 |