Java動態加載


今天初步接觸了一下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其實就是一種動態加載的應用場景呢


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM