获取Class信息最快的方法

在一般情况下获取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)
    }

}
复制代码

猜你喜欢

转载自juejin.im/post/7048967735430086687