Gibt es eine maximale Array Größe? Weil wenn ich sowas mache:
int[] array = new int[Integer.MAX_VALUE];
Bekomme ich den OutOfMemoryError mit der Meldung " Requested array size exceeds VM limit ". Durch googlen kam ich dann drauf, das die Maximale Array-Größe bei Integer-MAX_Value - 8 liegt (http://stackoverflow.com/questions/3038392/do-java-arrays-have-a-maximum-size). Allerdings geht bei mir die Meldung schon bei -2 weg.
Dafür komt dann aber ne andere Meldung, von wegen “Java Heap Size”. Und die geht auch erst weg, wenn ich "Integer.MAX_VALUE - 1_440_000_000 " schreibe. Aber wenn die max Array Größe drüber liegt, wieso kann ich dann das Array nur so groß machen?
Sowas hat auch nicht geholfen, auch wenns ichs mit -Xms4096m starte. Mach ich irgendwas falsch oder warum kommt das immer?
Xms? Meintest du Xmx? Wie auch immer, Xmx4096m würde nichts bringen: Ein int-Array der Größe Integer.MAX_VALUE würde etwas 8.5GB belegen. Ggf. mal mit Xmx9000m bzw. Xmx9G probieren, aber das besser nur dann, wenn dein PC ensprechend >9 GB RAM hat, sonst kann das langsam werden.
nun, ein int hat eine größe von 32bit, also 4byte
das ganze mal 2^31-1 ergibt insgesamt rund 8GB, darum bekommst du auch eine meldung das dein heap nicht ausreicht wenn du ihn nur 4GB groß machst
ich hab zwar 16GB RAM im system, aber wüsste jetzt nicht wirklich warum ich das mit EINER java-app ausreitzen wollen würde
das man nicht direkt MAX_VALUE nehmen kann hängt ein bisschen von der genutzten VM ab, denn je nach VM kostet auch das array selbst speicher
ich gehe aber mal davon aus das es sowas damit zu tun hat wie :
größe einer objekt-referenz + länge/größe des objektes + daten
würde zumindest erklären warum es bei dir mit MAX_VALUE - 2 funktioniert, wenn man halt die objekt-referenz selbst und dessen “größe” ebenfalls als 32bit int betrachtet (was auch unter einer 64bit VM der fall sein dürfte)
beiwort : warum diese frage immer wieder gestellt wird verstehe ich nicht wirklich, deutet für mich aber einfach auf unwissenheit der fragenden hin, denn man kann in jedem grundlagen-buch nachlesen das java vorzeichenbehaftete 32bit ints für array-indexe nutzt
hat man dies verstanden sollte die antwort eigentlich jedem selbst klar werden : maximal Integer.MAX_VALUE
dann noch diese frage zu stellen zeigt nur das man diese einfach basics scheinbar immer noch nicht verstanden hat
Je nach JVM benötigst du 32 oder 64bit für eine Objektreferenz.
Der Speicher wird bereits beim anlegen des Arrays voll reserviert, nicht erst beim füllen.
Bei einem int-Array von maxmimaler Größe sind das ~8.59 bzw 17.18 GB
Mit dem Wert den du abziehst kommst du auf ~2.83 bzw 5.66GB
Was auch erklärt, warum es bei dem kleinerem Wert mit 4GB zugewiesenem RAM funktioniert.
Gibt es eigentlich eine sinnvolle Anwendung mehr als 2 Milliarden zahlen gleichzeitig in den Memory zu schieben?
Gruß
hab ich jetzt irgendwie voll den rechenfehler drin ? wie kommt ihr auf über 8GB ? also mal von dem unterschied 32bit <-> 64bit abgesehen
aber 2^31-1 = 2147483647
das mal 4 byte macht laut meinem win-calc 8589934588 BYTE = 8388607,99609375 KILO-BYTE = 8191,999996185302734375 MEGA-BYTE = 7,9999999962747097015380859375 GIGA-BYTE
und wenn wir uns den spaß machen das beispiel mal ohne krume zahlen direkt mit 2^31 zu machen kommen wir auch locker auf
2147483648 * 4 byte = 8589934592 Byte = 8388608 KiloByte = 8192 MegaByte = 8 GigaByte
ich lass mich ja gerne korrigieren, aber den gleichen fehler wie die festplatten hersteller zu machen und 8000000000 Byte als 8 GB anstatt korrekterweise 7,45 GB zu verkaufen , bzw ums in diesem beispiel mal umzudrehen und zu sagen das 8589934592 Byte angeblich 8,59 GB , … , ne, sorry, aber von hobby-java-bastlern erwarte ich dann doch ETWAS mehr genauigkeit
Die ints sind zum Glück keine Objektreferenzen (und wenn es welche wären, gäbe es auch noch so einen magischen Schalter, mit dem man sie auf 32bit drücken könnte), also sind es schon nur 8.5GB. Rein technisch funktioniert das, aber mit weniger als 16GB RAM kann man damit seinen PC schön dazu verdonnern, ein paar Minuten lang hilflos-vollausgelastet vor sich hin zu rattern, also … nicht gut … (hab’s gerade probiert ;)). Die Frage, wofür man das braucht, wäre auch interessant, aber bisher bin ich naiverweise davon ausgegangen, dass es schon einen GUTEN Grund gibt, diese Frage zu stellen - rein akademisch oder wegen eines SEHR speziellen Anwendungsfalls, aber beides könnten GUTE Gründe sein
EDIT: @Unregistered : Ob 8 oder 8.5 ist so gesehen wurscht, weil es nur darum ging, dass es mehr als 4 sind, und auf einem PC mit <= 8GB nicht praktikabel sein wird. Ansonsten vielleicht mal nach sowas wie http://en.wikipedia.org/wiki/Gibibyte suchen (ja, es ist Bockmist, aber es IST eben so, und jeder kann sich aussuchen, wie er die Begriffe verwendet: http://xkcd.com/394/ )
[QUOTE=Unregistered]
beiwort : warum diese frage immer wieder gestellt wird verstehe ich nicht wirklich, deutet für mich aber einfach auf unwissenheit der fragenden hin, denn man kann in jedem grundlagen-buch nachlesen das java vorzeichenbehaftete 32bit ints für array-indexe nutzt
hat man dies verstanden sollte die antwort eigentlich jedem selbst klar werden : maximal Integer.MAX_VALUE
dann noch diese frage zu stellen zeigt nur das man diese einfach basics scheinbar immer noch nicht verstanden hat[/QUOTE]
auch nebenher:
Integer.MAX_VALUE hatte Schesam doch auch selber genannt,
wieso man dann -2 oder -5 oder -8 setzen muss ergibt sich ja nun wohl gar nicht aus den Basics,
Speicher-Rechnen naja, wurde ja auch angegangen
Edit: wieder al zu langsam, der Beitrag war @Unregistered
Hab ich da was durcheinander geworfen?
2147483647 bit in
Gigabyte: 10^9 (GB) -> 8.59
Gibibyte: 2^30 (GiB) -> 8
Gruß
@Marc o: was ist denn deiner Meinung nach der Unterschied zwischen Objektreferenzen und Referenzen zu primitiven Typen?
Das compressed-oops flag gilt für Referenzen jeder Art und sind seit Java 6u23 bzw Java 7 per default aktiviert.
[QUOTE=Noctarius]@Marc o:
[/QUOTE]
Wer ist denn dieser ‚Marc‘, der meine Mentions kaputt macht :verzweifel:
Die einen gibt es, die anderen nicht
Was soll denn eine „Referenz zu einem primitiven typen“ sein? In einem int[n]-Array stehen n*4 bytes, ggf. in einem Speicherblock hintereinanderweg. In einem byte[n]-Array entsprechend n bytes. In einem Integer[n]-Array (oder jedem anderen Array mit Objektreferenzen) stehen die Objektreferenzen, und die können 4 oder 8 byte lang sein.
Genau genommen machen es die Speicherhersteller richtig und die Informatiker falsch. Mathematisch findet der Wechsel der Begrifflichkeiten nämlich dezimal gesehen alle drei Zahlenstellen statt (1, 1000, 1000000, …). Dass in der Informatik die 1024er-Schritte auch so genannt werden, ist Mathematisch eigentlich falsch, daher gibt es auch die *ibi-Bezeichnungen. Weiß man das, dann passen die Größenangeben der Speicherhersteller so ziemlich genau (Schwund is bei Speichern leider immer, kaputte Sektoren, Bausteine, etc.) und zumindest im Linux-Umfeld wird auch vermehrt verstärkt drauf geachtet, dass die Bezeichnungen richtig gewählt werden. Will man sonst beim B, MB, GB, … bleiben, muss man sich auf 1000 oder 1024 einigen, damit alle Beteiligten wissen, um welche Größen es nun genau geht.
Was ich da mal wieder ausgelöst hab Der Grund für das war schlicht und ergreifend eine Aufgabe meines Info-Lehrers, ein programm zu erstellen, das minimum 20sek zum für die Ausführung braucht, ohne GUI usw.,einfach nur Konsolenausgabe, und am Ende etwas halbwegs sinnvolles dabei rausbringt. Hab dazu so ne Klasse geschrieben mit 2 Schleifen:
public static void main(String[] args) {
final Random r = new Random();
int einser = 0;
int nuller = 0;
int[] array = new int[Integer.MAX_VALUE - 1_000_000];
System.out.println("For");
for (int i = 0; i < array.length; i++) {
array** = (r.nextInt(2));
}
System.out.println("Switch");
for (int i : array) {
switch (i) {
case 1:
einser++;
break;
case 0:
nuller++;
break;
}
}
System.out.println("Die größe des Arrays ist " + array.length + ".");
System.out.println("Es gibt " + einser + " Einser und " + nuller + " Nuller im Array. "
+ "Es gibt also mehr " + ((einser >= nuller) ? "Einser":"Nuller") + " als " + ((einser >= nuller) ? "Nuller":"Einser") + ".");
boolean test = (array.length - 1) != (nuller + einser);
System.out.println(test);
}
}``` selbst wenn ichs mit -Xmx10G oder -Xms10G starte kommt der Error :D Hab btw 16GB drin, daran solls also nicht liegen
"java -Xmx10G package.Klasse" geb ich in die Kommandozeile ein.
Warum nicht einfach so:
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}```
oder (mehr arbeit für den Thread):
``` long start = System.currentTimeMillis();
while(System.currentTimeMillis()-start < 20000){
;
}```
Gruß
Das ist zwar richtig, trotzdem gibt es die Referenzen In C++ würde man sie Pointer nennen. Die Referenzierung erfolgt im Falle eines Arrays aus primitiven Types über den Array-Index (nicht treten ;-)).
@Firephoenix : weil da dann ja nichts halbwegs sinnvolles ausgegeben wird Bei mir werden zumindest 2 zufällige Zahlen ausgewertet und in jeden Index eine andere Zahl eingesetzt. Damit kann man dann theoretisch feststellen, obs wirklich Random-Zahlen sind. Ändert aber nichts daran, das ich gern wüsste warum das mit der Heap Size nicht geht
Hui, da werden aber Begriffe gedeeehhhnt Entscheidend war ja nur, dass z.B. in einem short[10] eben 10 shorts liegen, und nicht 10 Referenzen auf Short-Objekte. Aber das ist wohl klar bzw. geklärt.
und am Ende etwas halbwegs sinnvolles dabei rausbringt.
@TE: Wie wärs mit Primzahlen und nem unperformanten Algo, da kommste auch auf 20s - und es ist halbwegs sinnvoll (wie sinvoll unperformanter code auch immer sein kann :D)
Oder du suchst halt für 20s lang primzahlen und gibts die aus, man kann ja mehr als eine suchen, dafür muss man dann den code nciht mit absicht langsam machen
Der Grund für das war schlicht und ergreifend eine Aufgabe meines Info-Lehrers, ein programm zu erstellen, das minimum 20sek zum für die Ausführung braucht, ohne GUI usw.,einfach nur Konsolenausgabe, und am Ende etwas halbwegs sinnvolles dabei rausbringt.
Da bietet sich die Ackermannfunktion an.