Pergunta

Estou ficando fora do MemoryError: Java Heap

trechos do método:

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

Minha pergunta:

Cada vez que esse método é chamado, essa matriz é criada. É possível que a matriz não esteja sendo lançada.

No Windows TaskManager, posso ver a memória usada pelo Java é puramente incremental. Portanto, não é que, em um ponto, o tamanho da pilha seja menor, mas a memória é usada repetidamente e não é liberada de alguma forma.

Por favor, deixe -me saber se você precisar de mais destaque.

Por favor, ajude a depurar o erro.

Anuj

A parte do código que pode estar causando o erro:

int totalCombination = (int) math.pow (2.0, (duplo) vogalCount);

    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]);
            }
        }
Foi útil?

Solução

Poderes de dois crescem exponencialmente. Se vowelCount é alto, uma matriz sozinha pode causar facilmente OutOfMemoryError (2^32 = 4GB).

Você pode tentar ajustar seu requisito de memória máxima da VM (por exemplo, -Xmx512m), mas perceba que seu algoritmo está exigindo Muita memória. Você pode encontrar um algoritmo melhor, se possível.


Veja também


Após a edição: Assim como eu esperava, você está gerando uma enorme variedade cheia de todas as possibilidades binárias. Você raramente precisa armazenar toda essa matriz na memória. Você pode simplesmente gerar cada combinação possível "on-the-fly" e alimentá-la com quem precisa dos 0 e 1S "just-in-time".

Lembre O(2^N) para somente O(N), sua complexidade de tempo ainda é O(2^N).

Cada vez que esse método é chamado, essa matriz é criada. É possível que a matriz não esteja sendo lançada.

Sim, isso é muito possível, se a referência à matriz for vazada e, em seguida, algo em algum lugar se mantém nessa referência. O coletor de lixo não se importa realmente vocês pense é/não é lixo; Enquanto um objeto for referido por algo (e não é uma referência fraca etc.), não é lixo.


Depois de descobrir o que você está tentando fazer, aqui está minha solução. Observe que ele não gera uma variedade de bits.

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

Ele usa Regex para descobrir onde está a próxima vogal. Você pode usar um loop regular e o algoritmo geral ainda funcionará. Você pode otimizá -lo para usar StringBuilder Em vez disso (estou principalmente buscando concisão e esperançosamente clareza neste trecho).


Aqui está uma solução alternativa que usa split Para pré-atingir a sequência de entrada em pedaços (O(N) espaço), então usa um StringBuilder Para gerar todas as outras cordas (O(N) espaço).

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

A regex se divide "apple" em [ "a", "ppl", "e" ]. Ele se divide em todos os lugares após uma vogal, ou (se não for o começo da corda) em todos os lugares antes de uma vogal.

Deve ser óbvio agora que o requisito de espaço é O(N), então a menos que sua corda seja ridiculamente longo, isso não deve causar OutOfMemoryError.

Claro, se você é armazenando as cordas geradas - todas O(2^N) deles - na memória então é claro você terá OutOfMemoryError. Espero que esse fato seja óbvio.

Toda a ideia é não armazenar na memória nada que você não precise gerar essa enorme saída. Se você armazenar toda essa enorme saída na memória (em vez de, digamos, imprimi -los para stdout ou um arquivo), então ele derrota todo o propósito e você receberá um OutOfMemoryError como esperado.

Outras dicas

Você pode considerar usar um perfilador que possa fornecer uma imagem de que tipos de objetos existem a qualquer momento do seu programa. Como um exemplo, o NetBeans tem um perfil interno.

Com isso dito, o provável culpado é-como foi apontado por outros-a quantidade extraordinariamente alta de memória que sua matriz bidimensional exigirá à medida que a contagem de vogais cresce.

Suponho que você tenha algo como o seguinte código:

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

int[] arr = new int[totalCombination];

Em uma VM de 32 bits, a matriz nunca pode crescer mais de 4 GB, ou seja, 1024 milhões de entradas. Certifique -se de obter sempre números menores no código acima.

E talvez você deva tomar um algoritmo completamente diferente. Mas por isso você teria que nos dizer o que deseja alcançar, não Como as você está tentando.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top