2008-11-26 8 views
10

¿Qué sucede en la memoria cuando una clase instancia el siguiente objeto?Pasos en el proceso de asignación de memoria para objetos Java

public class SomeObject{ 

    private String strSomeProperty; 

    public SomeObject(String strSomeProperty){ 
     this.strSomeProperty = strSomeProperty; 
    } 
    public void setSomeProperty(String strSomeProperty){ 
     this.strSomeProperty = strSomeProperty; 
    } 
    public String getSomeProperty(){ 
     return this.strSomeProperty; 
    } 
} 

En la clase SomeClass1:

SomeObject so1 = new SomeObject("some property value"); 

En la clase SomeClass2:

SomeObject so2 = new SomeObject("another property value"); 

¿Cómo está la memoria asignada al objeto recién instanciado y sus propiedades? paso

Respuesta

9

Vamos a través de él:

SomeObject so1 = new SomeObject("some property value"); 

... En realidad, es más complicado de lo que parece, porque va a crear una nueva cadena. Puede ser que sea más fácil pensar en como:

String tmp = new String("some property value"); 
SomeObject so1 = new SomeObject(tmp); 
// Not that you would normally write it in this way. 

(Para ser absolutamente exacto - estos no son realmente equivalentes En el original se crea la 'nueva cadena' en tiempo de compilación y es parte de la imagen .class.. Puede pensar en esto como un hack de rendimiento.)

Por lo tanto, primero la JVM asigna espacio para la cadena. Por lo general, no conoce ni se preocupa por los aspectos internos de la implementación de String, así que confíe en que se está utilizando un trozo de memoria para representar "algún valor de propiedad". Además, tiene algo de memoria asignada temporalmente que contiene una referencia a la Cadena. En la segunda forma, se llama explícitamente tmp; en su forma original, Java lo maneja sin nombrarlo.

A continuación, la JVM asigna espacio para un nuevo SomeObject. Eso es un poco de espacio para la contabilidad interna de Java y espacio para cada uno de los campos del objeto. En este caso, solo hay un campo, strSomeProperty.

Tenga en cuenta que strSomeProperty es solo una referencia a una Cadena. Por ahora, se inicializará a nulo.

A continuación, se ejecuta el constructor.

this.strSomeProperty = strSomeProperty; 

Todo esto hace es copiar la referenciaa la cadena, en su campo de strSomeProperty.

Finalmente, se asigna espacio para la referencia de objeto so1. Esto se establece con una referencia al SomeObject.

so2 funciona exactamente de la misma manera.

+3

No, no es más complicado de lo que parece. "a" y una nueva cadena ("a") no son expresiones equivalentes. Los literales de cadena son internados por el compilador. No incurren en asignaciones de montón adicionales cuando se utilizan. – bendin

+0

http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.10.5 – bendin

+0

Touche :) Sin embargo, creo que la internación es conceptualmente aún más complicada de lo que describí. Supongo que la respuesta adecuada depende de la intención de la pregunta. – slim

6

Determining Memory Usage in Java por Dr. Heinz M. Kabutz da una respuesta precisa, más un programa para calcular el uso de la memoria. La parte pertinente:

  1. la clase lleva al menos 8 bytes. Entonces, si dices Objeto nuevo(); Asignarás 8 bytes en el montón.
  2. Cada miembro de datos ocupa 4 bytes, excepto el largo y el doble, que ocupan 8 bytes.Incluso si el miembro de datos es un byte, ¡aún ocupará 4 bytes! Además, la cantidad de memoria utilizada aumenta en bloques de 8 bytes. Por lo tanto, si tiene una clase que contiene un byte, ocupará 8 bytes para la clase y 8 bytes para los datos, totalizando 16 bytes (¡gemido!).
  3. Las matrices son un poco más inteligentes. Los primitivos se empaquetan en matrices, por lo que si tiene una matriz de bytes, cada uno ocupará un byte (wow!). El uso de la memoria, por supuesto, sigue aumentando en bloques de 8 bytes.

Como ya se ha señalado en los comentarios, las cadenas son un caso especial, ya que pueden ser internados. Puede razonar sobre el espacio que ocupan de la misma manera, pero tenga en cuenta que lo que parece ser copias múltiples de la misma Cadena puede apuntar a la misma referencia.

+1

Tenga en cuenta que esto tiene 7 años de antigüedad, y se basa en evidencia empírica que utiliza una JVM particular en un sistema operativo particular en ese momento (el artículo dice lo mismo). A menos que sepa con certeza en qué JVM se ejecutará, no puede ser tan preciso. – slim

+0

Buen punto. No me sorprendería si algunas cosas que solían tomar 4 bytes toman 8 en una plataforma de 64 bits. Sin embargo, el programa determina el tamaño de un objeto empíricamente. Ejecutarlo en la máquina virtual objetivo dará una respuesta precisa. –

+0

Eso es genial. Gracias. – DragonBorn

3

Puntos para recordar:

  1. Cuando se llama a un método, un marco se crea en la parte superior de la pila.
  2. Una vez que un método ha completado la ejecución, el flujo de control vuelve al método de llamada y se vacía el marco de pila correspondiente.
  3. Las variables locales se crean en la pila.
  4. Las variables de instancia se crean en el montón & son parte del objeto al que pertenecen.
  5. Las variables de referencia se crean en la pila.

Ref: http://www.javatutorialhub.com/java-stack-heap.html

+0

Pls exalain también sobre Gneración Premanente en Heap .. – Akash5288

+0

* Las variables de referencia Local * se crean en la pila. Los * miembros de la instancia de referencia * se crean en el objeto contenedor, en el montón. Nada de esto responde la pregunta. – EJP

Cuestiones relacionadas