Frage

Diese Frage ist für die Java-Sprache im Besonderen. Ich verstehe, dass es eine statische protion Speicher beiseite für alle statischen Code festgelegt ist.

Meine Frage ist, wie wird dieser statische Speicher gefüllt? Ist ein statisches Objekt in statische Speicher bei der Einfuhr setzen, oder auf dem ersten Referenz? Außerdem tun die gleichen Speicherbereinigungsregeln auf statische Objekte anwenden, wie sie für alle anderen Objekte tun?


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();
    }
}
War es hilfreich?

Lösung

Die Einfuhren mit irgendwelchen Anweisungen nicht in kompilierten Code korrelieren. Sie stellen Aliase für die Verwendung bei der Kompilierung nur.

Es gibt einige reflektierende Methoden, die die Klasse ermöglichen geladen werden, aber noch nicht initialisiert, aber in den meisten Fällen, können Sie davon ausgehen, dass, wenn eine Klasse referenziert wird, hat es initialisiert wurde.

Statischer Member Initialisierer und statischen Blöcke ausgeführt werden, als ob sie alle einen statischen Initialisierer Block, um Quellcode waren.

Ein Objekt durch eine statische Membervariable referenziert wird stark verwiesen, bis die Klasse entladen wird. Ein normaler ClassLoader leert nie eine Klasse, aber die von Anwendungsservern verwendet tun unter den richtigen Bedingungen. Aber es ist ein heikles Gebiet und hat die Quelle viele schwer zu diagnostizieren Speicherlecks-noch aus einem anderen Grunde war keine globalen Variablen verwendet werden.


Als (tangential) Bonus, hier ist eine schwierige Frage zu berücksichtigen:

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

Was wird dieser Code drucken? Probieren Sie es aus, und Sie werden sehen, dass es „6“ druckt. Es gibt ein paar Dinge bei der Arbeit hier, und man ist die Reihenfolge der statischen Initialisierung. Der Code wird ausgeführt, als ob es wie folgt geschrieben:

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. */
  }
}

Andere Tipps

Es ist normalerweise nicht so etwas wie „statischer“ Speicher. Die meisten VMs haben die permanente Erzeugung des Haufens (wo Klassen geladen werden), die normalerweise nicht Müll gesammelt.

Statische Objekte werden wie jedes andere Objekt zugeordnet. Aber, wenn sie für lange leben sie zwischen den verschiedenen Generationen in der Garbage Collector verschoben werden. Aber sie werden nicht in permgenspace enden.

Wenn Ihre Klasse wird auf dieses Objekt hält fest, wird es erst dann freigegeben werden, wenn die vm beendet wird.

Diese statische Variable some0 initialisiert wird, sobald Sie Ihre Klasse in Ihrem Code verwiesen wird. In Ihrem Beispiel wird dies in erster Linie Ihrer Haupt-Methode ausgeführt werden.

Sie können dies überprüfen, indem Sie einen statischen Initialisierer Block zu schaffen. Setzen Sie einen Haltepunkt in diesem Initialisierungsblocks und Sie werden sehen, wenn sie aufgerufen werden. Oder noch einfacher ... setzt einen Haltepunkt im Konstruktor von Someobject.

Die Initialisierung von statischen Variablen abgedeckt in Abschnitt

Es sollte beachtet werden, dass nur der Zeiger (oder irgendeine andere primitive Art) in dem PermGenSpace (das ist der richtige Name für den Bereich, in dem die statische Material gespeichert ist).

Also das Objekt durch den Zeiger referenzierten sitzt im normalen Haufen, wie jedes andere Objekt.

Wenn das statische Feld ein anderes Objekt zu verweisen geändert wird, wies das ursprüngliche Objekt durch das statische Feld für GC berechtigt ist, wie jedes andere Objekt.

Es könnte auch free'ed werden (auch wenn sie nicht auf Null gesetzt), wenn die Klasse selbst entladen und die gesamte Objektgraph wird aus dem Heap geschnitten. Natürlich, wenn eine Klasse entladen werden kann für eine Vielzahl von anderen Fragen ein gutes Thema ist ...:)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top