Cómo encontrar código no utilizado / muerto en proyectos de Java [cerrado]

306

¿Qué herramientas utiliza para encontrar código no utilizado / muerto en grandes proyectos de Java? Nuestro producto ha estado en desarrollo durante algunos años, y se está volviendo muy difícil detectar manualmente el código que ya no está en uso. Sin embargo, intentamos eliminar la mayor cantidad posible de código no utilizado.

También se agradecen las sugerencias de estrategias / técnicas generales (que no sean herramientas específicas).

Editar: Tenga en cuenta que ya usamos herramientas de cobertura de código (Clover, IntelliJ), pero estas son de poca ayuda. El código muerto todavía tiene pruebas unitarias y aparece como cubierto. Supongo que una herramienta ideal identificaría grupos de código que tienen muy poco otro código dependiendo de él, lo que permite la inspección manual de documentos.

Knatten
fuente
16
Mantenga las pruebas unitarias en un árbol fuente separado (de todos modos debería hacerlo) y ejecute las herramientas de cobertura solo en el árbol activo.
agnul
55
Comenzaría con la inspección "Declaración no utilizada" de IDEA y desmarcaría Incluir fuentes de prueba . ¿Puedes aclarar a qué te refieres cuando dices IDEA "de poca ayuda"?
David Moles
1
Formas de encontrar el código muerto: 1) no está vinculado por nada externo. 2) no se ha utilizado desde el exterior aunque esté vinculado en tiempo de ejecución. 3) Vinculado y llamado pero nunca utilizado como variable muerta. 4) estado lógicamente inalcanzable. Entonces, vincular, acceder a lo largo del tiempo, basado en la lógica, usar después de acceder.
Muhammad Umer
Use IntelliJ Idea y mi respuesta desde aquí: stackoverflow.com/questions/22522013/… :)
BlondCode
Además de la respuesta de David Mole: vea esta respuesta stackoverflow.com/a/6587932/1579667
Benj

Respuestas:

40

Instrumentaría el sistema en ejecución para mantener registros del uso del código y luego comenzaría a inspeccionar el código que no se usa durante meses o años.

Por ejemplo, si está interesado en clases no utilizadas, todas las clases podrían instrumentarse para iniciar sesión cuando se creen instancias. Y luego un pequeño script podría comparar estos registros con la lista completa de clases para encontrar clases no utilizadas.

Por supuesto, si va al nivel del método, debe tener en cuenta el rendimiento. Por ejemplo, los métodos solo podían registrar su primer uso. No sé cómo se hace esto mejor en Java. Lo hemos hecho en Smalltalk, que es un lenguaje dinámico y, por lo tanto, permite la modificación del código en tiempo de ejecución. Instrumentamos todos los métodos con una llamada de registro y desinstalamos el código de registro después de que un método se ha registrado por primera vez, por lo que después de algún tiempo no se producen más penalizaciones de rendimiento. Tal vez se pueda hacer algo similar en Java con banderas booleanas estáticas ...

akuhn
fuente
55
Me gusta esta respuesta, pero ¿alguien tiene una idea de cómo hacer esto en Java sin agregar explícitamente el registro en cada clase? Tal vez algo de magia 'Proxy'?
Outlaw Programmer
14
@Outlaw AOP parece ser un caso de uso perfecto para esto.
Pascal Thivent
66
Si comprende la estructura de carga de clases de la aplicación, puede usar AOP en el cargador de clases para rastrear los eventos de carga de clases. Esto sería menos invasivo en un sistema de producción que el consejo ante todos los constructores.
ShabbyDoo
55
Esta respuesta es bastante buena para un lenguaje dinámico pero terrible para un lenguaje estático que podría hacer MUCHO mejor. Con un lenguaje tipado estáticamente (aparte de la reflexión) puede saber con certeza exactamente qué métodos se usan y cuáles no, esta es una de las mayores ventajas de un lenguaje tipado estáticamente y debe usarlo en lugar del método fallable como se describe aquí .
Bill K
44
@BillK ocurre más reflexión de lo que piensas. Por ejemplo, Spring hace bastante magia debajo de las sábanas, incluida la reflexión. Su herramienta de análisis debe emular eso.
Thorbjørn Ravn Andersen
220

Un complemento de Eclipse que funciona razonablemente bien es el Detector de código no utilizado .

Procesa un proyecto completo o un archivo específico y muestra varios métodos de código inactivo / inactivo, además de sugerir cambios de visibilidad (es decir, un método público que podría estar protegido o privado).

Mikezx6r
fuente
Parece agradable, pero no pude hacerlo funcionar: la acción "Detectar un ... código" está desactivada y no encontré la forma de habilitarla.
Ondra Žižka
1
En efecto, encontrar métodos utilizados, sino también encontrar que mis EJB están siendo utilizado (mientras que son) porque estoy usando un patrón de diseño delegado de negocio
Eildosa
¿Todavía funciona en kepler? lanzamientos dicen sobre eclipse 3.8: ucdetector.org/releases.html
Mr_and_Mrs_D
Parece estar en perfectas condiciones de funcionamiento en Kepler.
Erik Kaplun
44
¿Desea agregar un enlace al marketplace marketplace.eclipse.org/content/unnecessary-code-detector ? Esto facilita la instalación y responde a la pregunta de si es compatible con las versiones más nuevas de Eclipse.
Thomas Weller
64

CodePro fue lanzado recientemente por Google con el proyecto Eclipse. Es gratis y altamente efectivo. El complemento tiene la función ' Buscar código muerto ' con uno / varios puntos de entrada. Funciona bastante bien

Berlin Brown
fuente
1
Ya no funcionará con el eclipse Kepler. Después de instalarlo con éxito a través del sitio de actualización, hace que eclipse se bloquee cada vez.
txulu
Desafortunadamente, parece que esta herramienta no se da cuenta de la existencia de Spring, por lo tanto, marcará a todos mis @Componentes como no utilizados, incorrectamente
Clint Eastwood
Ser muy viejo No funciona más Last updated this plugin March 27, 2012 developers.google.com/java-dev-tools/download-codepro
mumair
2
Todos los enlaces están desactualizados.
zygimantus
3
Desafortunadamente, parece que Google descargó el código en el proyecto Eclipse y lo olvidó todo.
Thorbjørn Ravn Andersen
30

Me sorprende que ProGuard no haya sido mencionado aquí. Es uno de los productos más maduros.

ProGuard es un reductor, optimizador, ofuscador y preverificador de archivos de clase Java gratuito. Detecta y elimina clases, campos, métodos y atributos no utilizados. Optimiza el código de bytes y elimina las instrucciones no utilizadas. Cambia el nombre de las clases, campos y métodos restantes utilizando nombres cortos sin sentido. Finalmente, preverifica el código procesado para Java 6 o para Java Micro Edition.

Algunos usos de ProGuard son:

  • Creación de código más compacto, para archivos de código más pequeños, transferencia más rápida a través de redes, carga más rápida y huellas de memoria más pequeñas.
  • Hacer que los programas y las bibliotecas sean más difíciles de realizar ingeniería inversa.
  • Listado de código muerto, por lo que puede eliminarse del código fuente.
  • Retargeting y preverificación de archivos de clase existentes para Java 6 o superior, para aprovechar al máximo su carga de clase más rápida.

Aquí ejemplo para el código muerto de la lista: https://www.guardsquare.com/en/products/proguard/manual/examples#deadcode

David d C e Freitas
fuente
8
Proporcionar una muestra de uso sería una mejor respuesta.
rds
1
Al leer la documentación, veo que reduce el código no utilizado, pero no puedo encontrar ningún lugar donde lo enumere . ¡De acuerdo, un ejemplo o un enlace a la sección relevante de la documentación sería muy útil!
pez orb
26

Una cosa que se sabe que hago en Eclipse, en una sola clase, es cambiar todos sus métodos a privados y luego ver qué quejas recibo. Para los métodos que se utilizan, esto provocará errores y los devolveré al nivel de acceso más bajo que pueda. Para los métodos que no se utilizan, esto provocará advertencias sobre los métodos que no se utilizan, y luego se pueden eliminar. Y como beneficio adicional, a menudo encuentra algunos métodos públicos que pueden y deben hacerse privados.

Pero es muy manual.

skiphoppy
fuente
44
Quizás no sea la respuesta ideal, pero eso es realmente inteligente.
Erik Reppen
8
Esto es inteligente ... hasta que reciba una llamada desde un código no utilizado de otra clase.
Danosaure
Iterar sobre este método podría eliminar grandes extensiones de código, ya que un método usado crea otros una vez que se elimina.
4myle
15

Use una herramienta de cobertura de prueba para instrumentar su base de código, luego ejecute la aplicación en sí, no las pruebas.

Emma y Eclemma le darán buenos informes de qué porcentaje de las clases se ejecutan para cualquier ejecución del código.

jamesh
fuente
1
+1 porque es un buen punto de partida, pero tenga en cuenta que, por ejemplo, las variables no utilizadas (aún declaradas) también aparecerán en verde.
DerMike
13

Hemos comenzado a utilizar Find Bugs para ayudar a identificar algunos de los funk en el entorno rico en objetivos de nuestra base de código para refactorizaciones. También consideraría la Estructura 101 para identificar puntos en la arquitectura de su base de código que son demasiado complicados, para que sepa dónde están los pantanos reales.

Alan
fuente
44
FindBugs no puede detectar código muerto y sin usar, solo campos sin usar. Mira esta respuesta .
Stefan Mücke
12

En teoría, no puede encontrar de manera determinista el código no utilizado. Hay una prueba matemática de esto (bueno, este es un caso especial de un teorema más general). Si tienes curiosidad, busca el problema de detención.

Esto puede manifestarse en el código Java de muchas maneras:

  • Carga de clases basadas en la entrada del usuario, archivos de configuración, entradas de bases de datos, etc.
  • Cargando código externo;
  • Pasar árboles de objetos a bibliotecas de terceros;
  • etc.

Dicho esto, uso IDEA IntelliJ como mi IDE de elección y tiene amplias herramientas de análisis para encontrar dependencias entre módulos, métodos no utilizados, miembros no utilizados, clases no utilizadas, etc. Es bastante inteligente como un método privado que no se llama etiquetado sin usar, pero un método público requiere un análisis más extenso.

cletus
fuente
1
Gracias por su aporte. Estamos usando IntelliJ, y estamos recibiendo ayuda allí. En cuanto al problema de detención y la indecidibilidad, estoy familiarizado con la teoría, pero no necesitamos necesariamente una solución determinista.
Knatten
12
La oración de apertura es demasiado fuerte. Al igual que con el problema de detención (también a menudo mal citado / abusado), no hay soluciones generales completas, pero hay muchos casos especiales que SON factibles de detectar.
joel.neely
99
Si bien no existe una solución general para los lenguajes con evaluación y / o reflexión, hay muchos casos en los que el código es inalcanzable.
pjc50
1
Sin reflexión y con el código fuente completo, cualquier lenguaje estáticamente escrito debería hacer que sea bastante fácil encontrar determinísticamente todo el código no utilizado.
Bill K
No puede encontrar que sea comprobable inalcanzable por reflexión o por personas externas que llaman, pero puede encontrar código que sea demostrable inalcanzable estáticamente desde un punto de entrada o conjunto de puntos de entrada
dado
8

En Eclipse, vaya a Windows> Preferencias> Java> Compilador> Errores / Advertencias
y cámbielos a errores. Corrige todos los errores. Esta es la forma más simple. Lo bueno es que esto te permitirá limpiar el código mientras escribes.

Captura de pantalla del código de Eclipse:

ingrese la descripción de la imagen aquí

smileprem
fuente
5

IntelliJ tiene herramientas de análisis de código para detectar código que no se utiliza. Debe intentar hacer tantos campos / métodos / clases como no públicos como sea posible y eso mostrará más métodos / campos / clases no utilizados

También trataría de localizar el código duplicado como una forma de reducir el volumen del código.

Mi última sugerencia es tratar de encontrar código fuente abierto que, si se usa, simplificaría su código.

Peter Lawrey
fuente
¿Algún ejemplo de cuáles son estas herramientas?
pez orb
@orbfish Puedes correr Analyse=> Run inspection by name=>unused
Peter Lawrey
5

La perspectiva de división de Structure101 proporcionará una lista (y un gráfico de dependencia) de los "huérfanos" o " grupos huérfanos " de clases o paquetes que no tienen dependencias hacia o desde el clúster "principal".

Chris Chedgey - Estructura101
fuente
¿Funciona esto, por ejemplo, con variables / métodos dentro de una clase?
Joeblackdev
¿Cómo sé si se supone que esto funciona, por ejemplo, con Eclipse 4.3?
Erik Kaplun
3

DCD no es un complemento para algunos IDE, pero se puede ejecutar desde hormiga o independiente. Parece una herramienta estática y puede hacer lo que PMD y FindBugs no pueden . Voy a intentarlo.

PD Como se menciona en un comentario a continuación, el Proyecto vive ahora en GitHub .

Heiner
fuente
Esto debería ir como un comentario no como respuesta
cuenta el
Actualice su respuesta para eliminar su afirmación de que DCD "parece muerto ahora". La versión 2.1 fue lanzada hace 12 días . Además, el enlace en su respuesta no funciona.
skomisa
2

Hay herramientas que codifican el perfil y proporcionan datos de cobertura del código. Esto le permite ver (a medida que se ejecuta el código) cuánto se llama. Puede obtener cualquiera de estas herramientas para averiguar cuánto código huérfano tiene.

Vaibhav
fuente
2
  • FindBugs es excelente para este tipo de cosas.
  • PMD (Project Mess Detector) es otra herramienta que se puede utilizar.

Sin embargo, ninguno puede encontrar métodos estáticos públicos que no se usen en un espacio de trabajo. Si alguien conoce esa herramienta, hágamelo saber.

Graveca
fuente
1

Herramientas de cobertura del usuario, como EMMA. Pero no es una herramienta estática (es decir, requiere ejecutar realmente la aplicación a través de pruebas de regresión y a través de todos los posibles casos de error, lo cual es, bueno, imposible :))

Aún así, EMMA es muy útil.

Vladimir Dyuzhev
fuente
1

Las herramientas de cobertura de código, como Emma, ​​Cobertura y Clover, instrumentarán su código y registrarán qué partes se invocan ejecutando un conjunto de pruebas. Esto es muy útil y debería ser una parte integral de su proceso de desarrollo. Le ayudará a identificar qué tan bien su conjunto de pruebas cubre su código.

Sin embargo, esto no es lo mismo que identificar un código muerto real. Solo identifica el código cubierto (o no cubierto) por las pruebas. Esto puede darle falsos positivos (si sus pruebas no cubren todos los escenarios), así como falsos negativos (si sus pruebas acceden al código que en realidad nunca se usa en un escenario del mundo real).

Me imagino que la mejor manera de identificar realmente el código muerto sería instrumentar su código con una herramienta de cobertura en un entorno de ejecución en vivo y analizar la cobertura del código durante un período prolongado de tiempo.

Si está ejecutando en un entorno redundante de carga equilibrada (y si no, ¿por qué no?), Supongo que tendría sentido instrumentar solo una instancia de su aplicación y configurar su equilibrador de carga de modo que una porción aleatoria, pero pequeña, de sus usuarios se ejecutan en su instancia instrumentada. Si hace esto durante un período prolongado de tiempo (para asegurarse de haber cubierto todos los escenarios de uso del mundo real, tales variaciones estacionales), debería poder ver exactamente qué áreas de su código se accede bajo el uso del mundo real y qué partes realmente nunca se accede y, por lo tanto, el código muerto.

Nunca lo he visto personalmente, y no sé cómo se pueden usar las herramientas antes mencionadas para instrumentar y analizar el código que no se invoca a través de un conjunto de pruebas, pero estoy seguro de que sí.

Vihung
fuente
1

Hay un proyecto Java: Detector de código muerto (DCD). Para el código fuente no parece funcionar bien, pero para el archivo .jar, es realmente bueno. Además, puedes filtrar por clase y por método.

Lukasz Czerwinski
fuente
0

Eclipse puede mostrar / resaltar código que no se puede alcanzar. JUnit puede mostrarle la cobertura del código, pero necesitará algunas pruebas y tendrá que decidir si falta la prueba relevante o si el código realmente no se utiliza.

Matthias Winkelmann
fuente
3
Eclipse solo le dirá si el alcance del método es local (es decir, privado); e incluso entonces no puede estar 100% seguro ... con el método privado de reflexión se podría llamar desde afuera.
p3t0r
0

Encontré la herramienta de cobertura Clover que codifica los instrumentos y resalta el código que se usa y que no se usa. A diferencia de Google CodePro Analytics, también funciona para aplicaciones web (según mi experiencia y puedo ser incorrecto sobre Google CodePro).

El único inconveniente que noté es que no tiene en cuenta las interfaces Java.

Kashif Nazar
fuente
De hecho, es una herramienta de CI del lado del servidor no libre.
Erik Kaplun
0

Utilizo Doxygen para desarrollar un mapa de llamadas a métodos para localizar métodos que nunca se llaman. En el gráfico encontrará islas de grupos de métodos sin llamadores. Esto no funciona para las bibliotecas, ya que siempre debe comenzar desde algún punto de entrada principal.

jbruni
fuente