2016-02-25 5 views
6

ich ein Programm, wo ich ein sehr großen short[] Array werden:Java erfordert größeren Heap-Speicher als das, was vernünftig ist

import java.lang.Math; 

public class HPTest { 

    public static void main(String[] args) { 
     int n = 30; 
     short[] a = new short[(int)Math.pow(2,n)]; 
    } 
} 

Soweit ich weiß, ein short[] Array 2 Bytes pro Element verwendet werden soll, und so ein Array mit 2^30 Elementen sollte etwa 2 GiB RAM benötigen.

Um das Programm auszuführen, habe ich versucht deshalb

java -Xms2000m HPTest 

aber immer noch einen Heap-Speicher Fehler bekam. Sogar bei 3000m habe ich den gleichen Fehler, aber bei 4000m hat es funktioniert.

Irgendwelche Ideen, warum ich so weit über die geschätzte Grenze von 2000m gehen musste?

EDIT: Wie von vielen Benutzern darauf hingewiesen wurde, machte ich einen sehr peinlichen Fehler bei der Erklärung, dass eine kurze braucht 1 Byte statt 2 Bytes. Die Frage sollte dann sein, warum es mit 2000m nicht ausreicht.

+7

short ist 2 Bytes ... –

+1

Ein 'Byte' ist ein Byte, daher der Name. Btw '1 << n' ist eine effizientere Methode, um 2 zu berechnen. –

+0

Trotzdem sollte 3000m/3GB für ihn genug sein? –

Antwort

5

Etwas so groß, wird viel glücklicher außerhalb des Heaps sein. Sie würden besser in NIO suchen und direkte Bytepuffer verwenden, um Ihr großes Short-Array zu sichern. Dieser Speicher kann außerhalb des Heapspeichers und von den Handschuhen des Garbage Collectors entfernt sein (der sich manchmal geneigt fühlen könnte, den Puffer von einem Bereich in den anderen zu kopieren).

Sehen Sie java.nio.ShortBuffer und fangen Sie an, von dort zu graben.

+0

Danke! Bei einem zweiten Gedanken könnte ich in der Lage sein, zu einem Byte-Array zu wechseln.Wie auch immer, ich werde das Array im Grunde als ein Array von Flags verwenden, die verschiedenen Containern mit allen Ganzzahlen von 0 bis 2^30-1 entsprechen. Wenn ich diese Ganzzahlen durchlaufe, setze ich deshalb das Flag auf den entsprechenden Index meines Kurz/Byte-Arrays auf einen bestimmten Wert. Soweit ich das sehen kann, kann ich dies erreichen, indem ich put() jedesmal auf den Pufferspeicher bringe. Wäre das sehr langsam? –

+0

Tatsächlich werden Zuweisungen, die so groß sind, direkt in den Pool "Old Gen" verschoben und nicht vom Garbage Collector kopiert. Ich habe das nur empirisch getestet, um wahr zu sein, und ich kann mich erinnern, dass ich das irgendwo gelesen habe, aber ich habe zu diesem Zeitpunkt keine Referenz. – Andreas

+0

@AlexandreVandermonde Wenn es sich nur um Flags handelt, sollten Sie es zu einem 'booleschen' Array machen, und die JVM kann 8 booleans in ein einzelnes Byte komprimieren. – Andreas

Verwandte Themen