2016-10-12 2 views
6

Ich versuche, ein Programm zu schreiben, das Speicher einer bestimmten Größe verbrauchen sollte. Ein Problem, das ich mich wundere, ist, dass ich outOfMemory Ausnahme bekomme, wenn es tatsächlich einen freien Platz im Haufen gibt. HierKann nicht gesamten Speicher verbrauchen

ist der Code:

import java.util.Vector; 
import java.lang.*; 

public class MemoryEater1 { 
    public static void main(String[] args) { 
    try { 
     long mb = Long.valueOf(args[0]); 
     Vector v = new Vector(); 
     Runtime rt = Runtime.getRuntime(); 
     while (true) { 
      if (v.size() > 0) { 
       if (((long) v.size())*100 < mb) { 
        System.out.println("total memory: " + rt.totalMemory()/1024/1024); 
        System.out.println("max memory: " + rt.maxMemory()/1024/1024); 
        System.out.println("free memory: " + rt.freeMemory()/1024/1024);       
        System.out.println("Trying to add 100 mb");     
        //100mb 
        byte b[] = new byte[104857600]; 
        v.add(b); 
       } 
      } else { 
       //100mb 
       byte b[] = new byte[104857600]; 
       v.add(b); 
       System.out.println("Added 100 mb");    
      } 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    } 
} 

Der Befehl zum Starten:

java -Xmx4096m MemoryEater1 3000 

Und die Ausgabe:

total memory: 2867 
max memory: 3641 
free memory: 59 
Trying to add 100 mb 
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 
     at MemoryEater1.main(MemoryEater1.java:18) 

Nun ist der Unterschied zwischen Max-Speicher und Gesamtspeicher ist 774mb, was genug sein sollte, um 100mb mehr zu verbrauchen, aber immer noch gibt es den Fehler und sogar die Maschinenresourcen es sind genug genug:

[[email protected] ~]$ free -m 
      total  used  free  shared buffers  cached 
Mem:   15950  3447  12502   0  210  2389 
-/+ buffers/cache:  847  15102 
Swap:   4031 1759218603  8941 

Warum kann das sein?

+6

Haben Sie bemerkt, dass freier Speicher niedriger als 100 MB ist? – Stephan

+3

Wenn Sie große Arrays zuweisen, besteht immer das Risiko, dass die JVM keinen großen zusammenhängenden Block für Sie finden kann, selbst wenn noch Platz übrig sein soll. –

+2

@Stephan Das wäre nur relevant, wenn 'totalMemory' bereits auf' maxMemory' erweitert wurde. –

Antwort

1

Ich glaube nicht, dass es Fragmentierung ist, da Sie nur einen Thread haben, der Speicher reserviert und nichts zurückfordert.

Es ist Ihre besondere Müllabfuhr, die Schuld zu geben, sie verwalten den Speicher anders, was dazu führt, dass mehr oder weniger für Ihre App nicht verfügbar ist. Sie können herausfinden, welcher verwendet wird, indem Sie die Ausgabe von java -XX:+PrintCommandLineFlags analysieren).

Sie können versuchen, G1 zu verwenden, das Speicher anders verwaltet.

java -Xmx4096m -XX:+UseG1GC MemoryEater1 3000 

Oder spielen mit Generationsgrößen z. -XX:NewSize und so weiter.

Für weitere Informationen lesen Sie VM options und alles auf Garbage-Collector-Algorithmen, z. [GC tuning]

Hier ist eine kurze Darstellung, wie die Aufteilung von Speicher für verschiedene Generationen es nicht verfügbar machen kann (http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html). Memory layout

+0

Es sieht so aus, als hätte keiner der großen Arrays seinen Gültigkeitsbereich verlassen und daher keine Möglichkeit zur Speicherbereinigung. – Brick

+0

Sein Code ist Design, um alles außer Kontrolle zu halten. – AxelH

0

Es ist möglich, die JVM-Flags für einen größeren Arbeitsspeicher als den physischen Arbeitsspeicher auf Ihrem Computer festzulegen. Mit den bis jetzt gegebenen Informationen scheint es am wahrscheinlichsten, dass Ihnen der physische Speicher fehlt, um dieses Array zuzuweisen. Mit anderen Worten fordert die JVM mehr Speicher von dem OS an und das OS sagt, dass es nichts zu geben gibt.

Eine andere Möglichkeit ist das Problem der Speicherfragmentierung, das in den Kommentaren zu Ihrer Frage erwähnt wird. Ich denke jedoch, dass dies in diesem Fall wegen der Struktur Ihres Programms weniger wahrscheinlich ist. Ich denke aber nicht, dass das ausgeschlossen werden kann.

Verwandte Themen