原文:https://mp.weixin.qq.com/s/RaFIPhG1y1kmhue--MD-EQ
定義需要加載的類
定義類加載器
編譯需要加載的類文件
編譯自定義的類加載器并執(zhí)行程序
總結(jié)
定義需要加載的類
為了能夠?qū)崿F(xiàn)類加載鸡典,并展示效果,定義一個(gè)Hello類枪芒,再為其定義一個(gè)sayHello()方法,加載Hello類之后谁尸,調(diào)用它的sayHello()方法舅踪。
public class Hello {
public static void sayHello(){
System.out.println("Hello,I am ....");
}
}
定義類加載器
自定義加載器,需要繼承ClassLoader,并重寫里面的findClass(String name) 方法良蛮。
public class MyClassLoader extends ClassLoader {
/**
* 重寫父類方法抽碌,返回一個(gè)Class對(duì)象
* ClassLoader中對(duì)于這個(gè)方法的注釋是:
* This method should be overridden by class loader implementations
*/
protected Class<?> findClass(String name) throws ClassNotFoundException {
Class clazz = null;
String classFilename = name + ".class";
File classFile = new File(classFilename);
if (classFile.exists()) {
try (FileChannel fileChannel = new FileInputStream(classFile)
.getChannel();) {
MappedByteBuffer mappedByteBuffer = fileChannel
.map(MapMode.READ_ONLY, 0, fileChannel.size());
byte[] b = mappedByteBuffer.array();
clazz = defineClass(name, b, 0, b.length);
} catch (IOException e) {
e.printStackTrace();
}
}
if (clazz == null) {
throw new ClassNotFoundException(name);
}
return clazz;
}
public static void main(String[] args) throws Exception{
MyClassLoader myClassLoader = new MyClassLoader();
Class clazz = myClassLoader.loadClass(args[0]);
Method sayHello = clazz.getMethod("sayHello");
sayHello.invoke(null, null);
}
}
編譯需要加載的類文件
類加載的時(shí)候加載的是字節(jié)碼文件,所以需要預(yù)先把定義的Hello類編譯成字節(jié)友文件决瞳。
javac Hello.java
編譯自定義的類加載器并執(zhí)行程序
編譯代碼
javac MyClassLoader.java
當(dāng)然我們也可以同時(shí)編譯我們所有的java源文件
javac *.java
執(zhí)行成功之后货徙,我們用下面的語(yǔ)句執(zhí)行代碼,測(cè)試是否成功皮胡,并查看結(jié)果
java MyClassLoader Hello
運(yùn)行結(jié)果
Hello,I am ....
當(dāng)程序按照預(yù)期顯示痴颊,就證明我自定義類加載器成功了。
總結(jié)
通過(guò)上面的程序代碼屡贺,簡(jiǎn)單的實(shí)現(xiàn)JVM的類加載過(guò)程蠢棱,知道了程序運(yùn)行的一點(diǎn)流程。但是在編寫的時(shí)候有如下坑需要注意:
類文件不需要指定包甩栈,否則加載的時(shí)候我們需要額外的處理泻仙,把包中的"."替換成文件系統(tǒng)的路徑"/"。
需要加載的Hello類中的反射調(diào)用的方法要用static修飾量没,這樣invoke的時(shí)候第一個(gè)參數(shù)才可以使用null關(guān)鍵字代替玉转,否則需要?jiǎng)?chuàng)建一個(gè)對(duì)應(yīng)的類實(shí)例。
官方文檔中有這樣一句話If the underlying method is static, then the specified obj argument is ignored. It may be null.