今天初步接觸了一下Java的動態加載概念,發現很多情景下我們都會遇到這種用法,自己當初並沒有意思到,只是把它當做那種奇奇怪怪的感覺...
首先,程序是如何跑起來的
第一步,編譯檢查、通過編譯
第二步,構建加載器對象、構建字節碼對象,完成靜態加載
第三步,在一切准備完成后,對已經加載的目標上跑線程
第四步,在跑線程過程中,獲取當前加載器對象、構建字節碼對象,完成動態加載
加載只是一個讀文件的過程,除了文件路徑並不會進行其他檢查
靜態加載可以說是動態加載的一種特殊情況
動態加載跳出了固定的編譯-加載-運行模式
典型的靜態加載
如果直接對一個Java源碼進行編譯,此時缺少Word.java,則無法通過編譯檢查,無法成功編譯
public class Office{
public static void main(String[] args) {
System.out.println("編譯完成,靜態加載完成,開始運行");
if ("Word".equals(args[0])) {
Word w = new Word();
w.start();
}
}
}
添加Word.java,成功編譯並進行靜態加載
class Word{
public static void start(){
System.out.println("word...start...");
}
}
運行結果
➜ Desktop java Office Word
編譯完成,靜態加載完成,開始運行
word...start...
運行時動態加載
將以上Office.java稍作改變,成功編譯並完成靜態加載
import java.lang.reflect.Method;
class OfficeBetter{
public static void main(String[] args){
System.out.println("編譯完成,靜態加載完成,開始運行");
if ("OfficeBetter".equals(args[0])) {
try{
Class c = Class.forName(args[1]); //動態加載類
System.out.println("完成動態加載,繼續運行");
System.out.println(c.getName());
Method[] methods = c.getMethods();
for (Method method: methods) {
System.out.print(method.getReturnType().getName() + "(");
Class[] params = method.getParameterTypes();
for (Class param: params) {
System.out.print(param.getName() + " ");
}
System.out.println(")");
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
程序在運行過程中會再次進行運行時檢查,運行結果
➜ Desktop java OfficeBetter isNotOfficeBetter
編譯完成,靜態加載完成,開始運行
➜ Desktop java OfficeBetter OfficeBetter
編譯完成,靜態加載完成,開始運行
java.lang.ArrayIndexOutOfBoundsException: 1
at OfficeBetter.main(OfficeBetter.java:8)
➜ Desktop java OfficeBetter OfficeBetter Word
編譯完成,靜態加載完成,開始運行
java.lang.ClassNotFoundException: Word
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at OfficeBetter.main(OfficeBetter.java:8)
路徑添加Word.class,運行結果
➜ Desktop java OfficeBetter OfficeBetter Word
編譯完成,靜態加載完成,開始運行
完成動態加載,繼續運行
Word
void()
void(long int )
void(long )
void()
boolean(java.lang.Object )
java.lang.String()
int()
java.lang.Class()
void()
void()
Java動態加載非常靈活,運用反射可以一定程度上繞過編譯器的檢查,JSP其實就是一種動態加載的應用場景呢