您的位置:首页 > 编程语言 > Java开发

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

2014-11-13 00:00 363 查看
摘要: 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文件,只要路径不错,应该就没有什么问题了。

祝成功!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息