Как мне исправить «java.lang.OutOfMemoryError at sun.misc.Unsafe.allocateMemory (собственный метод)»? - PullRequest
3 голосов
/ 25 января 2010

Я делаю Java-приложение, которое использует библиотеку Slick для загрузки изображений. Однако на некоторых компьютерах я получаю эту ошибку при попытке запустить программу:

Exception in thread "main" java.lang.OutOfMemoryError 
    at sun.misc.Unsafe.allocateMemory(Native Method) 
    at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:99) 
    at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:288) 
    at org.lwjgl.BufferUtils.createByteBuffer(BufferUtils.java:60) 
    at org.newdawn.slick.opengl.PNGImageData.loadImage(PNGImageData.java:692)
    at org.newdawn.slick.opengl.CompositeImageData.loadImage(CompositeImageData.java:62)
    at org.newdawn.slick.opengl.CompositeImageData.loadImage(CompositeImageData.java:43)

Мои параметры виртуальной машины:

-Djava.library.path=lib -Xms1024M -Xmx1024M -XX:PermSize=256M -XX:MaxPermSize=256M

Программа загружает несколько больших изображений (разрешение 1024 x 768) в начале.

Любая помощь в решении этой проблемы будет принята с благодарностью.

Ответы [ 5 ]

4 голосов
/ 25 января 2010

OutOfMemoryError просто означает, что JVM не хватило памяти. Первая строка трассировки стека здесь не очень актуальна, так как она просто «по стечению обстоятельств» ровно там , где JVM начинает исчерпывать память, а вся сборка мусора тщетна.

Существует два основных решения:

  1. Дайте JVM больше памяти.
  2. Устранение утечек памяти и / или выделение меньшего количества памяти в коде (т. Е. Сделать код более эффективным, не тратить слишком много ресурсов, таких как byte[], слишком долго и т. Д.).

Пункт 1 легко выполнить, но это не всегда решение, если в коде явно есть утечка памяти. Точку 2 лучше всего прибить с помощью Java-профилировщика .

2 голосов
/ 08 мая 2010

В зависимости от точного сценария, это может быть проявлением ошибки JVM, существующей с 2005 года.

Если вы посмотрите на код в классе java.nio.DirectByteBuffer, вы увидите, что он создает поток для освобождения запрошенной памяти. Если вы программируете использовать множество экземпляров этого класса (например, косвенно через IOUtils), вы можете получить OOME, даже если у вас достаточно памяти. Просто у нити не было возможности освободить память.

Это противный.

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6296278

1 голос
/ 25 января 2010

Обнаружил проблему, я пытался загрузить PNG 6144x6144 в свою программу.

После изменения размера изображения до 256x256 TGA программа загружается без ошибок.

0 голосов
/ 02 июля 2019

Когда вы получаете это конкретное исключение с трассировкой стека, заканчивающейся на Unsafe.allocateMemory(Native Method), это означает, что ОС отклонила запрос на выделение дополнительной памяти; Исключения, которые указывают на то, что вы достигли предела вашей JVM для памяти кучи Java, будут иметь другую трассировку стека.

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

Если при этом вы выделяете обычные объекты Java (а не собственные буферы памяти или очень большие массивы примитивов), я бы порекомендовал переписать ваш код только для экономии памяти или получить машину с большим объемом ОЗУ; поскольку сборщик мусора должен обходить каждый достижимый объект в куче, чтобы пометить их как живые, это означает, что объекты, на которые вы не будете часто ссылаться, все равно должны регулярно извлекаться в память с помощью JVM ... так что используется много подкачки для небольших объектов Java становится довольно дорогим.

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

0 голосов
/ 25 января 2010

@ BalusC в основном правильно объясняет причину и решения.

Однако, возможно, что непосредственной причиной OOME является то, что на некоторых компьютерах JVM не может расширить кучу до размера, заданного параметрами -XX. Например, если запрошенный объем памяти превышает оставшуюся доступную физическую память + пространство подкачки, ОС отклонит запрос JVM на расширение кучи. Это может объяснить, почему приложение работает на некоторых машинах, а не на других ... с одинаковыми параметрами виртуальной машины и (я думаю) процессорной архитектурой и версиями JVM.

Если это проблема, операционному оператору потребуется добавить больше физической памяти или увеличить пространство подкачки системы.

Чтобы расширить второе решение @ BalusC, OP может потребоваться изменить приложение, чтобы оно не загружало изображения при запуске. Скорее, он может загружать их лениво и использовать кэш со слабыми ссылками, чтобы гарантировать, что GC может их отбросить, если не хватает памяти. Однако, если критически важно, чтобы все изображения были предварительно загружены, у OP не остается иного выбора, кроме как выяснить, как обеспечить большую кучу JVM; см. выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...