在一般情况下获取class中的信息需要先转化成对应的Class对象,然后才能进行获取,当然还有其他办法,那就是使用org.objectweb.asm,这个库可以在不加载class的情况下动态获取class的信息,因为他根本的原因是暴力解析class结构,下面做几个演示。
显示字节码
fun main() {
var bytes =
File("./classes/java/main/TestJava.class").inputStream()
.readBytes()
val visitor = TraceClassVisitor(PrintWriter(System.out))
ClassReader(bytes).accept(visitor, 0)
}
复制代码
结果:
// class version 52.0 (52)
// access flags 0x21
public class TestJava {
// compiled from: TestJava.java
// access flags 0x1
public <init>()V
L0
LINENUMBER 1 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this LTestJava; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
}
复制代码
根据文件获取类名
var readBytes = File("/home/HouXinLin/project/java/KotlinDemo1/build/classes/java/main/TestJava.class").readBytes()
println(ClassReader(readBytes).className)
复制代码
获取整个类的信息
ClassNode表示一个类的的信息,继承ClassVisitor
负责解析class的是ClassReader对象,他解析的时会回调给ClassVisitor,而ClassNode就是把解析到的信息做一个整合,其中的方法等信息也都不是使用的java.lang.reflect包下的,都是自定义的。
fun getNode(bytez: ByteArray?): ClassNode? {
var cr: ClassReader? = ClassReader(bytez)
val cn = ClassNode()
try {
cr!!.accept(cn, ClassReader.EXPAND_FRAMES)
} catch (e: Exception) {
try {
cr!!.accept(cn, ClassReader.SKIP_FRAMES or ClassReader.SKIP_DEBUG)
} catch (e2: Exception) {
}
}
return cn
}
fun main() {
var readBytes = File("./classes/java/main/TestJava.class").readBytes()
var node = getNode(readBytes)
node?.methods?.forEach {
println(it.name)
}
node?.fields?.forEach {
println(it.signature+" "+ it.name)
}
}
复制代码
搜索目录下带有指定注解的类
fun getNode(bytez: ByteArray?): ClassNode? {
var cr: ClassReader? = ClassReader(bytez)
val cn = ClassNode()
try {
cr!!.accept(cn, ClassReader.EXPAND_FRAMES)
} catch (e: Exception) {
try {
cr!!.accept(cn, ClassReader.SKIP_FRAMES or ClassReader.SKIP_DEBUG)
} catch (e2: Exception) {
}
}
return cn
}
fun main() {
var resource = ClassLoader.getSystemResource(".")
var path = resource.file.replace("java/main", "kotlin/main")
var mutableListOf = mutableSetOf<ClassNode>()
Files.list(Paths.get(path)).forEach { `file` ->
if (file.toString().endsWith(".class")) {
var node = getNode(file.toFile().readBytes())
node?.visibleAnnotations?.forEach {
if (it.desc == "L" + Resource::class.java.name.replace(".", "/") + ";") {
mutableListOf.add(node)
}
}
}
}
mutableListOf.forEach {
var newInstance = Class.forName(it.name).newInstance()
println(newInstance)
}
}
复制代码