Domanda

Questa domanda riguarda in particolare il linguaggio java. Comprendo che esiste una protezione statica della memoria riservata a tutto il codice statico.

La mia domanda è: come viene riempita questa memoria statica? Un oggetto statico viene inserito nella memoria statica al momento dell'importazione o al primo riferimento? Inoltre, le stesse regole di garbage collection si applicano agli oggetti statici come fanno per tutti gli altri oggetti?


public class Example{
    public static SomeObject someO = new SomeObject();
}
/********************************/
// Is the static object put into static memory at this point?
import somepackage.Example;

public class MainApp{
    public static void main( Sting args[] ){
// Or is the static object put into memory at first reference?
       Example.someO.someMethod();
// Do the same garbage collection rules apply to a 
//     static object as they do all others?
       Example.someO = null;
       System.gc();
    }
}
È stato utile?

Soluzione

Le importazioni non sono correlate ad alcuna istruzione nel codice compilato. Stabiliscono alias da utilizzare solo in fase di compilazione.

Esistono alcuni metodi riflettenti che consentono di caricare la classe ma non ancora inizializzata, ma nella maggior parte dei casi, si può presumere che ogni volta che si fa riferimento a una classe, questa è stata inizializzata.

Gli inizializzatori e i blocchi statici dei membri statici vengono eseguiti come se fossero tutti un blocco di inizializzatori statici nell'ordine del codice sorgente.

Un oggetto a cui fa riferimento una variabile membro statica è fortemente referenziato fino a quando la classe non viene scaricata. Un normale ClassLoader non scarica mai una classe, ma quelli usati dai server delle applicazioni lo fanno nelle giuste condizioni. Tuttavia, è un'area difficile ed è stata la fonte di molte perdite di memoria difficili da diagnosticare & # 8212; ancora un altro motivo per non usare le variabili globali.


Come bonus (tangenziale), ecco una domanda delicata da considerare:

public class Foo {
  private static Foo instance = new Foo();
  private static final int DELTA = 6;
  private static int BASE = 7;
  private int x;
  private Foo() {
    x = BASE + DELTA;
  }
  public static void main(String... argv) {
    System.out.println(Foo.instance.x);
  }
}

Che cosa verrà stampato questo codice? Provalo e vedrai che stampa "6". Ci sono alcune cose al lavoro qui, e uno è l'ordine di inizializzazione statica. Il codice viene eseguito come se fosse scritto in questo modo:

public class Foo {
  private static Foo instance;
  private static final int DELTA = 6;
  private static int BASE;
  static {
    instance = null;
    BASE = 0;
    instance = new Foo(); /* BASE is 0 when instance.x is computed. */
    BASE = 7;
  }
  private int x;
  private Foo() {
    x = BASE + 6; /* "6" is inlined, because it's a constant. */
  }
}

Altri suggerimenti

Normalmente non esiste nulla come " statico " memoria. La maggior parte dei VM ha la generazione permanente dell'heap (dove vengono caricate le classi), che normalmente non viene raccolta in modo inutile.

Gli oggetti statici sono allocati proprio come qualsiasi altro oggetto. Ma se vivono a lungo verranno spostati tra le diverse generazioni nel cestino della spazzatura. Ma non finiranno nel permgenspace.

Se la tua classe si tiene permanentemente su questo oggetto, verrà rilasciata solo quando esce la VM.

Questa variabile statica some0 viene inizializzata non appena la tua classe viene referenziata nel tuo codice. Nel tuo esempio questo sarà eseguito nella prima riga del tuo metodo principale.

Puoi validarlo creando un blocco di inizializzatore statico. Inserisci un punto di interruzione in questo blocco di inizializzazione e vedrai quando verrà chiamato. O ancora più semplice ... metti un breakpoint nel costruttore di SomeObject.

L'inizializzazione delle variabili statiche è trattata nella Sezione 2.11 Inizializzatori statici di soli JVM spec. Le specifiche non definiscono l'implementazione della Garbage Collection, tuttavia immagino che le regole di Garbage Collection per gli oggetti statici varieranno a seconda della VM.

Va ??notato che solo il puntatore (o qualsiasi altro tipo primitivo) è archiviato in PermGenSpace (questo è il nome corretto per l'area in cui è memorizzato il materiale statico).

Quindi l'oggetto a cui fa riferimento il puntatore si trova nell'heap normale, come qualsiasi altro oggetto.

Se il campo statico viene modificato per fare riferimento a un oggetto diverso, l'oggetto originale a cui punta il campo statico è idoneo per GC come qualsiasi altro oggetto.

Potrebbe anche essere liberato (anche se non annullato) se la classe stessa viene scaricata e l'intero grafico oggetto viene tagliato dall'heap. Naturalmente, quando una classe può essere scaricata è un buon argomento per una serie di altre domande ... :)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top