雙親委派模型是Java加載類的機制.採用雙親委派模型的好處是Java類隨着它的類加載器一塊兒具有了一種帶有優先級的層級關係,經過這種層級關係能夠避免類的重複加載.java
1.雙親委派模型最大的好處就是讓Java類同其類加載器一塊兒具有了一種帶優先級的層次關係。這句話可能很差理解,咱們舉個例子。好比咱們要加載java.lang.Object類,不管咱們用哪一個類加載器去加載Object類,這個加載請求最終都會委託給Bootstrap ClassLoader,這樣就保證了全部加載器加載的Object類都是同一個類。若是沒有雙親委派模型,那就亂了套了,徹底可能搞出多個不一樣的Object類。
2.自上而下每一個類加載器都會盡力加載.算法
1.首先加載類調用的loadClass方法,咱們找到ClassLoader的loadClass():性能優化
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}複製代碼
protected Class<?> findClass(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}複製代碼
1.首先須要一個編譯好的class文件,筆者用了一個以前寫的斐波那契的類Fib.class(所在路徑:C:/Users/Think/crabapple),下面是用idea經過反編譯方式打開的class文件,注意記下class文件的包名,在後續代碼中須要使用類的全限定名稱.app
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package crabapple;
public class Fib {
public static int fib(int num) {
return num < 2 ? num : fib(num - 2) + fib(num - 1);
}
}複製代碼
2.繼承ClassLoader,重寫findClass方法:ide
class MyClassLoader extends ClassLoader {
private String classPath; // 保存的地址
/** * 傳入地址構造函數 * @param classPath */
public MyClassLoader(String classPath) {
this.classPath = classPath;
}
/** * 讀取class文件 * @param name * @return * @throws Exception */
private byte[] loadByte(String name) throws Exception {
String inPath = classPath + "/" + name + ".class";
FileInputStream fis = new FileInputStream(inPath);
int len = fis.available();
byte[] data = new byte[len];
fis.read(data);
fis.close();
return data;
}
/** * 重寫findClass方法,讓加載的時候調用findClass方法 * @param name * @return * @throws ClassNotFoundException */
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte[] data = loadByte(name);
// 將字節碼載入內存
return defineClass(name, data, 0, data.length);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}複製代碼
3.測試,一下將使用一些反射機制和class類的方法.函數
public class ClassLoaderTest extends ClassLoader {
//main函數本該拋出異常有 ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException,爲了好看,簡寫成Exception
public static void main(String[] args) throws Exception {
//初始化類加載器
MyClassLoader myClassLoader=new MyClassLoader("C:/Users/Think/crabapple");
//加載Fib類,筆者class文件包名爲crabapple
Class myClass=myClassLoader.loadClass("crabapple.Fib");
//獲取加載類的實例
Object object=myClass.newInstance();
//獲取該類一個名爲fib,且參數爲int的方法
Method method=myClass.getMethod("fib",int.class);
//執行這個方法
int result=method.invoke(object,4);
//打印結果
System.out.print(result);
//output
/** * 3 * Process finished with exit code 0 */
}
}複製代碼
後續會持續更新性能優化專題知識,寫的很差的地方也但願大牛能指點一下,你們以爲不錯能夠點個贊在關注下,之後還會分享更多文章!