Java反射機制,實現任意位置的class文件的解析

      以前一直在想如何讀取一個class文件,而且獲取其中的信息,Java有本身的ClassLoader ,能夠加載系統須要的class文件,或者用戶自定義的class文件,可是對目錄要求較高,須要時在classpath下,可是能不能將任意位置的class文件加載呢。java

     class文件是以二進制流的方式存在磁盤文件上的,ClassLoader也確定是在二進制文流讀到內存中去的。終於找到在ClassLoader類中存在一個  maven

defineClass(String name, byte[]b,int off,int len);

方法,
測試

         其中: String name  指的是類名,是一個完整的帶包名的類名,若是不知道,能夠使用 null this

                     byte []b 就是class文件的字節流 ,關鍵的東東啊spa

                     int  off    也就是起始位置 , len  讀取的字節長度了,很好理解啊code

 由於defineClass 是受保護的方法,不能直接訪問,那麼咱們寫一個方法繼承自ClassLoader 是否是就 OK了呢?繼承

        實現步驟:ip

          自定義Loader 內存

package com.jokingus.cls;

import java.io.FileInputStream;

public class Loader extends ClassLoader{

	static int maxsize=10000;
	
	public Class<?> load(String namefile,String className) throws Exception{
		
		Class<?> ctmp=	this.findLoadedClass(className);
		//查看class是否已經被加載了
		if(ctmp!=null){
			System.out.println("class文件已經被加載了");
			return ctmp;
		}
		
		FileInputStream in=new FileInputStream(namefile);
		byte[] classbyte=new byte[maxsize];
		int readsize;
		readsize=in.read(classbyte);
		System.out.println("readsize:"+readsize);
		in.close();
		
		return defineClass(null, classbyte, 0,readsize);
	}
	
}

   測試代碼:get

package com.jokingus.cls;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Test {

	public void parseMethod(Class<?> cls) {
		Method[] methods = cls.getDeclaredMethods();
		for (Method m : methods) {
			System.out.println(Modifier.toString(m.getModifiers()));
			Class<?> returnType = m.getReturnType();
			System.out.println(returnType.getName());

			Class<?>[] parameterTypes = m.getParameterTypes();
			for (Class<?> clas : parameterTypes) {

				String parameterName = clas.getName();
				System.out.println("參數名稱:" + parameterName);
			}
			System.out.println(m.getName());
			System.out.println("\n****************");

		}
	}

	public void parseDeclaration(Class<?> cls) {
		Field[] fields = cls.getDeclaredFields();
		for (Field f : fields) {
			System.out.print(Modifier.toString(f.getModifiers()) + " ");
			System.out.print(f.getGenericType().toString() + " ");
			System.out.print(f.getName() + " = ");
			try {
				f.setAccessible(true);
				System.out.println(f.get(f.getGenericType()));
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
			System.out.println();
		}
	}

	public void parseAnnotation(Class<?> cls) {
		Annotation[] annos = cls.getAnnotations();
		for (Annotation anno : annos) {
			System.out.println(anno.toString());
			Class<?> types = anno.annotationType();
			System.out.println(types.getName());
		}
	}

	public static void main(String[] args) throws Exception {
		Test t = new Test();
		Loader loader = new Loader();
		String namefile = "E:/Eclipse/IO/bin/com/wang/bytemodel/FileDemo.class";
		namefile = "E:/wangming/maven/high/target/classes/com/jokingus/dbutils/DBPool.class";
		namefile = "E:/wangming/maven/high/target/classes/com/jokingus/anno/SayHello.class";
		Class<?> c = loader.load(namefile, null);
		System.out.println(c.getName());
		String className = c.getName();

		// t.parseMethod(c);
		System.out.println("--------------------------------------");
		t.parseDeclaration(c);
		System.out.println("--------------------------------------");
		t.parseAnnotation(c);
		
		// loader.load(namefile,className);
	}

}


      保證namefile 爲你的電腦上實際存在的一個 class文件,只要路徑不錯,應該就沒有什麼問題了。

       祝成功!!!

相關文章
相關標籤/搜索