【问题标题】:How to find unused/dead code in java projects [closed]如何在java项目中找到未使用/死代码[关闭]
【发布时间】:2010-09-14 19:43:38
【问题描述】:

您使用哪些工具来查找大型 Java 项目中未使用的/死代码?我们的产品已经开发了几年,手动检测不再使用的代码变得非常困难。但是,我们会尽量删除未使用的代码。

对于一般策略/技术(特定工具除外)的建议也很受欢迎。

编辑:请注意,我们已经使用了代码覆盖工具(Clover、IntelliJ),但这些帮助不大。死代码仍然有单元测试,并显示为已覆盖。我想一个理想的工具会识别出几乎没有其他代码依赖于它的代码集群,从而允许手动检查文档。

【问题讨论】:

  • 将单元测试保存在单独的源代码树中(无论如何你都应该这样做),并且只在实时树上运行覆盖工具。
  • 我将从 IDEA 的 "Unused declaration" inspection 开始,并取消选中 Include test sources。你能澄清一下你说 IDEA 的“帮助不大”是什么意思吗?
  • 找到死代码的方法: 1) 没有被任何外部链接。 2) 即使在运行时链接,也没有从外部使用。 3)链接和调用但从未像死变量一样使用。 4) 逻辑上不可达的状态。所以链接,随着时间的推移访问,基于逻辑,访问后使用。
  • 使用 IntelliJ Idea 和我的回答:stackoverflow.com/questions/22522013/… :)
  • 大卫鼹鼠的回答:见这个回答stackoverflow.com/a/6587932/1579667

标签: java refactoring dead-code


【解决方案1】:

Eclipse 可以显示/突出显示无法访问的代码。 JUnit 可以向您显示代码覆盖率,但您需要进行一些测试,并且必须确定相关测试是否缺失或代码是否真的未使用。

【讨论】:

  • Eclipse 只会告诉你方法的范围是否是本地的(即私有的);即使那样你也不能 100% 确定......可以从外部调用反射私有方法。
【解决方案2】:

有一些工具可以分析代码并提供代码覆盖率数据。这使您可以看到(在运行代码时)调用了多少。您可以使用这些工具中的任何一个来找出您拥有多少孤儿代码。

【讨论】:

    【解决方案3】:

    理论上,您无法确定性地找到未使用的代码。有一个数学证明(嗯,这是一个更一般定理的特例)。如果您好奇,请查看停机问题。

    这可以通过多种方式体现在 Java 代码中:

    • 根据用户输入、配置文件、数据库条目等加载类;
    • 加载外部代码;
    • 将对象树传递给第三方库;

    话虽如此,我使用 IDEA IntelliJ 作为我选择的 IDE,它具有广泛的分析工具,用于查找模块、未使用的方法、未使用的成员、未使用的类等之间的依赖关系。它也非常智能,就像私有方法一样被调用的 t 被标记为未使用,但公共方法需要更广泛的分析。

    【讨论】:

    • 感谢您的意见。我们正在使用 IntelliJ,并正在那里获得一些帮助。至于停机问题和不可判定性,我对这个理论很熟悉,但我们不一定需要确定性的解决方案。
    • 开场白太强了。与停止问题(也经常被错误引用/滥用)一样,没有完整的通用解决方案,但有很多特殊情况可以检测。
    • 虽然没有针对具有 eval 和/或反射的语言的通用解决方案,但在很多情况下代码可能无法访问。
    • 没有反射和完整的源代码,任何静态类型的语言都应该可以很容易地确定性地找到所有未使用的代码。
    • 您找不到可通过反射或外部调用者证明无法访问的代码,但您可以找到可证明从给定入口点或一组入口点静态无法访问的代码
    【解决方案4】:

    我们已经开始使用Find Bugs 来帮助识别我们代码库的目标丰富的重构环境中的一些问题。我还会考虑使用Structure 101 来识别代码库架构中过于复杂的位置,以便您知道真正的沼泽在哪里。

    【讨论】:

    • FindBugs 无法检测死代码和未使用代码,只能检测未使用的字段。看到这个answer
    【解决方案5】:

    我会检测正在运行的系统以保留代码使用日志,然后开始检查数月或数年未使用的代码。

    例如,如果您对未使用的类感兴趣,则可以检测所有类以在创建实例时进行记录。然后一个小脚本可以将这些日志与完整的类列表进行比较,以找到未使用的类。

    当然,如果你在方法级别上,你应该牢记性能。例如,这些方法只能记录它们的第一次使用。我不知道如何在 Java 中最好地做到这一点。我们在 Smalltalk 中做到了这一点,它是一种动态语言,因此允许在运行时修改代码。我们使用日志调用检测所有方法,并在第一次记录方法后卸载日志代码,因此在一段时间后不会再发生性能损失。也许可以在 Java 中使用静态布尔标志完成类似的事情......

    【讨论】:

    • 我喜欢这个答案,但有没有人知道如何在 Java 中做到这一点,而无需在每个类中显式添加日志记录?也许是一些“代理”魔法?
    • @Outlaw AOP 似乎是完美的用例。
    • 如果您了解应用程序的类加载结构,您可以在类加载器上使用 AOP 来跟踪类加载事件。与所有构造函数之前的建议相比,这对生产系统的侵入性要小。
    • 这个答案对于动态语言来说非常好,但对于可以做得更好的静态语言来说却很糟糕。使用静态类型语言(除了反射),您可以确切地知道使用了哪些方法,哪些没有使用,这是静态类型语言的最大优点之一,您应该使用它而不是这里描述的错误方法.
    • @BillK 发生的反思比您想象的要多。例如。 Spring 在幕后做了很多魔法,包括反射。您的分析工具必须模仿这一点。
    【解决方案6】:

    一个运行良好的 Eclipse 插件是Unused Code Detector

    它处理整个项目或特定文件,并显示各种未使用/无效的代码方法,以及建议可见性更改(即可以保护或私有的公共方法)。

    【讨论】:

    • 看起来不错,但我无法让它工作 - “检测未...代码”操作已禁用,我没有找到启用它的方法。
    • 确实找到了未使用的方法,但也发现我的 EJB 未被使用(虽然它们是),因为我使用的是业务委托模式设计
    • 在开普勒上还能用吗?发布说关于 Eclipse 3.8:ucdetector.org/releases.html
    • 在开普勒上似乎处于完美的工作状态。
    • 您要添加指向市场的链接marketplace.eclipse.org/content/unnecessary-code-detector 吗?这使得安装更容易,并回答了新版本的 Eclipse 是否支持它的问题。
    【解决方案7】:

    用户覆盖率工具,例如 EMMA。但它不是静态工具(即它需要通过回归测试和所有可能的错误情况来实际运行应用程序,这是不可能的:))

    不过,EMMA 还是非常有用的。

    【讨论】:

      【解决方案8】:

      使用测试覆盖率工具来检测您的代码库,然后运行应用程序本身,而不是测试。

      EmmaEclemma 将为您提供关于任何给定代码运行的类运行百分比的良好报告。

      【讨论】:

      • +1 因为这是一个很好的起点,但请记住 e. G。未使用(尚未声明)的变量也会变为绿色。
      【解决方案9】:

      代码覆盖率工具(例如 Emma、Cobertura 和 Clover)将检测您的代码并通过运行一组测试记录其中的哪些部分被调用。这非常有用,应该是您开发过程中不可或缺的一部分。它将帮助您确定测试套件对代码的覆盖程度。

      但是,这与识别真正的死代码不同。它仅标识测试覆盖(或未覆盖)的代码。这可能会给您带来误报(如果您的测试未涵盖所有场景)以及误报(如果您的测试访问的代码实际上从未在现实世界场景中使用过)。

      我认为真正识别死代码的最佳方法是在实时运行环境中使用覆盖率工具检测您的代码,并在较长时间内分析代码覆盖率。

      如果您在负载平衡的冗余环境中运行(如果不是,为什么不呢?)那么我认为只检测您的应用程序的一个实例并配置您的负载平衡器是有意义的,以便随机但很小,您的部分用户在您的检测实例上运行。如果您在很长一段时间内执行此操作(以确保您已涵盖所有现实世界的使用场景 - 例如季节性变化),您应该能够准确地看到您的代码的哪些区域在现实世界使用中被访问以及哪些部分真的从来没有被访问过,因此是死代码。

      我从未亲眼见过这样做,也不知道如何使用上述工具来检测和分析未通过测试套件调用的代码 - 但我相信它们可以。

      【讨论】:

        【解决方案10】:
        • FindBugs 非常适合这类事情。
        • PMD(Project Mess Detector)是另一种可以使用的工具。

        但是,两者都找不到工作区中未使用的公共静态方法。如果有人知道这样的工具,请告诉我。

        【讨论】:

          【解决方案11】:

          众所周知,我在 Eclipse 中对单个类所做的一件事是将其所有方法更改为私有方法,然后看看我收到了哪些投诉。对于使用的方法,这将引发错误,我将它们返回到我可以的最低访问级别。对于未使用的方法,这将引发有关未使用方法的警告,然后可以将其删除。作为奖励,您经常会发现一些可以而且应该设为私有的公共方法。

          但它非常手动。

          【讨论】:

          • 也许不是理想的答案,但这真的很聪明。
          • 这很聪明......直到你从另一个类的未使用代码中调用它。
          • 迭代此方法可能会删除大量代码,因为一个使用过的方法会在删除后创建其他方法。
          【解决方案12】:

          IntelliJ 具有用于检测未使用代码的代码分析工具。您应该尝试将尽可能多的字段/方法/类设为非公开,这样会显示更多未使用的方法/字段/类

          我也会尝试定位重复代码以减少代码量。

          我的最后一个建议是尝试找到开源代码,如果使用它会使您的代码更简单。

          【讨论】:

          • 这些工具是什么的任何示例?
          • @orbfish 你可以运行Analyse => Run inspection by name => unused
          【解决方案13】:

          Structure101 slice perspective 将给出任何“孤儿”或“孤儿groups”的类或包的列表(和依赖图),这些类或包与“主”集群之间没有依赖关系。

          【讨论】:

          • 这对类中的实例变量/方法有效吗?
          • 我怎么知道这是否应该与例如Eclipse 4.3?
          【解决方案14】:

          CodePro 最近由 Google 与 Eclipse 项目一起发布。它是免费且高效的。该插件具有“Find Dead Code”功能,具有一个/多个入口点。效果很好。

          【讨论】:

          • 不会再与 Eclipse Kepler 一起工作了。通过更新站点成功安装后,每次都会使eclipse崩溃。
          • 很遗憾,这个工具似乎没有意识到Spring的存在,因此,它会将我所有的@Components标记为未使用,错误
          • 变老了 不再起作用 Last updated this plugin March 27, 2012 developers.google.com/java-dev-tools/download-codepro
          • 所有链接都已过时。
          • 不幸的是,Google 似乎将代码转储到了 Eclipse 项目中并忘记了它。
          【解决方案15】:

          我很惊讶ProGuard 在这里没有被提及。它是最成熟的产品之一。

          ProGuard 是一个免费的 Java 类文件收缩器、优化器、混淆器, 和预验证。它检测并删除未使用的类、字段、 方法和属性。它优化字节码并删除未使用的 指示。它重命名剩余的类、字段和方法 使用无意义的短名称。最后,它预先验证处理过的 Java 6 或 Java Micro Edition 的代码。

          ProGuard 的一些用途是:

          • 创建更紧凑的代码,用于更小的代码存档、更快的网络传输、更快的加载和更小的内存 脚印。
          • 使程序和库更难逆向工程。
          • 列出死代码,以便可以从源代码中删除。
          • 针对 Java 6 或更高版本重新定位和预验证现有类文件,以充分利用其更快的类加载。

          此处列出无效代码的示例:https://www.guardsquare.com/en/products/proguard/manual/examples#deadcode

          【讨论】:

          • 提供一个示例使用会是一个更好的答案。
          • 阅读文档,我发现它缩小了未使用的代码,但我找不到它列出它的任何地方 - 同意、示例或相关部分的链接的文档,会很有帮助!
          【解决方案16】:

          我找到了 Clover 覆盖工具,它检测代码并突出显示已使用和未使用的代码。与 Google CodePro Analytics 不同,它也适用于 WebApplications(根据我的经验,我对 Google CodePro 的看法可能不正确)。

          我注意到的唯一缺点是它没有考虑 Java 接口。

          【讨论】:

          • Afaict,它是一个非免费的服务器端 CI 工具。
          【解决方案17】:

          DCD 不是某些 IDE 的插件,但可以从 ant 或独立运行。它看起来像一个静态工具和it can do what PMD and FindBugs can't。我会试试的。

          附:正如下面评论中提到的,该项目现在位于GitHub

          【讨论】:

          • 这应该作为评论而不是回答
          • 请更新您的答案以删除您关于 DCD“现在看起来已死”的声明。 Version 2.1 was released 12 days ago。此外,您的答案中的链接不起作用。
          【解决方案18】:

          有一个 Java 项目 - Dead Code Detector (DCD)。对于源代码,它似乎不能很好地工作,但对于 .jar 文件 - 它真的很好。另外,您可以按类和方法进行过滤。

          【讨论】:

            【解决方案19】:

            在 Eclipse 中转到 Windows > 首选项 > Java > 编译器 > 错误/警告
            并将它们全部更改为错误。修复所有错误。这是最简单的方法。美妙之处在于,这将允许您在编写代码时清理代码。

            截图 Eclipse 代码:

            【讨论】:

              【解决方案20】:

              Netbeans 这是 Netbeans dead code detector 的插件。

              如果它可以链接并突出显示未使用的代码会更好。你可以在这里投票和评论:Bug 181458 - Find unused public classes, methods, fields

              【讨论】:

                【解决方案21】:

                我使用 Doxygen 开发了一个方法调用映射来定位从未调用过的方法。在图表上,您会发现没有调用者的方法集群孤岛。这不适用于库,因为您需要始终从某个主要入口点开始。

                【讨论】:

                  猜你喜欢
                  • 2012-03-20
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-05-30
                  • 1970-01-01
                  • 2010-09-18
                  • 2011-10-24
                  • 2010-09-19
                  相关资源
                  最近更新 更多