以前一直在想如何读取一个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文件,只要路径不错,应该就没有什么问题了。
祝成功!!!