Heim  >  Artikel  >  Java  >  JVM-Speicherverwaltung ------ Verschiedenes (im Folgenden wird auch obj = null besprochen)

JVM-Speicherverwaltung ------ Verschiedenes (im Folgenden wird auch obj = null besprochen)

黄舟
黄舟Original
2016-12-28 15:29:041248Durchsuche

Für einen Programmierer ist der Trainingsprozess wie für den Protagonisten in einem Fantasy-Roman. Es ist nicht nur wichtig, verschiedene Kampfkünste zu üben, sondern auch die Kultivierung der inneren Energie. Obwohl Kampfkünste die Kraft des Protagonisten schnell verbessern können, kann er bei zu geringer innerer Energie nicht ein Zehntel der Kampfkünste ausüben.
Daher ging LZ nach der Einführung externer Fähigkeiten wie Designmuster direkt zur internen Qi-Kultivierung über und besprach die Inhalte von JVM mit allen Affenfreunden.
Ursprünglich sollte dieses Kapitel Inhalte im Zusammenhang mit GC vorstellen, aber vorher wird LZ mit Ihnen einen kleinen Programmiertrick besprechen. Natürlich hängt dieser kleine Trick tatsächlich eng mit GC zusammen.
Ich weiß nicht, ob einer von Ihnen einige Artikel zum Thema JAVA-Speicher gelesen hat. Beim Auflisten von Vorschlägen wird oft ein solcher Vorschlag geschrieben.
Artikel XX: Nachdem Sie das Objekt verwendet haben, setzen Sie es bitte explizit auf null.
Die ursprünglichen Wörter sind vielleicht nicht so, aber die Bedeutung ist dieselbe. Die in den Worten beschriebene Bedeutung ist, dass wir beim Schreiben von Code in Zukunft auf diese Weise schreiben sollten.

Object obj = new Object();  
//to do something   
obj = null;

Dieser Code hat ein bisschen den C/C++-Stil obj=null ersetzt delete obj oder free(obj) in C/C++, was gleichbedeutend damit ist, uns daran zu erinnern, dass wir es auch mit GC mögen Da es keinen GC gibt, müssen Sie dem Objekt nach der Verwendung einen Nullwert zuweisen.
Was LZ hier zunächst erklären möchte, ist, dass sich die Zuweisung von obj zu einem Nullwert tatsächlich stark von delete in C/C++ unterscheidet. Der Grund, warum LZ sagt, dass sie delete und free ersetzen, liegt einfach darin, dass sie in der Code Die Positionen in sind einfach ähnlich.
obj=null bewirkt nur eine Aufgabe: Die Referenzvariable obj wird von der durch new Object() erstellten Instanz getrennt. Tatsächlich wird der von der Instanz belegte Speicherplatz immer noch nicht freigegeben.
Als dieser Vorschlag gemacht wurde, bestand die ursprüngliche Absicht vieler Blogger oder Buchautoren (da viele Blogger ihn wahrscheinlich aus Büchern lesen) darin, die Verknüpfung zwischen Referenzen und Instanzen so schnell wie möglich zu beseitigen und so GC zum Fortfahren zu veranlassen Bei der Sammlung wird der von der Instanz belegte Speicher freigegeben. In einigen Fällen geschieht dies auch, um Speicherlecks zu beseitigen.
LZ persönlich ist der Ansicht, dass die ursprüngliche Absicht vieler Blogger oder Buchautoren, diesen Vorschlag zu machen, hauptsächlich für Programmierer gedacht ist, die nicht mit den GC-Prinzipien und der Speicherverwaltung vertraut sind, denn ohne das entsprechende Wissen zu verstehen, Es ist leicht, es nicht zu verstehen Der Umfang der Variablen führt zu unnötiger Speicherverschwendung (ich persönlich bin der Meinung, dass dies nicht der Hauptzweck ist, denn solange kein Speicherverlust auftritt, wird der Speicher schließlich von GC freigegeben) oder sogar zu Speicherverlusten.
Aus Sicherheitsgründen haben einige Experten einen solchen Vorschlag gemacht.
In Anbetracht dessen ist LZ persönlich der Meinung, dass Sie diesen Vorschlag vollständig ignorieren können, nachdem jeder das entsprechende Wissen beherrscht hat, was natürlich die Klarheit des Codes verringert und die Belastung durch das Codieren erhöht Der Austausch erfolgt nur, um Speicherlecks zu vermeiden, die möglicherweise gar nicht vorhanden sind.
Hier finden Sie eine Erklärung, warum die Nichtzuweisung eines Objekts zu einem Nullwert manchmal zu Speicherverlusten führt. Betrachten wir den folgenden Codeabschnitt.

import java.util.Arrays;  
public class Stack {  
      
    private static final int INIT_SIZE = 10;  
    private Object[] datas;  
      
    private int size;  
    public Stack() {  
        super();  
        datas = new Object[INIT_SIZE];  
    }  
      
    public void push(Object data){  
        if (size == datas.length) {  
            extend();  
        }  
        datas[size++] = data;  
    }  
      
    public Object pop(){  
        if (size == 0) {  
            throw new IndexOutOfBoundsException("size is zero");  
        }  
        return datas[--size];  
    }  
      
    private void extend(){  
        datas = Arrays.copyOf(datas, 2 * size + 1);  
    }  
      
}

Dieser Code ist eine einfache Stack-Implementierung mit skalierbarer Länge. Wenn Sie einen Testcode schreiben, um ihn zu testen, werden Sie feststellen, dass es keine Probleme gibt. Aber leider liegt hier ein offensichtlicher „Speicherverlust“ vor, der dadurch verursacht wird, dass einige Objekte oder Referenzen nicht auf Nullwerte gesetzt werden.
Wenn Sie es noch nicht gesehen haben, wird LZ Sie daran erinnern und Sie werden es bemerken. In diesem Code wachsen die Objekte im Array nur unendlich und werden nicht kleiner, wenn die Elemente im Stapel entfernt werden. Was abnimmt, ist nur die Größe des nach außen angezeigten Stapels. Stellen Sie sich ein extremes Szenario vor. Angenommen, Sie haben 1 Million Objekte in den Stapel gelegt und schließlich werden 999.999 verwendet. Von außen ist nur noch ein Objekt im Stapel verfügbar, aber unser Stapel enthält immer noch Verweise auf 1 Million Objekte. Wenn die JVM überleben könnte, würde sie Sie definitiv zu Tode verwüsten.
Was uns fehlt, ist der Schritt, dem Objekt einen Nullwert zuzuweisen. Daher sollte die Pop-Methode in die folgende Methode geändert werden. Sie können sich den Quellcode der Remove-Methode in ArrayList ansehen, der einen hat ähnliche Idee.

public Object pop(){  
        if (size == 0) {  
            throw new IndexOutOfBoundsException("size is zero");  
        }  
        Object data = datas[--size];  
        datas[size] = null;  
        return data;  
    }

这个内存泄露是非常隐蔽的,而且实际使用当中不一定就能发现,因为随着Stack对象的回收,整个数组也会被回收,到时内存泄露就被掩盖了。
所以个人觉得上述的那个建议是完全没有必要的,就算遵从了上面的建议,如果对内存管理不熟悉的话,也不会想到上面这个代码中的问题。如果想彻底的避免内存泄露的发生,机械式的主动将对象赋为空值,并不是一个可以从根本上解决问题的办法。
真正能够解决问题的办法,就是掌握好GC的策略与原理,定义一个变量时多注意变量的作用域,如此才可以更好的避免内存泄露。
所以学好GC原理还是很有必要的,希望准备走JAVA之路的朋友,尤其是从培训机构出来的猿友们(此处没有鄙视培训机构出来的猿友们的意思,因为LZ本人也是半路出家,从培训机构走上编程之路的程序猿之一),一定不要只专注于各个框架的使用以及业务的深入,虽然这些事很有必要,但并不是全部。
follow me and go the memory world 吧(语法都是浮云)。

 以上就是JVM内存管理------杂谈(借此也论一论obj=null)的内容,更多相关内容请关注PHP中文网(www.php.cn)!


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