欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

重新對(duì)Java的類(lèi)加載器的學(xué)習(xí)方式

 更新時(shí)間:2025年05月13日 16:12:47   作者:找不到、了  
這篇文章主要介紹了重新對(duì)Java的類(lèi)加載器的學(xué)習(xí)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Java 類(lèi)加載器JVM 類(lèi)加載器是同一體系中的不同概念。

Java 類(lèi)加載器是一個(gè)更高抽象層面的概念,可以實(shí)現(xiàn)自定義加載器;而 JVM 類(lèi)加載器是 JVM 的實(shí)現(xiàn)部分,負(fù)責(zé)實(shí)際的字節(jié)碼加載。

類(lèi)加載器:負(fù)責(zé)將.class文件加載到內(nèi)存中,并為之生成對(duì)應(yīng)的Class對(duì)象(是JVM執(zhí)行類(lèi)加載機(jī)制的前提)

1、介紹

1.1、簡(jiǎn)介

在Java中,類(lèi)加載器(ClassLoader)是Java虛擬機(jī)(JVM)用來(lái)加載類(lèi)的核心組件。

它負(fù)責(zé)將Java字節(jié)碼文件(.class文件)動(dòng)態(tài)加載到內(nèi)存中,并將其轉(zhuǎn)化為JVM可以執(zhí)行的類(lèi)對(duì)象。類(lèi)加載器是Java運(yùn)行時(shí)系統(tǒng)的一部分,它支持Java的動(dòng)態(tài)特性,使得Java程序可以在運(yùn)行時(shí)加載類(lèi)和接口。

如下圖所示:

1.2、符號(hào)引用和直接引用

關(guān)于符號(hào)引用和直接引用的介紹這里先進(jìn)行一個(gè)理解,下面在類(lèi)加載器執(zhí)行過(guò)程的連接階段,有個(gè)解析的過(guò)程需要聯(lián)系到這里的知識(shí)。

  • 符號(hào)引用:指的是一個(gè)字符串,該字符串表示一個(gè)類(lèi)、字段或方法的名稱(chēng),這個(gè)名稱(chēng)由 JVM 在運(yùn)行時(shí)解析。
  • 直接引用:指的是內(nèi)存中對(duì)象的具體地址或偏移量,它用于直接訪問(wèn)該字段或調(diào)用該方法。

1、符號(hào)引用

符號(hào)引用通常在 Java 字節(jié)碼(class 文件)中以字符串的形式出現(xiàn)。它是類(lèi)與類(lèi)之間一種相對(duì)的、靈活的引用方式。這種引用方式在字節(jié)碼編譯時(shí)就已經(jīng)確定,但實(shí)際內(nèi)存地址在運(yùn)行時(shí)才會(huì)分配。

示例:符號(hào)引用的特點(diǎn)

考慮一下這段代碼:

class Example {
    void hello() {
        System.out.println("Hello, World!");
    }
}

在編譯成字節(jié)碼后,hello 方法的符號(hào)引用會(huì)包含:

  • 方法名:hello
  • 方法描述符:()V(意味著無(wú)參數(shù)且沒(méi)有返回值)

在字節(jié)碼中的常量池部分,可以看到以下條目(這里是簡(jiǎn)化的表示):

1. Class: 'Example'
2. Method: 'hello' with descriptor '()V'

這個(gè)符號(hào)引用不會(huì)包含任何內(nèi)存地址或具體實(shí)現(xiàn)細(xì)節(jié)。

2、直接引用

當(dāng) JVM 運(yùn)行時(shí)解析符號(hào)引用時(shí),它會(huì)將符號(hào)引用轉(zhuǎn)換為直接引用。直接引用是指向內(nèi)存中對(duì)象或方法入口的確切地址,這樣 JVM 就可以直接訪問(wèn)它們。

示例:直接引用的獲取過(guò)程

下面的例子展示了符號(hào)引用到直接引用的過(guò)程。

public class Main {
    public static void main(String[] args) {
        Example example = new Example(); // 創(chuàng)建 Example 對(duì)象
        example.hello(); // 調(diào)用 hello 方法
    }
}

class Example {
    void hello() {
        System.out.println("Hello, World!");
    }
}

在這個(gè)代碼中:

  1. example.hello() 是調(diào)用 hello 方法。在編譯時(shí),hello 方法的引用是符號(hào)引用。
  2. 當(dāng) JVM 到達(dá)這行代碼時(shí),它首先會(huì)解析 hello 的符號(hào)引用。

3、符號(hào)轉(zhuǎn)直接的過(guò)程

1.指向類(lèi)定義

在符號(hào)引用查找過(guò)程中,JVM 會(huì)查找并確認(rèn) Example 類(lèi)的符號(hào)引用,即它的名稱(chēng) Example。

2.處理方法

一旦 Example 類(lèi)被確認(rèn)可用,JVM 將查找 hello 方法的符號(hào)引用。當(dāng)它找到這個(gè)符號(hào)引用時(shí),它會(huì)定位到方法在內(nèi)存中的地址(也就是直接引用)。

這個(gè)直接引用通常是方法在內(nèi)存中相對(duì)于類(lèi)對(duì)象的偏移。

3.執(zhí)行調(diào)用

最后,JVM 使用這個(gè)直接引用來(lái)調(diào)用 hello 方法,從而直接在內(nèi)存中找到并執(zhí)行方法的字節(jié)碼。

2、加載流程

Java是一個(gè)動(dòng)態(tài)語(yǔ)言,這意味著類(lèi)在程序運(yùn)行時(shí)被加載,而不是在編譯時(shí)完成加載。類(lèi)加載器的主要任務(wù)就是將類(lèi)的字節(jié)碼文件從文件系統(tǒng)或網(wǎng)絡(luò)等資源加載到內(nèi)存中。

具體而言,類(lèi)加載器的職責(zé)包括:

  • 加載類(lèi):將Java字節(jié)碼文件讀取到內(nèi)存,并轉(zhuǎn)換為Class對(duì)象。
  • 鏈接類(lèi):將類(lèi)的二進(jìn)制數(shù)據(jù)合并到JVM運(yùn)行時(shí)環(huán)境中。這一步包括驗(yàn)證、準(zhǔn)備和解析。
  • 初始化類(lèi):執(zhí)行類(lèi)的靜態(tài)初始化塊和靜態(tài)變量的初始化。

關(guān)于上述各個(gè)階段的主要流程下面進(jìn)行了詳細(xì)的介紹。

由上圖可知:

ClassLoader在整個(gè)裝載階段,只能影響到類(lèi)的加載,而無(wú)法通過(guò)ClassLoader去改變類(lèi)的鏈接和初始化行為。

整個(gè)執(zhí)行過(guò)程可以分為三大步:加載、連接、初始化。

1.加載:將字節(jié)碼文件通過(guò)IO流讀取到JVM的方法區(qū),并同時(shí)在堆中生成Class對(duì)像。

2.鏈接:

  • 驗(yàn)證:校驗(yàn)字節(jié)碼文件的正確性。
  • 準(zhǔn)備:為類(lèi)的靜態(tài)變量分配內(nèi)存,并初始化為默認(rèn)值;對(duì)于final static修飾的變量,在編譯時(shí)就已經(jīng)分配好內(nèi)存了。
  • 解析:將類(lèi)中的符號(hào)引用轉(zhuǎn)換為直接引用。

注意:如果類(lèi)加載后,未通過(guò)驗(yàn)證,則不能被使用。

3.初始化:對(duì)類(lèi)的靜態(tài)變量和靜態(tài)代碼塊初始化為指定的值,執(zhí)行靜態(tài)代碼。

  • ClassLoader是Java的核心組件,所有的Class都是由ClassLoader進(jìn)行加載的。
  • ClassLoader是否可以運(yùn)行,則由Execution Engine決定。
  • ClassLoader負(fù)責(zé)通過(guò)各種方式將Class信息的二進(jìn)制數(shù)據(jù)流讀入JVM內(nèi)部,轉(zhuǎn)換為一個(gè)與目標(biāo)類(lèi)對(duì)應(yīng)的java.lang.Class對(duì)象實(shí)例,然后交給Java虛擬機(jī)進(jìn)行鏈接、初始化等操作。

3、類(lèi)加載的分類(lèi)

分為顯式加載 vs 隱式加載(即JVM加載class文件到內(nèi)存的方式)

3.1、顯示加載:

在代碼中顯示調(diào)用ClassLoader加載class對(duì)象。

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

  • 1.Class.forName(name)
  • 2.this.getClass().
  • 3.getClassLoader().loadClass() 。

加載class對(duì)象。

3.2、隱式加載:

通過(guò)虛擬機(jī)自動(dòng)加載到內(nèi)存中,是不直接在代碼中調(diào)用ClassLoader的方法加載class對(duì)象,類(lèi)在被引用(如調(diào)用靜態(tài)方法或訪問(wèn)靜態(tài)字段)時(shí)自動(dòng)加載。

如在加載某個(gè)類(lèi)的class文件時(shí),該類(lèi)的class文件中引用了另外一個(gè)類(lèi)的對(duì)象,此時(shí)額外引用的類(lèi)將通過(guò)JVM自動(dòng)加載到內(nèi)存中。

代碼示例:

// 隱式加載
User user = new User();
// 顯式加載,并初始化
Class clazz = Class.forName("com.test.java.User");
// 顯式加載,但不初始化
ClassLoader.getSystemClassLoader().loadClass("com.test.java.Parent"); 

心得:

  • 隱式加載:為開(kāi)發(fā)者簡(jiǎn)化了加載過(guò)程,不需要顯式調(diào)用,通常在程序中不易察覺(jué)。
  • 顯式加載:可用于動(dòng)態(tài)加載類(lèi),靈活控制加載時(shí)機(jī)。

4、命名空間

命名空間指的是在一定范圍內(nèi),標(biāo)識(shí)符(如類(lèi)名、變量名等)被唯一綁定到一個(gè)特定的實(shí)體。對(duì)于類(lèi)加載器而言,命名空間是指每個(gè)類(lèi)加載器有其各自的發(fā)現(xiàn)和加載類(lèi)的范圍,它負(fù)責(zé)自己加載的類(lèi)及其依賴(lài)關(guān)系。

4.1、類(lèi)加載器和命名空間的關(guān)系

1.隔離性

每個(gè)類(lèi)加載器都有一個(gè)獨(dú)立的命名空間。相同類(lèi)名的類(lèi)可以在不同的類(lèi)加載器中存在,而彼此不會(huì)干擾。

例如,一個(gè) JAR 中的 com.example.MyClass 可以通過(guò)不同的類(lèi)加載器各自加載,而不會(huì)發(fā)生沖突。

2.父類(lèi)優(yōu)先原則

當(dāng)一個(gè)類(lèi)加載器加載類(lèi)時(shí),它會(huì)首先將加載請(qǐng)求委托給它的父類(lèi)加載器。這種機(jī)制確保了核心類(lèi)庫(kù)得以?xún)?yōu)先加載,從而避免了相同名稱(chēng)的類(lèi)在不同上下文中出現(xiàn)。

4.2、示例

以下是一個(gè)簡(jiǎn)單的示例,展示不同類(lèi)加載器之間的命名空間如何影響類(lèi)的加載。

MyClass.java:

package com.example;

public class MyClass {
    static {
        System.out.println("MyClass loaded!");
    }
}

CustomClassLoader.java:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class CustomClassLoader extends ClassLoader {
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String filePath = name.replace('.', File.separatorChar) + ".class";
        try (FileInputStream fis = new FileInputStream(new File(filePath))) {
            byte[] b = new byte[fis.available()];
            fis.read(b);
            return defineClass(name, b, 0, b.length);
        } catch (IOException e) {
            throw new ClassNotFoundException("Class not found: " + name, e);
        }
    }
}

Main.java:

public class Main {
    public static void main(String[] args) {
        try {
            CustomClassLoader loader1 = new CustomClassLoader();
            CustomClassLoader loader2 = new CustomClassLoader();

            // 使用兩個(gè)自定義類(lèi)加載器加載同一類(lèi)
            Class<?> class1 = loader1.loadClass("com.example.MyClass");
            Class<?> class2 = loader2.loadClass("com.example.MyClass");

            // 檢查兩個(gè)類(lèi)加載器加載的類(lèi)是否相同
            System.out.println("Are class1 and class2 the same? " + (class1 == class2));

            // 創(chuàng)建實(shí)例
            Object instance1 = class1.getDeclaredConstructor().newInstance();
            Object instance2 = class2.getDeclaredConstructor().newInstance();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

當(dāng)運(yùn)行 Main.java 時(shí),輸出可能會(huì)是:由于加載器不同。

MyClass loaded!
MyClass loaded!
Are class1 and class2 the same? false

解釋

  • 雙重加載:由于我們使用了兩個(gè)不同的自定義類(lèi)加載器 (loader1loader2) 來(lái)加載同一個(gè)類(lèi) com.example.MyClass,因此它們?cè)趦?nèi)存中生成了兩個(gè)不同的 Class 實(shí)例。
  • 命名空間隔離class1class2 雖然指向同一個(gè)類(lèi)的符號(hào)引用,但由于在不同的類(lèi)加載器中加載,它們擁有獨(dú)立的命名空間,因此 class1 == class2 結(jié)果為 false。

總結(jié)

  • 命名空間:為每個(gè)類(lèi)加載器創(chuàng)建了一個(gè)獨(dú)立的命名空間,使得相同名稱(chēng)的類(lèi)可以共存于不同的上下文中。
  • 父類(lèi)優(yōu)先原則:用于提升類(lèi)加載的安全性,優(yōu)先通過(guò)父類(lèi)加載器查找類(lèi)。
  • 自定義類(lèi)加載器:可以實(shí)現(xiàn)輕松管理類(lèi)加載過(guò)程,提供更多靈活性和控制權(quán)。

5、類(lèi)加載器的分類(lèi)

JVM支持兩種類(lèi)型的類(lèi)加載器,分別為引導(dǎo)類(lèi)加載器(Bootstrap ClassLoader)和自定義類(lèi)加載器(C z ClassLoader)。

  • Bootstrap ClassLoader(啟動(dòng)類(lèi)加載器)
  • Extension ClassLoader(擴(kuò)展類(lèi)加載器)
  • Application ClassLoader(系統(tǒng)類(lèi)加載器):

自定義類(lèi)加載器:擴(kuò)展 java.lang.ClassLoader

代碼示例:

public class ClassTestLoader extends ClassLoader{
    public static void main(String[] args) throws ClassNotFoundException {
        ClassLoader classLoader = new ClassTestLoader();
        Class<?> clazz = classLoader.loadClass("com.ali.sls.test.Counter");
        System.out.println("class loader:=="+ clazz.getClassLoader());
        System.out.println("class loader:=="+ clazz.getClassLoader().getParent());
        System.out.println("class loader:=="+ clazz.getClassLoader().getParent().getParent());
    }
}

class loader:==sun.misc.Launcher$AppClassLoader@18b4aac2
class loader:==sun.misc.Launcher$ExtClassLoader@6433a2
class loader:==null

6、雙親委派

Java的類(lèi)加載機(jī)制采用了雙親委派模型(Parent Delegation Model)。該模型的核心思想是:當(dāng)一個(gè)類(lèi)加載器試圖加載某個(gè)類(lèi)時(shí),它會(huì)先將這個(gè)請(qǐng)求委托給父類(lèi)加載器,而不是自己直接加載。只有當(dāng)父類(lèi)加載器無(wú)法找到該類(lèi)時(shí),才由當(dāng)前類(lèi)加載器嘗試加載。

6.1、緩存機(jī)制


每個(gè)類(lèi)加載器(包括父類(lèi)加載器)都會(huì)維護(hù)一個(gè)緩存,用于存儲(chǔ)已經(jīng)加載過(guò)的類(lèi)。當(dāng)類(lèi)加載器收到加載請(qǐng)求時(shí),會(huì)首先檢查緩存中是否已經(jīng)加載過(guò)該類(lèi)。如果已經(jīng)加載過(guò),則直接返回緩存的類(lèi),而不會(huì)重新加載。

  • 子類(lèi)加載器加載的類(lèi)

子類(lèi)加載器加載的類(lèi)會(huì)存儲(chǔ)在子類(lèi)加載器的緩存中,父類(lèi)加載器無(wú)法訪問(wèn)子類(lèi)加載器的緩存。

  • 父類(lèi)加載器加載的類(lèi)

父類(lèi)加載器加載的類(lèi)會(huì)存儲(chǔ)在父類(lèi)加載器的緩存中,子類(lèi)加載器可以通過(guò)雙親委派機(jī)制訪問(wèn)父類(lèi)加載器的緩存。

因此,如果子類(lèi)加載器已經(jīng)加載了某個(gè)類(lèi),父類(lèi)加載器不會(huì)再次加載該類(lèi),因?yàn)楦割?lèi)加載器無(wú)法感知子類(lèi)加載器的緩存。

6.2、類(lèi)的唯一性

在JVM中,類(lèi)的唯一性是由 類(lèi)的全限定名 + 類(lèi)加載器 共同決定的。即使兩個(gè)類(lèi)加載器加載了同一個(gè)類(lèi)的字節(jié)碼,JVM也會(huì)將它們視為不同的類(lèi)。

如果子類(lèi)加載器加載了一個(gè)類(lèi),父類(lèi)加載器再次嘗試加載同一個(gè)類(lèi),JVM會(huì)認(rèn)為這是兩個(gè)不同的類(lèi)(因?yàn)轭?lèi)加載器不同)。這可能導(dǎo)致 類(lèi)沖突 或 類(lèi)型轉(zhuǎn)換異常,因?yàn)镴VM認(rèn)為這兩個(gè)類(lèi)是獨(dú)立的。

6.3、工作流程:

類(lèi)加載器接收到加載請(qǐng)求時(shí),首先將請(qǐng)求委派給父類(lèi)加載器。

如果父類(lèi)加載器能找到該類(lèi),則加載成功;如果父類(lèi)加載器無(wú)法加載該類(lèi),則由當(dāng)前類(lèi)加載器加載。這種機(jī)制確保了Java核心類(lèi)庫(kù)不會(huì)被用戶(hù)自定義的類(lèi)加載器替代或覆蓋。

6.4、如何打破

1:自定義類(lèi)加載器

我們將創(chuàng)建一個(gè)自定義的類(lèi)加載器,它直接加載某個(gè)特定包中的類(lèi),而不經(jīng)過(guò)父加載器。

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class MyClassLoader extends ClassLoader {
    private String classPath;

    public MyClassLoader(String classPath) {
        this.classPath = classPath;
    }

    @Override
    protected Class<?> loadClass(String name) throws ClassNotFoundException {
        // 檢查是否需要執(zhí)行自定義加載
        if (name.startsWith("com.example")) {
            // 這里實(shí)際上不調(diào)用父類(lèi)加載器
            return findClass(name);
        }
        // 否則,使用默認(rèn)的父類(lèi)加載器
        return super.loadClass(name);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String filePath = classPath + File.separator + name.replace('.', File.separatorChar) + ".class";
        try (FileInputStream fis = new FileInputStream(filePath)) {
            byte[] b = new byte[fis.available()];
            fis.read(b);
            return defineClass(name, b, 0, b.length);
        } catch (IOException e) {
            throw new ClassNotFoundException("Class not found: " + name, e);
        }
    }
}

解釋

  • loadClass 方法中,我們直接處理以 com.example 開(kāi)頭的類(lèi),調(diào)用 findClass 來(lái)加載。而對(duì)于其他類(lèi),則調(diào)用 super.loadClass(name),這表明默認(rèn)的父類(lèi)加載器將處理它。

注意:確保 com/example/MyClass.class 文件在 "path/to/classes" 目錄中。

2.使用 Thread 的上下文類(lèi)加載器

在某些情況下,也可以通過(guò)設(shè)置當(dāng)前線程的上下文類(lèi)加載器(context class loader)來(lái)打破雙親委派。

public class ContextClassLoaderExample {
    public static void main(String[] args) {
        // 設(shè)置自定義類(lèi)加載器為當(dāng)前線程的上下文類(lèi)加載器
        Thread.currentThread().setContextClassLoader(new MyClassLoader("path/to/classes"));

        // 然后通過(guò)上下文類(lèi)加載器加載類(lèi)
        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        try {
            Class<?> myClass = contextClassLoader.loadClass("com.example.MyClass"); // 直接調(diào)用上下文類(lèi)加載器
            System.out.println("Loaded class: " + myClass.getName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

7、類(lèi)的卸載

Java 的 GC(垃圾回收)會(huì)在類(lèi)引用不存在時(shí)進(jìn)行類(lèi)的卸載。只有使用 ClassLoader 加載的類(lèi),如果其 ClassLoader 被卸載,該類(lèi)才會(huì)被卸載。

類(lèi)的卸載并不是一個(gè)強(qiáng)制性的操作,只有在特定條件下才會(huì)發(fā)生。

7.1、卸載條件

類(lèi)的卸載發(fā)生在以下情況下:

1.類(lèi)加載器被垃圾回收

當(dāng)沒(méi)有任何引用指向某個(gè)類(lèi)加載器時(shí),該類(lèi)加載器及其所加載的類(lèi)有可能被卸載。JVM 可以回收類(lèi)加載器,并同時(shí)卸載它加載的所有類(lèi)。

2.類(lèi)及其類(lèi)加載器均無(wú)法到達(dá)

類(lèi)和類(lèi)加載器不僅沒(méi)有引用,而且它們?cè)诔A砍?、棧幀等處也不再被引用時(shí),可以進(jìn)行卸載。

7.2、觸發(fā)條件

雖然部分類(lèi)可以在 Java 程序運(yùn)行時(shí)被卸載,但是的確沒(méi)有顯式的方法去卸載類(lèi),整個(gè)卸載過(guò)程是由 JVM 的垃圾回收器自動(dòng)處理。

以下是一些觸發(fā)類(lèi)卸載的條件。

1.動(dòng)態(tài)類(lèi)加載

當(dāng)使用自定義類(lèi)加載器動(dòng)態(tài)加載類(lèi)時(shí),如果不再有引用指向這個(gè)類(lèi)和類(lèi)加載器,它們會(huì)被視為垃圾對(duì)象,從而可能被回收。

2.Classpath 變化

如果應(yīng)用程序在運(yùn)行時(shí)改變了類(lèi)路徑(比如加載新版本的同名類(lèi)),舊的類(lèi)及其加載器可能被卸載。

以下是一個(gè)類(lèi)卸載的簡(jiǎn)單示例:

public class ClassUnloadingExample {
    public static void main(String[] args) {
        CustomClassLoader classLoader = new CustomClassLoader();
        
        try {
            Class<?> clazz1 = classLoader.loadClass("com.example.MyClass");
            
            // 使用 clazz1
            Object instance = clazz1.getDeclaredConstructor().newInstance();
            System.out.println("Class Loaded: " + clazz1.getName());

            // 設(shè)置 classLoader 為 null,解除引用
            classLoader = null;

            // 觸發(fā)垃圾回收
            System.gc();
            Thread.sleep(1000); // 確保 GC 有足夠時(shí)間運(yùn)行

            // 這里將不會(huì)再有引用指向這個(gè)類(lèi),可能被卸載
            System.out.println("Unloading classes...");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

// 自定義類(lèi)加載器
class CustomClassLoader extends ClassLoader {
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // 加載類(lèi)的邏輯
        // 假設(shè)類(lèi)文件框架完整
        return super.findClass(name);
    }
}

8、類(lèi)加載異常處理

在類(lèi)加載過(guò)程中可能會(huì)遇到的異常主要有:

  • ClassNotFoundException: 當(dāng)請(qǐng)求的類(lèi)不存在時(shí)拋出。
  • NoClassDefFoundError: 類(lèi)存在但不再可用,通常是因?yàn)?class 文件被刪除或 JVM 啟動(dòng)時(shí)未找到。
  • UnsupportedClassVersionError: 由于 Java 版本不兼容導(dǎo)致的錯(cuò)誤。

總結(jié)

通過(guò)上述文章的介紹,希望可以幫助開(kāi)發(fā)者在項(xiàng)目日常中更加清晰了解java類(lèi)的加載機(jī)制原理。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論