Heim  >  Artikel  >  Java  >  Analyse der Heap-, Stack- und konstanten Speicherzuweisungspools in Java

Analyse der Heap-, Stack- und konstanten Speicherzuweisungspools in Java

巴扎黑
巴扎黑Original
2017-08-01 10:56:351492Durchsuche

Die Java-Speicherzuweisung umfasst hauptsächlich die folgenden Bereiche:

1. Register: Wir haben keine Kontrolle im Programm

2. Stapel: speichert grundlegende Datentypen und Objektreferenzen, aber die Das Objekt selbst wird nicht auf dem Stapel gespeichert, sondern im Heap

3. Speichert die mit der neuen

4 generierten Daten 🎜>

5. Konstantenpool: Konstanten speichern

6. Nicht-RAM-Speicher (Random Access Memory): permanenter Speicherplatz wie Festplatte

****** ************************************************** * ********

Stack in Java-Speicherzuweisung

Einige

in Funktionen definierte Grundtypen Die variablen Daten und die Referenzvariable des -Objekts werden im Stapelspeicher der Funktion allokiert. Wenn eine Variable in einem Codeblock definiert wird, weist Java der Variablen Speicherplatz auf dem Stapel zu. Wenn die Variable den Gültigkeitsbereich verlässt, gibt Java automatisch den für die Variable zugewiesenen Speicherplatz frei und der Speicherplatz kann sofort verwendet werden. für andere Zwecke verwendet werden.

Heap in der Java-Speicherzuweisung

Heap-Speicher wird zum Speichern von Objekten verwendet, die von

new und array erstellt wurden . Der im Heap zugewiesene Speicher wird vom automatischen Garbage Collector der Java Virtual Machine verwaltet.

Nach dem Generieren eines Arrays oder Objekts im Heap können Sie auch eine spezielle Variable im Stapel definieren, sodass der Wert dieser Variablen im Stapel gleich der ersten Adresse des Arrays oder Objekts im Stapel ist Heap-Speicher. Diese Variable wird zu einer Referenzvariablen des Arrays oder Objekts. Eine Referenzvariable ist gleichbedeutend damit, einem Array oder Objekt einen Namen zu geben. Sie können dann die Referenzvariable im Stapel verwenden, um auf das Array oder Objekt im Heap im Programm zuzugreifen. Eine Referenzvariable entspricht der Namensgebung für ein Array oder Objekt.

Referenzvariablen sind gewöhnliche Variablen, die bei der Definition auf dem Stapel zugewiesen werden. Die Referenzvariablen werden freigegeben, nachdem das Programm außerhalb seines Gültigkeitsbereichs ausgeführt wurde. Die Arrays und Objekte selbst werden im Heap zugewiesen. Auch wenn das Programm außerhalb des Codeblocks ausgeführt wird, in dem sich die Anweisung befindet, die das Array oder Objekt generiert, wird der vom Array und Objekt selbst belegte Speicher nicht freigegeben Objekte haben keine Referenzvariablen, die auf sie verweisen, sie werden zu Müll und können nicht mehr verwendet werden, aber sie belegen immer noch den Speicherplatz und werden zu einem unbestimmten Zeitpunkt später vom Garbage Collector gesammelt (freigegeben). Dies ist auch der Grund, warum Java mehr Speicher beansprucht.

 

Tatsächlich verweisen die Variablen im Stapel auf Variablen im Heapspeicher. Dies ist ein Zeiger in Java!

Konstanter Pool (Konstantenpool)

Der Konstantenpool bezieht sich auf den Pool, der bei der Kompilierung ermittelt und im gespeichert wird kompilierte Datei. Einige Daten in der .class-Datei. Zusätzlich zu den

konstanten Werten (endgültig)Grundtypen (z. B. int, long usw.) und Objekttypen (z. B. String und Array) im Code definiert 🎜> enthält auch einige Symbolverweise in Textform, wie zum Beispiel:

Vollständig qualifizierte Namen von Klassen und Schnittstellen; 🎜>Namen von Feldern und Deskriptoren;
  1. Methoden und Namen und Deskriptoren.
  2. Die virtuelle Maschine muss für jeden geladenen Typ einen konstanten Pool verwalten. Der Konstantenpool ist ein geordneter Satz von Konstanten, die von diesem Typ verwendet werden, einschließlich direkter Konstanten (String-, Ganzzahl- und Gleitkommakonstanten) und symbolischer Verweise auf andere Typen, Felder und Methoden.
  3. Bei String-Konstanten liegen ihre Werte im Konstantenpool. Der Konstantenpool in der JVM liegt in Form einer Tabelle im Speicher vor. Für den String-Typ gibt es eine Tabelle fester Länge, die zum Speichern literaler String-Werte verwendet wird, keine Symbole . Vor diesem Hintergrund sollten Sie den Speicherort von Zeichenfolgenwerten im Konstantenpool genau kennen.

     
  4. Wenn das Programm ausgeführt wird, wird der Konstantenpool im Methodenbereich anstelle des Heaps gespeichert.

Heap und Stack

Der Java-Heap ist ein Laufzeitdatenbereich, aus dem Klasse (Objekte) Speicherplatz zuweisen. Diese Objekte werden durch erstellt Anweisungen wie new, newarray, anewarray und multianewarray erfordern keine explizite Freigabe des Programmcodes.

Der Heap ist für die Speicherbereinigung verantwortlich. Größe und Lebensdauer müssen dem Compiler nicht im Voraus mitgeteilt werden, da er zur Laufzeit dynamisch Speicher zuweist und der Garbage Collector von Java diese nicht mehr verwendeten Daten automatisch sammelt. Aufgrund der Notwendigkeit, Speicher zur Laufzeit dynamisch zuzuweisen,

ist die Zugriffsgeschwindigkeit langsamer

.

 Der Vorteil des Stapels besteht darin, dass die Zugriffsgeschwindigkeit schneller ist als die des Heaps, nur nach dem Register an zweiter Stelle, und der StapelDaten können gemeinsam genutzt werden. Der Nachteil besteht jedoch darin, dass die Größe und Lebensdauer der im Stapel gespeicherten Daten bestimmt werden muss , was an Flexibilität mangelt. Der Stapel speichert hauptsächlich einige Grundtypen variabler Daten (int, short, long, byte, float, double, boolean, char) und Objekthandles (Referenzen).

************************************************ **** ************************

Hier geht es uns hauptsächlich um den Stack, Heap und Konstantenpool. Für den Stapel können Objekte im Konstantenpool gemeinsam genutzt werden , Objekte im Heap können jedoch nicht gemeinsam genutzt werden . Die Größe und der Lebenszyklus der Daten im Stapel können bestimmt werden. Wenn kein Verweis auf die Daten vorhanden ist, verschwinden die Daten. Die Objekte im Heap werden vom Garbage Collector recycelt, sodass Größe und Lebenszyklus nicht bestimmt werden müssen und eine große Flexibilität besteht.

String-Speicherzuordnung:

Für Strings werden Verweise auf ihre

-Objekte im Stapel , gespeichert Wenn es während der Kompilierung erstellt wurde (direkt mit doppelten Anführungszeichen definiert), wird es im Konstantenpool gespeichert. Wenn es während der Laufzeit ermittelt wird (neu), wird es im Heap gespeichert. Für gleiche Zeichenfolgen gibt es immer nur eine Kopie im Konstantenpool und mehrere Kopien im Heap.

Zum Beispiel der folgende Code:


        String s1 = "china";
        String s2 = "china";
        String s3 = "china";

        String ss1 = new String("china");
        String ss2 = new String("china");
        String ss3 = new String("china");

Hier ist eine Erklärung der drei gelben Pfeile, die Wird eine neue Zeichenfolge generiert (angenommen, es handelt sich um „China“), wird zunächst geprüft, ob im Konstantenpool bereits ein „China“-Objekt vorhanden ist. Wenn nicht, erstellen Sie ein Zeichenfolgenobjekt im Konstantenpool und erstellen Sie dann ein anderes Konstantenpool im Heap. Das Kopierobjekt dieses „China“-Objekts.

Dies ist auch eine Interviewfrage: Strings=newString(“xyz”); Wie viele Objekte werden generiert? Eins oder zwei. Wenn der Konstantenpool kein „xyz“ enthält, sind es zwei.

Der in der .class-Datei vorhandene Konstantenpool wird zur Laufzeit von der JVM geladen und kann erweitert werden. Die intern()-Methode von String ist eine Methode zum Erweitern des Konstantenpools. Wenn eine String-Instanz str die intern()-Methode aufruft, prüft Java, ob im Konstantenpool eine Stringkonstante mit demselben Unicode vorhanden ist seine Referenz. Wenn nicht, fügen Sie eine Unicode-Zeichenfolge gleich str im Konstantenpool hinzu und geben Sie ihre Referenz

wie folgt zurück:


        String s0= "kvill";   
        String s1=new String("kvill");   
        String s2=new String("kvill");   
        System.out.println( s0==s1 );     
        s1.intern();   
        s2=s2.intern(); //把常量池中"kvill"的引用赋给s2   
        System.out.println( s0==s1);   
        System.out.println( s0==s1.intern() );   
        System.out.println( s0==s2 );
Ausgabe Ergebnis:

falsch
falsch
wahr
wahr

String Mehrere Beispiele für konstante Poolprobleme:


【1】
String a = "ab"= "b"= "a" +== b)); = "ab" String bb = "b"= "a" +== b)); = "ab" String bb == "a" +== b));   "b"
Analyse:

 [1], JVM hat String-Referenzen, weil in der Zeichenfolge In „+“-Verbindung, es gibt eine Zeichenfolgenreferenz, und der Wert der Referenz kann während der Programmkompilierung nicht bestimmt werden, d. h. „a“ + bb kann vom Compiler nicht optimiert werden. Es kann nur während der Programmausführung dynamisch zugewiesen und verbunden werden . Die neue Adresse wird b zugewiesen. Das Ergebnis des obigen Programms ist also falsch.

Der einzige Unterschied zwischen [2] und [1] besteht darin, dass die bb-Zeichenfolge endgültig geändert wird. Für die endgültig geänderte Variable wird sie zur Kompilierungszeit in eine lokale Kopie des konstanten Werts analysiert und darin gespeichert Eigene Konstante. Gepoolt oder in den Bytecode-Stream eingebettet. Die Wirkung von „a“ + bb und „a“ + „b“ ist zu diesem Zeitpunkt also dieselbe. Daher ist das Ergebnis des obigen Programms wahr.

[3] Die JVM kann den Wert der Zeichenfolgenreferenz bb während der Kompilierung nicht ermitteln. Erst nachdem die Methode während der Programmausführung aufgerufen wurde, werden der Rückgabewert der Methode und „a“ dynamisch verbunden und die Adresse ermittelt b zugewiesen, daher ist das Ergebnis des obigen Programms falsch.

Schlussfolgerung:

String ist eine spezielle Verpackungsklasse, ihre Referenz wird auf dem Stapel gespeichert und der Objektinhalt muss gemäß der Erstellungsmethode (konstanter Pool) bestimmt werden und Heap). Einige werden während der Kompilierung erstellt und im String-Konstantenpool gespeichert, während andere zur Laufzeit erstellt werden. Verwenden Sie das Schlüsselwort new und speichern Sie sie im Heap.

Zuordnung von Variablen und Konstanten von Grundtypen im Speicher

Für Variablen und Konstanten von Grundtypen werden Variablen und Referenzen gespeichert Auf dem Stapel werden Konstanten in einem Konstantenpool gespeichert.

Zum Beispiel der folgende Code:


        int i1 = 9;        int i2 = 9;        int i3 = 9;        final int INT1 = 9;        final int INT2 = 9;        final int INT3 = 9;

  编译器先处理int i1 = 9;首先它会在栈中创建一个变量为i1的引用,然后查找栈中是否有9这个值,如果没找到,就将9存放进来,然后将i1指向9。接着处理int i2 = 9;在创建完i2的引用变量后,因为在栈中已经有9这个值,便将i2直接指向9。这样,就出现了i1与i2同时均指向9的情况。最后i3也指向这个9。

成员变量和局部变量在内存中的分配

  对于成员变量和局部变量:成员变量就是方法外部,类的内部定义的变量;局部变量就是方法或语句块内部定义的变量。局部变量必须初始化。 形式参数是局部变量,局部变量的数据存在于栈内存中。栈内存中的局部变量随着方法的消失而消失。 成员变量存储在堆中的对象里面,由垃圾回收器负责回收。   如以下代码:


class BirthDate {    private int day;    private int month;    private int year;    public BirthDate(int d, int m, int y) {
        day = d;
        month = m;
        year = y;
    }    // 省略get,set方法………}public class Test {    public static void main(String args[]) {        int date = 9;
        Test test = new Test();
        test.change(date);
        BirthDate d1 = new BirthDate(7, 7, 1970);
    }    public void change(int i) {
        i = 1234;
    }
}

  对于以上这段代码,date为局部变量,i,d,m,y都是形参为局部变量,day,month,year为成员变量。下面分析一下代码执行时候的变化:    

  1. main方法开始执行:int date = 9; date局部变量,基础类型,引用和值都存在栈中。

  2. Test test = new Test();test为对象引用,存在栈中,对象(new Test())存在堆中。 

  3. test.change(date);  i为局部变量,引用和值存在栈中。当方法change执行完成后,i就会从栈中消失。

  4. BirthDate d1= new BirthDate(7,7,1970); d1为对象引用,存在栈中,对象(new BirthDate())存在堆中,其中d,m,y为局部变量存储在栈中,且它们的类型为基础类型,因此它们的数据也存储在栈中。day,month,year为成员变量,它们存储在堆中(new BirthDate()里面)。当BirthDate构造方法执行完之后,d,m,y将从栈中消失。 

  5. main方法执行完之后,date变量,test,d1引用将从栈中消失,new Test(), new BirthDate()将等待垃圾回收。

Das obige ist der detaillierte Inhalt vonAnalyse der Heap-, Stack- und konstanten Speicherzuweisungspools in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn