2011-08-14 21 views

Respuesta

27

Esto es algo que probablemente no desee hacer.

Si realmente quiere hacer esto, algo así como el código podría ayudar:

package test; 

import java.lang.reflect.Field; 

import sun.misc.Unsafe; 

public class Addresser 
{ 
    private static Unsafe unsafe; 

    static 
    { 
     try 
     { 
      Field field = Unsafe.class.getDeclaredField("theUnsafe"); 
      field.setAccessible(true); 
      unsafe = (Unsafe)field.get(null); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    public static long addressOf(Object o) 
    throws Exception 
    { 
     Object[] array = new Object[] {o}; 

     long baseOffset = unsafe.arrayBaseOffset(Object[].class); 
     int addressSize = unsafe.addressSize(); 
     long objectAddress; 
     switch (addressSize) 
     { 
      case 4: 
       objectAddress = unsafe.getInt(array, baseOffset); 
       break; 
      case 8: 
       objectAddress = unsafe.getLong(array, baseOffset); 
       break; 
      default: 
       throw new Error("unsupported address size: " + addressSize); 
     }  

     return(objectAddress); 
    } 


    public static void main(String... args) 
    throws Exception 
    { 
     Object mine = "Hi there".toCharArray(); 
     long address = addressOf(mine); 
     System.out.println("Addess: " + address); 

     //Verify address works - should see the characters in the array in the output 
     printBytes(address, 27); 

    } 

    public static void printBytes(long objectAddress, int num) 
    { 
     for (long i = 0; i < num; i++) 
     { 
      int cur = unsafe.getByte(objectAddress + i); 
      System.out.print((char)cur); 
     } 
     System.out.println(); 
    } 
} 

Pero

    no
  • portable a través de JVM o incluso diferentes versiones
  • objetos pueden moverse debido de GC en cualquier momento, y no se puede sincronizar a través de los GC, por lo que los resultados pueden no tener sentido
  • no probado CA Ross todas las arquitecturas, endianess, etc. podría hacer esto no funciona en todas partes
+1

Parece que 'unsafe.addressSize()' en Sun JDKs de 64 bits devuelve 8 incluso cuando UseCompressedOpps está activado. Usando 'unsafe.arrayIndexScale (Object []. Class)', que devuelve 4 en ese caso, parece ser más probable que funcione con esta técnica (después de todo, está almacenando el objeto en una matriz de objetos). Con ¡uy comprimido, la dirección devuelta no es una dirección verdadera, se puede desplazar a la derecha por 3 bits, etc. – BeeOnRope

9

Sin utilizar funciones específicas de JVM, esto no se puede hacer. Java oculta deliberadamente la ubicación asociada a cada objeto para darle más flexibilidad a la implementación (la JVM a menudo mueve los objetos en la memoria cuando realiza la recolección de elementos no utilizados) y para mejorar la seguridad (no puede usar punteros sin procesar para destruir la memoria o acceder a objetos inexistentes).

+0

¿Y qué hay de la implementación predeterminada de 'Object.hashCode()'? Devuelve la dirección de memoria del objeto, ¿no es así? ¿Utiliza la clase Inseguro de la que @prunge habló? Sé que es un método nativo, así que tal vez esto es simplemente un lanzamiento de puntero a int en C++. –

+1

'Object.hashCode()' does * not * devuelve la dirección de memoria del objeto. Es específico de la implementación. Pasé varios meses trabajando en una implementación de JavaScript de una JVM donde no se puede trabajar con direcciones sin formato y se implementó 'Object.hashCode()' con solo tener un contador que incrementé para cada objeto. En algunas implementaciones, puede ser así como funciona 'Object.hashCode()', pero debido a que muchas JVM mueven objetos en la memoria, no puede confiar en que esto sea cierto. – templatetypedef

+0

'System.identityHashcode (Object)' es significativamente más complicado que devolver la dirección de memoria de un objeto ... incluso si eso es lo que parece * hacer *. Para empezar, tiene que devolver el mismo valor incluso si el GC ha movido el objeto. Esto generalmente implica * guardar * el valor en el objeto. (Algunas JVM hacen esto de una manera inteligente que minimiza la sobrecarga ... pero al final pagas). –

-2

Quiero saber la ubicación que JVM asigna a los objetos

No se puede, ya que no existe . Cambia con el tiempo debido a la acción del recolector de basura. No existe tal como 'la ubicación'.

+2

Los saldos de mi tarjeta de crédito cambian, lamentablemente todavía existen. – weston

+1

@weston El saldo de su tarjeta de crédito cambia, por lo tanto, no puede confiar en que siempre será el mismo. – EJP

+1

No dijeron que necesitaban confiar en que no cambiara. Mi punto (broma) fue que eso no significa que no exista. Pero, de todos modos, hay formas de anclarlo: secciones críticas de JNI, por ejemplo, donde la ubicación es exacta y se garantiza que no cambiará. – weston

-1

Puede usar http://openjdk.java.net/projects/code-tools/jol para analizar diseños de objetos. Para un objeto, puede usar:

System.out.println(
    GraphLayout.parseInstance(someObject).toPrintable()); 
+0

a) Las respuestas solo de enlace no se consideran buenas respuestas aquí, ver [respuesta]. b) Esta pregunta ya tiene muchas otras respuestas de alta calidad; ¿Qué significa esto? – EJoshuaS

+0

Gracias por los comentarios. Se agrega una referencia a la herramienta moderna estándar - JOL, que no están aquí. Es una forma más limpia y portátil, que para la tarea del autor toma una fila de código, en lugar de un ejemplo inseguro. También agregué ejemplos de código para la pregunta. – egorlitvinenko

Cuestiones relacionadas