通常來講,咱們把java的類加載過程分爲三個主要步驟:加載,連接,初始化。 首先是加載階段,它是java將字節碼數據從不一樣的數據源讀取到JVM中,並映射爲JVM承認的數據結構,並映射爲JVM承認的數據結構(Class對象),這裏的數據源多是各類各樣的形態,如jar文件,class文件,甚至是網絡數據源;若是輸入的數據不是ClassFile的結構,則會拋出ClassFormatError。 第二階段是連接(Linking),這是核心的步驟,簡單說是吧原始的類定義信息平滑地轉化如JVM運行的過程當中。這裏可進一步新氛圍三個步驟:java
package com.wzl.day11; /** * @author wuzhilang * @Title: Day11 * @ProjectName questions * @Description: TODO * @date 8/27/20196:27 PM */ /** * 編譯並反編譯一下: * 命令:Javac Day11.java * Javap –v Day11.class */ public class Day11 { public static int a = 100; public static final int INT_CONSTANT = 1000; public static final Integer INTEGER_CONSTANT = Integer.valueOf(10000); }
運行安全
javac -encoding UTF-8 Day11.java Javap –v Day11.class
輸出的結果爲網絡
Classfile /D:/questions/question/src/com/wzl/day11/Day11.class Last modified Aug 27, 2019; size 471 bytes MD5 checksum c71fc3ab252eb1585d635d591ac61712 Compiled from "Day11.java" public class com.wzl.day11.Day11 minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #6.#21 // java/lang/Object."<init>":()V #2 = Fieldref #5.#22 // com/wzl/day11/Day11.a:I #3 = Methodref #23.#24 // java/lang/Integer.valueOf:(I)Ljava/lang/Integer; #4 = Fieldref #5.#25 // com/wzl/day11/Day11.INTEGER_CONSTANT:Ljava/lang/Integer; #5 = Class #26 // com/wzl/day11/Day11 #6 = Class #27 // java/lang/Object #7 = Utf8 a #8 = Utf8 I #9 = Utf8 INT_CONSTANT #10 = Utf8 ConstantValue #11 = Integer 1000 #12 = Utf8 INTEGER_CONSTANT #13 = Utf8 Ljava/lang/Integer; #14 = Utf8 <init> #15 = Utf8 ()V #16 = Utf8 Code #17 = Utf8 LineNumberTable #18 = Utf8 <clinit> #19 = Utf8 SourceFile #20 = Utf8 Day11.java #21 = NameAndType #14:#15 // "<init>":()V #22 = NameAndType #7:#8 // a:I #23 = Class #28 // java/lang/Integer #24 = NameAndType #29:#30 // valueOf:(I)Ljava/lang/Integer; #25 = NameAndType #12:#13 // INTEGER_CONSTANT:Ljava/lang/Integer; #26 = Utf8 com/wzl/day11/Day11 #27 = Utf8 java/lang/Object #28 = Utf8 java/lang/Integer #29 = Utf8 valueOf #30 = Utf8 (I)Ljava/lang/Integer; { public static int a; descriptor: I flags: ACC_PUBLIC, ACC_STATIC public static final int INT_CONSTANT; descriptor: I flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL ConstantValue: int 1000 public static final java.lang.Integer INTEGER_CONSTANT; descriptor: Ljava/lang/Integer; flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL public com.wzl.day11.Day11(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 16: 0 static {}; descriptor: ()V flags: ACC_STATIC Code: stack=1, locals=0, args_size=0 0: bipush 100 2: putstatic #2 // Field a:I 5: sipush 10000 8: invokestatic #3 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 11: putstatic #4 // Field INTEGER_CONSTANT:Ljava/lang/Integer; 14: return LineNumberTable: line 17: 0 line 19: 5 } SourceFile: "Day11.java"
能夠看出,普通原始類型靜態變量和引用類型(即便是變量),是須要額外調用putstatic等jvm指令的,這些是在顯式初始化階段執行,而不是準備階段調用;而原始類型的變量,則不須要這樣的步驟。數據結構
# 指定新的bootclasspath,替換java.*包的內部實現 java -Xbootclasspath:<your_boot_classpath> your_App # a意味着append,將指定目錄添加到bootclasspath後面 java -Xbootclasspath/a:<your_dir> your_App # p意味着prepend,將指定目錄添加到bootclasspath前面 java -Xbootclasspath/p:<your_dir> your_App
用法其實很易懂,例如,使用最多見的 「/p」 ,既然是前置,就有機會替換個別基礎類的實現。 咱們通常可使用下面方法獲取類加載器,可是一般的JDK/JRE實現中,擴展類加載器getParent()都只能返回null。架構
public final ClassLoader getParent()
java -Djava.system.class.loader=com.yourcorn.YourClassLodader HelloWorld
若是咱們指定了這個桉樹,JDK內建的應用類加載器就會後才能爲定製加載器的父類,這種方式一般用在相似須要改變雙親委派模式的場景。app
具體的操做以下: 一般類加載機制有三個基本特徵:框架