1. 程式人生 > >【深入理解Java虛擬機器 】類載入器的名稱空間以及類的解除安裝

【深入理解Java虛擬機器 】類載入器的名稱空間以及類的解除安裝

類載入器的名稱空間

  • 每個類載入器又有一個名稱空間,由其以及其父載入器組成

類載入器的名稱空間的作用和影響

  • 每個類載入器又有一個名稱空間,由其以及其父載入器組成
  • 在每個類載入器自己的名稱空間中不能出現相同類名的類 (此處值得是類的全名,包含包名)
  • 在不同的類名稱空間中,可能會出現多個相同的類名的類

如下面的程式碼示例中, 首先定義一個類載入器 MyClassLoader

  static class MyClassLoader extends ClassLoader {

    private String classLoaderName;

    private String classPath;

    public MyClassLoader(String classPath, String classLoaderName) {
      super(); // 未指定則預設使用應用類載入器
      this.classLoaderName = classLoaderName;
      this.classPath = classPath;
    }

    public MyClassLoader(ClassLoader parent, String classLoaderName) {
      super(parent); // 顯式的指定父類載入器
      this.classLoaderName = classLoaderName;
    }

    @Override
    protected Class<?> findClass(String name) {
      System.out.println("MyClassLoader.findClass");
      byte[] bytes = null;
      try {
        bytes = loadClassByte(name);
        return defineClass(name, bytes, 0, bytes.length);
      } catch (Exception e) {

        throw new RuntimeException(e);
      }
    }

    private byte[] loadClassByte(String name) throws Exception {
      name = name.replace(".", "/");
      File file = new File(this.classPath + name + ".class");

      try (ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
          InputStream fileStream = new FileInputStream(file)) {

        int ch;
        while ((ch = fileStream.read()) != -1) {
          byteStream.write(ch);
        }
        return byteStream.toByteArray();
      }
    }
  }

下面我們嘗試使用此類載入載入一個磁碟的class檔案,程式碼如下:

  public static void main(String[] args) throws ClassNotFoundException {
    MyClassLoader classLoader = new MyClassLoader("/tmp/", "CustomClassLoader");
    Class<?> aClass = classLoader.loadClass("com.zhoutao.classload.ReferenceExample004");
    ClassLoader loader = aClass.getClassLoader();
    System.out.println(loader);

    System.out.println("----------------------");

    MyClassLoader classLoader2 = new MyClassLoader("/tmp/", "CustomClassLoader");
    Class<?> aClass2 = classLoader2.loadClass("com.zhoutao.classload.ReferenceExample004");
    ClassLoader loader2 = aClass2.getClassLoader();
    System.out.println(loader);
  }

按照之前的理論,由於 ReferenceExample004 類在classLoader 中已經被載入,那麼在 classLoader2 中將不會被載入,我們看一下輸出的結果

MyClassLoader.findClass
com.zhoutao.classload.ReferenceExample010$MyClassLoader@610455d6
----------------------
MyClassLoader.findClass
com.zhoutao.classload.ReferenceExample010$MyClassLoader@60e53b93

總結

可以看到,類載入器的findClass(String) 方法被執行了兩次,這是因為載入該類的類載入器是兩個不同的物件,在文章的開頭提及:每個類載入器又有一個名稱空間,由其以及其父載入器組成

上面的兩個類載入器顯然名稱空間不一致,所以findClass() 方法會被執行兩次

類的解除安裝

在記憶體中的 Class 類沒有引用的時候就會被 JVM 解除安裝,因為 JVM 自帶的類載入 啟動類載入器,拓展類載入器以及應用類載入器,在三個類載入的例項一直被 JVM 引用,所以JVM 自帶的類載入器載入的類一直被其載入器引用,所以不會被解除安裝
但是自定義的類載入器的例項可以被手動的設定為null,這導致類載入不再被引用,其所載入的 class 類在沒有例項其沒有類載入器引用的情況下就會被解除安裝,解除安裝的時間發生在系統垃圾回收的時候

類的解除安裝測試

同類的載入一樣,要觀察到類的解除安裝,可以通過新增 JVM 引數-XX:+TraceClassUnloading 的方式輸入類的解除安裝資訊。

  public static void main(String[] args) throws ClassNotFoundException, InterruptedException {
    MyClassLoader classLoader = new MyClassLoader("/tmp/", "CustomClassLoader");
    Class<?> aClass = classLoader.loadClass("com.zhoutao.classload.ReferenceExample004");

    classLoader = null;
    aClass = null;

    // 手動觸發GC 觀察類回收的資訊

    System.gc();

    TimeUnit.SECONDS.sleep(10);
  }

通過控制檯可以觀察到類的解除安裝記錄:

MyClassLoader.findClass
[Unloading class com.zhoutao.classload.ReferenceExample004 0x00000007c0061028]

或者通過JVisual 工具觀察到類的解除安裝過程, 為了便於觀察,適當加長 延時的時間 TimeUnit.SECONDS.sleep(100);, 終端或者CMD終端 輸入 jvisualvm 命令啟動,啟動測試程式,在 jvisualvm 工具中接連到該執行緒,可以看到下面的資訊:

已解除安裝的總數為: 1

歡迎關注微信公眾號獲取更多開發技巧幹貨

相關推薦

深入理解Java虛擬機器載入機制

本文內容來源於《深入理解Java虛擬機器》一書,非常推薦大家去看一下這本書。本系列其他文章:【深入理解Java虛擬機器】垃圾回收機制1、類載入機制概述虛擬機器把描述類的資料從Class檔案載入到記憶體,並對資料進行校驗、轉換解析和初始化,最終形成可以被虛擬機器直接使用的Jav

深入理解Java虛擬機器 載入名稱空間以及解除安裝

類載入器的名稱空間 每個類載入器又有一個名稱空間,由其以及其父載入器組成 類載入器的名稱空間的作用和影響 每個類載入器又有一個名稱空間,由其以及其父載入器組成 在每個類載入器自己的名稱空間中不能出現相同類名的類 (此處值得是類的全名,包含包名) 在不同的類名稱空間中,可能會出現多個相同的類名的類 如下

深入理解Java 虛擬機器學習筆記一

目錄 執行時資料區域 根索引演算法 垃圾回收演算法 垃圾收集器 雙親委派模型 JDK命令列工具Jstack 和 JConsole 1、執行時資料區域 執行緒共享:方法區、堆 執行緒私有:虛擬機器棧、本地方法棧、程式計數器 2、根索引演

深入理解java虛擬機器第0集--Java記憶體區域和java記憶體模型

首先我們清楚【記憶體區域】和【記憶體模型】是兩個不一樣的概念。當時我電面阿里的時候,面試官讓我講講記憶體模型的理解,我巴拉巴拉說了一通方法區-堆分割槽,垃圾演算法,面試官耐心的聽我說完就把電話掛了。 【記憶體區域】對應的是jvm程序。jvm啟動之後,自身是一個大的程序,作業

深入理解Java虛擬機器學習小結

第一章 走近Java 摘書 Java各個版本新特性 1.0:Java1.0提供了一個純解釋執行的Java虛擬機器實現(Sun Classic VM)。JDK1.0版本的代表技術包括:Java虛擬機

深入理解Java虛擬機器Java記憶體區域模型、物件建立過程、常見OOM

本文內容來源於《深入理解Java虛擬機器》一書,非常推薦大家去看一下這本書。最近開始看這本書,打算再開一個相關係列,來總結一下這本書中的重要知識點。呃呃呃,說好的那個圖片請求框架呢~  不要急哈,因為這個請求框架設計的內容還是比較廣的,目前業餘時間正在編寫當中,弄好了之後就會

深入理解Java虛擬機器垃圾回收機制

本文內容來源於《深入理解Java虛擬機器》一書,非常推薦大家去看一下這本書。本系列其他文章:1、垃圾回收要解決的問題垃圾收集(Garbage Collection,GC),要設計一個GC,需要考慮解決下面三件事情:(1)哪些記憶體需要回收?(2)什麼時候回收?(3)如何回收?

深入理解 Java 虛擬機器筆記檔案結構

5.類檔案結構 由於最近十年內虛擬機器以及大量建立在虛擬機器之上的程式語言如雨後春筍般出現並蓬勃發展,將我們編寫的程式編譯成二進位制本地機器碼(Native Code)已不再是唯一的選擇,越來越多的程式語言選擇了作業系統和機器指令集無關的、平臺中立的格式作為程式

深入理解 Java 虛擬機器筆記虛擬機器位元組碼執行引擎

7.虛擬機器位元組碼執行引擎 執行引擎是 Java 虛擬機器最核心的組成部分之一。在 Java 虛擬機器規範中制定了虛擬機器位元組碼執行引擎的概念模型,這個概念模型成為各種虛擬機器執行引擎的統一外觀(Facade)。不同的虛擬機器實現,執行引擎可能會有解釋執行和編譯執行兩種,有可能兩

深入理解 Java 虛擬機器筆記虛擬機器效能監控與故障處理工具

3.虛擬機器效能監控與故障處理工具 定位問題時,知識和經驗是關鍵基礎、資料(執行日誌、異常堆疊、GC日誌、執行緒快照、堆轉儲快照)是依據、工具是運用知識處理資料的手段。 思維導圖 JDK的命令列工具 jps: 虛擬機器程序狀況工具 jps(JVM Proce

深入理解JVM虛擬機器第1章 走進java

1.1Java技術體系 Sun 官方定義的Java技術體系包括以下幾個組成部分: Java 程式設計語言 各種硬體平臺上的 Java 虛擬機器 Class 檔案格式 Java API 類庫 第三方 Java 類庫 1.1.1 Java API 按照技術所服

深入理解JVM虛擬機器第3章 垃圾收集與記憶體分配策略

3.1 概述 垃圾收集(Garbage Collection , GC)的歷史遠遠比Java久遠。它需要完成三件事: 哪些記憶體需要回收 什麼時候回收 如何回收 程式計數器、虛擬機器棧、本地

[深入理解Java虛擬機器]第九章 位元組碼執行引擎-載入及執行子系統的案例與實戰

概述 在Class檔案格式與執行引擎這部分中,使用者的程式能直接影響的內容並不太多, Class檔案以何種格式儲存,型別何時載入、如何連線,以及虛擬機器如何執行位元組碼指令等都是由虛擬機器直接控制的行為,使用者程式無法對其進行改變。能通過程式進行操作的,主要是

深入理解Java虛擬自動內存管理機制——內存區域劃分

現在 深入 元素 原因 生成 內存泄漏 即時編譯器 內存劃分 責任 ??Java與C++之間有一堵有內存動態分配和垃圾收集技術所圍成的“高墻”,墻外面的人想進去,墻裏面的人卻想出來。C/C++程序員既擁有每一個對象的所有權,同時也擔負著每一個對象生命從開始到終結的維護責任,

閱讀筆記-深入理解java虛擬機器-1-垃圾回收

垃圾蒐集器可以混用 垃圾收集其是記憶體回收的具體實現。收集演算法是記憶體回收的方法論 Serial收集器: 基本,最久的回收器,並不僅僅是使用一個CPU或者一條收集執行緒完成垃圾收集工作,重要的是在垃圾回收時必須暫停其他所有的工作執行緒(stop the world)

深入理解java虛擬機器之垃圾收集

  前言   如果說收集演算法是記憶體回收的方法論,那麼垃圾收集器就是記憶體回收的具體實現。java虛擬機器規範中對垃圾收集器應該如何實現並沒有任何規定,因此不同的廠商、不同的版本的虛擬機器所提供的垃圾收集器都有可能會有很大的區別,並且一般都會提供引數供使用者根據自己的應用特點和要求組合出各個年代所使用的收集

Java深入理解Java虛擬機器」學習筆記(1) - Java語言發展趨勢

這本書寫的比較早,現在這些功能都已經不同程度的實現了。 1、模組化     JDK9之前的版本都是一個整體,使用者可能只需要使用一個小功能,但他不得不下載整個JDK。不能滿足定製化需求,顯然Java語言的發展因此大大受限。   所以,Sun公司在OpenJDK建立了一個Jigsaw(拼圖)的專案來推動模

Java深入理解Java虛擬機器」學習筆記(2)-記憶體管理

 一、執行時資料區   JVM在執行Java程式的時候,將其執行時資料區劃分為若干不同區域。它們的用途和建立及銷燬的時間不同。      1、程式計數器(Program Counter Register)     是一塊很小的記憶體空間。當執行緒執行的是Java方法,它記錄的是當前正在執行的

Java面試寶典深入理解JAVA虛擬機器

一、執行時資料區域   執行緒隔離:執行緒隔離的意思,就是給不同的執行緒多分配的資源用,以做到不爭用。   執行緒共享:執行緒共享就是資源只有一個沒有辦法分配更多,只能共享。   Java虛擬機器管理的記憶體包括幾個執行時資料記憶體:方法區、虛擬機器棧、本地方法棧、堆、程式計數器,其中方法區和堆是由執行

[連載] 深入理解Java虛擬機器(JVM高階特性與最佳實踐)之 走近Java

連載目錄 :    http://blog.csdn.net/u010903284/article/details/53117958 1.1 Java概述:               Java 不僅僅是一門程式語言,還是一個由一系列計算機軟體和規範形成的技術體系,這個技