Um Speicherlecks zu vermeiden, habe ich meines Wissens aufgelistet, wann die Speicherbereinigung funktioniert und wann nicht.
Eine Funktion, die ein Objekt nach Java-Ermessen automatisch zerstört, wenn es von keiner Variablen mehr verarbeitet wird. Die "finalize () -Methode" zerstört das Objekt, aber in Java kann das Timing nicht verwaltet werden, selbst wenn diese Methode definiert ist.
Da ich es mit einem einfachen Vorgang bestätigt habe, habe ich den Heap-Bereich verkleinert, um Speicherlecks zu vermeiden. (Wie Speicherverlust bei 2M) Anfangsgröße von heap-Xms1m Maximale Heap-Größe - Xmx2m
Da "einer Variablen Null zuweisen = die Variable kein Objekt darstellt", funktioniert dies, wenn alle Variablen, die ein bestimmtes Objekt darstellen, null werden. Substitute null = Es ist so, als würde man sagen "Ich benutze das nicht mehr", also wird Garbage Collection beurteilen, dass es unnötig ist.
public class AddList01 {
public static void main(String[] args) {
//Prozess 1
List<String> list1 = new ArrayList<>();
addList(list1);
list1 = null;
//Prozess 2
List<String> list2 = new ArrayList<>();
addList(list2);
list2 = null;
}
private static void addList(List<String> list) {
for (int i = 0; i < 100000; i++) {
list.add("a");
}
}
}
Die Speicherbereinigung funktioniert, wenn die Variable, die das Objekt verarbeitet, nicht mehr aufgeführt ist. "Ich habe die ganze Quelle gesehen, aber sie wird nicht mehr verarbeitet, daher ist es in Ordnung, den Inhalt wegzuwerfen."
public class AddList02 {
public static void main(String[] args) {
List<String> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
//Prozess 1
for (int i = 0; i < 100000; i++) {
list1.add("a");
}
//Prozess 2
for (int i = 0; i < 100000; i++) {
list2.add("b");
}
}
}
Die Speicherbereinigung funktioniert, wenn ein abgeschlossenes Objekt in einer Schleife, z. B. in einer Schleife deklariert oder instanziiert, die Schleife verlässt. Dies liegt daran, dass innerhalb der Schleife deklarierte Variablen nicht außerhalb der Schleife verarbeitet werden können.
public class AddList03 {
public static void main(String[] args) {
try {
//Prozess 1
for (int i = 0; i < 10; i++) {
List<String> list1 = new ArrayList<>();
for (int j = 0; j < 100000; j++) {
list1.add("a");
}
}
//Prozess 2
List<String> list2 = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list2 = new ArrayList<>();
for (int j = 0; j < 100000; j++) {
list2.add("b");
}
}
//Prozess 3
int i = 0;
while (i < 10) {
List<String> list3 = new ArrayList<>();
for (int j = 0; j < 100000; j++) {
list3.add("c");
}
i++;
}
//Prozess 4
List<String> list4 = new ArrayList<>();
for (int j = 0; j < 100000; j++) {
list4.add("d");
}
} catch (Exception e) {
e.printStackTrace();
}
//Prozess 5
List<String> list5 = new ArrayList<>();
for (int j = 0; j < 100000; j++) {
list5.add("e");
}
}
}
Übrigens, wenn die Variable "list2" nach der Schleife behandelt wird, bleibt nur die letzte Schleifeninstanz übrig.
public class AddList031 {
public static void main(String[] args) {
List<String> list2 = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list2 = new ArrayList<>();
for (int j = 0; j < 50000; j++) {
list2.add("b");
}
}
System.out.println(String.join("", list2));
}
}
Es ist das gleiche Prinzip wie die Schleife von ③. Der Wert, auf den sich das Argument bezieht, und der Rückgabewert bleiben jedoch erhalten.
public class AddList04 {
public static void main(String[] args) {
addList();
addList();
addList();
}
private static void addList() {
List<String> list = new ArrayList<>();
for (int j = 0; j < 100000; j++) {
list.add("a");
}
}
}
In Fall (2), der funktioniert, wurde das Objekt, das nicht mehr behandelt wird, verworfen. Wenn Sie jedoch mit einer anderen Methode auf das Objekt verweisen, funktioniert die Garbage Collection nicht. Warum ist das?
public class AddList05 {
public static void main(String[] args) {
//Prozess 1
List<String> list1 = new ArrayList<>();
addList(list1);
//Prozess 2
List<String> list2 = new ArrayList<>();
addList(list2);
}
private static void addList(List<String> list) {
for (int i = 0; i < 100000; i++) {
list.add("a");
}
}
}
Da es an verschiedenen Stellen in der Klasse verwendet wird, wird es im Feld beschrieben, sodass es nicht viele Argumente gibt. Der Umfang der Liste scheint zu groß zu sein, um zu entscheiden, dass die Speicherbereinigung nicht erforderlich ist.
public class AddList06 {
private List<String> list1 = new ArrayList<>();
private List<String> list2 = new ArrayList<>();
public static void main(String[] args) {
AddList06 addList06 = new AddList06();
//Prozess 1
for (int i = 0; i < 100000; i++) {
addList06.list1.add("a");
}
//Prozess 2
for (int i = 0; i < 100000; i++) {
addList06.list2.add("a");
}
}
}
Auch wenn die Hauptmethode keine Instanz erstellt, bleibt diejenige erhalten, die von der aufgerufenen Methode erstellt und als Rückgabewert empfangen wird.
public class AddList07 {
public static void main(String[] args) {
//Prozess 1
List<String> list = addList();
//Prozess 2
list = addList();
//Prozess 3
list = addList();
}
private static List<String> addList() {
List<String> list = new ArrayList<>();
for (int i = 0; i < 50000; i++) {
list.add("a");
}
return list;
}
}
Selbst wenn Sie die Listenmethode verwenden, um Werte zu löschen, die in der von Ihnen verwendeten Liste nicht mehr verwendet werden, scheint das Objekt weiterhin referenziert zu werden, da es nicht null ist.
public class AddList08 {
public static void main(String[] args) {
//Prozess 1
List<String> list1 = new ArrayList<>();
addList(list1);
list1.clear();
//Prozess 2
List<String> list2 = new ArrayList<>();
addList(list2);
for (int i = 0; i < list2.size(); i++) {
list2.remove(i);
}
//Prozess 3
List<String> list3 = new ArrayList<>();
addList(list3);
}
private static void addList(List<String> list) {
for (int i = 0; i < 50000; i++) {
list.add("a");
}
}
}
Du denkst vielleicht, es ist nicht so einfach, aber vorerst ・ "Teilen Sie die Verarbeitung so weit wie möglich nach Methoden in kleine Teile und lassen Sie sie lokal ausführen." ・ "Verwenden Sie diese Option, wenn Sie sie wiederverwenden können, ohne vergeblich Variablen und Instanzen zu erstellen." ・ "Bitte deklarieren Sie keine Variablen im Feld" Ich fühlte, dass.
Wenn danach eine Verarbeitung wie SQL-Erfassung und Registrierung von DB erfolgt, wird diese nach Verarbeitungszweck aufgeteilt? Es kann einige Zeit dauern, wenn mehrere SQLs vorhanden sind, aber ich dachte, es wäre besser als die Verlangsamung der Verarbeitung.
Recommended Posts