Java Java.lang.OutOfMemoryError: java heap space

Fleischsalat

Cadet 3rd Year
Registriert
Jan. 2013
Beiträge
48
Hallo zusammen,
ich habe bei einem von mir geschriebenen Programm obige Fehlermeldung bekommen.
Komplette Fehlermeldung:
"A error occured in a file for which the source cannot be found:
class: source line number: sun.reflect.NativeConstructorAccessorImpl: -2:
java.lang.OutOfMemoryError: Java heap space (in sun.reflect.NativeConstructorAccessorImpl )"

Ich benutze BlueJ (bitte nicht damit kommen, dass das schlecht is, mir reichts, ist nur für die Schule).
Hier der Quellcode:

import java.util.*;

public class Modulo10 {
private ArrayList<byte[]> liste;
public Modulo10() {
liste = new ArrayList<byte[]>();
for(byte a = 0; a < 10; a++)
{
for(byte b = 0; b < 10; b++)
{
for(byte c = 0; c < 10; c++)
{
for(byte d = 0; d < 10; d++)
{
for(byte e = 0; e < 10; e++)
{
for(byte f = 0; f < 10; f++)
{
for(byte g = 0; g < 10; g++)
{
for(byte h = 0; h < 10; h++)
{
byte[] feld = new byte[10];
feld[0]=a;
feld[1]=b;
feld[2]=c;
feld[3]=d;
feld[4]=e;
feld[5]=f;
feld[6]=g;
feld[7]=h;
liste.add(feld);
}
}
}
}
}
}
}
}
}
}

Letztendlich werden 10 Milliarden Felder erschaffen, die in einer Arraylist gespeichert werden sollen. (bis jetzt sinds noch nich alle, ich hab nur geschaut wie viel ich wegmachen muss, bis der Fehler nicht mehr auftaucht, jetzt sinds wieder zu viele).
Damit sollen schlussendlich Prüfzifferverfahrn wie die ISBN allgemein gelöst werden können, aber das ist ja hier nicht wichtig (ich finds selber auch nicht so sinnvoll, es ist einfacher sie einzeln zu implementieren, aber mein Infolehrer wills halt....).
Wie kann ich diesen Fehler denn umgehen? Und es sollte auch möglichst leicht auf anderen PCs gehen, denn das Programm ist Teil meiner Facharbeit und muss letztendlich auch auf dem Pc meines Lehrers laufen, wenn der sie dann korrigiert.

Schonmal Danke für die Hilfe

MfG Fleischsalat

PS: ich bin jetzt nicht so der Programmierprofi, mit der Schulinformatik komm ich zwar spielend zurecht, aber das wars dann auch schon, also bitte versuchen einigermaßen verständlich zu antworten, danke ;)
 
Hast du mal ausgerechnet, wie viel Ram dein kleines Stückchen Code da oben frisst, selbst ohne Einberechnung des Overheads? Das wird keine default heap-size einer JVM schhaffen, wenn man sie nicht explizit erhöht. Hast du nicht einen alternativen, weniger exotischen Ansatz? Prüfziffern zu erstellen sind meist nur ein paar wenige Multiplikationen, vor allem bei ISBNs, da stellt sich die Frage, für was du die Tonnen an Speicher benötigst. Ich verstehe, dass du ein generisches Verfahren haben möchtest, aber vielleicht könntest du die Idee dahinter etwas näher erläutern.
 
Zuletzt bearbeitet:
Wow, eine 8-fach-verschachtelte Schleife, sinnlose Arrays... macht euer Info-Lehrer eine Schock-Therapie mit euch mit allen No-Gos der Programmierung? oO


Frag deinen Info-Lehrer am besten nochmal genau, was er möchte... denn das kann er eigentlich nicht wollen...
 
Die meisten Prüfziffern werden über die Modular-Arithmetik berechnet, wenn ich micht nicht täusche ist das auch bei ISBN so.

Was du da tun willst ist mir vollkommen fraglich, aber bei 10 Milliarden Feldern kann dir jetzt schon jeder sagen, dass du aufhören solltest soetwas zu fabrizieren.

Dass der heap Space hierfür nicht ausreicht braucht man dann auch nicht erst durch Try & Error herausfinden.

Hast du überhaupt einen allgemeinen Lösungsansatz für dein Problem?
Wenn ja, poste ihn hier. Anschließend wird sich sicherlich herausstellen wo du falsch abgebogen bist ;-)
 
Ich versteh nicht wozu du eine riesige Liste aus Arrays brauchst. Du solltest dich vermutlich zunächst mit der Mathematik hinter Prüfziffersystemen beschäftigen. Im Endeffekt läuft es stets auf das Lösen einer Gleichung heraus, welche je nach dem was man gerade betrachtet anders ist. Für ISBN10 ist es zum Beispiel diese http://www.wolframalpha.com/input/?i=sum_i=1^10((11-i)*w_i)+mod+11=0 (wolfram alpha, da ich zu faul bin hier mit Fomeln rumzuhampeln). w10 ist die Prüfziffer und muss so gewählt werden, dass die Gleichung auf geht. Das Verfahren ist so wie gesagt für alle Prüfziffersysteme gleich und die entsprechende Kontrollgleichung ist individuell und muss bekannt sein.
Falls du nicht die Prüfziffer berechnen, oder prüfen willst ob eine Folge Teil des Codes ist musst du dich nochmal erklären. Wie mib schon sagt, kann das was du da fabrizierst nicht die Lösung sein.
 
Ja, mir ist durchaus klar, dass das ein ziemlich aufwändiger Ansatz ist.
Zum Verständnis:
Ich bin am Gymnasium, 11. Klasse, muss also auch eine Facharbeit/Seminararbeit schreiben.
Mein Thema beinhaltet unter anderem ein Programm, dem du eine Prüfziffer gibts und diese dir sagt welches Verfahren angewendet wurde (ISBN, EAN, Eurobanknoten, was auch immer).
Dazu habe ich bereits ein, in meinen Augen ausreichendes Programm geschrieben, das 15 der häufigsten Verfahren beeinhaltet. (falls es Interesse gibt, diese Seite ist nicht schlecht: pruefziffernberechnung.de)

Mein Lehrer hat sich jedoch in den Kopf gesetzt / täte es toll finden, wenn man einen allgemeinen Algorithmus für hier 10stellige Prüfzifferverfahren ( sehen letztendlich so aus: a1 * x1 + a2 * x2 + a3 * x3 + ..... + a10 * x10* modulo 10 = 0) zu implementieren. Die x1 - x10 sind eine Prüfziffer, die übergeben wird, die a1 - a 10 sind eins der 10 Milliarden Felder, nach 10 übergebenen Prüfziffern ist eine eindeutige Auswahl möglich.

Zur Berechnung des benötigten Speicherplatzes (hätt ich vorhermachen sollen:( ):
32bit * 10 * 10 000 000 000 = 3,2 * 10^12 bit; = 4*10^11 byte; = 400 gigabyte; stimmt so? 32bit sind ein int, 10 weil 10 int pro Feld, 10 000 000 000 weil so viele Felder.
Gut, sollte das richtig sein ist dieser Ansatz eh Geschichte.
 
Zuletzt bearbeitet:
Die Berechnung stimmt.
Du möchtest also anhand einer 10-stelligen Zeichenfolge bestimmen welches Verfahren angewendet wurde? Es kann sein, dass ich etwas übersehen habe, aber das halte ich für nicht möglich. Die Koeffizienten a_i sind schließlich nicht eindeutig bestimmbar, oder doch?
 
Naja, ich hab ein Gleichungssystem mit 10 Unbekannten, d.h. dass ich mindestens 10 Gleichungen, also 10 richtige Zahlen brauche um ein eindeutiges Ergebnis zu kriegen.
Naja, das sagt zumindest mein Lehrer, der hat unteranderem Mathe studiert, mit nem Doktor, also vertrau ich dem mal dass das stimmt, selber hab ich um ehrlich zu sein weniger Ahnung (mit so was beschäftigt man sich nicht in der Schule und in meiner Freizeit hab ich ehrlichgesagt besseres zu tun ;-) ), aber das sollte so stimmen.

Nachdem das mit allem Speichern nicht geht, habe ich mir überlegt, das in eine Methode mitreinzuschreiben, also immmer ein Feld erstellen, prüfen ob es passt, wenn nein, dann nächstes, wenn ja, dann speichern. Um auf einen realistischen Wert zu kommen, müsste ich 3 wahre Zahlen übergeben, dann sind noch 400 MB Speicherplatz nötig.

Gibt es also eine Möglichkeit, Java diese 400MB zuzuweisen? Google hat mir erzählt, dass es geht, allerdings nur an Beispielen von Eclipse oder andren Programmen, ich bräuchte es halt für BlueJ (und in einer Verständlichen Ausführung, bei Englischen Fachgesprächen steig ich leider aus).

MfG
 
Um den Java Heap Space zu erweitern musst du beim Aufrufen selbiger die entsprechende Option mitgeben.
Ob BlueJ in der Lage ist diese Argumente weiterzugeben weiß ich nicht, ich selbst war lange Zeit Eclipse Nutzer und mittlerweile zu IntelliJ gewechselt.

Du kannst jedoch mit dem JDK deinen Code selbst kompilieren und Aufrufen, spätestens dort kannst du dann also den entsprechenden Parameter hinzufügen.

Dein Ansatz zur Lösung der Gleichung wirkt mir auf den ersten Blick nach ziemlichen Brute-Force.. falls das so ist viel Erfolg.

Alles in allem halte ich das Problem aber so erstmal nicht lösbar nach dem was ich gelesen habe. Lasse mich bei geeignetem Verfahren aber auch gerne überzeugen. Brute-Force ist für mich aber nie ein Verfahren.
 
Und was hat das Gleichungssystem damit zu tun, dass du 10^10 Einträge in eine Array legen musst? oO

Du kannst ja testen, ob die Werte passen, auch ohne sie ins Array zu legen ... aber ich weiß, die Idee wäre verrückt...
 
Fleischsalat schrieb:
Naja, ich hab ein Gleichungssystem mit 10 Unbekannten, d.h. dass ich mindestens 10 Gleichungen, also 10 richtige Zahlen brauche um ein eindeutiges Ergebnis zu kriegen.
Das könnte man im ersten Moment vermuten. Das Problem ist aber, dass der linke Term eben nicht "gleich" 0 ist sondern nur "kongruent" 0 mod 10. Mit anderen Worten kann er 0, 10, 20, 30, ... liefern und es passt trotzdem. Es gibt unendlich viele Lösungen (da bestimmte Bedingungen an die a_i gestellt werden sind es hier sicher endlich viele, aber weit mehr als eine).

Beispiel:
1 2 3 4 5 6 6 7 8 6 ist der Code
1 1 1 1 1 3 1 1 1 1 eine Möglichkeit für die a_i. Das ergibt 60 und ist mod 10 = 0
3 3 1 1 1 1 1 1 3 1 andere Möglichkeit. Das ergibt 70 und ist mod 10 = 0
 
Zuletzt bearbeitet: (Beispiel leicht überarbeitet)
Also,
@1668mib:
1. Das Gleichungssystem hat insofern mit der Arraylist zu tun, dass es beweißt, dass eine Eindeutige zuordnung theoretisch möglich ist, wenn du mir sagst wie ich das auch so in Java umsetzen kann, dann
2. So in etwa mein ich es ja auch in meinen 2. Vorschlag, da der erste zu viel Speicher braucht ;) , ich speicher halt nur die Felder, die zutreffen, womit sich pro eingegebener Zahl, die Anzahl der Felder um eine Stelle verringern sollte (bei 3 eingegebenen Zahlen also nur noch 10 Millionen Felder, was 400 MB Speicherplatz benötigen würde, was jetzt eher weniger ein Problem sein sollte).
@Keepers:
Ja, dass man den Heap Space irgendwie erhöhen kann, hab ich gehört, jedoch wie?
Google sagt mir das:

Bei BlueJ musst du die VM Argumente wohl von Hand in der bluej.defs im lib-Verzeichnis eintragen, um den Speicher zu erhöhen:
bluej.vm.args=-Xmx1024m

Weißt du, oder wer anders, wo ich das Verzeichnis finde?

MfG

Und zu Freezedevil:
Da ich ja verschiedene Zahlen eingebe fallen ja einige weg, bei deinem Beispiel wenn ich jetzt noch zusätzlich
1 3 2 4 5 6 6 7 8 6
eingebe fällt die 2. Möglichkeit ja weg, da nun 72 rauskommt, was nicht = 0 mod 10 ist.
Falls es missverständlich war: ich brauche 10 Zahlen, die allesamt mit den gleichen Vorfaktoren multipliziert = 0 mod 10 sind, dann sollte eine eindeutige Lösung herauskommen.
 
Zuletzt bearbeitet: (Neuer Post)
Ehrlich gesagt versteh ich nicht so recht was du vor hast. Ich hab es so verstanden, dass du eine Zeichenfolge auf die du keinen Einfluss hast wie im Beispiel 1 2 3 4 5 6 6 7 8 6 bekommst und jetzt herausfinden sollst ob das ISBN, EAN oder sonst was ist. Das kannst du ja meiner Meinung nach nur über die a_i. Was genau ist an meinem Beispiel jetzt ungültig, bzw. was hab ich an der Aufgabenstellung falsch verstanden?
 
Ja, ich habe keinen Einfluss auf die Zeichenfolge, ich muss halt nur 10 Zeichenfolgen bekommen, z.b. 10 verschiedene EANs wenn sie halt 10 lang wären..., sonst hast du recht und es ist keine eindeutige Zuordnung möglich.
 
Man könnte sich auch andere Datenstrukturen überlegen, aber ich versteh nach wie vor den Sinn des Arrays nicht ...

Und die Fragestellung genauso wenig ^^
 
Ja, hab jetzt mal alles in eine Methode gepackt,
die is aber bissl zu lang, um hier reingepostet zu werden, zum testen hatte ich außerdem noch keine Zeit, prüft jetzt halt gleich, welche Zahlenfolge von den 10 Milliarden in Frage kommt, und gibt die dann aus.
 
Sorry, hab gedacht ich hätte einen Fehler, hab aber während dem Schreiben gemerkt, dass ich beim eingeben einen fehler gemacht hab, sollte der danach noch da sein meld ich mich nochmal :)

MfG
 
Zuletzt bearbeitet:
10 Milliarden Felder, die je 10 Byte lang sind, belegen zusammengenommen 100 Gigabyte Speicherplatz. Bevor du da mit "Heapgröße erhöhen" was wirst, musst du erst mal den RAM deines Rechners aufrüsten, und zwar gewaltig :D
 
@NullPointer: Wieso? Hat halt die virtuelle Speicherverwaltung einiges zu tun...
 
Zurück
Oben