Java heap space sas ошибка

Обновлено: 06.07.2024

Я пишу клиентское приложение Swing (графический дизайнер шрифтов) на Java 5 . Недавно я столкнулся с ошибкой java.lang.OutOfMemoryError: Java heap space , потому что я не консервативен в использовании памяти. Пользователь может открывать неограниченное количество файлов, а программа сохраняет открытые объекты в памяти. После быстрого исследования я нашел эргономику в виртуальной машине 5.0 Java и другие говорят, что на машине Windows максимальный размер кучи JVM по умолчанию равен 64MB .

Я мог бы увеличить максимальный размер кучи с помощью опции командной строки до java, но для этого потребуется выяснить доступный RAM и написать какую-нибудь запускающую программу или скрипт. Кроме того, увеличение до некоторого конечного максимума в конечном счете не избавляет от этой проблемы.

Я мог бы переписать часть своего кода, чтобы часто сохранять объекты в файловой системе (использование базы данных - это одно и то же), чтобы освободить память. Это может сработать, но это, вероятно, тоже много работы.

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

В конечном счете, у вас всегда есть конечный максимум кучи для использования независимо от того, на какой платформе вы работаете. В 32-битном Windows это около 2GB (не конкретно куча, а общий объем памяти на процесс). Просто так получилось, что Java решил сделать значение по умолчанию меньше (предположительно, чтобы программист не мог создавать программы с беглым выделением памяти, не столкнувшись с этой проблемой и не изучив точно, что они делают).

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

В общем, если вы не можете гарантировать, что ваша программа будет работать в некотором конечном объеме памяти (возможно, в зависимости от размера входных данных), вы всегда столкнетесь с этой проблемой. Только после исчерпания всего этого вам нужно будет заглянуть в кэширование объектов на диск и т. д. На этом этапе у вас должна быть очень веская причина сказать "I need Xgb of memory" для чего-то, и вы не можете обойти это, улучшив свои алгоритмы или шаблоны распределения памяти. Как правило, это относится только к алгоритмам, работающим с большими наборами данных (такими как база данных или какая-либо программа научного анализа), и тогда становятся полезными такие методы, как кэширование и отображение памяти IO.

Запустите Java с параметром командной строки -Xmx ,который устанавливает максимальный размер кучи.

Если вы словили OutOfMemoryError, то это вовсе не значит, что ваше приложение создает много объектов, которые не могут почиститься сборщиком мусора и заполняют всю память, выделенную вами с помощью параметра -Xmx. Я, как минимум, могу придумать два других случая, когда вы можете увидеть эту ошибку. Дело в том, что память java процесса не ограничивается областью -Xmx, где ваше приложение программно создает объекты.

image

Область памяти, занимаемая java процессом, состоит из нескольких частей. Тип OutOfMemoryError зависит от того, в какой из них не хватило места.

1. java.lang.OutOfMemoryError: Java heap space

Не хватает место в куче, а именно, в области памяти в которую помещаются объекты, создаваемые программно в вашем приложении. Размер задается параметрами -Xms и -Xmx. Если вы пытаетесь создать объект, а места в куче не осталось, то получаете эту ошибку. Обычно проблема кроется в утечке памяти, коих бывает великое множество, и интернет просто пестрит статьями на эту тему.

2. java.lang.OutOfMemoryError: PermGen space

Данная ошибка возникает при нехватке места в Permanent области, размер которой задается параметрами -XX:PermSize и -XX:MaxPermSize. Что там лежит и как бороться с OutOfMemoryError возникающей там, я уже описал подробнейшим образом тут.

3. java.lang.OutOfMemoryError: GC overhead limit exceeded

Данная ошибка может возникнуть как при переполнении первой, так и второй областей. Связана она с тем, что памяти осталось мало и GC постоянно работает, пытаясь высвободить немного места. Данную ошибку можно отключить с помощью параметра -XX:-UseGCOverheadLimit, но, конечно же, её надо не отключать, а либо решать проблему утечки памяти, либо выделять больше объема, либо менять настройки GC.

4. java.lang.OutOfMemoryError: unable to create new native thread

На самом деле это очень просто воспроизвести на windows на 32-битной машине, так как там процессу выделяется не больше 2Гб.

Допустим у вас есть приложение с большим количеством одновременно работающих пользователей, которое запускается с параметрами -Xmx1024M -XX:MaxPermSize=256M -Xss512K. Если всего процессу доступно 2G, то остается свободным еще коло 768M. Именно в данном остатке памяти и создаются стеки потоков. Таким образом, примерно вы можете создать не больше 768*(1024/512)=1536 (у меня при таких параметрах получилось создать 1316) нитей (см. рисунок в начале статьи), после чего вы получите OutOfMemoryError. Если вы увеличиваете -Xmx, то количество потоков, которые вы можете создать соответственно уменьшается. Вариант с уменьшением -Xss, для возможности создания большего количества потоков, не всегда выход, так как, возможно, у вас существуют в системе потоки требующие довольно больших стеков. Например, поток инициализации или какие-нибудь фоновые задачи. Но все же выход есть. Оказывается при программном создании потока, можно указать размер стека: Thread(ThreadGroup group, Runnable target, String name,long stackSize). Таким образом вы можете выставить -Xss довольно маленьким, а действия требующие больших стеков, выполнять в отдельных потоках, созданных с помощью упомянутого выше конструктора.

Более подробно, что же лежит в стеке потока, и куда уходит эта память, можно прочитать тут.

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

1. Обзор

2. Симптомы

Как правило, есть два возможных сценария, когда мы сталкиваемся с ошибкой.
Во-первых, когда мы запускаем процесс Java с параметром max heap size limit ( -Xmx )
и значение больше, чем может иметь процесс в операционной системе
.

Ограничение размера кучи варьируется в зависимости от нескольких ограничений:

  • аппаратная архитектура (32/64 бит)
  • Разрядная версия JVM (32/64 бит)
  • операционная система, которую мы используем

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

3. Размер Кучи

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

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

3.1. Максимальный Размер Кучи

Максимальный теоретический предел кучи для 32-разрядной и 64-разрядной JVM легко определить, посмотрев на доступное пространство памяти: 2^32 (4 ГБ) для 32-разрядной JVM и 2^64 (16 экзабайт) для 64-разрядной JVM.

На практике, из-за различных ограничений, предел может быть намного ниже и варьируется в зависимости от операционной системы. Например, в 32-разрядных системах Windows максимальный размер кучи составляет от 1,4 ГБ до 1,6 ГБ . В отличие от этого, в 32-разрядных системах Linux максимальный размер кучи может достигать 3 ГБ.

По этой причине если приложению требуется большая куча, мы должны использовать 64-разрядную JVM . Однако при большой куче у сборщика мусора будет больше работы, поэтому важно найти хороший баланс между размером кучи и производительностью.

3.2. Как Контролировать Ограничения Размера Кучи?

У нас есть два варианта управления ограничениями размера кучи JVM.

Во-первых, используя параметры командной строки Java | при каждой инициализации JVM:

Для значения размера мы можем добавить букву k или K , m или M и g или G , чтобы указать килобайты, мегабайты и гигабайты соответственно. Если буква не указана, используется единица измерения по умолчанию (байт).

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

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

4. Заключение

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

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

Я пишу на стороне клиента качели приложение (графический конструктор шрифтов) на Java 5. Недавно я столкнулся с java.lang.OutOfMemoryError: Java heap space ошибка, потому что я не консервативен в использовании памяти. Пользователь может открывать неограниченное количество файлов, и программа сохраняет открытые объекты в памяти. После быстрого исследования я нашел эргономика в виртуальной машине 5.0 Java и другие говорят на машине Windows, что JVM по умолчанию максимальный размер кучи как 64MB .

учитывая эту ситуацию, как я должен бороться с этим ограничением?

я мог бы увеличить максимальный размер кучи используя командная строка опция java, но для этого потребуется выяснить доступную ОЗУ и написать некоторую программу запуска или скрипт. Кроме того, увеличение до некоторого конечного максимума в конечном итоге не избавляет от проблемы.

я мог бы переписать часть моего кода, чтобы часто сохранять объекты в файловой системе (используя базу данных то же самое), чтобы освободить память. Это может сработать, но это, вероятно, тоже много работы.

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

в конечном счете у вас всегда есть конечный максимум кучи, чтобы использовать независимо от того, на какой платформе вы работаете. В Windows 32 бит это около 2 Гб (не конкретно куча, но общий объем памяти на процесс). Просто случается, что Java решает сделать значение по умолчанию меньше (предположительно, чтобы программист не мог создавать программы с неуправляемым распределением памяти, не сталкиваясь с этой проблемой и не изучая точно, что они делают).

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

В общем, если вы не можете гарантировать, что ваша программа будет работать в некотором конечном объеме памяти (возможно, в зависимости от размера ввода), вы всегда столкнетесь с этой проблемой. Только после исчерпания всего этого вам нужно будет посмотреть в кэширование объектов на диск и т. д. На данный момент у вас должна быть очень веская причина сказать: "Мне нужен Xgb памяти" для чего-то, и вы не можете обойти это, улучшив свои алгоритмы или шаблоны выделения памяти. Как правило, это происходит только в случае алгоритмов, работающих с большими наборами данных (например, с базой данных или какой-либо программой научного анализа), а затем становятся полезными такие методы, как кэширование и сопоставление памяти.

запустите Java с параметром командной строки -Xmx , который устанавливает максимум размер кучи.

Читайте также: