Pour éviter les fuites de mémoire, j'ai répertorié autant que je sache quand le ramasse-miettes fonctionne et quand il ne fonctionne pas.
Une fonction qui détruit automatiquement un objet à la discrétion de Java lorsqu'il n'est plus géré par aucune variable. La "méthode finalize ()" détruit l'objet, mais en Java, même si cette méthode est définie, le timing ne peut pas être géré.
Depuis que je l'ai confirmé avec un processus simple, j'ai réduit la zone de tas pour faciliter les fuites de mémoire. (Comme une fuite de mémoire à 2M) Taille initiale du tas-Xms1m Taille maximale du tas-Xmx2m
Puisque "assigner null à une variable = la variable ne représente aucun objet", cela fonctionne lorsque toutes les variables représentant un certain objet deviennent nulles. Substitute null = C'est comme dire "Je ne l'utilise plus", donc Garbage Collection le jugera inutile.
public class AddList01 {
public static void main(String[] args) {
//Processus 1
List<String> list1 = new ArrayList<>();
addList(list1);
list1 = null;
//Processus 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");
}
}
}
Le garbage collection fonctionne lorsque la variable qui gère l'objet n'est plus répertoriée. "J'ai vu toute la source, mais elle n'est plus gérée, donc c'est normal de jeter le contenu."
public class AddList02 {
public static void main(String[] args) {
List<String> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
//Processus 1
for (int i = 0; i < 100000; i++) {
list1.add("a");
}
//Processus 2
for (int i = 0; i < 100000; i++) {
list2.add("b");
}
}
}
Le garbage collection fonctionne lorsqu'un objet terminé dans une boucle, tel que déclaré dans une boucle ou instancié, quitte la boucle. En effet, les variables déclarées à l'intérieur de la boucle ne peuvent pas être gérées en dehors de la boucle.
public class AddList03 {
public static void main(String[] args) {
try {
//Processus 1
for (int i = 0; i < 10; i++) {
List<String> list1 = new ArrayList<>();
for (int j = 0; j < 100000; j++) {
list1.add("a");
}
}
//Processus 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");
}
}
//Processus 3
int i = 0;
while (i < 10) {
List<String> list3 = new ArrayList<>();
for (int j = 0; j < 100000; j++) {
list3.add("c");
}
i++;
}
//Processus 4
List<String> list4 = new ArrayList<>();
for (int j = 0; j < 100000; j++) {
list4.add("d");
}
} catch (Exception e) {
e.printStackTrace();
}
//Processus 5
List<String> list5 = new ArrayList<>();
for (int j = 0; j < 100000; j++) {
list5.add("e");
}
}
}
Au fait, si la variable "list2" est gérée après la boucle, il ne reste que la dernière instance de boucle.
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));
}
}
C'est le même principe que la boucle de ③. Cependant, la valeur référencée par l'argument et la valeur de retour restent.
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");
}
}
}
Dans le cas (2) qui fonctionne, l'objet qui n'est plus géré a été ignoré, mais si vous faites référence à l'objet avec une autre méthode, le garbage collection ne fonctionnera pas. Pourquoi est-ce?
public class AddList05 {
public static void main(String[] args) {
//Processus 1
List<String> list1 = new ArrayList<>();
addList(list1);
//Processus 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");
}
}
}
Puisqu'il est utilisé à divers endroits de la classe, c'est un cas où il est décrit dans le champ afin qu'il n'y ait pas beaucoup d'arguments. Il semble que la portée de la liste soit trop large pour décider que le garbage collection est inutile.
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();
//Processus 1
for (int i = 0; i < 100000; i++) {
addList06.list1.add("a");
}
//Processus 2
for (int i = 0; i < 100000; i++) {
addList06.list2.add("a");
}
}
}
Même si la méthode principale ne crée pas d'instance, celle qui est créée par la méthode appelée et reçue comme valeur de retour reste.
public class AddList07 {
public static void main(String[] args) {
//Processus 1
List<String> list = addList();
//Processus 2
list = addList();
//Processus 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;
}
}
Même si vous utilisez la méthode list pour supprimer des valeurs qui ne sont plus utilisées dans la liste que vous utilisez, l'objet semble rester référencé car il n'est pas nul.
public class AddList08 {
public static void main(String[] args) {
//Processus 1
List<String> list1 = new ArrayList<>();
addList(list1);
list1.clear();
//Processus 2
List<String> list2 = new ArrayList<>();
addList(list2);
for (int i = 0; i < list2.size(); i++) {
list2.remove(i);
}
//Processus 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");
}
}
}
Vous pourriez penser que ce n'est pas si simple, mais pour le moment ・ "Autant que possible, divisez le traitement en petites parties par méthode et ayez-le localement" ・ "Utilisez là où vous pouvez réutiliser sans créer de variables et d'instances en vain" ・ "Veuillez ne pas déclarer de variables dans le champ" J'ai ressenti cela.
Après cela, s'il y a un traitement tel que l'acquisition SQL et l'enregistrement à partir de DB, sera-t-il divisé en fonction du but du traitement? Cela peut prendre du temps s'il y a plusieurs SQL, mais je pensais que c'était mieux que le ralentissement du traitement.
Recommended Posts