Sequência
Este artigo estuda principalmente algumas precauções para migrar para Java9.
Tipos de migração
1. O código não é modular, primeiro migra para o JDK9 para fazer uso da API do JDK9
2. O código também é migrado modularmente
Algumas coisas para observar
Classes ilegíveis
Por exemplo, Sun.security.x509 é classificado no módulo Java.base em Java9, mas o módulo não exporta o pacote.
Você pode modificar as configurações de exportação adicionando-ADD-Exports java.base/sun.security.x509 = sem vergonha ao executar
Classe interna
Por exemplo, o Sun.misc.unsafe originalmente queria usar a equipe do Oracle JDK, mas como essas classes são amplamente utilizadas, o Java9 fez compromissos para serem compatibilidade com versões anteriores, mas apenas classificaram essas classes no módulo JDK.Unsupated e não limitaram sua legibilidade.
➜ ~ java -d jdk.unsupportdjdk.unsupportd@9Exports com.sun.nio.fileExports sun.miscexports sun.refletrequires java.base mandatedopens sol sun.miscons sun.reflelect
Classe excluída
Java9 excluído Sun.misc.base64Encoder, neste caso, você só pode usar outras APIs, como java.util.base64
ClassPath vs Module-Path
O Java9 introduziu um sistema de módulo, e seu próprio JDK também foi modularizado, e o Module-Path foi introduzido para blocos de classe. Ou seja, o Module-Path é preferido em Java9. Afinal, o próprio JDK é modular. Se o aplicativo em si não for modular, o Java9 será implicitamente modularizado por meio de módulos sem nome e mecanismos de módulos automáticos. Obviamente, o ClassPath pode continuar sendo usado no Java9, como o uso do módulo.
Um frasco sem modularidade será classificado como módulos sem nome em ClassPath; No módulo-path, ele será criado automaticamente como módulos automáticos (um módulo automático declarará que o transitivo depende de todos os módulos nomeados e sem nome e, em seguida, exportará seu próprio pacote)
Um nome de pacote não pode aparecer em vários módulos (pacotes divididos)
Como as exportações podem ser especificadas para outros módulos em módulos, se vários módulos exportarem o mesmo nome do pacote, isso causará confusão. Especialmente se houver outras bibliotecas de classes que exigem esses dois módulos ao mesmo tempo, você não sabe qual módulo deve ser referenciado.
Dependências transitivas
Se os parâmetros da interface ou o tipo de retorno de um módulo usarem as classes de outros módulos, é recomendável exigir módulos transitivos depende.
Tenha cuidado com dependências circulares
Ao projetar módulos, considere se haverá dependências circulares o máximo possível. Nesse caso, você precisa redesenhá -los.
Use serviços para implementar dependências opcionais
Os serviços são particularmente adequados para dissociar as dependências dos chamadores e classes de implementação. Se a interface possui várias classes de implementação, o chamador não precisará exigir todas as classes de implementação, mas requer apenas a interface requer e usar o tipo de serviço para carregar instâncias da classe de implementação. A dissociação é alcançada adicionando dinamicamente os módulos de implementação no caminho do módulo.
Gerenciamento de versão do módulo
O módulo-info.java não suporta a declaração de números de versão, mas ao criar pacotes JAR, você pode defini-los por-Module-Version. No entanto, quando o sistema do módulo procura módulos, ele ainda usa o nome do módulo para pesquisar (se houver vários módulos duplicados no caminho do módulo, o sistema do módulo saberá usar o primeiro encontrado e ignorar automaticamente o módulo subsequente com o mesmo nome). O problema de dependência da versão não está dentro do escopo da solução do sistema de módulos e é deixado para ferramentas de gerenciamento de dependência como o Maven a serem gerenciadas.
Acesso ao recurso do módulo
Após a modularização, o arquivo de recursos também é protegido e o módulo pode acessar apenas o arquivo de recursos do próprio módulo. Se o acesso ao módulo cruzado for necessário, você também deverá usar o ModuleLayer para encontrar o módulo de destino e ligar para o módulo de destino para carregar o arquivo de recursos do módulo.
Uso da reflexão
Isso envolve a questão de reflexão profunda. A chamada reflexão profunda é chamar o elemento não público de uma classe através da reflexão. As exportações do Module-Info.java declaram que o pacote permite apenas a classe à qual o pacote pertence diretamente ao acesso ao seu elemento público e não permite chamadas de reflexão para elementos não públicos.
A reflexão precisa de declarações especiais para serem permitidas no sistema de módulos (usando declarações de abre para permitir uma reflexão profunda), o que leva a muitas bibliotecas de classes que usam reflexão como a mola, que exigem uma configuração adicional a ser migrada para Java9. Existem duas soluções: uma é abrir o nome do pacote para módulos que precisam de reflexão, como primavera. O outro é abrir diretamente o módulo inteiro.
O padrão-ACLESSO DE ACESSO = ACESSO DE ACESSA, e essa configuração é aplicável apenas a pacotes antes do Java9 que não têm permissão para acessar no Java9 e não são aplicáveis a novos pacotes que não podem acessar em Java9. (É recomendável definir para negar ao migrar para um sistema modular)
No entanto, no sistema de módulos, os nomes dos pacotes são diferentes e não há relação de herança. Por exemplo, com.service.func1 e com.service.func2 são pacotes diferentes. Você não pode simplesmente abrir o Com.Service, mas deve especificá -los separadamente, o que leva a mais pacotes que exigem abertura. Portanto, abrir o módulo inteiro pode ser mais fácil de usar, mas também é uma abordagem relativamente difícil.O método acima é fazer alterações no módulo original-info.java. Outro método é modificar o relacionamento original através do comando especificado ao executar Java ou Javac. por exemplo
Java ...-ADD-Apens-Module/Fonte-Package = Module de destino
Se você precisar exportar para módulos sem nome, o módulo de destino é totalmente inútil
Obviamente, se for um novo sistema, não é recomendável usar a reflexão. MethodHandles e varhandles podem ser usados.
Perguntas frequentes e medidas
ClassNotFoundException/NoclassDeffoundError
Por exemplo, javax.xml.bind.jaxBexception, o JAXB foi classificado no módulo java.xml.bind e é adicionado após a nomeação de Java.
--Add-Modules java.xml.bind
Se você quiser economizar problemas, adicione $ java_home e toda
--DD-Modules All-Module-Module
Acesso reflexivo ilegal por xxx ao método java.lang.classloader.defineclass
As causas de reflexão, porque o sistema antigo não possui o módulo Info, adicione parâmetros ao nome Java e modifique-o.
--Add-Opens java.base/java.lang = All-inNamed
Determine o módulo de dependência
Análise via IDE ou JDEPS
JDeps -Class -Path 'Classes/lib/*' -Recursive -Summary App.jar
O JDEPS é apenas uma análise de código estático. Se houver uma classe que use reflexão, você não pode analisá -la. Você precisa exigir manualmente. Se a dependência for opcional, você pode exigir estática.
Problemas de legibilidade para testes de unidade de módulo
Se um módulo for usado para testes de unidade, o módulo de teste de unidade poderá receber recursos de legibilidade e reflexão do módulo de destino através de-ADD-Exports ou-ADD-abert em tempo de execução. Além disso, devido a problemas de pacotes divididos, o nome do pacote da classe de teste de unidade não pode ser duplicado com o nome do pacote do módulo de destino. Acontece que o teste do projeto Maven
resumo
Você pode passar para o Java9 em duas etapas. Primeiro, você não é modular primeiro, você está executando apenas o JDK9 primeiro; Então você é modular.