我正在开发一个库,我们想确定我们的库有多少被使用。IE 我们想知道我们的库中有多少方法是公开的,但从未被调用。
目标:静态分析 确定当前项目中有多少行代码调用包A中的每个公共方法。如果调用次数为零,则应报告该方法。
我正在开发一个库,我们想确定我们的库有多少被使用。IE 我们想知道我们的库中有多少方法是公开的,但从未被调用。
目标:静态分析 确定当前项目中有多少行代码调用包A中的每个公共方法。如果调用次数为零,则应报告该方法。
我相信你正在寻找这个 Eclipse 插件 --> UCDetector
从文档(注意第二个要点)
在更大的范围内,如果您想进行对象级静态分析,请查看 IBM 提供的这个工具 --> Structural Analysis for Java。它对库、API 等的对象分析非常有帮助。
不完全是您正在寻找的东西,但是:
使用代码覆盖工具(如Cobertura)可以完成类似的操作。他们不对源代码进行静态检查,而是检测字节码以在运行时收集指标。当然,您需要以一种练习所有使用模式的方式来驱动应用程序,并且可能会错过更罕见的代码路径。
在静态分析方面,也许这些工具可以帮助您(Apache 项目使用它们来检查新版本的 API 兼容性,似乎该任务与您正在尝试做的事情有些相关):
客户端使用反射调用是静态分析中需要考虑的一个漏洞。因为没有办法确定某个特定的方法没有通过一些奇怪的反射方案被调用。所以,也许运行时和静态分析的结合可能是最好的。
我认为您无法衡量需要一个类或一个函数的“频率”。
有一些简单的问题:
结论:
我不知道您要完成什么。
如果你想显示你的代码依赖关系,还有其他工具可以做到这一点。如果您尝试测量代码执行情况,可以使用 Java分析器或基准测试。如果您是统计极客,您会对RapidMiner感到满意;)
祝你好运!
我建议 JDepend 向您展示包和类之间的依赖关系,非常适合找到循环依赖关系! http://clarkware.com/software/JDepend.html (它有一个 Eclipse 插件:http ://andrei.gmxhome.de/jdepend4eclipse/
以及其他指标的 PMD http://pmd.sourceforge.net/
IntelliJ 有一个工具来检测方法、字段、类,这些可以有更多的限制修饰符。它还可以快速修复应用这些更改,这也可以为您节省大量工作。如果您不想为此付费,您可以获得 30 天的 eval 许可证,这足以更改您的代码,这不是您应该经常做的事情。
顺便说一句:IntelliJ 有大约 650 次代码检查来提高代码质量,大约一半有自动修复,所以我建议花几天时间使用它来重构/整理你的代码。
请看一下死代码检测器。它声称可以满足您的需求:使用静态分析查找未使用的代码。
以下是一些 Java 代码覆盖率工具列表。我没有亲自使用过这些,但它可能会让你开始:
Proguard 也可能是一种选择(http://proguard.sourceforge.net/):
“ProGuard 的一些用途是:
另请参阅http://proguard.sourceforge.net/manual/examples.html#deadcode
您可以使用 ASM 字节码分析库 ( http://asm.ow2.org )为此编写自己的实用程序(阅读本文后一小时内)。您需要实现 ClassVisitor 和 MethodVisitor。您将使用 ClassReader 解析库中的类文件。
维护一张地图来进行计数。键代表方法(见下文)。这是一些代码:
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());
}
}
享受!