文章目錄
- 1.jvm虛拟機記憶體模型
- 2.類加載過程
- 3.類加載器:
- 4. 檢視jvm位元組碼執行情況
- 5. 自定義類加載器 和類加載器不生效的處理
1.jvm虛拟機記憶體模型
類加載子系統
運作時資料區: 堆
棧
本地方法棧
方法區(元空間):常量+靜态變量+類元資訊
程式計數器
位元組碼執行引擎
2.類加載過程
加載; 在硬碟上查找并通過IO讀入位元組碼檔案,使用類時才會加載,例如調用類的main()方法,new對象等等
驗證: 校驗位元組碼檔案的正确性
準備: 給類的靜态變量配置設定記憶體,并賦予預設值
解析: 将符号引用替換為直接引用,該階段會把一些靜态方法(符号引用,比如main()方法)替換為指向資料所存記憶體的指針,
或句柄等(直接引用),這是所謂的靜态連接配接過程(類加載期間完成),動态連結是在程式運作期間完成的将符号引用替換為
直接引用
初始化: 對類的靜态變量初始化為指定的值,執行靜态代碼塊
public class Tuling {
public static void main(String[] args) {
System.out.println(String.class.getClassLoader());
System.out.println(com.sun.crypto.provider.DESedeKeyFactory.class.getClassLoader().getClass().getName());
System.out.println(Tuling.class.getClassLoader().getClass().getName());
System.out.println(ClassLoader.getSystemClassLoader().getClass().getName());
}
運作結果:
null
sun.misc.Launcher$ExtClassLoader
sun.misc.Launcher$AppClassLoader
sun.misc.Launcher$AppClassLoader
3.類加載器:
啟動類加載器: jvm運作的位于jre/lib 目錄下的核心類庫 比如:rt.jar, charsets.jar等
擴充類加載器: 負責加載 位于jie的lib目錄下的ext擴充目錄中的jar類包
應用程式類加載器: 負責加載classPath路徑下的類包,主要就是加載你自己寫的那些類
自定義加載器:負責加載使用者自定義路徑下的類包
4. 檢視jvm位元組碼執行情況
- javap -c Tuling.class
5. 自定義類加載器 和類加載器不生效的處理
- 自定義類加載器
package com.tuling;
/**
* Title: User
* Description: TODO
*
* @author hfl
* @version V1.0
* @date 2020-11-23
*/
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
protected void finalize() throws Throwable {
System.out.println("關閉資源,user " + name + "即将回收");
}
public void sout(){
System.out.println("=============自己的加載器加載類調用方法============");
}
}
package com.tuling;
import java.io.FileInputStream;
import java.lang.reflect.Method;
/**
* Title: MyClassLoaderTest
* Description: TODO
*
* @author hfl
* @version V1.0
* @date 2020-11-23
*/
public class MyClassLoaderTest {
static class MyClassLoader extends ClassLoader {
private String classPath;
public MyClassLoader(String classPath) {
this.classPath = classPath;
}
private byte[] loadByte(String name) throws Exception {
name = name.replaceAll("\\.", "/");
FileInputStream fis = new FileInputStream(classPath + "/" + name + ".class");
int len = fis.available();
byte[] data = new byte[len];
fis.read(data);
fis.close();
return data;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte[] data = loadByte(name);
return defineClass(name, data, 0, data.length);
} catch (Exception e) {
e.printStackTrace();
throw new ClassNotFoundException();
}
}
}
public static void main(String[] args) throws Exception {
MyClassLoader classLoader = new MyClassLoader("D:/test");
Class<?> clazz = classLoader.loadClass("com.tuling.User");
Object obj = clazz.newInstance();
Method method = clazz.getDeclaredMethod("sout", null);
method.invoke(obj, null);
System.out.println(clazz.getClassLoader().getClass().getName());
}
}
運作結果: