Q : Comment une fuite de mémoire peut-elle se produire en Java ?
R : En Java, les fuites de mémoire peuvent avoir de nombreuses causes. Un exemple typique est une classe Key qui n'implémente pas les méthodes hasCode et
equals et est enregistrée dans un HashMap. Au final, de nombreux objets en double seront générés. Toutes les fuites de mémoire
finiront par lever une exception OutOfMemoryError. Ce qui suit est un bref exemple de simulation d'une fuite de mémoire
via une boucle infinie.
import java.util.HashMap; import java.util.Map; public class MemoryLeak { public static void main(String[] args) { Map<Key, String> map = new HashMap<Key, String>(1000); int counter = 0; while (true) { // creates duplicate objects due to bad Key class map.put(new Key("dummyKey"), "value"); counter++; if (counter % 1000 == 0) { System.out.println("map size: " + map.size()); System.out.println("Free memory after count " + counter + " is " + getFreeMemory() + "MB"); sleep(1000); } } } // inner class key without hashcode() or equals() -- bad implementation static class Key { private String key; public Key(String key) { this.key = key; } } //delay for a given period in milli seconds public static void sleep(long sleepFor) { try { Thread.sleep(sleepFor); } catch (InterruptedException e) { e.printStackTrace(); } } //get available memory in MB public static long getFreeMemory() { return Runtime.getRuntime().freeMemory() / (1024 * 1024); } }
Les résultats sont les suivants :
map size: 1000 Free memory after count 1000 is 4MB map size: 2000 Free memory after count 2000 is 4MB map size: 1396000 Free memory after count 1396000 is 2MB map size: 1397000 Free memory after count 1397000 is 2MB map size: 1398000 Free memory after count 1398000 is 2MB map size: 1399000 Free memory after count 1399000 is 1MB map size: 1400000 Free memory after count 1400000 is 1MB map size: 1401000 Free memory after count 1401000 is 1MB ..... ..... map size: 1452000 Free memory after count 1452000 is 0MB map size: 1453000 Free memory after count 1453000 is 0MB Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.HashMap.addEntry(HashMap.java:753) at java.util.HashMap.put(HashMap.java:385) at MemoryLeak.main(MemoryLeak.java:10)
Q : Comment résoudre la fuite de mémoire ci-dessus ?
A : Implémentez les méthodes equals et hasCode de la classe Key.
..... static class Key { private String key; public Key(String key) { this.key = key; } @Override public boolean equals(Object obj) { if (obj instanceof Key) return key.equals(((Key) obj).key); else return false; } @Override public int hashCode() { return key.hashCode(); } } .....
La réexécution du programme obtiendra les résultats suivants :
map size: 1 Free memory after count 1000 is 4MB map size: 1 Free memory after count 2000 is 4MB map size: 1 Free memory after count 3000 is 4MB map size: 1 Free memory after count 4000 is 4MB ... Free memory after count 73000 is 4MB map size: 1 Free memory after count 74000 is 4MB map size: 1 Free memory after count 75000 is 4MB
Q : Dans des scénarios réels, comment trouvez-vous les fuites de mémoire ?
A : Obtenez l'ID du fil via le code suivant
C:\>jps 5808 Jps 4568 MemoryLeak 3860 Main
Ouvrez jconsole via la ligne de commande
C:\>jconsole 4568
La classe Key qui implémente hasCode et égal et le graphique sans implémentation sont les suivants :
Aucune fuite de mémoire :
Provoquant une fuite de mémoire :
Plus de Java Pour les articles liés aux problèmes typiques de fuite de mémoire et aux solutions, veuillez prêter attention au site Web PHP chinois !