首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

《Java 深度歷險》讀書筆記 (一):JRE 尋找邏輯、類別載入器層次與 JNI 實戰

     編輯:Java 相關知識

前言

王森《Java 深度歷險》以 JVM 內部機制為主線,深入剖析類別載入、JNI、執行緒、記憶體模型等核心主題。本文整理前三章關鍵知識點,作為深入理解 Java 運行時期的基石。

第一章:JRE 尋找與啟動邏輯

執行 java MyClass 時,啟動器依序搜尋 JRE:

  1. 當前工作目錄 下是否存在 jre 目錄。
  2. 父目錄 下的 jre 子目錄。
  3. Windows 登錄表 HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment 記錄的安裝路徑。

實務啟示:環境變數 JAVA_HOME 與 PATH 設定須與實際安裝一致,避免多版本 JRE 共存導致「類別版本不符」或「找不到 JVM」錯誤。

第二章:類別載入器層次與雙親委派模型

動態載入兩種方式

  • Class.forName("className"):預設使用呼叫者類別的載入器,會執行靜態初始化 (<clinit>)。
  • ClassLoader.loadClass("className"):指定載入器,**不執行靜態初始化**,需手動 clazz.newInstance() 觸發。

JVM 內建三大載入器 (雙親委派模型)

載入器實現語言搜尋路徑來源修改方式職責
Bootstrap ClassLoaderC++ (JVM 內建)sun.boot.class.path (預設 jre/lib/rt.jar 等)java -Xbootclasspath/p:path (前置) / /a: (附加)核心類別庫 (java.*, javax.*)
Extension ClassLoaderJava (sun.misc.Launcher$ExtClassLoader)java.ext.dirs (預設 jre/lib/ext)java -Djava.ext.dirs=path擴充套件 (JCE, XML Parser 等)
Application ClassLoaderJava (sun.misc.Launcher$AppClassLoader)java.class.path (環境變數 CLASSPATH 或 -cp)java -cp path / Class-Path Manifest應用程式類別

委派流程

AppClassLoader.loadClass()
   │ 委派給父載入器
   ▼
ExtClassLoader.loadClass()
   │ 委派給父載入器
   ▼
Bootstrap Loader.findClass() → 找到則返回
   │ 找不到
   ▼
ExtClassLoader.findClass() → 找到則返回
   │ 找不到
   ▼
AppClassLoader.findClass() → 找到則返回 / 拋出 ClassNotFoundException

核心原則:請求向上委派,載入向下尋找。確保核心類別不被應用程式竄改 (如無法自定 java.lang.String)。

Context ClassLoader (執行緒上下文載入器)

  • JDBC 驅動 (DriverManager)、JNDI、SPI 機制 (ServiceLoader) 需要**逆向載入**:啟動器載入的類別 (如 java.sql.DriverManager) 需載入應用程式提供的實作類別。
  • Thread.currentThread().getContextClassLoader() 通常指向 AppClassLoader,打破雙親委派限制。

第三章:JNI (Java Native Interface) 實戰

為什麼需要 JNI

  • 存取平台特有功能 (Windows Registry, Linux inotify, 硬體驅動)。
  • 重用既有 C/C++ 庫 (影像處理、加密、壓縮)。
  • 效能關鍵路徑 (數值計算、遊戲引擎) 下沉至 Native。

開發流程

  1. Java 類別宣告 native 方法:public native void createWordDoc(String path);
  2. javac 編譯 → javah -jni ClassName 產生 .h 標頭檔。
  3. C/C++ 實作 Native 方法 (包含 jni.h,使用 JNIEnv* 操作 Java 物件)。
  4. 編譯為共享庫:Windows .dll, Linux/macOS .so。
  5. Java 執行時 System.loadLibrary("mylib") 載入,或 System.load("/full/path/libmylib.so")。

關鍵 JNI 函式

函式用途
FindClass載入 Java 類別
GetMethodID / GetFieldID取得方法/欄位 ID
CallVoidMethod / CallIntMethod呼叫 Java 實例方法
NewStringUTF / GetStringUTFCharsJava String ↔ C char* 轉換
NewObjectArray / GetObjectArrayElement陣列操作
ThrowNew拋出 Java 例外
RegisterNatives靜態註冊 (效能優於動態查找)

記憶體管理警示

  • JNI 區分 **Local Reference** (Native 方法返回自動釋放) 與 **Global Reference** (手動 NewGlobalRef/DeleteGlobalRef)。
  • 長時間持有 Local Reference 會阻礙 GC,導致記憶體洩漏。
  • 大量物件建立時使用 PushLocalFrame/PopLocalFrame 管理引用框架。

下一章預告

  • Java 執行緒模型與同步機制底層實現。
  • JVM 記憶體結構:堆、棧、方法區、直接記憶體。
  • GC 演算法演進:Serial → Parallel → CMS → G1 → ZGC/Shenandoah。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved