2010-01-20 19 views
70

Tengo una declaración de matriz de esta manera:¿Hay una matriz Java de primitivas almacenadas en pila o montón?

int a[]; 

Aquí a es un conjunto de primitivas int tipo. ¿Dónde está almacenada esta matriz? ¿Está almacenado en montón o pila? Este es un tipo primitivo int, todos los tipos primitivos no se almacenan en el montón.

+35

Eso no es una matriz. Es una referencia a una matriz. La referencia misma podría almacenarse en el montón si es miembro de una clase u objeto, o en la pila si es una variable local en un método. Y los tipos primitivos se pueden almacenar en el montón si son miembros de una clase u objeto. – UncleO

Respuesta

32

se almacenará en la montón

porque matriz es un objeto en Java.

EDITAR:. Si tiene

int [] testScores; 
testScores = new int[4]; 

parece este código como diciendo al compilador, "Crear un objeto de matriz que contendrá cuatro enteros, y asignarlo a la variable de referencia con nombre testScores también , continúe y configure cada elemento int en cero. Gracias. "

+2

Y la variable de referencia llamada testScores (que apunta a la matriz en el montón) estará en la pila. – Zaki

+8

El código solo dice "Gracias" si proporciona la opción '-g' al compilador. De lo contrario, se optimizará. – mob

+0

@mob Estás asumiendo que este es el único código. Probablemente sea mejor suponer que estas dos líneas son parte de un programa más grande que realmente usa la matriz. –

18

Es una matriz de tipos primitivos que en sí mismo no es primitivo. Una buena regla empírica es cuando la nueva palabra clave está involucrada, el resultado estará en el montón.

132

Como dijo gurukulki, está almacenado en el montón. Sin embargo, su publicación sugirió un malentendido probablemente debido a una persona bien intencionada que propaga el mito de que "los primitivos siempre viven en la pila". Esto no es cierto. Las variables locales tienen sus valores en la pila, pero no todas las variables primitivas son locales ...

Por ejemplo, considere esto:

public class Foo 
{ 
    int value; 
} 
... 

public void someOtherMethod() 
{ 
    Foo f = new Foo(); 
    ... 
} 

Ahora, ¿dónde vive f.value? El mito sugeriría que está en la pila, pero en realidad es parte del nuevo objeto Foo, y vive en el montón . (Tenga en cuenta que el valor de f en sí mismo es una referencia, y vive en la pila.)

A partir de ahí, es un paso fácil para las matrices. Se puede pensar en una matriz como simplemente ser un montón de variables - por lo new int[3] es un poco como tener una clase de esta forma:

public class ArrayInt3 
{ 
    public readonly int length = 3; 
    public int value0; 
    public int value1; 
    public int value2; 
} 

De hecho, es más complicado que esto. La distinción pila/montón es principalmente un detalle de implementación. Creo que algunas JVM, posiblemente experimentales, pueden decir cuándo un objeto nunca "escapa" de un método, y pueden asignar el objeto completo en la pila. Sin embargo, es conceptualmente en el montón, si elige cuidar.

+1

Acerca del "análisis de escape" en Java: http://blog.juma.me.uk/2008/12/17/objects-with-no-allocation-overhead/ Dice que está presente desde el acceso temprano lanzamiento de JDK 6 Actualización 14, y habilitado por defecto desde la actualización 23 de JDK 6. –

+0

¿cambia algo si la matriz es pública estática final? ¿No debería ser parte del grupo constante entonces? – Malachiasz

+0

@Malachiasz: No. Una matriz nunca es una constante. –

14

Solo quería compartir algunas pruebas que realicé sobre este tema.

matriz de tamaño 10 millones

public static void main(String[] args) { 
    memInfo(); 
    double a[] = new double[10000000]; 
    memInfo(); 
} 

Salida:

------------------------ 
max mem = 130.0 MB 
total mem = 85.0 MB 
free mem = 83.6 MB 
used mem = 1.4 MB 
------------------------ 
------------------------ 
max mem = 130.0 MB 
total mem = 130.0 MB 
free mem = 48.9 MB 
used mem = 81.1 MB 
------------------------ 

Como ves tamaño de la pila usada se incrementa en un ~ 80 MB, que es de 10 m * sizeof (doble).

Pero si hemos usar doble en vez de doble

public static void main(String[] args) { 
    memInfo(); 
    Double a[] = new Double[10000000]; 
    memInfo(); 
} 

salida se mostrará 40MB. Solo tenemos referencias dobles, no están inicializadas.

llenándolo con doble

public static void main(String[] args) { 
    memInfo(); 
    Double a[] = new Double[10000000];  
    Double qq = 3.1d; 
    for (int i = 0; i < a.length; i++) { 
     a[i] = qq; 
    } 
    memInfo(); 
} 

Aún 40MB. Porque todos apuntan al mismo objeto doble.

Inicialización con doble en vez

public static void main(String[] args) { 
    memInfo(); 
    Double a[] = new Double[10000000]; 
    Double qq = 3.1d; 
    for (int i = 0; i < a.length; i++) { 
     a[i] = qq.doubleValue(); 
    } 
    memInfo(); 
} 

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 

Line

a[i] = qq.doubleValue(); 

es equivalente a

a[i] = Double.valueOf(qq.doubleValue()); 

que es equivalente a

a[i] = new Double(qq.doubleValue()); 

Como creamos nuevos objetos dobles cada vez, volamos el montón. Esto muestra que los valores dentro de la clase doble se almacenan en el montón.

Cuestiones relacionadas