Java:使用javassist读取class文件并获得其中的内容信息

Posted 你是小KS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java:使用javassist读取class文件并获得其中的内容信息相关的知识,希望对你有一定的参考价值。

1. 声明

当前内容主要为本人学习和复习使用javassit操作读取class文件并获取其中的信息,这个信息主要包括,注解声明,方法,接口,java编译器版本

主要操作:

  1. 主要使用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)

Javassist使用

javassist使用全解析

使用JAVASSIST怎样向Class文件中加入import语句?

使用jd-gui+javassist修改已编译好的class文件