查找 Java 类中的所有依赖项

2022-01-15 00:00:00 dependencies java generics

我正在尝试获取 Java 类中的所有依赖项,包括用于泛型参数化和局部变量类型的类.到目前为止,我发现的最好的框架是 apache bcel.使用它,我可以轻松地从字节码中找到所有字段、方法参数和局部变量.基本上除了泛型和局部变量类型之外的所有内容.例如,从 List 行开始.points = new ArrayList(); 我只能找到一个依赖项 - 使用 bcel 中的 JavaClass.getConstantPool() 方法的 ArrayList.它既检测不到 List 接口也检测不到 Point 类.我还尝试了 tattletale 和 CDA,不幸的是没有成功(结果相同).检查导入是不够的——我还需要来自同一个包的依赖项,而且我不能接受通配符.如果有任何帮助,我将不胜感激.

I'm trying to get all dependencies in a Java class, including classes used for generics parametrization and local variables types. So far best framework I've found is apache bcel. Using it I can easily find all fields, method arguments and local variables from byte code. Basically everything except of generics and local variables types. For example, from line List<Point> points = new ArrayList<Point>(); I can only find one dependency - ArrayList using JavaClass.getConstantPool() method from bcel. It can't detect neither List interface nor Point class. I also tried tattletale and CDA, unfortunately without success (the same results). Examining imports is not enough - I need also dependencies from the same package and I can't accept wildcards. I would be grateful for any help.

推荐答案

我终于找到了解决方案.ASM 字节码框架 是正确的工具.使用官方 tutorial 和对 example 很容易获得所有需要的依赖项.在示例中,已经有一个访问者类 DependencyVisitor 可以满足我的要求.为了获得正确的格式,我只需要更改 DependencyVistitor 示例代码中的一种方法,因此它添加了完整的类名而不是只添加包:

I've finally found solution. ASM Bytecode Framework is the right tool to use. Using official tutorial and right example it's quite easy to get all needed dependencies. In the example there is already a visitor class DependencyVisitor which does what I want. To get right formatting I had to change only one method in DependencyVistitor example code, so it adds full class names instead of packages only:

private String getGroupKey(String name)
{
        //Just comment that block so you can get full class names instead of package only
        /*
        int n = name.lastIndexOf('/');
        if (n > -1)
        {
            name = name.substring(0, n);
        }
       */
        // Replace resource char with package separator char        
        packages.add(name.replace("/", "."));
        //packages.add(name);
        return name;
}

查看 DependencyVisitor 代码,您可以轻松了解它的作用并根据需要对其进行修改.在我的示例类上运行它会给我很好的、有用的输出:[java.util.ArrayList, java.lang.Object, java.util.List, java.awt.Point, goobar.test.asmhello.TestClass, java.lang.String, java.lang.Integer, java.awt.Graphics,goobar.test.asmhello.TestClass2].它包含我使用过的每个类和接口以及用于泛型参数化的每个类型.

Looking at DependencyVisitor code you can easily understand what it does and modify it to your needs. Running it on my example class it gives me nice, useful output: [java.util.ArrayList, java.lang.Object, java.util.List, java.awt.Point, goobar.test.asmhello.TestClass, java.lang.String, java.lang.Integer, java.awt.Graphics, goobar.test.asmhello.TestClass2]. It contains every class and interface I've used and every type used for generics parameterization.

相关文章