我工作上的一个图书馆,在那里,我们想要确定有多少我们的图书馆,正在使用。E.I.我们想知道如何许多的方法在我们的图书馆都是公开的,但从来没有被称为。

目标:静态分析 确定有多少代码行的呼叫每个公用的方法包A在目前的项目。如果电话的数量为零的方法,该方法应该是报告为如此。

有帮助吗?

解决方案

我相信你是在找这个日食的插件--> UCDetector

从文件(请注意以第二个圆点)

  • 不必要的(死亡)的代码
  • 代码在哪里能见度可以被改变以保护,或默认的 私
  • 方法的领域,它可能最终

在规模较大,如果你想要做的对象的平静态分析,看看这个工具,从IBM-->结构分析对于Java.它是真正有用的对象分析的图书馆,Api,等等。

其他提示

不正是你所寻找的,但是:

类似的东西被复盖代码工具(喜欢 Cobertura).他们不这样做的静态检查的源代码,但仪器的码来收集指标在运行时间。当然,你需要来驱动应用的一个方式演习所有的使用模式,并且可能会错过的罕见码的路径。

在静态分析前,也许这些工具可以帮助您(Apache项目使用他们来检查API兼容性的新版本,似乎喜欢那个任务有些与什么有关你正在尝试做):

  • Clirr 是一个工具,检查Java库为二进制和来源的兼容性更旧的版本。基本上你得到这两个组罐子文件和Clirr甩出一个列表中的变化的公共api。
  • JDiff 是如果是的话,为什么不试doclet其产生HTML报告的所有软件包、类的构造、方法和领域已被删除,加入或以任何方式改变,包括它们的文件中,当两个Api比较。

反射呼叫的客户端应用是在静态分析一个孔来考虑。由于没有办法确切知道某个特定方法不被通过一些奇怪的反射机制调用。所以,也许运行时和静态分析的结合可能是最好的。

我不认为你能够衡量"通常"一类或功能是必要的。
有一些简单的问题:

  • 什么样的定义,如果使用情况统计的你的游戏库,是"正常的"或"异常"?这是错误的杀死在自己的游戏往往?你将使用"killScreen"类更经常像一个很好的玩家。
  • 什么定义"太多"?时间或使用计数?独的将占用稀少的时间,但是使用相当频繁。

结论:
我不知道你想什么来完成。
如果你想显示你的代码依存关系,还有其他的 工具 这样做。如果你想的措施代码的执行,还有 探查或基准 为Java。如果你是一个怪胎的统计数据,你会很快乐 ;)

那祝你好运!

我会建议JDepend显示你的包和类之间的依赖关系,优秀的发现循环依赖! http://clarkware.com/software/JDepend.html (它有一个Eclipse插件: http://andrei.gmxhome.de/jdepend4eclipse/

和也PMD其他指标 http://pmd.sourceforge.net/

的IntelliJ具有工具来检测方法,字段,它可以有更多的限制调节剂类。它也是一个具有速战速决应用这些变化,这可以为您节省大量的工作为好。如果你不想为它付出,你可以得到30天的eval许可证,这是时间上绰绰有余改变你的代码,它不是你应该需要经常做的。

BTW:拥有的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分析这类文件在图书馆。

  • 你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());
    }
}

享受!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top