Manipulando NoClassDefFoundError para JAXBException no Java 9
1. Introdução
Para qualquer um que tentou atualizar para o Java 9, eles provavelmente experimentaram algum tipo deNoClassDefFoundError ao compilar o código que funcionava anteriormente em versões anteriores do Java.
Neste artigo, veremos uma classe ausente comum,JAXBException, e diferentes maneiras de resolvê-la. As soluções fornecidas aqui são geralmente aplicáveis a qualquer classe que possa estar ausente ao atualizar para o Java 9.
2. Por que o Java 9 não consegue encontrarJAXBException?
Um dos recursos mais discutidos do Java 9 é o sistema de módulos. The goal of the Java 9 module system is to break apart the core JVM classes and related projects into stand-alone modules. Isso nos ajuda a criar aplicativos com dimensões menores, incluindo apenas as classes mínimas necessárias para execução.
A desvantagem é que muitas classes não estão mais disponíveis no caminho de classe por padrão. Nesse caso, a varredura da classeJAXBExceptionpode ser encontrada em um dos novos módulos Java EE denominadojava.xml.bind. Como este módulo não é exigido pelo Java runtime principal, ele não está disponível no classpath por padrão.
Tentar executar um aplicativo que usaJAXBExceptionresulta em:
NoClassDefFoundError: javax/xml/bind/JAXBException
Para contornar essewe must include the java.xml.bindmodule. Como veremos a seguir, existem várias maneiras de fazer isso.
3. Solução de curto prazo
A maneira mais rápida de garantir que as classes da API JAXB estejam disponíveis para um aplicativo é adicionaruse the –add-modules command line argument:
--add-modules java.xml.bind
No entanto, isso pode não ser uma boa solução por alguns motivos.
Primeiro, o sargumento–add-modules também é novo no Java 9. Para aplicativos que precisam executar em várias versões do Java, isso apresenta alguns desafios. Teríamos que manter vários conjuntos de arquivos de construção, um para cada versão Java em que o aplicativo é executado.
Para contornar isso, também podemos usar o argumento de linha de comando-XX:+IgnoreUnrecognizedVMOptionspara compiladores Java mais antigos.
No entanto, isso significa que qualquer erro de digitação ou erro ortográfico não será levado ao nosso conhecimento. Por exemplo, se tentarmos definir um tamanho mínimo ou máximo de heap e digitarmos incorretamente o nome do argumento, não receberemos um aviso. Nosso aplicativo ainda será iniciado, mas estará executando com uma configuração diferente da esperada.
Em segundo lugar, a versão–add-modules erá descontinuada em uma versão futura do Java. Isso significa que em algum ponto depois de atualizar para uma nova versão do Java, enfrentaremos o mesmo problema de usar um argumento de linha de comando desconhecido e teremos que resolver o problema novamente.
4. Solução a longo prazo
Existe uma abordagem melhor que funcionará em diferentes versões do Java e não romperá com versões futuras.
A solução éutilize a dependency management tool such as Maven. Com essa abordagem, adicionaríamos a biblioteca da API JAXB como uma dependência, como qualquer outra biblioteca:
javax.xml.bind
jaxb-api
2.3.0
A biblioteca acima contém apenas as classes da API JAXB, que incluiJAXBException. Dependendo da aplicação, podemos precisar incluir outros módulos.
Lembre-se também de queMaven artifact names may be different than the Java 9 module name, como é o caso da API JAXB. Ele pode ser encontrado emMaven Central.
5. Conclusão
O sistema do módulo Java 9 oferece vários benefícios, como diminuir o tamanho do aplicativo e melhorar o desempenho.
No entanto, também apresenta algumas conseqüências não intencionais. Ao atualizar para o Java 9, é importante entender quais módulos um aplicativo realmente requer e executar etapas para garantir que estejam disponíveis no caminho de classe.