以前一直在想如何讀取一個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文件,只要路徑不錯,應該就沒有什麼問題了。
祝成功!!!