5

我正在开发一个库,我们想确定我们的库有多少被使用。IE 我们想知道我们的库中有多少方法是公开的,但从未被调用。

目标:静态分析 确定当前项目中有多少行代码调用包A中的每个公共方法。如果调用次数为零,则应报告该方法。

4

10 回答 10

9

我相信你正在寻找这个 Eclipse 插件 --> UCDetector

从文档(注意第二个要点)

  • 不必要的(死)代码
  • 可见性可以更改为受保护、默认或私有的代码
  • 字段的方法,可以是最终的

在更大的范围内,如果您想进行对象级静态分析,请查看 IBM 提供的这个工具 --> Structural Analysis for Java。它对库、API 等的对象分析非常有帮助。

于 2009-06-02T02:28:06.727 回答
3

不完全是您正在寻找的东西,但是:

使用代码覆盖工具(如Cobertura)可以完成类似的操作。他们不对源代码进行静态检查,而是检测字节码以在运行时收集指标。当然,您需要以一种练习所有使用模式的方式来驱动应用程序,并且可能会错过更罕见的代码路径。

在静态分析方面,也许这些工具可以帮助您(Apache 项目使用它们来检查新版本的 API 兼容性,似乎该任务与您正在尝试做的事情有些相关):

  • Clirr是一个检查 Java 库与旧版本的二进制和源代码兼容性的工具。基本上你给它两组 jar 文件,Clirr 会转储出公共 api 中的更改列表。
  • JDiff是一个 Javadoc doclet,当比较两个 API 时,它会生成所有已被删除、添加或更改的所有包、类、构造函数、方法和字段的 HTML 报告,包括它们的文档。
于 2009-04-20T00:38:44.163 回答
3

客户端使用反射调用是静态分析中需要考虑的一个漏洞。因为没有办法确定某个特定的方法没有通过一些奇怪的反射方案被调用。所以,也许运行时和静态分析的结合可能是最好的。

于 2009-06-02T03:03:34.580 回答
1

我认为您无法衡量需要一个类或一个函数的“频率”。
有一些简单的问题:

  • 什么定义,如果您的游戏库的使用统计是“正常”或“异常值”?经常在游戏中杀死自己是错误的吗?你会像一个优秀的游戏玩家一样更频繁地使用“killScreen”类。
  • 什么定义了“很多”?时间或使用次数?POJO 会消耗很少的时间,但会非常频繁地使用。

结论:
我不知道您要完成什么。
如果你想显示你的代码依赖关系,还有其他工具可以做到这一点。如果您尝试测量代码执行情况,可以使用 Java分析器或基准测试如果您是统计极客,您会对RapidMiner感到满意;)

祝你好运!

于 2009-04-20T08:48:59.150 回答
1

我建议 JDepend 向您展示包和类之间的依赖关系,非常适合找到循环依赖关系! http://clarkware.com/software/JDepend.html (它有一个 Eclipse 插件:http ://andrei.gmxhome.de/jdepend4eclipse/

以及其他指标的 PMD http://pmd.sourceforge.net/

于 2009-04-20T13:42:45.933 回答
1

IntelliJ 有一个工具来检测方法、字段、类,这些可以有更多的限制修饰符。它还可以快速修复应用这些更改,这也可以为您节省大量工作。如果您不想为此付费,您可以获得 30 天的 eval 许可证,这足以更改您的代码,这不是您应该经常做的事情。

顺便说一句:IntelliJ 有大约 650 次代码检查来提高代码质量,大约一半有自动修复,所以我建议花几天时间使用它来重构/整理你的代码。

于 2009-06-06T09:42:21.400 回答
1

请看一下死代码检测器。它声称可以满足您的需求:使用静态分析查找未使用的代码。

于 2009-06-08T07:17:55.090 回答
0

以下是一些 Java 代码覆盖率工具列表。我没有亲自使用过这些,但它可能会让你开始:

于 2009-04-20T00:32:52.463 回答
0

Proguard 也可能是一种选择(http://proguard.sourceforge.net/):

“ProGuard 的一些用途是:

  • ...
  • 列出死代码,因此可以从源代码中删除。
  • ……”

另请参阅http://proguard.sourceforge.net/manual/examples.html#deadcode

于 2009-06-04T22:50:43.497 回答
0

您可以使用 ASM 字节码分析库 ( http://asm.ow2.org )为此编写自己的实用程序(阅读本文后一小时内)。您需要实现 ClassVisitor 和 MethodVisitor。您将使用 ClassReader 解析库中的类文件。

  • 您的 ClassVisitor 的 visitMethod(..) 将为每个声明的方法调用。
  • 您的 MethodVisitor 的 visitMethodInsn(..) 将为每个调用的方法调用。

维护一张地图来进行计数。键代表方法(见下文)。这是一些代码:

class MyClassVisitor {
    // ...
    public void visit(int version, int access, String name, ...) {
        this.className = name;
    }
    public MethodVisitor visitMethod(int access, String name, String desc, ...):
        String key = className + "." + name + "#" + desc;
        if (!map.containsKey() {
            map.put(key, 0);
        }
        return new MyMethodVisitor(map);
    }
    // ...
}

void class MyMethodVisitor {
    // ...
    public visitMethodInsn(int opcode, String name, String owner, String desc, ...) {
        String key = owner + "." + name + "#" + desc;
        if (!map.containsKey() {
            map.put(key, 0);
        }
        map.put(key, map.get(key) + 1);
    }
    // ...
}

基本上就是这样。你的节目是这样开始的:

Map<String,Integer> map = new HashMap<String,Integer>();
for (File classFile : my library) {
    InputStream input = new FileInputStream(classFile);
    new ClassReader(input).accept(new MyClassVisitor(map), 0);
    input.close();
}
for (Map.Entry<String,Integer> entry : map.entrySet()) {
    if (entry.getValue() == 0) {
        System.out.println("Unused method: " + entry.getKey());
    }
}

享受!

于 2009-06-05T22:44:21.483 回答