Prefácio
Este artigo apresenta principalmente conteúdo relevante sobre a classe insegura em Java. É compartilhado para sua referência e aprendizado. Não vou dizer muito abaixo. Vamos dar uma olhada na introdução detalhada juntos.
1. Introdução a classe insegura
A classe insegura está sob o pacote Sun.Misc e não pertence ao padrão Java. No entanto, muitas bibliotecas de classes básicas do Java, incluindo algumas bibliotecas de desenvolvimento de alto desempenho amplamente utilizadas, são desenvolvidas com base em classe insegura, como Netty, Hadoop, Kafka, etc.
Inseguro pode ser usado para acessar diretamente os recursos de memória do sistema e gerenciar independentemente. A classe insegura desempenha um grande papel na melhoria da eficiência da operação do Java e no aprimoramento dos recursos de operação subjacente do idioma Java.
O inseguro pode ser considerado um backdoor à esquerda em Java, fornecendo algumas operações de baixo nível, como acesso direto à memória, agendamento de threads, etc.
Não é seguro não é recomendado.
Aqui estão alguns exemplos de uso inseguro.
1.1 Instanciar uma aula privada
importar java.lang.reflect.field; importar sun.misc.unsfe; classe pública Unsefeplayer {public static void main (string [] args) lança exceção {// instanciado no campo inseguro f = insefa.class.getDecaredfield ("theusafe"); f.SetAccessível (verdadeiro); Inseguro inseguro = (inseguro) f.get (nulo); // instanciado jogador jogador jogador = (jogador) inseguro.AllocateInstance (player.class); player.setName ("Li Lei"); System.out.println (player.getName ()); }} classe player {nome da string privada; private player () {} public String getName () {Nome de return; } public void setName (nome da string) {this.name = name; }} 1.2CAS Operação, altere o valor do medidor através da modificação do endereço de deslocamento da memória
Use CAS para atualizar a parte superior da pilha no TransferStack no pacote de simultaneidade Síncrono no Java.
/ UNSAFE MECÂNICA PRIVIDO ESTÁTICO SOL.MISC.UNSAFE UNSAFE; PRIVADO ESTÁTICO LONGOFFSET LONGOFFTIVO DE LONGO; ESTÁTICA {TRY {UNSAFE = SUN.MISC.UNSAVE.GETUNSAFE (); Classe <?> K = transferstack.class; timeffset = insefa.ObjectFielfOffset (K.GetDecLaredField ("Head")); } catch (Exceção e) {lança um novo erro (e); }} // Snode de cabeça volátil; // Atualize a parte superior da pilha boolean Cashead (Snode H, Snode NH) {return H == Head && UnsAfe.compareandswapobject (this, timeffset, H, NH);} 1.3 acesso direto à memória
Acesso à memória direta da UNSAGE: O espaço de memória aberto com inseguro não ocupa o espaço da pilha e, é claro, ele não possui função de recuperação automática de memória. Possibilite o uso de recursos de memória do sistema livremente como C.
2. Análise de código -fonte de classe insegura
A maioria das APIs da UNSAGE são métodos nativos, incluindo principalmente as seguintes categorias:
1) Relacionado a classe. Fornece principalmente os métodos de operação de classe e seus campos estáticos.
2) Relacionado ao objeto. Fornece principalmente os métodos de operação de objeto e seus campos.
3) Related ARRRAY. Fornece principalmente os métodos de operação de matrizes e elementos neles.
4) Correlação simultânea. Ele fornece principalmente primitivas de sincronização de baixo nível, como CAS, agendamento de threads, barreira volátil, barreira de memória, etc.
5) Relacionado à memória. Ele fornece um método de acesso direto à memória (ignorando a pilha Java e manipulando diretamente a memória local), que pode utilizar livremente os recursos de memória do sistema como C.
6) Relacionado ao sistema. Ele retorna principalmente algumas informações de memória de baixo nível, como tamanho de endereço e tamanho da página de memória.
2.1 Classe relacionada
// O deslocamento dos atributos estáticos é usado para ler e gravar atributos estáticos no objeto de classe correspondente public nativo long staticfielffset (campo f); Objeto nativo público estáticos estáticos (Campo F); // julgar se uma classe precisa ser inicializada booleana nativa pública deve ser qualificada (classe <?> c); // garantir que a classe seja inicializada nativa nativa, secureclassinitialized (classe <?> c); // de que uma classe pode ser usada para ser usada dinamicamente a classes <? Carregador de classe, ProtectionDomain ProtectionDomain); // Defina uma classe anônima que pode ser usada para criar classes dinamicamente public nativas classes <?> DefileanonyMousousClass (classe <?> Hostclass, byte [] dados, objeto [] cppatches);
2.2 Relacionado ao objeto
Existem os seguintes métodos para tipos básicos (boolean, byte, char, curta, int, longa, flutuação, dupla) e tipos de referência de objetos em java.
// Obter o compensação do campo do objeto Public Native Long ObjectFielfOffset (Campo F); // obtenha o valor int do endereço de objeto especificado compensar o público nativo Int GetInt (objeto O, deslocamento longo); // Defina o valor int do endereço de objeto fornecido compensar o nativo public nativo void putInt (objeto o, deslocamento longo, int x);
// Crie um objeto, mas seu construtor não será chamado. Se a classe não for inicializada, a classe será inicializada. Public Native Object aloceInstance (classe <?> cls) lança instantiationException;
2.3 Relacionado da matriz
/** * Relate o deslocamento do primeiro elemento na alocação de armazenamento de uma * dada aula de matriz. Se {@link #ArrayIndexScale} retornar um valor diferente de zero * para a mesma classe, você poderá usar esse fator de escala, juntamente com esse * deslocamento de base, para formar novas compensações para acessar elementos de matrizes da classe * dada. * * @See #getInt (objeto, longo, int) * /// retorna o endereço deslocado do primeiro elemento na matriz public nativo int arraybaseoffset (classe <?> Arrayclass); // boolean, byte, curto, int, intray, prisioneiro, duplo e tipos de objeto têm os seguintes métodos/** o valor de {@code. Array_boolean_base_offset = theunsafe.arraybaseoffset (classe boolean []. /** * Relate o fator de escala para abordar os elementos na alocação de armazenamento * de uma determinada classe de matriz. No entanto, as matrizes de tipos "estreitos" * geralmente não funcionam corretamente com acessores como {@link * #getbyte (objeto, int)}, portanto o fator de escala para essas classes é relatado * como zero. * * @see #ArrayBaseoffset * @see #getInt (objeto, longo) * @see #putInt (objeto, longo, int) * /// retorna o tamanho ocupado por cada elemento no Array public native int ArrayIndexScale (classe <?> Arrayclass); // boolean, byte, curto, char, int, longa, flutuação, dupla e tipos de objetos têm os seguintes métodos/** o valor de {@code ArrayIndexScale (boolean []. classe)}*/public static final int array_boolean_index_scale = theunsafe.arrayIavaxScale (boolean []. A localização de cada elemento na matriz na memória pode ser localizada através do ArrayBaseoffset e ArrayIndexScale.
2.4 Relacionado à simultaneidade
2.4.1Cas relacionadas
CAS: Comparandswap, deslocamento do endereço do deslocamento da memória, valor esperado esperado, novo valor x. Se o valor da variável no horário atual e o valor esperado for igual, tente atualizar o valor da variável para x. Retornar true se a atualização for bem -sucedida; Caso contrário, retorne FALSE.
// Atualize o valor da variável para x, se o valor atual for esperado // o: deslocamento do objeto: deslocamento esperado: valor esperado x: novo valor public final nativo boolean comparaandswapobject (objeto o, deslocamento longo, objeto esperado, objeto x); Public Final Native Boolean Comparanswapint (objeto O, deslocamento longo, esperado, int x); Public Final Native Boolean Comparanswaplong (objeto O, deslocamento longo, esperado há muito tempo, longo x);
Começando com o Java 8, os seguintes métodos são fornecidos em inseguro:
// Adicione public final int getandaddint (objeto o, deslocamento longo, int delta) {int v; do {v = getIntVolatile (O, deslocamento); } while (! comparandswapint (O, deslocamento, v, v + delta)); retornar v;} public final long getandaddlong (objeto o, deslocamento longo, delta longo) {long v; do {v = getLongVolatile (O, deslocamento); } while (! comparandswaplong (O, deslocamento, v, v + delta)); return v;} // defina public final int getandSetInt (objeto o, deslocamento longo, int newValue) {int v; do {v = getIntValatile (O, deslocamento); } while (! comparandswapint (O, deslocamento, V, newValue)); retornar v;} public final long getandSetlong (objeto o, deslocamento longo, novo valor) {long v; do {v = getLongValatile (O, deslocamento); } while (! Comparanswaplong (O, deslocamento, V, newValue)); return v;} public final objeto getAndSetObject (objeto o, deslocamento longo, objeto newvalue) {objeto v; do {v = getObjectValatile (O, deslocamento); } while (! comparandswapobject (O, deslocamento, V, newValue)); retornar v;2.4.2 Agendamento de tópicos relacionado
// sem preenchimento de fio público nativo void UMPARK (fio de objeto); // Bloqueio de fio Public Native Void Park (booleano isabsolute, longo tempo); // Obtenha o bloqueio do objeto Public Native Void Monitorante (objeto O); // Liberação de objeto Public nativo monitorexit (objeto O) // tentativa para obter o objeto Lock, retorno ou falso indicado para indicar que é bem -sucedido (objeto);
2.4.3 Leitura e escrita voláteis
Existem os seguintes métodos para tipos básicos (boolean, byte, char, curta, int, longa, flutuação, dupla) e tipos de referência de objetos em java.
// Obtenha a referência da variável a partir do deslocamento especificado do objeto e use a semântica de carga de volátil // equivalente à versão volátil do objeto nativo public (objeto) do GetObject (Long) GetObjectVolatile (objeto o, deslocamento longo); // armazenamento a referência da variável ao deslocamento especificado do objeto e use a semântica de armazenamento de volátil // equivalente à versão volátil do putobject (objeto, objeto, objeto) public nativo nativo putObjectvolile (objeto o, deslocamento longo, objeto x);
/** * Versão de {@link #putObjectVolatile (objeto, longo, objeto)} * que não garante visibilidade imediata da loja para * outros threads. Esse método geralmente é útil apenas se o campo * subjacente for uma java volátil (ou se uma célula de matriz, uma * que, de outra forma, é acessada apenas usando acessos voláteis). */public nativo void putorderDObject (objeto o, deslocamento longo, objeto x); /** Versão ordenada/preguiçosa de {@link #putIntVolatile (objeto, longo, int)}*/public nativo void putorderDint (objeto o, deslocamento longo, int x); /** Versão ordenada/preguiçosa de {@link #putLongVolatile (objeto, longo, longo)}*/public nativo void putorderedlong (objeto o, deslocamento longo, longo x);2.4.4 Barreira de memória relacionada
O Java 8 foi introduzido para definir barreiras de memória para evitar a reordenação do código.
// A barreira da memória, proíbe que as operações de carga sejam reordenadas, ou seja, operações de carga antes que a barreira não possa ser reordenada à barreira, as operações de carga depois que a barreira não pode ser reordenada na frente da barreira nativa pública void loadfence () // barreira de memória, proibição de operações de armazenamento antes da barreira, operações de armazenamento de barreiras; as operações de serem reordenadas para a frente da barreira pública nativa void fullfence ();
2.5 Acesso à memória direta (memória não heap)
A memória alocada pela alocatememoria precisa ser manualmente livre (não reciclada pelo GC)
// (booleano, byte, char, curto, int, longo, flutuante, duplo) têm os dois métodos a seguir: Get and Put. // Obtenha o valor int no endereço especificado public nativo int getint (endereço longo); // Defina o valor int no endereço fornecido public nativo nativo putInt (endereço longo, int x); // obtenha ponteiro local public nativo long getaddress (endereço longo); // armazenamento o ponteiro local para o endereço de memória fornecida public native putaddress (long long, x); // aloca a memória pública alocatememoria longa nativa (bytes longos); // realocate a memória public nativo reallocatememory (endereço longo, bytes longos); // inicialize o conteúdo da memória public nativo void SetMemory (objeto O, com deslocamento longo, longs, byte valor); address, bytes, value);}//Initialize the memory content public native void copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes);//Initialize the memory content public void copyMemory(long srcAddress, long destAddress, long bytes) { copyMemory(null, srcAddress, null, destAddress, bytes);} // Libere a memória public nativo void freememory (endereço longo); 2.6 Relacionado ao sistema
// retorna o tamanho do ponteiro. O valor de retorno é 4 ou 8. /** O valor de {@code addressSize ()}*/public static final int address_size = theunsafe.addressSize (); // O tamanho da página de memória. public Native int PageSize ();3. Materiais de referência
//www.vevb.com/article/140709.htm Vamos falar sobre a classe insegura em java
//www.vevb.com/article/140721.htm Java Magic Class: Sun.misc.unsfe
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.