• Nenhum resultado encontrado

3.6.4 (RQ4) Qual o impacto das exceções descobertas?

3.7 Comparando Análise Estática com Mineração de stack traces

Como mencionado anteriormente, a geração do grafo de chamadas com técnicas de análise estática está suscetível à incompletude, podendo apresentar limitações quando combinada com características de linguagens modernas. Quando métodos de interfaces ou polimórficos são invocados, fluxos excepcionais não são identificados com precisão em virtude de tais métodos serem definidos em tempo de execução - dependendo do algoritmo de geração do grafo de chamadas ele pode incluir fluxos que na prática nunca iriam acontecer (falsos positivos) como também deixar de incluir fluxos que na prática acontecem por não terem estaticamente informações que permitam identificar o fluxo (falsos negativos). Por outro lado, a análise de stack traces está limitada à investigar apenas as stacks resultantes de terminações abruptas. Por esta característica, possíveis fluxos excepcionais falso-negativos podem ser obtidos, porém não sofre de ocorrências de falso-positivos.

Diante das características dessas duas estratégias, nesta seção fazemos um compara- tivo da identificação de interfaces excepcionais das duas abordagens, para o conjunto de bibliotecas alvo. Essa comparação tem o objetivo de investigar se a análise de stack traces pode de alguma forma enriquecer as informações obtidas através de técnicas de análise

estática.

Para realizarmos a comparação, confrontamos as exceções que fluíram pelos métodos públicos das bibliotecas, identificadas através da análise das stack traces com as que foram assinaladas com o auxílio da análise estática da ferramenta PLEA (ver a Seção 3.3.6). Da mesma forma que fizemos em análises anteriores, consideramos apenas as exceções des- cobertas (i.e. exceções não checadas que não estão documentadas e que não são lançadas implicitamente).

A interface excepcional de cada método pode ser composta por várias exceções e cada uma dessas pode se manifestar com mais frequência do que a outra. Por essas carac- terísticas, optamos por realizar a contabilização em termos dos pares método-exceção. Entendemos como par método-exceção cada exceção associada ao método que compõe a interface excepcional. No exemplo da Figura 16, o método loadPropertiesFile pos- sui em sua interface excepcional, as exceções java.lang.IllegalArgumentException e java.lang.RuntimeException, por tanto, para este exemplo contabilizamos dois pares método-exceção.

Figura 16: Código que exemplifica dois pares método-exceção.

Uma vez contabilizados todos os pares método-exceção identificados através da PLEA e da análise das stack traces, obtivemos os números apresentados na Figura 17.

Apesar da grande quantidade de pares método-exceção identificados com a análise es- tática, poucos destes estão presentes nas stack traces reportadas (apenas 34). No entanto, foi possível observar um número significativo de pares descobertos somente através da análise das stack traces (2971). Além disso, observamos que apenas uma pequena parte das exceções identificadas pela análise estática, estavam relatadas nas issues. Isso nos faz supor que tais exceções não checadas e não documentadas sejam relevantes para os desen- volvedores, pois escaparam aos testes iniciais e tiveram que ser relatadas posteriormente

Figura 17: Exceções descobertas por cada abordagem, para o conjunto de bibliotecas alvo. em issues trackers. Na próxima seção apresentaremos alguns exemplos e possíveis causas para a existência deste conjunto.

3.7.1 Exceções Mineradas e não Detectadas Estaticamente

Como a análise estática faz uso de um grafo de chamadas, é esperado que este compre- enda todos os fluxos possíveis de execução de uma aplicação, incluindo todas as exceções que possam ser lançadas. Diante disso, era esperado que o conjunto de exceções identifica- das por essa técnica fosse maior, e que essas exceções também compreendessem o conjunto de exceções descobertas através da análise de stack traces. No entanto, identificamos um conjunto de pares não detectados com a análise estática, presentes nas stack traces anali- sadas. Realizamos a inspeção manual de alguns desses pares e constatamos que, de fato, tais exceções podem fluir pelos métodos.

Devido a restrição de tempo, optamos por sortear dez pares método-exceção para a inspeção manual. Diante dos casos inspecionados, observamos que 60% deles, de fato po- dem ocorrer nas versões das bibliotecas analisadas. Entendemos que esse comportamento pode ser resultado de: (i) fluxos falso-negativos decorrentes de heurísticas adotadas pela análise estática; ou (ii) versões diferentes das bibliotecas.

A Figura 18 apresenta o método channelRead da classe ReadTimeoutHandler. A análise estática não identificou nenhuma exceção que pudesse ser lançada a partir desse método, ao passo que a análise das stack traces identificou a exceção DecoderException.

Figura 18: Método channelRead da classe ReadTimeoutHandler.

Atribuímos essa não identificação com a análise estática, ao fato do tipo de pa- râmetro definido na assinatura do método ser uma interface. Isso permite que o mé- todo receba como parâmetro, qualquer objeto que atenda ao contrato definido na in- terface ChannelHandlerContext. O uso da interface impossibilita que durante a execu- ção da análise estática seja identificado com exatidão qual o objeto concreto que imple- menta tal interface deverá ser utilizado. Desse modo, ao identificar a chamada ao método fireChannelRead (definido na interface ChannelHandlerContext), a geração do grafo de chamadas não consegue realizar a ligação com a classe concreta, o que só será possível em tempo de execução.

A estratégia de análise de stack traces, como dito anteriormente, está limitada à in- vestigar apenas as stacks que são reportadas. Diante disso, podemos atribuir o número de pares descobertos apenas com esta abordagem à: (i) exceções que não foram reportadas pelos desenvolvedores em issues; ou (ii) exceções que nunca se manifestaram. Outro fator que pode ter influenciado no número destes pares está relacionado com algumas caracterís- ticas das stack traces Java. Mais precisamente, stack traces não armazenam informações acerca da versão das bibliotecas utilizadas, tampouco informações sobre os parâmetros dos métodos. Essas características impedem que possamos afirmar que os métodos pre- sentes nas stacks sejam pertencentes às versões de bibliotecas analisadas, e também que possamos distinguir entre métodos sobrecarregados (do inglês, overloaded methods).

Documentos relacionados