Моя программа Java бросила OutOfMemoryError . Как отлаживать и исправлять эту проблему?
Многие новички в Java борются за то, чтобы справиться с OutOfMemoryError . Это попытка создать канонический вопрос, который будет отвечать на наиболее часто задаваемые вопросы о OutOfMemoryError . Я создаю этот новый вопрос, вместо того, чтобы адаптировать один из многочисленных предыдущих вопросов о OutOfMemoryError , потому что эти вопросы и их ответы тесно связаны с конкретной проблемой человека.
4 ответа
OutOfMemoryError — это исключение, созданное виртуальной машиной Java (JVM), потому что ему необходимо выделить память для (нового) объекта, но для объекта недостаточно памяти. JVM сначала попытается освободить память, используемую мертвыми объектами, запустит сборщик мусора .
Поскольку OutOfMemoryError является VirtualMachineError , JVM разрешено бросить его в любое время , хотя он должен попытаться освободить память через сборку мусора в первую очередь .
Однако на практике это, скорее всего, будет выбрано из new , который пытался создать объект, для которого память не может быть выделена. Таким образом, вы должны сначала изучить stacktrace, связанный с исключением, для подсказки о причине проблемы, , как и для любого другого исключения .
- Если исключение из-за попытки выделить массив (например, int[] values = new int[n] ) причиной может быть то, что вы пытаетесь создать слишком большой массив (слишком большой размер n ). Вы ошиблись при вычислении размера массива, который вам нужен?
- Если исключение выбрано из попытки выделить массив в методе класса контейнера, написанном кем-то другим, причина может быть что ваш код просит контейнер хранить чрезмерное количество вещей. Такие методы, как ArrayList.reserve(int) и HashMap(int) , должны выделять хранилище для будущего использования. Вы допустили ошибку при вычислении размера контейнера, который вам нужен?
- Если исключение выбрасывается из цикла, причиной может быть то, что код слишком много циклов. Правильно ли установлено условие завершения цикла? Если это for цикл, вы просите его зациклировать правильное количество раз?
Если stacktrace не дает достаточного количества подсказок, вы можете попробовать использовать профилировщик кучи. Это программа мониторинга, которая позволяет вам анализировать память, используемую для объектов во время работы программы, или рассматривает кучу кучи кучи , записанную при выходе программы. Он может предоставлять информацию о размерах, числе и классах объектов, хранящихся в памяти.
JVM имеет конечный объем памяти , доступный для него. Вы можете сделать вывод, что программа работает правильно, но для этого требуется больше памяти для работы, чем было доступно для нее. Если вы явно не укажете JVM, сколько памяти использовать, большинство реализаций выберет разумную величину по умолчанию в зависимости от объема оперативной памяти, которую имеет ваш компьютер, но эта сумма может быть слишком мала для вашей программы , Параметры командной строки для JVM могут управлять объемом памяти. Для большинства реализаций JVM наиболее важными из них являются -Xmx и -Xms .
How do I fix java.lang.OutOfMemoryError: Java heap space when compiling my Android project?
I get this after I upgraded to version 1 of Android Studio. But, I don’t think this is the problem. Most likely when I start upgrading my app to SDK 21 (before this was SDK 20). But I wasn’t so sure either.
I’ve googled around for some fix, but couldn’t find one that works. Most of the fix are for Eclipse IDE.
This is the full logcat error that I get when compiling:
Is it because of one jar library I used (zip4j)? I did try to remove it, but the OOM error still occurs. Any idea how to fix this?
Edit:
I’ve also edited gradlew file to increase the -Xmx size.
Edit 2:
Also did this fix but couldn’t help it too:
Try the following:
Ctrl + Alt + S -> Compiler -> Gradle
I am getting OutOfMemoryError: java heap
snippets of the method:
each time this method is called, that array is getting created. Is it possible that the array is not getting released .
In windows taskmanager i can see memory used by java is purely incremental. So it is not that at a point heap size is less, but memory is repetitively used and not released somehow.
Please let me know if you need more detal.
Please help to debug the error.
The part of the code which might be causing the error:
int totalCombination = (int) Math.pow(2.0, (double) vowelCount);
3 Answers 3
Powers of two grows exponentially. If vowelCount is high, one array alone could easily cause OutOfMemoryError ( 2^32 = 4GB ).
You can try to tweak your VM maximum memory requirement (e.g. -Xmx512m ), but do realize that your algorithm is requiring A LOT OF MEMORY. You may want to find a better algorithm if at all possible.
See also
- Wikipedia: exponential growth
- Wheat and chessboard problem — famous anecdote to show just how surprisingly quick powers of two can grow
After edit: just as I expected, you’re generating a huge array filled with all binary possibilities. You rarely need to actually store this whole array in memory. You can just generate each possible combination "on-the-fly" and feed it to whoever needs the 0s and 1s "just-in-time".
Do keep in mind that this is still exponential growth, so even though you’ve taken care of your memory requirement from O(2^N) to just O(N) , your time complexity is still O(2^N) .
each time this method is called, that array is getting created. Is it possible that the array is not getting released .
Yes, that is very possible, if the reference to the array is ever leaked, and then something somewhere holds on to this reference. The garbage collector doesn’t really care what you think is/isn’t garbage; as long as an object is referred to by something (and it’s not a weak reference etc), it’s NOT garbage.
After figuring out what you’re trying to do, here’s my solution. Note that it doesn’t generate an array of bits at all.
It uses regex to find where the next vowel is. You can use a regular for-loop instead and the general algorithm will still work. You can optimize it to use StringBuilder instead (I’m mostly going for conciseness and hopefully clarity in this snippet).
Here’s an alternative solution that uses split to pre-chop the input string into pieces ( O(N) space), then uses a StringBuilder to generate all the other strings ( O(N) space).
The regex splits "apple" into [ "a", "ppl", "e" ] . It splits everywhere after a vowel, or (if it’s not the beginning of the string) everywhere before a vowel.
It should be obvious now that the space requirement is O(N) , so unless your string is ridiculously long, this should not cause OutOfMemoryError .
Of course, if you’re storing the generated strings — all O(2^N) of them — in memory then of course you’ll get OutOfMemoryError . I hope this fact is obvious.
The entire idea is to not store in memory anything that you don’t need to generate this HUGE OUTPUT. If you then store all of this HUGE OUTPUT in memory (instead of, say, printing them to stdout or a file) then it defeats the whole purpose and you’ll get an OutOfMemoryError as expected.