Me deparei com o pacote sun.misc.Unsafe no outro dia e fiquei surpreso com o que poderia fazer.
Obviamente, a classe não é documentada, mas eu estava pensando se havia alguma boa razão para usá-la. Quais cenários podem surgir onde você precisaria usá-lo? Como pode ser usado em um cenário do mundo real?
Além disso, se você fazer necessidade ele, isso não indica que algo provavelmente está errado com o seu design?
Por que o Java inclui essa classe?
Respostas:
exemplos
VM "intrinsificação". ou seja, CAS (comparar e trocar) usado em tabelas de hash sem bloqueio, por exemplo: sun.misc.Unsafe.compareAndSwapInt, pode fazer chamadas JNI reais em código nativo que contém instruções especiais para CAS
leia mais sobre o CAS aqui http://en.wikipedia.org/wiki/Compare-and-swap
A funcionalidade sun.misc.Unsafe da VM do host pode ser usada para alocar objetos não inicializados e, em seguida, interpretar a chamada do construtor como qualquer outra chamada de método.
É possível recuperar os dados do endereço nativo. É possível recuperar o endereço de memória de um objeto usando a classe java.lang.Unsafe e operar seus campos diretamente através de métodos inseguros de obtenção / colocação!
Otimizações de tempo de compilação para JVM. Alto desempenho da VM usando "mágica", exigindo operações de baixo nível. por exemplo: http://en.wikipedia.org/wiki/Jikes_RVM
Alocando Memória, sun.misc.Unsafe.allocateMemory, por exemplo: - O construtor DirectByteBuffer a chama internamente quando ByteBuffer.allocateDirect é chamado
Rastreando a pilha de chamadas e reproduzindo com valores instanciados por sun.misc.Unsafe, útil para instrumentação
sun.misc.Unsafe.arrayBaseOffset e arrayIndexScale podem ser usados para desenvolver arraylets, uma técnica para dividir eficientemente grandes matrizes em objetos menores para limitar o custo em tempo real da verificação, atualização ou movimentação de operações em objetos grandes
http://robaustin.wikidot.com/how-to-write-to-direct-memory-locations-in-java
mais sobre referências aqui - http://bytescrolls.blogspot.com/2011/04/interesting-uses-of-sunmiscunsafe.html
fonte
Apenas ao executar uma pesquisa em algum mecanismo de pesquisa de código, obtenho os seguintes exemplos:
Existem muitos outros exemplos, basta seguir o link acima ...
fonte
Interessante, eu nunca tinha ouvido falar dessa aula (o que provavelmente é uma coisa boa, na verdade).
Uma coisa que vem à mente é usar o Unsafe # setMemory para zerar buffers que continham informações confidenciais em um ponto (senhas, chaves, ...). Você pode até fazer isso em campos de objetos "imutáveis" (então, novamente, suponho que uma reflexão simples e antiga possa fazer o truque aqui também). Eu não sou especialista em segurança, então leve isso com um pouco de sal.
fonte
I'd never even heard of this class
... Eu já falei sobre isso tantas vezes! suspiro + :(park()
documentação deles : "Bloqueie o encadeamento atual, retornando quando ocorrer um descompasso de balanceamento, ou já tiver ocorrido um descompasso de balanceamento, ou o encadeamento for interrompido ou, se não for absoluto e o tempo não for zero, o dado tempo, os nanossegundos transcorreram, ou se forem absolutos, o prazo especificado em milissegundos desde que a Época passou, ou espúrios (ou seja, retornando sem motivo) ". Quase tão bom quanto "a memória é liberada quando o programa sai ou, a intervalos aleatórios, o que ocorrer primeiro".Com base em uma análise muito breve da biblioteca Java 1.6.12 usando eclipse para rastreamento de referência, parece que todas as funcionalidades úteis
Unsafe
são expostas de maneiras úteis.As operações do CAS são expostas através das classes Atomic *. As funções de manipulação de memória são expostas através das instruções do DirectByteBuffer Sync (estacionar, desarmar) são expostas através do AbstractQueuedSynchronizer, que por sua vez é usado pelas implementações de bloqueio.
fonte
LockSupport
não AQS (esta última é mais uma impl bloqueio do parque / desestacionar.)Unsafe.throwException - permite lançar exceções verificadas sem declará-las.
Isso é útil em alguns casos em que você lida com reflexão ou AOP.
Suponha que você Construa um proxy genérico para uma Interface definida pelo usuário. E o usuário pode especificar qual exceção é lançada pela implementação em um caso especial, apenas declarando a exceção na interface. Então esta é a única maneira que conheço, de gerar uma exceção verificada na Implementação dinâmica da interface.
fonte
Thread.stop(Throwable)
nenhuma necessidade para inseguro, no mesmo segmento que você pode jogar qualquer coisa de qualquer maneira (não há nenhuma verificação de compilação)UnsupportedOperationException
no thread atual a partir do Java 8. No entanto, a versão sem argumento que lançaThreadDeath
ainda funciona.Um uso é nas
java.util.concurrent.atomic
classes:fonte
Para uma cópia de memória eficiente (mais rápida de copiar que System.arraycopy () para blocos curtos, pelo menos); conforme usado pelos codecs Java LZF e Snappy . Eles usam 'getLong' e 'putLong', que são mais rápidos que fazer cópias byte a byte; especialmente eficiente ao copiar itens como blocos de 16/32/64 bytes.
fonte
getLong/putLong
(e você tem que calcular o endereço também)getLong
/putLong
: idealmente, prefeririaSystem.arraycopy()
a simplicidade e tudo; mas os testes reais mostraram o contrário nos casos que testei.Recentemente, eu estava trabalhando na reimplementação da JVM e descobri que um número surpreendente de classes é implementado em termos de
Unsafe
. A classe é projetada principalmente para os implementadores de bibliotecas Java e contém recursos que são fundamentalmente inseguros, mas necessários para a criação de primitivas rápidas. Por exemplo, existem métodos para obter e gravar deslocamentos brutos de campo, usando sincronização no nível de hardware, alocando e liberando memória, etc. Não se destina a ser usado por programadores Java normais; não é documentado, é específico da implementação e é inerentemente inseguro (daí o nome!). Além disso, acho que oSecurityManager
acesso à Internet não será permitido em quase todos os casos.Em resumo, ele existe principalmente para permitir que os implementadores de bibliotecas acessem a máquina subjacente sem precisar declarar todos os métodos em determinadas classes, como
AtomicInteger
nativo. Você não precisa usar ou se preocupar com isso na programação Java de rotina, pois o ponto principal é tornar o restante das bibliotecas rápido o suficiente para que você não precise desse tipo de acesso.fonte
Unsafe.class.getDeclaredField("theUnsafe")
com.setAccessible(true)
e, em seguida,.get(null)
vai obtê-lo tambémUse-o para acessar e alocar grandes quantidades de memória com eficiência, como em seu próprio mecanismo voxel! (ou seja, jogo no estilo Minecraft).
Na minha experiência, a JVM geralmente não consegue eliminar a verificação de limites no local em que você realmente precisa. Por exemplo, se você estiver iterando em uma matriz grande, mas o acesso à memória real estiver oculto sob uma chamada de método * não virtual * no loop, a JVM ainda poderá executar uma verificação de limites com cada acesso à matriz, em vez de uma vez antes o laço. Portanto, para obter ganhos de desempenho potencialmente grandes, é possível eliminar a verificação de limites da JVM dentro do loop por meio de um método que emprega sun.misc.Unsafe para acessar a memória diretamente, certificando-se de fazer a verificação de limites nos locais corretos. (Você está sentirei limites verificar em algum nível, certo?)
* por não virtual, quero dizer que a JVM não deveria resolver dinamicamente qualquer que seja o seu método específico, porque você garantiu corretamente que classe / método / instância são uma combinação de static / final / what-have-you.
Para o meu mecanismo de voxel desenvolvido em casa, isso resultou em um ganho de desempenho dramático durante a geração e a serialização de blocos (em locais onde eu estava lendo / escrevendo para toda a matriz de uma só vez). Os resultados podem variar, mas se o problema for a falta de eliminação de limites, será corrigido.
Existem alguns problemas potencialmente importantes com isso: especificamente, quando você fornece a capacidade de acessar a memória sem verificação de limites para os clientes da sua interface, eles provavelmente a abusarão. (Não se esqueça que os hackers também podem ser clientes da sua interface ... especialmente no caso de um mecanismo voxel escrito em Java.) Portanto, você deve projetar sua interface de maneira a não prejudicar o acesso à memória ou você deve ser extremamente cuidadoso ao validar os dados do usuário antes que eles possam se misturar à sua interface perigosa. Considerando as coisas catastróficas que um hacker pode fazer com acesso não verificado à memória, provavelmente é melhor adotar as duas abordagens.
fonte
Coleções fora da pilha podem ser úteis para alocar grandes quantidades de memória e desalocá-la imediatamente após o uso, sem interferência do GC. Eu escrevi uma biblioteca para trabalhar com matrizes / listas fora da pilha com base em
sun.misc.Unsafe
.fonte
Implementamos coleções enormes, como Arrays, HashMaps, TreeMaps usando Unsafe.
E para evitar / minimizar a fragmentação, implementamos o alocador de memória usando os conceitos de dlmalloc sobre inseguro.
Isso nos ajudou a obter o desempenho em simultâneo.
fonte
Unsafe.park()
eUnsafe.unpark()
para a construção de estruturas personalizadas de controle de concorrência e mecanismos de agendamento cooperativo.fonte
java.util.concurrent.locks.LockSupport
Eu ainda não o usei, mas suponho que se você tiver uma variável que, ocasionalmente, é lida por mais de um segmento (para que você não queira torná-lo volátil), você pode usá-
putObjectVolatile
lo ao escrevê-lo no segmento principal ereadObjectVolatile
ao fazer leituras raras de outros tópicos.fonte
É necessário se você precisar substituir a funcionalidade fornecida por uma das classes que a utiliza atualmente.
Isso pode ser serialização / desserialização mais compacta / rápida / mais compacta, uma versão mais rápida / maior de buffer / redimensionável do ByteBuffer ou adicionar uma variável atômica, por exemplo, uma variável não suportada atualmente.
Eu tenho usado para todos estes em algum momento.
fonte
Um exemplo de seu uso é o método aleatório, que chama o inseguro para alterar a semente .
Este site também possui alguns usos .
fonte
O objeto parece estar disponível para funcionar em um nível inferior ao que o código Java normalmente permite. Se você estiver codificando um aplicativo de alto nível, a JVM abstrai o manuseio da memória e outras operações para longe do nível do código, para que seja mais fácil programar. Ao usar a biblioteca Insegura, você está efetivamente concluindo operações de baixo nível que normalmente seriam feitas para você.
Como woliveirajr afirmou, "random ()" usa Unsafe para propagar, assim como muitas outras operações usarão a função assignateMemory () incluída em Unsafe.
Como programador, você provavelmente poderia se safar de nunca precisar dessa biblioteca, mas ter um controle estrito sobre os elementos de baixo nível é útil (é por isso que ainda existe o código Assembly e (em menor grau) C de derivação nos principais produtos)
fonte