JVM學習(2):類載入器

来源:https://www.cnblogs.com/xuyiqing/archive/2020/03/12/12468440.html
-Advertisement-
Play Games

什麼是類載入器: public class ClassInit { public static void main(String[] args) { ClassLoader c=ClassInit.class.getClassLoader(); } } 上面這個ClassLoader就是類載入器 打 ...


什麼是類載入器:

public class ClassInit {
    public static void main(String[] args) {
        ClassLoader c=ClassInit.class.getClassLoader();
    }
}

上面這個ClassLoader就是類載入器

列印c,註意到一個Launcher類:

sun.misc.Launcher$AppClassLoader@18b4aac2

 

進入Launcher類,註意到其中的兩段代碼:

var1 = Launcher.ExtClassLoader.getExtClassLoader();
this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);

其中的ExtClassLoader和AppClassLoader有什麼關係呢?

 

修改成如下代碼:

public class ClassInit {
    public static void main(String[] args) {
        ClassLoader c = ClassInit.class.getClassLoader();
        while (c != null) {
            System.out.println(c);
            c = c.getParent();
        }
    }
}

列印:

sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@1540e19d

 於是得到了結論:AppClassLoader有一個父親是ExtClassLoader

 

繼續分析ClassLoader,註意到一段代碼:

    protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e)

獨占鎖保證了同時只能載入一個類

然後檢查這個類是否被載入過,如果被載入過直接返回;

如果沒有被載入過,那麼就遞歸載入他的父親,直到沒有父親,最後執行findBootstrapClassOrNull()

 

往下看發現這樣一段代碼:

    // return null if not found
    private native Class<?> findBootstrapClass(String name);

這個函數沒有函數體,被native修飾,代表調用一個本地方法

這裡調用本地方法,根據操作系統的不同,調用的本地方法介面不同,然後調用本地方法庫

 

得出結論:

一個類的載入順序是:BootstrapClassLoader--->ExtClassLoader--->AppClassLoader

一個類的檢查順序是:AppClassLoader--->ExtClassLoader--->BootstrapClassLoader

 

為什麼載入順序要從BootstrapClassLoader開始呢?

寫一個新代碼,包名和類名與java源碼的List一樣:

package java.util;

public class List{
 public static void main(String[] args){
   xxxxxx
 }
}

發現無法運行,報錯:在類java.util.List中找不到main方法

無法運行是非常合理的,否則一個黑客豈不是可以輕易植入病毒代碼,然後通過自定義類載入器加入到JVM中

 

這種機制稱為:雙親委任

目的:安全

1.父類如果可以載入,那麼不允許子類載入

2.保證一個類只載入一次

 

判斷兩個對象是不是相等,最重要的條件是看是不是一個類載入器:

寫一個代碼:

package org.dreamtech.cl;

import java.io.IOException;
import java.io.InputStream;

public class ClassInit {
    //自定義類載入器
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        ClassLoader loader = new ClassLoader() {
            @Override
            public Class<?> loadClass(String name) throws ClassNotFoundException {
                try {
                    String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
                    InputStream is = getClass().getResourceAsStream(fileName);
                    if (is == null) {
                        return super.loadClass(name);
                    }
                    byte[] b = new byte[is.available()];
                    is.read(b);
                    return defineClass(name, b, 0, b.length);
                } catch (IOException e) {
                    throw new ClassNotFoundException();
                }
            }
        };
        String className = "org.dreamtech.cl.ClassInit";
        Object o1 = ClassInit.class.getClassLoader().loadClass(className).newInstance();
        Object o2 = loader.loadClass(className).newInstance();
        System.out.println(o1 == o2);
        System.out.println(o1.equals(o2));
        System.out.println(o1 instanceof org.dreamtech.cl.ClassInit);
        System.out.println(o2 instanceof org.dreamtech.cl.ClassInit);
        System.out.println(o1.getClass().getClassLoader());
        System.out.println(o2.getClass().getClassLoader());
    }
}

列印如下:

false
false
true
false
sun.misc.Launcher$AppClassLoader@18b4aac2
org.dreamtech.cl.ClassInit$1@14ae5a5

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本人免費整理了Java高級資料,涵蓋了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高併發分散式等教程,一共30G,需要自己領取。傳送門:https://mp.weixin.qq.com/s/osB-BOl6W-ZLTSttTkqMPQ 關 ...
  • 有天上飛的概念,就要有落地的實現 概念十遍不如代碼一遍,朋友,希望你把文中所有的代碼案例都敲一遍 先贊後看,養成習慣 SpringBoot 圖文教程系列文章目錄 1. "SpringBoot圖文教程1—SpringBoot+Mybatis 環境搭建" 2. "SpringBoot圖文教程2—日誌的使 ...
  • 轉載至:https://www.cnblogs.com/skywang12345/p/3324958.html 本章的內容主要解決下麵幾個問題: 1 equals() 的作用是什麼? 2 equals() 與 == 的區別是什麼? 3 hashCode() 的作用是什麼? 4 hashCode() ...
  • ***************************APPLICATION FAILED TO START*************************** Description: Failed to configure a DataSource: 'url' attribute is no ...
  • Android系統測試, 開始測試前,我們需要先確認所測試的系統版本是否正確, 還有報bug的時候,開發需要你提供具體的系統版本信息。 還有系統打版時間等, 不同的版本修複了不同的bug,合入了不同的新功能等, 如果測試人員測試的系統版本都不對,會直接被開發懟到哭。 如何一鍵獲取Android系統版 ...
  • 模板模式 作用:定義一個操作中的演算法的骨架。而將一些步驟延遲到子類中,模板方法使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟。其關鍵是將通用演算法(邏輯)封裝在抽象基類中,並將不同的演算法細節放到子類中實現。 在我看來,模板模式的好處在於能減少代碼段的復用,把公共行為封裝到基類中,把行為 ...
  • 前幾天本猿的大學同學,一個漂亮的小姐姐工作時遇到了一個問題,她的需求是,在公司區域網的電腦上下載大量的圖片重命名成指定得1、2、3.....以此類推,需要當天完成,我就臨時給寫了一個小demo。 我的想法是採用linux的原理不就好實現嗎,直接mv到指定文件夾下再給一個新的名字不就實現了嗎 我給出的 ...
  • 題目地址:https://www.luogu.com.cn/problem/P4850 題解原地址:https://createsj.blog.luogu.org/solution-p4850 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...