2010-01-20 13 views
70

Ho un dichiarazione di array come questo:È una matrice Java di primitivi memorizzati nello stack o nell'heap?

int a[]; 

Qui a è un array di primitivo int tipo. Dove è archiviata questa matrice? È archiviato su heap o stack? Questo è un tipo primitivo int, tutti i tipi primitivi non sono archiviati nell'heap.

+35

Questo non è un array. È un riferimento a un array. Il riferimento stesso potrebbe essere memorizzato sull'heap se è un membro di una classe o di un oggetto o sullo stack se è una variabile locale in un metodo. E i tipi primitivi possono essere memorizzati nell'heap se sono membri di una classe o di un oggetto. – UncleO

risposta

32

verrà memorizzato sul mucchio

perché array è un oggetto in Java.

EDIT:. Se avete

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

pensare a questo codice come dire al compilatore, "Creazione di un oggetto array che conterrà quattro interi, e assegnarlo alla variabile di riferimento denominata testScores anche , vai avanti e imposta ogni elemento int a zero. Grazie. "

+2

E la variabile di riferimento denominata testScores (che punta alla matrice sull'heap) sarà in pila. – Zaki

+8

Il codice dice solo "Grazie" se si fornisce l'opzione '-g' al compilatore. Altrimenti sarà ottimizzato. – mob

+0

@mob Si presume che questo sia l'unico codice. Probabilmente è meglio presumere che queste due linee facciano parte di un programma più grande che effettivamente utilizza l'array. –

18

È un array di tipi primitivi che di per sé non è primitivo. Una buona regola empirica è quando la nuova parola chiave è coinvolta, il risultato sarà sullo heap.

132

Come ha detto gurukulki, è archiviato nell'heap. Tuttavia, il tuo post ha suggerito un malinteso probabilmente a causa di una persona ben intenzionata che diffonde il mito secondo cui "i primitivi vivono sempre in pila". Questo non è vero. variabili locali hanno i loro valori nello stack, ma non tutte le variabili primitive sono locali ...

Ad esempio, si consideri questo:

public class Foo 
{ 
    int value; 
} 
... 

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

Ora, da dove viene f.value vivere? Il mito suggerirebbe di essere in pila, ma in realtà fa parte del nuovo oggetto Foo e vive nell'heap . (Si noti che il valore di f è di per sé un riferimento e vive in pila.)

Da lì, è un semplice passaggio agli array. Si può pensare a un array come solo di essere un sacco di variabili - così new int[3] è un po 'come avere una classe di questa forma:

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

In realtà, è più complicato di così. La distinzione stack/heap è principalmente un dettaglio di implementazione - credo che alcune JVM, possibilmente sperimentali, possano dire quando un oggetto non "scappa" mai da un metodo e può allocare l'intero oggetto sullo stack. Tuttavia, è concettualmente sullo heap, se si sceglie di preoccuparsi.

+1

Informazioni sulla "analisi di fuga" in Java: http://blog.juma.me.uk/2008/12/17/objects-with-no-allocation-overhead/ Si dice che sia presente dal primo accesso rilascio di JDK 6 Update 14 e abilitato di default dall'aggiornamento JDK 6 23. –

+0

cambia qualcosa se array è public static final? Non dovrebbe essere parte della piscina costante allora? – Malachiasz

+0

@Malachiasz: No. Un array non è mai una costante. –

14

Volevo solo condividere alcuni test su questo argomento.

array di dimensione 10 milioni

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

uscita:

------------------------ 
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 
------------------------ 

Come vedete dimensione heap utilizzato è aumentato di ~ 80 MB, che è 10m * sizeof (doppia).

Ma se abbiamo Doppia uso al posto del doppio

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

uscita mostrerà 40MB. Abbiamo solo riferimenti doppi, non sono inizializzati.

riempiendolo con doppio

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(); 
} 

Ancora 40MB. Perché puntano tutti allo stesso oggetto Double.

Inizializzazione con doppia invece

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 

Linea

a[i] = qq.doubleValue(); 

è equivalente a

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

che equivale a

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

Ogni volta che creiamo nuovi oggetti Double, facciamo saltare in aria l'heap. Questo mostra che i valori all'interno della classe Double sono memorizzati nell'heap.

Problemi correlati