Java反射机制,实现任意位置的class文件的解析

      之前一直在想如何读取一个class文件,并且获取其中的信息,Java有自己的ClassLoader ,可以加载系统需要的class文件,或者用户自定义的class文件,但是对目录要求较高,需要时在classpath下,但是能不能将任意位置的class文件加载呢。

     class文件是以二进制流的方式存在磁盘文件上的,ClassLoader也肯定是在二进制文流读到内存中去的。终于找到在ClassLoader类中存在一个  

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

方法,

         其中: String name  指的是类名,是一个完整的带包名的类名,如果不知道,可以使用 null 

                     byte []b 就是class文件的字节流 ,关键的东东啊

                     int  off    也就是起始位置 , len  读取的字节长度了,很好理解啊

 因为defineClass 是受保护的方法,不能直接访问,那么我们写一个方法继承自ClassLoader 是不是就 OK了呢?

        实现步骤:

          自定义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);
	}
	
}

   测试代码:

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

       祝成功!!!


      

 


转载于:https://my.oschina.net/u/1186193/blog/344020

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值