Antes de iniciar o texto principal deste artigo, vamos dar uma olhada no seguinte código:
O papel do inteiro da classe inteira em Java
Nome do pacote: java.lang
Nome do arquivo: Integer.java
Nome do método: Integercache
O código do método é o seguinte:
classe estática privada integercache {estático final int alto; Cache inteiro final estático []; estático {final int low = -128; // Alto valor pode ser configurado pela propriedade int h = 127; if (integercacheHighPropValue! = null) {// use long.decode aqui para evitar a invocação de métodos que // requerem o cache de autoboxing inteiro para ser inicializado int i = long.Decode (IntegerCacheHighPropValue) .IntValue (); i = math.max (i, 127); // O tamanho máximo da matriz é inteiro.max_value h = math.min (i, integer.max_value - -low); } alta = h; cache = novo número inteiro [(alto - baixo) + 1]; int j = baixo; for (int k = 0; k <cache.length; k ++) cache [k] = novo número inteiro (j ++); } private integercache () {}}Vemos no código que o baixo é -128 e o alto é 127. Dessa forma, na programação Java, se você deseja usar um objeto no intervalo -128-127, você usará diretamente o objeto neste cache.
O exposto acima é uma breve introdução para ajudar todos a entender o Integercache. A seguir, o texto principal deste artigo:
introdução
Há 5 anos, publiquei um post sobre húngaro sobre como mudar o Integercache no JDK. Essa abordagem é realmente aprofundar o tempo de execução do Java e não é realmente usado em cenários. Quando você desenvolve esse código de pesquisa, você pode entender melhor como funciona a reflexão e como a classe inteira implementa.
A classe inteira possui um aninhado privado chamado Integercache, que contém objetos inteiros com valores que variam de -127 a 128.
Quando o código precisa ser anexado do Int Type em um objeto inteiro, e o valor está dentro desse intervalo, o Java Runtime usará esse cache em vez de criar um novo objeto inteiro. Isso é principalmente para considerações de otimização de desempenho. Devemos ter em mente que muitos valores int estão geralmente dentro desse intervalo no programa (como o índice subscrito de uma matriz).
O efeito colateral disso é que, muitas vezes, ao usar o operador de sinal igual para comparar dois objetos inteiros, desde que o valor esteja dentro do intervalo, ele seja válido. Isso é típico nos testes de unidade. No modo de execução, quando o valor for maior que 128, a execução do código falhará.
Usando a reflexão para acessar as classes do Integercache pode causar alguns efeitos colaterais estranhos, observe que isso afeta toda a JVM. Se um servlet redefine um valor de cache de pequeno número inteiro, todos os outros servlets que funcionam sob o mesmo tomcat encontram o mesmo problema.
Existem outros artigos acima no Lukas Eder e no SitePoint.
Agora que estou jogando com os primeiros lançamentos do Java 9, tudo o que sempre tive em mente é experimentar novas versões Java. Antes de começarmos, vamos dar uma olhada em como fazê -lo no Java 8.
No artigo de Lukas, publiquei seu código de amostra aqui:
importar java.lang.reflect.field; importar java.util.random; public class Entropy {public static void main (string [] args) lança exceção {// extraia o integgercache através da classe de reflexão <<? > clazz = classe.ForName ("java.lang.integer $ integercache"); Campo de campo = clazz.getDeclaredfield ("cache"); field.setAccessible (true); Número inteiro [] cache = (inteiro []) field.get (clazz); // reescreva o cache inteiro para (int i = 0; i <cache.length; i ++) {cache [i] = new Integer (new aleatom (). NextInt (cache.length)); } // Prove a aleatoriedade para (int i = 0; i <10; i ++) {System.out.println ((inteiro) i); }}}Esse código acessa o integgercache através da reflexão e, em seguida, usa valores aleatórios para preencher o cache (travesso!).
Tentamos executar o mesmo código em Java 9, não esperemos diversão. Quando alguém tenta violá -lo, descobrirá que o Java 9 é mais restritivo.
Exceção em thread "main" java.lang.reflect.inaccessibleObjectException: Não é possível tornar o campo estático final java.lang.integer [] java.lang.integer $ INTEGERCACHE.cache acessível: module java.base não "open java.lang" para module donamed module
O programa lança uma exceção, que não ocorrerá no Java 8. É equivalente a dizer que os objetos não são baseados em modelo. Por causa do módulo Java.Base, esta é parte integrante do JDK. É importado automaticamente quando cada programa Java é iniciado e os módulos sem nome não podem ser abertos. Esta exceção é lançada quando tentamos definir a propriedade acessível de campo.
Os objetos que podemos acessar facilmente no Java 8 agora não estão acessíveis no Java 9 porque o novo sistema de módulos protege isso. O código pode acessar apenas campos, métodos e outras informações que podem ser acessados por reflexão, apenas se a classe estiver no mesmo módulo, ou o módulo tiver um pacote aberto para acesso à reflexão. Isso pode ser implementado através do arquivo de definição do módulo módulo-info.java:
módulo mymodule {exports com.javax0.module.demo; abre.javax0.module.demo;} Este módulo java.base não é necessário para abri -lo por conta própria para acesso à reflexão, especialmente para módulos sem nome. Se criarmos um módulo e nomearmos, a mensagem de erro conterá o nome do módulo.
Podemos abrir módulos no programa? O módulo java.lang.reflect.Module possui um método addotens que pode ser feito.
É viável?
A má notícia para os desenvolvedores é: não é viável. Ele só pode abrir um pacote em um módulo em outro módulo, e o pacote foi aberto nesse módulo chamando esse método. Esse método só pode permitir que os módulos sejam transmitidos para outros direitos do módulo, desde que o outro módulo tenha aberto o mesmo pacote de alguma forma e não possa abrir pacotes fechados (nota do tradutor: é difícil de entender, não é?).
Mas, ao mesmo tempo, a boa notícia é: Java 9 não é tão fácil de quebrar quanto o Java 8. Pelo menos essa vulnerabilidade está fechada. Parece que Java está começando a se desenvolver em um nível profissional, não apenas um brinquedo (nota do tradutor: quem disse que Java é um brinquedo?). Em um futuro próximo, você pode migrar projetos nos idiomas RPG e COBOL para Java muito seriamente. (Desculpe, eu estava brincando)
Resumir
O acima é o conteúdo inteiro deste artigo. Espero que o conteúdo deste artigo tenha certo valor de referência para o estudo ou trabalho de todos. Se você tiver alguma dúvida, pode deixar uma mensagem para se comunicar. Obrigado pelo seu apoio ao wulin.com.
Este artigo é traduzido de: https://dzone.com/articles/hacking-the-integercache-in-java-9