關於classloader

jvm自帶的三個classloader

1.Bootstrap classloader,是jvm的一部分,由C寫成,調用的是核心庫。

   sun java下,可以用以下語句查看調用類路徑

  

URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs(); 

 

寫道
%JAVA_HOME%/jre/lib/resources.jar
%JAVA_HOME%/jre/lib/rt.jar
%JAVA_HOME%/jre/lib/sunrsasign.jar
%JAVA_HOME%/jre/lib/jsse.jar
%JAVA_HOME%/jre/lib/jce.jar
%JAVA_HOME%/jre/lib/charsets.jar
%JAVA_HOME%/jre/lib/jfr.jar
%JAVA_HOME%/jre/classes

 

2.ExtClassLoader,調用系統擴展類

  

寫道
%JAVA_HOME%/jre/lib/ext/access-bridge.jar
%JAVA_HOME%/jre/lib/ext/cldrdata.jar
%JAVA_HOME%/jre/lib/ext/dnsns.jar
%JAVA_HOME%/jre/lib/ext/jaccess.jar
%JAVA_HOME%/jre/lib/ext/jfxrt.jar
%JAVA_HOME%/jre/lib/ext/localedata.jar
%JAVA_HOME%/jre/lib/ext/nashorn.jar
%JAVA_HOME%/jre/lib/ext/sunec.jar
%JAVA_HOME%/jre/lib/ext/sunjce_provider.jar
%JAVA_HOME%/jre/lib/ext/sunmscapi.jar
%JAVA_HOME%/jre/lib/ext/sunpkcs11.jar
%JAVA_HOME%/jre/lib/ext/zipfs.jar

 3.AppClassLoader,調用classpath裏的類

 

這三個類遵循雙親委派模型,也就是先每裝載一個類時,先從父裝載器裝載,找不到才一級級往下找,這也就是classpath裏的類無法覆蓋jdk裏自帶類的原因。

 

像tomcat等應用,涉及到webapp隔離,所以在裝載每個webapp裏的類時,沒有遵循雙親委派模型,而是優先自己所調用的類,另外這裏有個關鍵點,就是隱式裝載也就是用關鍵字new創建對象時,裝載這個類所使用的裝載器是使用new關鍵字所在類的裝載器

以下代碼可以模擬這個過程。

 

自定義類裝載器

package jp.co.wqf;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class MyClassLoader extends ClassLoader {
	private String name;
	private String path = "D:/";
    private final String fileType = ".class";
	public MyClassLoader(String name){
		super();
		this.name = name;
	}
	public MyClassLoader(String name, ClassLoader cl){
		super(cl);
		this.name = name;
	}
	public String getPath() {
		return path;
	}
	public void setPath(String path) {
		this.path = path;
	}
	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		byte[] data = loaderClassData(name);
		return this.defineClass(name, data, 0, data.length);
	}
    private byte[] loaderClassData(String className){
        InputStream is = null;
        byte[] data = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        String fileName = className.replace(".", "/");
        try {
            is = new FileInputStream(new File(path + fileName + fileType));
            int c = 0;
            while(-1 != (c = is.read())){
                baos.write(c);
            }
            data = baos.toByteArray();

        } catch (Exception e) {
            e.printStackTrace();
        } finally{
            try {
                is.close();
                baos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return data;
    }
}

 測試

package jp.co.wqf;

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		MyClassLoader classLoader = new MyClassLoader("classload1");
		classLoader.setPath("/eclipse/workspace/Test/bin/");
		try {
			Class<?> clsA = classLoader.loadClass("jp.co.wqf.A");
			Object objA = clsA.newInstance();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

 

以下類不要放在上面代碼的classpath裏

package jp.co.wqf;

public class A {
	private B b;
	public A(){
		this.b = new B();
	}
}

 

package jp.co.wqf;

public class B {
	private C c;
	public B(){
		this.c = new C();
	}
}

 

package jp.co.wqf;

public class C {
	public C(){
		System.out.println("create class c!");
	}
}

 

發佈了151 篇原創文章 · 獲贊 1 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章