Existem muitas perguntas sobre o acesso reflexivo ilegal no Java 9.
Agora, o que não consigo encontrar porque tudo o que o Google expele são pessoas tentando contornar as mensagens de erro, é o que um acesso reflexivo ilegal realmente é.
Portanto, minha pergunta é bastante simples:
O que define um acesso reflexivo ilegal e quais circunstâncias acionam o aviso?
Concluí que tem algo a ver com os princípios de encapsulamento que foram introduzidos no Java 9, mas como tudo se encaixa e o que dispara o aviso em qual cenário não consigo encontrar uma explicação.
java
java-9
java-module
Tschallacka
fonte
fonte
Respostas:
Além de compreender os acessos entre os módulos e seus respectivos pacotes. Acredito que o ponto crucial disso está no Módulo System # Relaxed-strong-encapsulation e eu selecionaria as partes relevantes para tentar responder à pergunta.
Para ajudar na migração para Java-9, o encapsulamento forte dos módulos pode ser relaxado.
Uma implementação pode fornecer acesso estático , ou seja, por bytecode compilado.
Pode fornecer um meio de invocar seu sistema de tempo de execução com um ou mais pacotes de um ou mais de seus módulos abertos para código em todos os módulos não nomeados , ou seja, para código no classpath. Se o sistema de tempo de execução for invocado dessa forma, e ao fazer isso, algumas invocações das APIs de reflexão serão bem-sucedidas onde, de outra forma, teriam falhado.
Nesses casos, você acabou fazendo um acesso reflexivo que é "ilegal", já que em um mundo modular puro você não deveria fazer tais acessos.
Esse relaxamento do encapsulamento é controlado no tempo de execução por uma nova opção do ativador
--illegal-access
que, por padrão, no Java9 é igualpermit
. Opermit
modo garanteOs modos são configuráveis com valores
debug
(mensagem, bem como rastreamento de pilha para cada acesso),warn
(mensagem para cada acesso) edeny
(desativa essas operações).Poucas coisas para depurar e corrigir nos aplicativos seriam: -
--illegal-access=deny
para conhecer e evitar a abertura de pacotes de um módulo para outro sem uma declaração de módulo incluindo tal diretiva (opens
) ou o uso explícito de--add-opens
VM arg.jdeps
ferramenta com a--jdk-internals
opçãoPerguntas para esse exemplo de aviso: = JDK9: Ocorreu uma operação de acesso reflexivo ilegal. org.python.core.PySystemState
Por último e uma observação importante, ao tentar garantir que você não enfrente tais avisos e esteja seguro no futuro, tudo que você precisa fazer é garantir que seus módulos não estejam fazendo aqueles acessos reflexivos ilegais. :)
fonte
Há um artigo da Oracle que encontrei sobre o sistema de módulos Java 9
Conforme apontado em https://stackoverflow.com/a/50251958/134894 , as diferenças entre o
AccessibleObject#setAccessible
para JDK8 e JDK9 são instrutivas. Especificamente, JDK9 adicionadoque destaca a importância dos módulos e suas exportações (em Java 9)
fonte
–illegal-access=permit
...fun
Basta olhar para o
setAccessible()
método usado para acessarprivate
campos e métodos:https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible-boolean-
https://docs.oracle.com/javase/9/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible-boolean-
Agora, são necessárias muito mais condições para que esse método funcione. A única razão pela qual ele não quebra quase todos os softwares mais antigos é que os módulos gerados automaticamente a partir de JARs simples são muito permissivos (abrem e exportam tudo para todos).
fonte
Se você quiser ir com a opção add-open, aqui está um comando para descobrir qual módulo fornece qual pacote ->
java --list-modules | tr @ " " | awk '{ print $1 }' | xargs -n1 java -d
o nome do módulo será mostrado com @ enquanto o nome dos pacotes sem ele
NOTA: testado com JDK 11
IMPORTANTE: obviamente é melhor que o provedor do pacote não faça o acesso ilegal
fonte