如何在Java项目中查找未使用/无效的代码[关闭]


306

您使用什么工具在大型Java项目中查找未使用/无效的代码?我们的产品已经开发了几年,并且很难手动检测不再使用的代码。但是,我们确实尝试删除尽可能多的未使用的代码。

对于一般策略/技术(除特定工具之外)的建议也将受到赞赏。

编辑:请注意,我们已经使用了代码覆盖率工具(Clover,IntelliJ),但是这些帮助不大。无效代码仍具有单元测试,并显示为已覆盖。我猜一个理想的工具可以识别出几乎没有其他代码依赖的代码集群,从而可以对文档进行手动检查。


16
将单元测试保存在单独的源代码树中(无论如何,还是应该如此),并且仅在活动树上运行coverage工具。
08年

5
我将从IDEA的“未使用的声明”检查开始,然后取消选中“ 包括测试源”。当您说出IDEA的“无济于事”时,您能否阐明您的意思?
David Moles

1
查找无效代码的方法:1)不被任何外部链接。2)即使在运行时链接,也没有从外部使用过。3)链接和调用,但从未像死变量一样使用。4)逻辑上无法达到的状态。因此,链接,随时间访问,基于逻辑,访问后使用。
穆罕默德·乌默

从这里使用IntelliJ Idea和我的答案:stackoverflow.com/questions/22522013/… :)
BlondCode

除了大卫·摩尔的答案:看到这个答案stackoverflow.com/a/6587932/1579667
Benj 2016年

Answers:


40

我将对正在运行的系统进行检测以保留代码使用情况的日志,然后开始检查几个月或几年未使用的代码。

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

当然,如果您使用方法级别,则应牢记性能。例如,这些方法只能记录其首次使用。我不知道这是如何用Java最好完成的。我们是在Smalltalk中完成的,Smalltalk是一种动态语言,因此可以在运行时修改代码。我们使用日志记录调用对所有方法进行检测,并在首次记录方法后卸载日志记录代码,因此一段时间后,不再发生性能损失。也许可以使用静态布尔值在Java中完成类似的操作...


5
我喜欢这个答案,但是没有人知道如何在Java中执行此操作,而无需在每个类中显式添加日志记录吗?也许有些“代理”魔术?
Outlaw程序员,

14
@Outlaw AOP似乎是完美的用例。
Pascal Thivent

6
如果了解应用程序的类加载结构,则可以在类加载器上使用AOP来跟踪类加载事件。在生产系统上,这比在向所有构造函数提供建议之前的侵入性要小。
ShabbyDoo

5
对于动态语言来说,这个答案是相当不错的,但对于静态语言来说,答案可能会更好。使用静态类型语言(除了反射),您可以确切地知道使用了哪些方法,哪些没有使用,这是静态类型语言的最大优点之一,您应该使用它,而不是使用此处所述的易失方法。 。
比尔K

4
@BillK发生的反射比您想象的要多。例如,Spring在幕后做了很多魔术,包括反射。您的分析工具必须模仿这一点。
托尔比约恩Ravn的安德森

220

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

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


看起来不错,但我无法使它正常工作-“检测到...代码”操作已禁用,并且我找不到启用它的方法。
Ondra参观Žižka

1
确实确实找到了未使用的方法,但同时也发现我的EJB未使用(因为它们在使用中),因为我正在使用业务委托模式设计
Eildosa 2012年

它仍然可以在开普勒上工作吗?发布有关日食3.8的说法:ucdetector.org/releases.html
Mr_and_Mrs_D 2013年

似乎在开普勒上处于完美的工作状态。
埃里克·卡普伦2014年

4
您是否要添加到市场marketplace.eclipse.org/content/unnecessary-code-detector的链接?这使安装更加容易,并回答了新版本的Eclipse是否支持该问题。
Thomas Weller 2015年

64

Google最近通过Eclipse项目发布了CodePro。它是免费且高效的。该插件具有“ 查找死代码 ”功能,具有一个/多个入口点。效果很好。


1
不再与日食开普勒一起使用。通过更新站点成功安装后,每次都会使eclipse崩溃。
txulu 2014年

不幸的是,该工具似乎没有意识到Spring的存在,因此,它将我所有的@Components标记为未使用
Clint Eastwood

变得很老了,不再起作用Last updated this plugin March 27, 2012 developers.google.com/java-dev-tools/download-codepro
mumair 2015年

2
所有链接已过时。
zygimantus '16

3
不幸的是,Google似乎将代码转储到了Eclipse项目中,并全都忘记了。
托尔比约恩Ravn的安德森

30

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

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

ProGuard的一些用途是:

  • 创建更紧凑的代码,以实现更小的代码归档,更快的网络传输,更快的加载和更小的内存占用。
  • 使程序和库更难以逆向工程。
  • 列出无效代码,因此可以将其从源代码中删除。
  • 重新定位和预验证Java 6或更高版本的现有类文件,以充分利用它们更快的类加载速度。

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


8
提供样本用法将提供更好的答案。
rds 2015年

1
阅读文档后,我发现它会缩小未使用的代码,但是在列出它的任何地方都找不到-同意的示例或指向文档相关部分的链接将非常有帮助!
orbfish

26

我已经知道在Eclipse上的一个类中要做的一件事是将其所有方法都更改为私有方法,然后查看我收到的投诉。对于使用的方法,这会引发错误,我将它们返回到可以达到的最低访问级别。对于未使用的方法,这将引发关于未使用方法的警告,然后可以将其删除。另外,您经常会发现一些可以并且应该私有的公共方法。

但这是非常手动的。


4
也许不是理想的答案,但这确实很聪明。
Erik Reppen

8
这很聪明……直到您从另一个类的未使用代码中对其进行了调用。
Danosaure

迭代此方法可能会删除大量的代码,因为一个使用过的方法一旦删除就会创建其他代码。
4myle

15

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

艾玛(Emma)埃克莱玛(Eclemma)将为您提供有关任何给定代码运行量的百分比百分比的漂亮报告。


1
+1是一个很好的起点,但是请记住,例如,未使用(尚未声明)的变量也将变为绿色。
DerMike 2010年

13

我们已开始使用“ 查找错误”来帮助识别代码库的目标丰富环境中的某些功能,以进行重构。我还将考虑使用结构101来识别代码库体系结构中过于复杂的点,以便您知道真正的沼泽在哪里。


4
FindBugs无法检测无效和未使用的代码,只能检测未使用的字段。看到这个答案
StefanMücke'4

12

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

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

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

就是说,我将IDEA IntelliJ用作我的首选IDE,它具有用于模块,未使用的方法,未使用的成员,未使用的类等之间的依赖关系的广泛分析工具。它非常智能,就像未调用的私有方法是标记为未使用,但公共方法需要更广泛的分析。


1
谢谢您的意见。我们正在使用IntelliJ,并在那里获得了一些帮助。关于停止问题和不确定性,我对理论很熟悉,但是我们不必一定要有确定性的解决方案。
knatten

12
开场白太强了。与停止问题(也经常被错误引用/滥用)一样,没有完整的常规解决方案,但是有很多可以检测到的特殊情况。
joel.neely

9
虽然没有针对具有评估和/或反思功能的语言的通用解决方案,但在很多情况下,代码证明是无法访问的。
pjc50

1
没有反射,没有完整的源代码,任何静态类型的语言都应该很容易确定性地找到所有未使用的代码。
比尔K

您无法通过反射或外部调用者找到无法证明的可证明性,但是您可以从给定的入口点或一组入口点中找到无法静态证明的可证明性的代码
nafg

8

在Eclipse中,转到Windows>首选项> Java>编译器>错误/警告
然后将它们全部更改为错误。修复所有错误。这是最简单的方法。这样做的好处是,您可以在编写代码时清理代码。

屏幕截图Eclipse代码:

在此处输入图片说明


5

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

我还将尝试查找重复的代码,以减少代码量。

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


这些工具是什么例子?
orbfish

@orbfish您可以运行Analyse=> Run inspection by name=>unused
Peter Lawrey



2

有一些工具可以分析代码并提供代码覆盖率数据。这样一来,您可以查看(在运行代码时)调用了多少代码。您可以使用这些工具中的任何一种来查明您有多少孤立代码。


2
  • FindBugs对于这种事情非常有用。
  • PMD(项目混乱检测器)是可以使用的另一种工具。

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


1

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

尽管如此,EMMA还是非常有用的。


1

艾玛(Emma),柯贝图拉(Cobertura)和三叶草(Clover)等代码覆盖工具将对您的代码进行检测,并记录通过运行一系列测试来调用其中的哪些部分。这非常有用,并且应该是开发过程中不可或缺的一部分。这将帮助您确定测试套件覆盖代码的程度。

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

我想,真正识别无效代码的最佳方法是在实时运行的环境中使用覆盖率工具对代码进行检测,并分析长时间的代码覆盖率。

如果您在负载平衡的冗余环境中运行(如果不是,为什么呢?),那么我认为只对应用程序的一个实例进行检测并配置负载均衡器是合理的,这样可以使其中的一部分随机但很小。您的用户在您的检测实例上运行。如果您在较长的时间内执行此操作(以确保您已涵盖所有实际使用情况-这样的季节性变化),则应该能够准确查看在实际使用情况下访问了哪些代码区域以及哪些部分实际上从未被访问过,因此代码无效。

我从来没有亲眼目睹这件事的完成,也不知道上述工具如何用于检测和分析未通过测试套件调用的代码-但我相信它们可以做到。




0

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


3
Eclipse只会告诉您该方法的范围是否是本地的(即私有的);即使这样,您也不能100%确定...使用反射私有方法可以从外部调用。
p3t0r

0

我发现了四叶草覆盖率工具,该工具可检测代码并突出显示已使用和未使用的代码。与Google CodePro Analytics不同,它也适用于WebApplications(根据我的经验,我对Google CodePro可能不正确)。

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


Afaict,它是一种非免费的服务器端CI工具。
埃里克·卡普伦2014年

0

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.