黑馬程序員--java高新技術--類加載器的深入講解與應用

---------------------- android培訓java培訓、期待與您交流! ----------------------

=========8單元:類加載器的深入講解與應用=============

44.類加載器及其委託機制的深入分析

45.自定義類加載器的編寫原理分析

46.編寫對class文件進行加密的工具類

47.編寫和測試自己編寫的解密類加載器

48.類加載器的一個高級問題的實驗分析

********************************************************************************************************************

=========8單元:類加載器的深入講解與應用=============

39.類加載器及其委託機制的深入分析

簡要介紹什麼是類加載器和類加載器的作用

Java虛擬機中可以安裝多個類加載器,系統默認三個主要類加載器,每個類負責加載特定位置的類:BootStrap,ExtClassLoader,AppClassLoader

類加載器也是Java類,因爲其他是java類的類加載器本身也要被類加載器加載,顯然必須有第一個類加載器不是不是java類,這正是BootStrap

Java虛擬機中的所有類裝載器採用具有父子關係的樹形結構進行組織,在實例化每個類裝載器對象時,需要爲其指定一個父級類裝載器對象或者默認採用系統類裝載器爲其父級類加載。 

Java虛擬機要加載一個類時,到底派出哪個類加載器去加載呢?

首先當前線程的類加載器去加載線程中的第一個類。

如果類A中引用了類BJava虛擬機將使用加載類A的類裝載器來加載類B。 

還可以直接調用ClassLoader.loadClass()方法來指定某個類加載器去加載某個類。

每個類加載器加載類時,又先委託給其上級類加載器。

當所有祖宗類加載器沒有加載到類,回到發起者類加載器,還加載不了,則拋ClassNotFoundException,不是再去找發起者類加載器的兒子,因爲沒有getChild方法,即使有,那有多個兒子,找哪一個呢?

對着類加載器的層次結構圖和委託加載原理,解釋先前將ClassLoaderTest輸出成jre/lib/ext目錄下的itcast.jar包中後,運行結果爲ExtClassLoader的原因。

45.自定義類加載器的編寫原理分析

46.編寫對class文件進行加密的工具類

47.編寫和測試自己編寫的解密類加載器

知識講解:

自定義的類加載器的必須繼承ClassLoader

loadClass方法與findClass方法

defineClass方法

模版方法設計模式:

父類-->loadclass/findClass();/得到class文件的轉換成-字節碼-->defineClass()

子類1(自己幹)

子類2(自己幹)

編程步驟:

編寫一個對文件內容進行簡單加密的程序。

編寫了一個自己的類裝載器,可實現對加密過的類進行裝載和解密。

編寫一個程序調用類加載器加載類,在源程序中不能用該類名定義引用變量,因爲編譯器無法識別這個類。程序中可以除了使用ClassLoader.load方法之外,還可以使用設置線程的上下文類加載器或者系統類加載器,然後再使用Class.forName

實驗步驟:

對不帶包名的class文件進行加密,加密結果存放到另外一個目錄,例如: java MyClassLoader MyTest.class F:\itcast

運行加載類的程序,結果能夠被正常加載,但打印出來的類裝載器名稱爲AppClassLoaderjava MyClassLoader MyTest F:\itcast

用加密後的類文件替換CLASSPATH環境下的類文件,再執行上一步操作就出問題了,錯誤說明是AppClassLoader類裝載器裝載失敗。

刪除CLASSPATH環境下的類文件,再執行上一步操作就沒問題了。

48.類加載器的一個高級問題的實驗分析

編寫一個能打印出自己的類加載器名稱和當前類加載器的父子結構關係鏈的MyServlet,正常發佈後,看到打印結果爲WebAppClassloader

MyServlet.class文件打jar包,放到ext目錄中,重啓tomcat,發現找不到HttpServlet的錯誤。

servlet.jar也放到ext目錄中,問題解決了,打印的結果是ExtclassLoader 

父級類加載器加載的類無法引用只能被子級類加載器加載的類,原理如下圖:

package cn.itcast.day2;




import java.util.Date;


public class ClassLoaderAttachment extends Date {
	public String toString(){
		return "hello,itcast";
	} 
}
package cn.itcast.day2;

import java.util.Date;

public class ClassLoaderTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		System.out.println(
				ClassLoaderTest.class.getClassLoader().getClass().getName()
				);
		System.out.println(
				System.class.getClassLoader()
				);
		System.out.println("xxx");
		ClassLoader loader = ClassLoaderTest.class.getClassLoader();
		while(loader != null){
			System.out.println(loader.getClass().getName());
			loader = loader.getParent();
		}
		System.out.println(loader);
		
		//System.out.println(new ClassLoaderAttachment().toString());
		System.out.println("xxx2");
		Class clazz = new MyClassLoader("itcastlib").loadClass("cn.itcast.day2.ClassLoaderAttachment");
		Date d1 =  (Date)clazz.newInstance();
		System.out.println(d1);
	}

}

package cn.itcast.day2;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

public class MyClassLoader extends ClassLoader{

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		String srcPath = args[0];
		String destDir = args[1];
		FileInputStream fis = new FileInputStream(srcPath);
		String destFileName = srcPath.substring(srcPath.lastIndexOf('\\')+1);
		String destPath = destDir + "\\" + destFileName;
		FileOutputStream fos = new FileOutputStream(destPath);
		cypher(fis,fos);
		fis.close();
		fos.close();
	}
	
	private static void cypher(InputStream ips ,OutputStream ops) throws Exception{
		int b = -1;
		while((b=ips.read())!=-1){
			ops.write(b ^ 0xff);
		}
	}

	private String classDir;

	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		// TODO Auto-generated method stub
		String classFileName = classDir + "\\"  + name.substring(name.lastIndexOf('.')+1) + ".class";
		try {
			FileInputStream fis = new FileInputStream(classFileName);
			ByteArrayOutputStream  bos = new ByteArrayOutputStream();
			cypher(fis,bos);
			fis.close();
			System.out.println("aaa");
			byte[] bytes = bos.toByteArray();
			return defineClass(bytes, 0, bytes.length);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	public MyClassLoader(){
		
	}
	
	public MyClassLoader(String classDir){
		this.classDir = classDir;
	}
}



---------------------- android培訓java培訓、期待與您交流! ----------------------詳細請查看:http://edu.csdn.net/heima
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章