Вопрос

Я получаю OutofMemoryError: Java Heap

фрагменты метода:

{
// 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
}

Мой вопрос:

Каждый раз, когда этот метод называется, этот массив создается. Возможно ли, что массив не выпускается.

В Windows TaskManager я могу видеть память, используемую Java, чисто инкрементно. Так что не то, что в точечном размере куча меньше, но память повторяется и не выпущена как-то.

Пожалуйста, дайте мне знать, если вам нужно больше доклада.

Пожалуйста, помогите отладить ошибку.

Ануй

Часть кода, которая может вызвать ошибку:

INT TotalCombination = (int) math.pow (2.0, (двойной) 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]);
            }
        }
Это было полезно?

Решение

Полномочия из двух вырастают экспоненциально. Если vowelCount высокий, один массив один может легко вызвать OutOfMemoryError (2^32 = 4GB).

Вы можете попытаться настроить требование максимальной памяти VM (например, -Xmx512m), но осознайте, что ваш алгоритм требует Много памяти. Отказ Вы можете найти лучший алгоритм, если вообще возможно.


Смотрите также


После редактирования: Точно так же, как я ожидал, вы генерируете огромный массив, заполненный всеми двоичными возможностями. Вам редко нужно на самом деле сохранить весь этот массив в памяти. Вы можете просто генерировать каждую возможную комбинацию «On-Fly» и кормить его тем, кто нуждается в 0S и 1S «просто вовремя».

Имейте в виду, что это все еще экспоненциальный рост, поэтому, даже если вы позаботились о вашем требовании к памяти от O(2^N) чтобы просто O(N), Ваше временное сложность все еще O(2^N).

Каждый раз, когда этот метод называется, этот массив создается. Возможно ли, что массив не выпускается.

Да, это очень возможно, если ссылка на массив когда-либо утечка, а потом что-то где-то держится на эту ссылку. Сборщик мусора на самом деле не заботится о том, что ты думаю, не мусор; Пока объект называется чем-то (и это не слабая ссылка и т. Д.), Это не мусор.


После выяснения того, что вы пытаетесь сделать, вот мое решение. Обратите внимание, что вообще не генерирует массив битов.

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");

Он использует Regex, чтобы найти, где находится следующий гласный. Вместо этого вы можете использовать регулярную петлю, и общий алгоритм все равно будет работать. Вы можете оптимизировать его, чтобы использовать StringBuilder вместо этого (я в основном собираюсь в краткости и, надеюсь, ясность в этом фрагменте).


Вот альтернативное решение, которое использует split предварительно нарезать входную строку на куски (O(N) пространство), затем использует StringBuilder генерировать все другие строки (O(N) Космос).

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");

Регез расщепляется "apple" в [ "a", "ppl", "e" ]. Отказ Он разбивается везде после гласного или (если это не начало строки) везде перед гласным.

Теперь должно быть очевидно, что требование космического пространства O(N), Так что, если ваша строка не смешно долго, это не должно вызывать OutOfMemoryError.

Конечно, если вы хранение сгенерированные строки - все O(2^N) из них - в память тогда конечно ты получишь OutOfMemoryError. Отказ Я надеюсь, что этот факт очевиден.

Вся идея Чтобы не хранить в памяти ничего, что вам не нужно генерировать этот огромный выход. Если вы тогда храните все этот огромный выход в память (вместо того, чтобы сказать, печатать их stdout или файл), затем он побеждает все цели, и вы получите OutOfMemoryError как и ожидалось.

Другие советы

Возможно, вы захотите рассмотреть возможность использования профилировщика, который может дать вам изображение того, какие типы объектов существуют в любой момент времени в вашей программе. В качестве одного примера NetBeans имеет встроенный профилировщик.

С тем, что было сказано, что вероятность виновника - как указывалось другими - необычайно большая память, которую ваш двумерный массив потребует в качестве гласного количества.

Я предполагаю, что у вас есть что следующий код:

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

int[] arr = new int[totalCombination];

В 32-битной VM Array не может расти дальше 4 ГБ, это 1024 миллиона записей. Убедитесь, что вы всегда получаете меньшие числа, напечатанные в вышеуказанном коде.

И, возможно, вы должны взять совершенно другой алгоритм. Но для этого вам придется сказать нам, что вы хотите достичь, а не как Вы пытаетесь это.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top