Java:使用javassist读取class文件并获得其中的内容信息
Posted 你是小KS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java:使用javassist读取class文件并获得其中的内容信息相关的知识,希望对你有一定的参考价值。
1. 声明
当前内容主要为本人学习和复习使用javassit操作读取class文件并获取其中的信息,这个信息主要包括,注解声明,方法,接口,java编译器版本
主要操作:
- 主要使用ClassFile方式读取class文件的信息
2. demo
首先准备一个接口,和一个实现类
public interface ByteCodeResolver {
ClassFileInfo resolver(byte[] bytes);
}
实现类
@Deprecated
public class DefaultByteCodeResolver implements ByteCodeResolver{
//
@Override
public ClassFileInfo resolver(byte[] bytes) {
// TODO Auto-generated method stub
return null;
}
}
解析的demo
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.AttributeInfo;
import javassist.bytecode.ClassFile;
import javassist.bytecode.ConstPool;
import javassist.bytecode.DeprecatedAttribute;
import javassist.bytecode.MethodInfo;
import javassist.bytecode.SourceFileAttribute;
import javassist.bytecode.annotation.Annotation;
/**
*
* @author hy
* @createTime 2021-07-17 13:42:58
* @description 当前内容主要为使用javaassit的ClassFile来获取当前的文件信息
*
*/
public class JavaassitClassFileTest {
public static void main(String[] args) {
String classFilePath = "D:\\\\eclipse-workspace\\\\Java8BasicReStudy\\\\target\\\\classes\\\\com\\\\hy\\\\java\\\\bytecode\\\\DefaultByteCodeResolver.class";
try (DataInputStream dis = new DataInputStream(new FileInputStream(new File(classFilePath)))) {
ClassFile classFile = new ClassFile(dis);
int minorVersion = classFile.getMajorVersion();
System.out.println("获取当前的class文件的jdk编译版本信息:" + minorVersion);
String[] interfaces = classFile.getInterfaces();
System.out.println("当前classFile中的所有的接口名称为:" + Arrays.toString(interfaces));
System.out.println("开始输出常量池中的内容:");
ConstPool constPool = classFile.getConstPool();
Set<String> classNames = constPool.getClassNames();
System.out.println("classNames=" + classNames);
boolean isInterface = classFile.isInterface();
System.out.println("当前的这个类是否为接口?" + isInterface);
// 获取这个类上面的注解属性
List<AttributeInfo> attributes = classFile.getAttributes();
if (attributes == null || attributes.isEmpty()) {
System.out.println("没有任何的属性!");
}
for (AttributeInfo attributeInfo : attributes) {
// 获取注解属性
if (attributeInfo instanceof AnnotationsAttribute) {
AnnotationsAttribute attr = (AnnotationsAttribute) attributeInfo;
Annotation[] annotations = attr.getAnnotations();
System.out.println("解析获得注解:" + Arrays.toString(annotations));
} else if (attributeInfo instanceof DeprecatedAttribute) {
// 获取DeprecatedAttribute属性
DeprecatedAttribute attr = (DeprecatedAttribute) attributeInfo;
System.out.println("attr=" + attr.tag);
} else if (attributeInfo instanceof SourceFileAttribute) {
// 获取源文件属性
SourceFileAttribute attr = (SourceFileAttribute) attributeInfo;
String fileName = attr.getFileName();
System.out.println("fileName=" + fileName);
}
}
// 由于获取了注解所以可以使用各种其他的操作
// 获取当前的方法
System.out.println("输出当前的所有的方法:");
List<MethodInfo> methods = classFile.getMethods();
if(methods==null||methods.isEmpty()) {
System.out.println("没有任何方法.....");
}else {
for (MethodInfo methodInfo : methods) {
System.out.println(methodInfo.getName()+","+methodInfo.getDescriptor());
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
执行结果如下:
3. 总结
1. 注解属性存在于Attributes中,有一个AnnotationsAttribute
2. 直接通过getInterface方法可以获取到当前类实现的接口
3. 通过getMethods方法可以获取所有的方法,但是这些获取到的方法的Descriptor为(方法参数类型)返回值类型,其中V表示void方法,其他的表示其他类型的[B表示byte数组
以上是关于Java:使用javassist读取class文件并获得其中的内容信息的主要内容,如果未能解决你的问题,请参考以下文章
Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)
Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)