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文件,只要路径不错,应该就没有什么问题了。

       祝成功!!!

相关文章
相关标签/搜索