Na programação Java tradicional, você não precisará mais lidar com objetos Java ou locais da memória. Quando você discute isso em fóruns, a primeira pergunta que surge é: por que você precisa saber o endereço de um objeto Java? É uma pergunta válida. Mas no passado, reservávamos-nos o direito de realizar julgamentos. Não há nada de errado em explorar questões em território desconhecido. Eu fiz um experimento usando pacotes da Sun Company. Inseguro é um pacote pertencente a sun.misc. Talvez este pacote seja um pouco desconhecido para você, dê uma olhada no código-fonte e nos métodos e você saberá a que estou me referindo.
O gerenciamento de segurança do Java fornece ocultação suficiente para garantir que você não possa mexer na memória tão facilmente. Como primeiro passo, pensei em obter a localização da memória de um objeto Java. Até explorar, eu tinha 100% de certeza de que era impossível encontrar a localização do endereço de um objeto em Java.
A documentação da API Unsafe.java da Sun mostra que temos acesso ao endereço usando o método objectFieldOffset. Este método parece dizer: "A classe no relatório aloca sua localização em uma área específica de armazenamento". Ele também diz: "Este é apenas um acessador onde o cookie é passado para uma memória heap insegura". De qualquer forma, consigo alocar o local da memória onde um objeto está armazenado a partir do armazenamento de sua classe. Você poderia argumentar que o que obtemos não é o endereço absoluto da memória física de um objeto. No entanto, obtivemos o endereço da memória lógica. O programa a seguir será de grande interesse para você!
Como primeiro passo, preciso obter um objeto da classe Unsafe. Isso é difícil porque os construtores são privados. Existe um método chamado getUnsafe que retorna um objeto inseguro. O gerenciamento de segurança Java requer que você conceda privilégios ao código-fonte. Usei um pouco de reflexão e consegui uma instância. Sei que existem maneiras melhores de obter uma instância, mas escolhi o método a seguir para contornar o gerenciamento de segurança.
Para usar objetos inseguros, basta chamar objectFieldOffset e staticFieldOffset. O resultado é o endereço de alocação de memória da classe.
O programa de exemplo a seguir pode ser executado em JDK1.6.
classe pública ObjectLocation {
privado estático int maçã = 10;
privado int laranja = 10;
public static void main(String[] args) lança exceção {
Inseguro inseguro = getUnsafeInstance();
Campo appleField = ObjectLocation.class.getDeclaredField("apple");
System.out.println("Localização da Apple: "
+ inseguro.staticFieldOffset(appleField));
Campo orangeField = ObjectLocation.class.getDeclaredField("laranja");
System.out.println("Localização de Laranja: "
+ inseguro.objectFieldOffset(orangeField));
}
private static Unsafe getUnsafeInstance() lança SecurityException,
NoSuchFieldException, IllegalArgumentException,
IlegalAccessException {
Campo theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeInstance.setAccessible(true);
return (Inseguro) theUnsafeInstance.get(Unsafe.class);
}
}