Frage

Ich erhalte OutOfMemoryError: java heap

Schnipsel des Verfahrens:

{
// step 1: I am creating a 2 dim array
  int totalCombination = (int) Math.pow(2.0, (double) vowelCount);
// here vowelCount > 10

// step2: initializing my array
// step3: and using that array
}

Meine Frage:

jedes Mal diese Methode aufgerufen wird, das Array erstellt zu werden. Ist es möglich, dass das Array wird nicht freigegeben zu werden.

In Windows Taskmanager i Speicher von Java verwendet sehen kann, ist rein inkrementell. So ist es nicht, dass Größe an einem Punkt Haufen kleiner, aber Speicher wird wiederholt verwendet und nicht irgendwie freigegeben.

Bitte lassen Sie mich wissen, wenn Sie mehr detal benötigen.

Bitte helfen Sie, den Fehler zu debuggen.

Anuj

Der Teil des Codes, die den Fehler verursachen könnten:

int totalCombination = (int) Math.pow (2,0, (double) vowelCount);

    int lookupArray[][] = new int[totalCombination][vowelCount];

    // initialize lookupArray

    for (int i = 0; i < totalCombination; i++) {
        for (int j = 0; j < vowelCount; j++) {
            lookupArray[i][j] = 0;
        }
    }

    // populate lookupArray
    //vowelCount : number of vowels in a word
    // if count is 2, then array will contain 00,01,10,11

    for (int i = 1; i < totalCombination; i++) {
        for (int c = 0; c < vowelCount; c++) {
            lookupArray[i][c] = lookupArray[i - 1][c];
        }
        boolean flag = true;
        for (int j = vowelCount - 1; j >= 0 && flag; j--) {
            if (lookupArray[i - 1][j] == 1) {
                lookupArray[i][j] = 0;
            } else if (lookupArray[i - 1][j] == 0) {
                lookupArray[i][j] = 1;
                flag = false;
            }
        }
    }


  // this part total combination of a word having different combination of vowels in it.


    for (int i = 0; i < totalCombination; i++) {
        int vcount = vowelCount - 1;
        StringBuffer stringBuffer = new StringBuffer();

        for (int j = 0; j < word.length(); j++) {
            if (wordArr[j] == 'a' || wordArr[j] == 'e' || wordArr[j] == 'i'
                    || wordArr[j] == 'o' || wordArr[j] == 'u') {
                if (lookupArray[i][vcount] == 1) {
                    stringBuffer.append(wordArr[j]);
                }
                vcount--;
            } else {
                stringBuffer.append(wordArr[j]);
            }
        }
War es hilfreich?

Lösung

Zweierpotenzen wächst exponentiell. Wenn vowelCount hoch ist, ein Array allein könnte leicht dazu führen OutOfMemoryError (2^32 = 4GB).

Sie können versuchen, Ihren VM maximalen Speicherbedarf zu optimieren (z -Xmx512m), aber nicht erkennen, dass Ihr Algorithmus erfordert eine Menge Speicher . Sie können einen besseren Algorithmus, wenn überhaupt möglich finden möchten.


Siehe auch


Nach bearbeiten: So wie ich erwartet habe, sind Sie eine riesige Auswahl mit allen binären Möglichkeiten gefüllt zu erzeugen. Sie müssen nur selten tatsächlich im Speicher diese ganze Array speichern. Sie können einfach jede mögliche Kombination "on-the-fly" erzeugen und ihn an, wer braucht die 0 und 1 "just-in-time".

Do beachten Sie, dass dies immer noch ein exponentielles Wachstum ist, so dass, obwohl Sie die Pflege Ihrer Speicherbedarf von O(2^N) nur O(N) genommen haben, Ihre Zeit Komplexität ist noch O(2^N).

  

jedes Mal diese Methode aufgerufen wird, das Array erstellt zu werden. Ist es möglich, dass das Array wird nicht freigegeben zu werden.

Ja, das ist sehr gut möglich, wenn der Verweis auf das Array immer durchgesickert ist, und dann irgendwo etwas hält auf diese Referenz. Der Garbage Collector kümmert sich nicht wirklich das, was Sie denken ist / ist nicht Müll; solange ein Objekt von etwas bezeichnet wird (und es ist nicht eine schwache Referenz usw.), ist es nicht Müll.


Nach herauszufinden, was Sie versuchen, zu tun, hier ist meine Lösung. Beachten Sie, dass es nicht eine Reihe von Bits überhaupt nicht erzeugen.

static void generate(String prefix, String suffix) {
    int i = suffix.replaceAll("[aeiou].*", "").length();
    if (i == suffix.length()) {
        System.out.println(prefix + suffix);
    } else {
        generate(prefix + suffix.substring(0, i), suffix.substring(i + 1));
        generate(prefix + suffix.substring(0, i+1), suffix.substring(i + 1));
    }
}

// generate("", "apple");

Es verwendet regex zu finden, wo die nächste Vokal ist. Sie können einen regulären for-Schleife verwenden, statt und der allgemeine Algorithmus wird immer noch funktionieren. Sie können sie optimieren StringBuilder zu verwenden, anstatt (ich bin vor allem für Prägnanz gehen und hoffentlich Klarheit in diesem Snippet).


Hier ist eine alternative Lösung, dass Anwendungen split die Eingabezeichenfolge in Stücke (O(N) Raum) vorab hacken, dann ein StringBuilder verwendet alle anderen Saiten (O(N) Raum) zu erzeugen.

static void generate(StringBuilder sb, String[] parts, int i) {
    if (i == parts.length) {
        System.out.println(sb.toString());
    } else {
        if ("aeiou".contains(parts[i])) {
            generate(sb, parts, i + 1);
        }
        sb.append(parts[i]);
        generate(sb, parts, i + 1);
        sb.setLength(sb.length() - parts[i].length());
    }
}
static void generate(String s) {
    generate(
        new StringBuilder(),
        s.split("(?<=[aeiou])|(?=(?!^)[aeiou])"),
        0
    );
}

// generate("apple");

Die regex spaltet "apple" in [ "a", "ppl", "e" ]. Es spaltet überall nach einem Vokal, oder (wenn es nicht der Anfang der Zeichenfolge ist) überall vor einem Vokal.

Es sollte klar sein, jetzt, dass der Platzbedarf O(N) ist, so dass, wenn die Zeichenfolge ist lächerlich lange , sollte dies nicht Ursache OutOfMemoryError.

Natürlich, wenn Sie auf Speichern die erzeugten Strings - alle O(2^N) von ihnen - im Speicher dann natürlich Sie OutOfMemoryError erhalten. Ich hoffe, diese Tatsache ist offensichtlich.

Die gesamte Idee ist nicht im Speicher etwas zu speichern, dass Sie nicht brauchen, diese riesige Ausgabe zu erzeugen. Wenn Sie dann alle dieser großen OUTPUT im Speicher speichern (statt, sagen, sie stdout oder eine Datei drucken) dann besiegt er die ganze Zweck und Sie werden eine OutOfMemoryError erhalten wie erwartet .

Andere Tipps

Sie möchten vielleicht einen Profiler betrachten, die Ihnen ein Bild von dem, was Typen von Objekten geben können jederzeit in Ihrem Programm existiert an. Als ein Beispiel hat NetBeans einen eingebauten in Profiler.

Damit wird gesagt, die wahrscheinlich Schuldige sind - wie bereits von anderen darauf hingewiesen wird -. Die außerordentlich hohe Menge an Speichern, dass Ihre zweidimensionale Anordnung erfordert als die Vokal Zahl wächst

Ich nehme an, Sie so etwas wie den folgenden Code haben:

int totalCombination = 1 << vowelCount;
System.out.println("totalCombination = " + totalCombination);
System.out.println("totalCombination (in Millions) = " + totalCombination / 1000 / 1000);

int[] arr = new int[totalCombination];

In einem 32-Bit-VM kann das Array nicht immer weiter wächst als 4 GB, von 1024 Millionen Einträge sind. Achten Sie darauf, immer kleiner werden Zahlen ausgedruckt in dem obigen Code.

Und vielleicht sollten Sie einen ganz anderen Algorithmus nehmen. Aber, dass Sie möchten, dass wir haben sagen, was Sie erreichen wollen, nicht wie Sie versuchen es.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top