一個自定義的載入器
阿新 • • 發佈:2019-01-07
我們的自定義類載入器
- package cn.gd.cjz.class_loader;
- import java.io.*;
- import java.nio.ByteBuffer;
- import java.nio.channels.FileChannel;
- /**
- * 自定義類載入器
- */
- publicclass CustomClassLoader extends ClassLoader {
- /**類名**/
- private String name;
- /**通過構造方法設定父類載入器和要熱載入的類名**/
-
public CustomClassLoader(ClassLoader parent , String name) {
- super(parent);
- if(name == null || name.length() <= 0)
- thrownew NullPointerException();
- this.name = name;
- }
- @Override
- protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
-
Class<?> clazz = null
- /**如果是我們想要熱載入的類則呼叫我們重寫的findClass方法來載入**/
- if(this.name.equals(name) && !"java".equals(name)){
- /**先看看要熱載入的類之前是否已經載入過了,因為一個類載入器只能載入一個類一次,載入多次會報異常**/
- clazz = findLoadedClass(name);
- /**clazz==null說明之前沒有載入過**/
- if(clazz == null)
-
clazz = findClass(name);
- /**
- * 類的生命週期包括:載入、驗證、準備、解析、初始化、使用、解除安裝。其中驗證、準備、解析統稱為連線
- * 如果要連線類
- */
- if(resolve)
- resolveClass(clazz);//如果類已連線過,resolveClass方法會直接返回
- return clazz;
- }
- returnsuper.loadClass(name , resolve);
- }
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- String fileName = c2f(name);
- byte[] bytes = f2b(fileName);
- return defineClass(name, bytes, 0, bytes.length);
- }
- /**
- * 類名轉為檔名
- * @param name
- * @return
- */
- private String c2f(String name){
- /**編譯後的class檔案存放的目錄**/
- String baseDir = "F:\\idea_workspace\\Test\\target\\classes\\";
- name = name.replace("." , File.separator);
- name = baseDir + name + ".class";
- return name;
- }
- /**
- * 讀取檔案byte陣列
- * @param fileName
- * @return
- */
- privatebyte[] f2b(String fileName){
- RandomAccessFile file = null;
- FileChannel channel = null;
- byte[] bytes = null;
- try {
- /**隨機存取檔案物件,只讀取模式**/
- file = new RandomAccessFile(fileName , "r");
- /**NIO檔案通道**/
- channel = file.getChannel();
- /**NIO位元組緩衝**/
- ByteBuffer buffer = ByteBuffer.allocate(1024);
- int size = (int) channel.size();
- bytes = newbyte[size];
- int index = 0;
- /**從NIO檔案通道讀取資料**/
- while (channel.read(buffer) > 0){
- /**位元組緩衝從寫模式轉為讀取模式**/
- buffer.flip();
- while (buffer.hasRemaining()){
- bytes[index] = buffer.get();
- ++index;
- }
- /**位元組緩衝的readerIndex、writerIndex置零**/
- buffer.clear();
- }
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }finally {
- if (channel != null) {
- try {
- channel.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if (file != null) {
- try {
- file.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- return bytes;
- }
- /**
- * 熱載入類
- * @return
- */
- public Class<?> loadClass(){
- try {
- return loadClass(name);
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- returnnull;
- }
- }
- }
將要被熱載入的類介面
- package cn.gd.cjz.class_loader;
- /**
- * 測試類介面
- */
- publicinterface IPrinter {
- publicvoid print();
- }
將要被熱載入的類
- package cn.gd.cjz.class_loader;
- /**
- * 測試類
- */
- publicclass Printer implements IPrinter {
- @Override
- publicvoid print() {
- System.out.println("彪悍的人生不需要解釋是誰說的?");
- }
- }
好了,寫個測試類來測試一下
- package cn.gd.cjz.class_loader;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- /***
- * 自定義類載入器測試類
- */
- publicclass CustomClassTest {
- publicstaticvoid main(String[] args) {
- /**要進行熱載入的類名**/
- String name = "cn.gd.cjz.class_loader.Print