天天看點

雙親委派機制雙親委派機制:

雙親委派機制:

1.雙親委派機制的優勢:

①:避免類的重複加載

②:保護程式安全,防止核心API被随意修改

例如自定義類:java.lang.String

說的再多不如直接上代碼

package java.lang;

public class String {
    static {
        System.out.println("這是自定義類的String類的靜态代碼塊");
    }

    public static void main(com.cdc.runtime_data_area.classloader.java.lang.String[] args) {
        System.out.println("hello String");
    }
}
           

可以看到,我在src下定義了一個java.lang.String類,與java自帶的java.lang.String是重複的

雙親委派機制雙親委派機制:

在這裡,我們直接運作裡面的main方法:

錯誤: 在類 java.lang.String 中找不到 main 方法, 請将 main 方法定義為:
   public static void main(String[] args)
否則 JavaFX 應用程式類必須擴充javafx.application.Application

Process finished with exit code 1
           

可以看到,出了異常,異常資訊為在java.lang.String中找不到main方法,這是由于雙親委派機制的,對java的核心API進行了保護,讓我們無法對其随意進行更改

之後,又寫了一個demo,對該類進行測試

public class StringDemo {


    public static void main(String[] args) {
        java.lang.String str=new java.lang.String();
        System.out.println("hello World");
    }
}
           

運作結果為:

"C:\Program Files\Java\jdk1.8.0_202\bin\java.exe" "-javaagent:F:\JetBrains\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=53986:F:\JetBrains\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_202\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\rt.jar;F:\Java自學\jvm\JVMDemo\out\production\JVMDemo" java.StringDemo
java.lang.SecurityException: Prohibited package name: java
	at java.lang.ClassLoader.preDefineClass(ClassLoader.java:662)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:761)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" 
Process finished with exit code 1
           

在這裡,可以看到:java.lang.SecurityException: Prohibited package name: java,說明java這個包名是不能随便定義的。

2.雙親委派機制是如何進行工作的呢(工作原理):

①:如果一個類加載器收到了類加載的請求,它并不會自己先去加載,而是将請求委托給父類的加載器去執行

②:如果父類加載器還存在其父類加載器,則進一步向上委托,依次遞歸,請求最終達到頂層的啟動類加載器

③:如果父加載器可以完成類加載任務,就成功傳回,倘若父類加載器無法完成加載任務,子加載器才會去嘗試自己加載,這就是雙親委派機制

雙親委派機制雙親委派機制:

例如在剛剛的那個代碼中,系統類加載器收到類加載的請求,并沒有直接加載,而是往上發送委托,由拓展類加載器進行加載,但是拓展類加載器上面還有父類,是以繼續向上委托,交給了引導類加載器進行加載。這時,引導類加載器隻加載包名為java、javax、sun開頭的包名下面的類,發現我們自定義的String類正好是由java開頭的,便由他來加載,便不再向下委托。此時我們自定義的String類變成了核心API中的String類,而在核心API中的String類是沒有main方法的,是以便報了在類java.lang.String類中找不到main方法的異常。

再舉一個生活中的例子:

情況一:有一個蘋果,你拿到之後,發現自己母親在,然後就拿去問:媽媽,你吃不吃蘋果啊。這時候母親又拿着蘋果去問奶奶,奶奶一看,這麼硬的蘋果,我牙都沒了咋吃啊。于是就說:我不吃。蘋果又到了母親手上,一看,蘋果有點酸,我還是不吃了,又給了你,這時候蘋果就成了你的,就由你來吃。

情況二:拿到蘋果時,由母親拿給奶奶,奶奶說,正好想吃一個蘋果。這時候蘋果就給了奶奶吃,就沒下面兩人啥事了。

jvm