Como encontrar código não utilizado / morto em projetos java [fechado]

306

Quais ferramentas você usa para encontrar código não utilizado / morto em grandes projetos java? Nosso produto está em desenvolvimento há alguns anos e está ficando muito difícil detectar manualmente o código que não está mais em uso. No entanto, tentamos excluir o máximo de código não utilizado possível.

Sugestões para estratégias / técnicas gerais (além de ferramentas específicas) também são apreciadas.

Edit: Observe que já usamos ferramentas de cobertura de código (Clover, IntelliJ), mas essas são de pouca ajuda. O código morto ainda tem testes de unidade e aparece como coberto. Eu acho que uma ferramenta ideal identificaria clusters de código que possuem muito pouco outro código dependendo dele, permitindo a inspeção manual de documentos.

Knatten
fonte
16
Mantenha os testes de unidade em uma árvore de origem separada (você deveria mesmo assim) e execute as ferramentas de cobertura apenas na árvore ativa.
Agnul 2/10/08
5
Gostaria de começar com a inspeção "Declaração não utilizada" da IDEA e desmarcar a opção Incluir fontes de teste . Você pode esclarecer o que quer dizer quando diz "pouca ajuda" da IDEA?
David Moles
1
Maneiras de encontrar código morto: 1) não vinculado por nada externo. 2) não foi usado de fora, embora esteja vinculado em tempo de execução. 3) Vinculado e chamado, mas nunca usado como variável morta. 4) estado logicamente inacessível. Então, vincular, acessar ao longo do tempo, com base na lógica, usar após o acesso.
Muhammad Umer
Use IntelliJ IDEA e minha resposta a partir daqui: stackoverflow.com/questions/22522013/... :)
BlondCode
Além da resposta de David Mole: consulte esta resposta stackoverflow.com/a/6587932/1579667
Benj

Respostas:

40

Eu instrumentaria o sistema em execução para manter registros do uso do código e, em seguida, começaria a inspecionar o código que não é usado por meses ou anos.

Por exemplo, se você estiver interessado em classes não utilizadas, todas as classes poderão ser instrumentadas para registrar quando as instâncias forem criadas. E um pequeno script poderia comparar esses logs com a lista completa de classes para encontrar classes não utilizadas.

Obviamente, se você for no nível do método, lembre-se do desempenho. Por exemplo, os métodos podem registrar apenas o primeiro uso. Eu não sei como isso é melhor feito em Java. Fizemos isso no Smalltalk, que é uma linguagem dinâmica e, portanto, permite a modificação do código em tempo de execução. Instrumentamos todos os métodos com uma chamada de registro e desinstalamos o código de registro após um método ter sido registrado pela primeira vez, assim, após algum tempo, não ocorrem mais penalidades de desempenho. Talvez algo semelhante possa ser feito em Java com sinalizadores estáticos booleanos ...

akuhn
fonte
5
Eu gosto desta resposta, mas alguém tem uma idéia de como fazer isso em Java sem adicionar explicitamente o log em todas as classes? Talvez alguma mágica 'Proxy'?
Outlaw Programmer
14
@ AOP ilegal parece ser o caso de uso perfeito para isso.
Pascal Thivent
6
Se você entender a estrutura de carregamento de classes do aplicativo, poderá usar o AOP no carregador de classes para rastrear eventos de carregamento de classe. Isso seria menos invasivo em um sistema de produção do que o aconselhamento antes de todos os construtores.
ShabbyDoo
5
Esta resposta é muito boa para uma linguagem dinâmica, mas terrível para uma linguagem estática que poderia ser MUITO melhor. Com uma linguagem de tipo estático (além da reflexão), você pode saber com certeza exatamente quais métodos são usados ​​e quais não são, essa é uma das maiores vantagens de um idioma de tipo estaticamente e você deve usá-lo em vez do método falível, conforme descrito aqui .
Bill K
4
@ BillK acontece mais reflexão do que você pensa. Por exemplo, a primavera faz um pouco de mágica sob as cobertas, incluindo a reflexão. Sua ferramenta de análise deve emular isso.
Thorbjørn Ravn Andersen 21/03
220

Um plug-in do Eclipse que funciona razoavelmente bem é o Unused Code Detector .

Ele processa um projeto inteiro ou um arquivo específico e mostra vários métodos de código não utilizados / mortos, além de sugerir alterações de visibilidade (isto é, um método público que pode ser protegido ou privado).

Mikezx6r
fonte
Parece bom, mas não consegui fazê-lo funcionar - a ação "Detectar um ... código" está desativada e não encontrei uma maneira de ativá-lo.
Ondra Žižka
1
De fato, encontrar métodos não utilizados, mas também descobrir que meus EJBs estão sendo utilizado (quando são) porque eu estou usando um design padrão delegado de negócios
Eildosa
Ainda funciona no kepler? Os lançamentos dizem sobre o eclipse 3.8: ucdetector.org/releases.html
Mr_and_Mrs_D
Parece estar em perfeitas condições de funcionamento no Kepler.
Erik Kaplun
4
Deseja adicionar um link ao marketplace marketplace.eclipse.org/content/unnecessary-code-detector ? Isso facilita a instalação e responde à pergunta se ele é suportado nas versões mais recentes do Eclipse.
Thomas Weller
64

O CodePro foi lançado recentemente pelo Google com o projeto Eclipse. É gratuito e altamente eficaz. O plug-in possui o recurso ' Localizar código morto ' com um / muitos pontos de entrada. Funciona muito bem.

Berlin Brown
fonte
1
Não funcionará mais com o eclipse Kepler. Depois de instalá-lo com sucesso através do site de atualização, o eclipse sempre falha.
txulu
Infelizmente, parece que esta ferramenta não percebe a existência de Primavera, portanto, ele vai marcar todos os meus @Components como não utilizado, erroneamente
Clint Eastwood
Tornar-se muito velho Não funciona mais Last updated this plugin March 27, 2012 developers.google.com/java-dev-tools/download-codepro
mumair
2
Todos os links estão desatualizados.
Zygimantus 17/03/16
3
Infelizmente, parece que o Google lançou o código no projeto Eclipse e esqueceu tudo.
Thorbjørn Ravn Andersen 21/03
30

Estou surpreso que o ProGuard não tenha sido mencionado aqui. É um dos produtos mais maduros do mercado.

O ProGuard é um encolhedor , otimizador, ofuscador e pré-verificador de arquivos de classe Java gratuito. Ele detecta e remove classes, campos, métodos e atributos não utilizados. Otimiza o bytecode e remove instruções não utilizadas. Renomeia as demais classes, campos e métodos usando nomes curtos e sem sentido. Por fim, ele pré-verifica o código processado para Java 6 ou para Java Micro Edition.

Alguns usos do ProGuard são:

  • Criando código mais compacto, para arquivos de código menores, transferência mais rápida entre redes, carregamento mais rápido e menor consumo de memória.
  • Tornando mais difícil a engenharia reversa de programas e bibliotecas.
  • Listando código morto, para que possa ser removido do código fonte.
  • Redirecionamento e pré-verificação de arquivos de classe existentes para Java 6 ou superior, para aproveitar ao máximo seu carregamento de classe mais rápido.

Aqui está um exemplo de código morto da lista: https://www.guardsquare.com/en/products/proguard/manual/examples#deadcode

David d C e Freitas
fonte
8
Fornecer uma amostra de uso seria uma resposta melhor.
rds
1
Ao ler a documentação, vejo que ele reduz o código não utilizado, mas não consigo encontrar em nenhum lugar onde ele o lista - concordou, um exemplo ou um link para a seção relevante da documentação seria muito útil!
orbfish
26

Uma coisa que eu soube fazer no Eclipse, em uma única classe, é alterar todos os seus métodos para privados e ver as reclamações que recebo. Para métodos usados, isso provocará erros e eu os retorno ao nível de acesso mais baixo possível. Para métodos que não são utilizados, isso provocará avisos sobre métodos não utilizados, que poderão ser excluídos. E como bônus, você costuma encontrar alguns métodos públicos que podem e devem ser tornados privados.

Mas é muito manual.

skiphoppy
fonte
4
Talvez não seja a resposta ideal, mas isso é realmente inteligente.
Erik Reppen
8
Isso é inteligente ... até que você receba uma ligação de um código não utilizado de outra classe.
21713 Danosaure
A iteração sobre esse método pode remover grandes quantidades de código, pois um método usado cria outros assim que é removido.
4myle
15

Use uma ferramenta de cobertura de teste para instrumentar sua base de código e execute o próprio aplicativo, não os testes.

Emma e Eclemma fornecerão ótimos relatórios sobre qual porcentagem de quais classes são executadas para qualquer execução do código.

jamesh
fonte
1
+1, pois é um bom ponto de partida, mas lembre-se de que, por exemplo, variáveis ​​não utilizadas (ainda declaradas) também ficarão verdes.
DerMike
13

Começamos a usar o Find Bugs para ajudar a identificar parte do funk no ambiente rico em alvos da nossa base de código para refatorações. Também consideraria a Estrutura 101 para identificar pontos na arquitetura da sua base de código que são muito complicados, para que você saiba onde estão os pântanos reais.

Alan
fonte
4
O FindBugs não pode detectar código morto e não utilizado, apenas campos não utilizados. Veja esta resposta .
Stefan Mücke
12

Em teoria, você não pode encontrar deterministicamente o código não utilizado. Existe uma prova matemática disso (bem, este é um caso especial de um teorema mais geral). Se você estiver curioso, procure o Problema da Parada.

Isso pode se manifestar no código Java de várias maneiras:

  • Carregando classes com base na entrada do usuário, arquivos de configuração, entradas do banco de dados, etc;
  • Carregando código externo;
  • Passagem de árvores de objetos para bibliotecas de terceiros;
  • etc.

Dito isto, eu uso o IDEA IntelliJ como meu IDE de escolha e ele possui extensas ferramentas de análise para encontrar dependências entre módulos, métodos não utilizados, membros não utilizados, classes não utilizadas etc. É bastante inteligente também como um método privado que não é chamado. marcado como não utilizado, mas um método público requer uma análise mais abrangente.

cleto
fonte
1
Obrigdo por sua contribuição. Estamos usando o IntelliJ e estamos recebendo ajuda lá. Quanto ao problema da parada e à indecidibilidade, estou familiarizado com a teoria, mas não precisamos necessariamente de uma solução determinística.
knatten
12
A frase de abertura é muito forte. Assim como no Problema de Parada (também frequentemente citado / abusado), não há soluções gerais completas, mas há muitos casos especiais que SÃO viáveis ​​de detectar.
22410 joel.neely
9
Embora não exista uma solução geral para idiomas com avaliação e / ou reflexão, há muitos casos em que o código é comprovadamente inacessível.
Pjc50 3/08/09
1
Sem reflexão e com o código-fonte completo, qualquer linguagem de tipo estaticamente deve facilitar a localização determinística de todo o código não utilizado.
Bill K
Você não pode achar que é provável inalcançável por reflexão ou por chamadores externos, mas você pode encontrar o código que é provável inacessível estaticamente a partir de um determinado ponto de entrada ou conjunto de pontos de entrada
nafg
8

No Eclipse, vá para Windows> Preferências> Java> Compilador> Erros / Avisos
e altere todos eles para erros. Corrija todos os erros. Esta é a maneira mais simples. A vantagem é que isso permitirá que você limpe o código enquanto escreve.

Código Eclipse da captura de tela:

insira a descrição da imagem aqui

smileprem
fonte
5

O IntelliJ possui ferramentas de análise de código para detectar código não utilizado. Você deve tentar criar o maior número possível de campos / métodos / classes não públicos, o que mostrará mais métodos / campos / classes não utilizados

Eu também tentaria localizar o código duplicado como uma maneira de reduzir o volume do código.

Minha última sugestão é tentar encontrar código-fonte aberto que, se usado, tornaria seu código mais simples.

Peter Lawrey
fonte
Algum exemplo do que são essas ferramentas?
orbfish
@orbfish Você pode executar Analyse=> Run inspection by name=>unused
Peter Lawrey
5

A perspectiva de fatia do Structure101 fornecerá uma lista (e gráfico de dependência) de quaisquer "órfãos" ou " grupos órfãos " de classes ou pacotes que não possuem dependências de ou para o cluster "principal".

Chris Chedgey - Estrutura101
fonte
Isso funciona, por exemplo, variáveis ​​/ métodos dentro de uma classe?
Joeblackdev 21/07
Como sei se isso deve funcionar com, por exemplo, o Eclipse 4.3?
Erik Kaplun
3

O DCD não é um plug-in para algum IDE, mas pode ser executado a partir do ant ou autônomo. Parece uma ferramenta estática e pode fazer o que o PMD e o FindBugs não podem . Eu vou tentar isso.

PS Como mencionado em um comentário abaixo, o Projeto agora vive no GitHub .

Heiner
fonte
Isso deve ir para baixo como um comentário, não responder
Contagem
Atualize sua resposta para remover sua declaração de que o DCD "parece morto agora". A versão 2.1 foi lançada 12 dias atrás . Além disso, o link na sua resposta não funciona.
Skomisa # 11/18
2

Existem ferramentas que perfilam código e fornecem dados de cobertura de código. Isso permite que você veja (enquanto o código é executado) quanto está sendo chamado. Você pode obter qualquer uma dessas ferramentas para descobrir quanto código órfão você possui.

Vaibhav
fonte
2
  • FindBugs é excelente para esse tipo de coisa.
  • O PMD (Project Mess Detector) é outra ferramenta que pode ser usada.

No entanto, nenhum dos dois pode encontrar métodos estáticos públicos que não são usados ​​em um espaço de trabalho. Se alguém souber dessa ferramenta, entre em contato.

graveca
fonte
1

Ferramentas de cobertura do usuário, como EMMA. Mas não é uma ferramenta estática (ou seja, é necessário executar o aplicativo através de testes de regressão e de todos os casos de erro possíveis, o que é, bem, impossível :))

Ainda assim, o EMMA é muito útil.

Vladimir Dyuzhev
fonte
1

As ferramentas de cobertura de código, como Emma, ​​Cobertura e Clover, instrumentarão seu código e registrarão quais partes dele são invocadas executando um conjunto de testes. Isso é muito útil e deve ser parte integrante do seu processo de desenvolvimento. Isso o ajudará a identificar até que ponto sua suíte de testes cobre seu código.

No entanto, isso não é o mesmo que identificar código morto real. Ele identifica apenas o código coberto (ou não coberto) pelos testes. Isso pode fornecer falsos positivos (se seus testes não abrangem todos os cenários), bem como falsos negativos (se seus testes acessarem código que na verdade nunca é usado em um cenário do mundo real).

Eu imagino que a melhor maneira de realmente identificar o código morto seria instrumentá-lo com uma ferramenta de cobertura em um ambiente de execução ao vivo e analisar a cobertura do código por um longo período de tempo.

Se você estiver executando em um ambiente redundante com balanceamento de carga (e, se não, por que não?), Suponho que faria sentido instrumentar apenas uma instância do seu aplicativo e configurar seu balanceador de carga de forma que uma parte aleatória, mas pequena, do seus usuários executam em sua instância instrumentada. Se você fizer isso por um longo período de tempo (para se certificar de ter coberto todos os cenários de uso do mundo real - variações sazonais), poderá ver exatamente quais áreas do seu código são acessadas no uso do mundo real e quais partes nunca são realmente acessados ​​e, portanto, código morto.

Eu nunca vi isso pessoalmente, e não sei como as ferramentas mencionadas podem ser usadas para instrumentar e analisar o código que não está sendo chamado por meio de um conjunto de testes - mas tenho certeza de que sim.

Vihung
fonte
1

Existe um projeto Java - Dead Code Detector (DCD). Para o código fonte, parece não funcionar bem, mas para o arquivo .jar - é realmente bom. Além disso, você pode filtrar por classe e por método.

Lukasz Czerwinski
fonte
0

O Eclipse pode mostrar / destacar código que não pode ser alcançado. O JUnit pode mostrar a cobertura do código, mas você precisará de alguns testes e terá que decidir se o teste relevante está faltando ou se o código está realmente sem uso.

Matthias Winkelmann
fonte
3
O Eclipse informará apenas se o escopo do método é local (por exemplo, privado); e mesmo assim você não pode ter 100% de certeza ... com o método privado de reflexão pode ser chamado de fora.
P3t0r 02/10/08
0

Encontrei a ferramenta de cobertura Clover, que instrui o código e destaca o código que é usado e o que não é usado. Ao contrário do Google CodePro Analytics, ele também funciona para aplicativos Web (conforme minha experiência e posso estar incorreto sobre o Google CodePro).

A única desvantagem que notei é que ela não leva em consideração as interfaces Java.

Kashif Nazar
fonte
Afinal, é uma ferramenta de CI do lado do servidor não livre.
Erik Kaplun
0

Eu uso o Doxygen para desenvolver um mapa de chamada de método para localizar métodos que nunca são chamados. No gráfico, você encontrará ilhas de clusters de métodos sem chamadores. Isso não funciona para bibliotecas, pois você sempre precisa começar de algum ponto de entrada principal.

jbruni
fonte