Java heap space sas ошибка
Я пишу клиентское приложение Swing (графический дизайнер шрифтов) на Java 5 . В последнее время я сталкиваюсь с java.lang.OutOfMemoryError: Java heap space ошибкой, потому что я не консервативен в использовании памяти. Пользователь может открывать неограниченное количество файлов, а программа сохраняет открытые объекты в памяти. После быстрого исследования я обнаружил, что эргономика в виртуальной машине Java 5.0 и другие говорят, что на машине с Windows JVM по умолчанию имеет максимальный размер кучи, равный 64MB .
Я мог бы увеличить максимальный размер кучи, используя опцию командной строки для java, но это потребовало бы выяснения доступной оперативной памяти и написания некоторой запускающей программы или скрипта. Кроме того, увеличение до некоторого конечного максимума в конечном итоге не избавит от проблемы.
Я мог бы переписать часть своего кода, чтобы часто сохранять объекты в файловой системе (использование базы данных - то же самое), чтобы освободить память. Это может сработать, но, вероятно, это тоже много работы.
Если бы вы могли указать мне на детали вышеупомянутых идей или некоторые альтернативы, такие как автоматическая виртуальная память, динамически увеличивая размер кучи , это было бы здорово.
В конечном итоге у вас всегда есть конечный максимум кучи для использования независимо от того, на какой платформе вы работаете. В Windows 32 бит это примерно 2GB (не куча, а общий объем памяти на процесс). Просто так получается, что Java решает уменьшить размер по умолчанию (предположительно, так, чтобы программист не мог создавать программы с распределенным выделением памяти, не сталкиваясь с этой проблемой и не проверяя, что именно они делают).
Если вы решите, что вы распределяете эти объекты по какой-то причине и вам нужно хранить ссылки (в зависимости от того, что вы делаете, это может иметь место), вам просто нужно будет увеличить максимальный размер кучи при запуске программы. Однако, как только вы выполните профилирование памяти и поймете, как распределяются ваши объекты, у вас должно быть лучшее представление о том, сколько памяти вам нужно.
В общем, если вы не можете гарантировать, что ваша программа будет работать в ограниченном объеме памяти (возможно, в зависимости от размера ввода), вы всегда столкнетесь с этой проблемой. Только после исчерпания всего этого вам нужно будет изучить кэширование объектов на диск и т. Д. В этот момент у вас должна быть очень веская причина сказать «мне нужен Xgb памяти» для чего-то, и вы не сможете обойти это, улучшив ваши алгоритмы или шаблоны распределения памяти. Обычно это будет иметь место только в случае алгоритмов, работающих с большими наборами данных (например, с базой данных или какой-либо программой научного анализа), и тогда становятся полезными такие методы, как кэширование и ввод-вывод в память.
OpenJDK и OracleJDK имеют встроенный профилировщик - jvisualvm. Если вы хотите больше удобств, я бы предложил коммерческий Yourkit.
Итак, обычно есть две причины этой аномалии:
1. В программе есть бесконечный цикл.
2. Программа занимает слишком много памяти, что превышает максимальное значение, установленное кучей JVM.
В первом случае вам необходимо самостоятельно проверить программный код, поэтому я не буду здесь говорить больше.
Во втором случае мы вручную расширяем настройки параметров кучи JVM. Настройка кучи JVM относится к настройке пространства памяти, которое JVM может выделить и использовать во время выполнения программы java. Когда JVM запускается, куча JVM автоматически устанавливает значение размера кучи. Обычно значение по умолчанию для начального пространства (например, -Xms) составляет 1/64 физической памяти, а максимальное пространство составляет 1/4 физической памяти. Его можно установить с помощью таких параметров, как -Xmn -Xms -Xmx, предоставляемых JVM. Вот объяснение значения каждого параметра:
-Xms: начальное значение
-Xmx: максимум
-Xmn: минимальное значение
Размер кучи не должен быть слишком маленьким или слишком большим. Если параметр слишком мал, скорость отклика программы будет ниже, потому что сборщик мусора занимает больше времени, а приложение выделяет меньше времени на выполнение. Слишком большой размер также приведет к потере места и повлияет на нормальную работу других программ. Размер кучи не должен превышать 80% доступной физической памяти. Рекомендуется установить одинаковые параметры -Xms и -Xmx, а -Xmn составляет 1/4 значения -Xmx.
Основные методы настройки следующие:
1. Этот параметр добавляется при выполнении файла класса JAVA, где className - это имя класса, который необходимо выполнить. (Включая имя пакета) Например: java -Xms32m -Xmx800m className Это не только решает проблему, но и скорость выполнения намного выше, чем когда она не установлена. Если это тест разработки, вы также можете установить его прямо в eclipse. Введите -Xms32m -Xmx800m в аргументы виртуальной машины в Eclipse -> run -arguments.
2. Вы можете изменить системные переменные среды в Windows и добавить JAVA_OPTS = -Xms64m -Xmx512m.
3. Если вы используете tomcat под окнами, вы можете добавить в C: \ tomcat5.5.9 \ bin \ catalina.bat (конкретный путь зависит от местоположения вашего tomcat): установить JAVA_OPTS = -Xms64m -Xmx256m (размер зависит от вашей собственной памяти) Местоположение: rem Угадайте CATALINA_HOME, если не определено Добавьте соответствующее в этой строке.
4. Если это система Linux, добавьте набор JAVA_OPTS = ’- Xms64 -Xmx512’ перед /bin/catalina.sh
Поскольку программе необходимо прочитать около 10 Вт строк записей из данных для обработки, возникает ошибка типа java.lang.OutOfMemoryError: пространство кучи Java появляется при чтении 9 Вт.
Проверка в Интернете может быть причиной того, что параметр стека JAVA слишком мал.
Согласно ответам в Интернете, существует примерно два решения:
1. Задайте переменные среды.
set JAVA_OPTS= -Xms32m -Xmx512m
можно изменить в соответствии с объемом памяти вашего компьютера, но моя проверка этого метода не решила проблему. Это может быть где еще нужно установить.
2、java -Xms32m -Xmx800m className
- добавить этот параметр при выполнении файла класса JAVA, где className - это фактическое имя класса, который должен быть выполнен. (Включая название пакета)
Это решает проблему. И скорость выполнения намного выше, чем без настройки.
Если вы можете использовать Eclispe при тестировании, вам необходимо ввести параметр -Xms32m -Xmx800m в аргументы виртуальной машины в Eclipse -> run -arguments.
Исключение возникает при использовании программы Java для запроса большого количества данных из базы данных:
java.lang.OutOfMemoryError: Java heap space
Настройка кучи JVM относится к настройке пространства памяти, которое JVM может выделить и использовать во время выполнения программы java.
JVM автоматически установит значение размера кучи при запуске.Его начальное пространство (-Xms) составляет 1/64 физической памяти, а максимальное пространство (-Xmx) - 1/4 физической памяти. Его можно установить с помощью таких параметров, как -Xmn -Xms -Xmx, предоставляемых JVM.
Например: java -jar -Xmn16m -Xms64m -Xmx128m MyApp.jar
Я подумал, что слишком поздно перерабатывать из-за частых операций, поэтому я добавил Thread.sleep (1000) после каждого цикла и обнаружил, что он умрет в этом каталоге, поэтому я изменил 1000 на 5000 или умер там. Я думаю, что это может быть не так просто перерабатывать, возможно, JVM Sun просто не выпускает для этой ситуации.
Затем я добавил -Xmx256M к параметру запуска, на этот раз все было нормально.
Подумав об этом, я до сих пор мало что знаю о принципах сборки мусора, я проверил это в Интернете и нашел несколько хороших статей.
Также существуют: Управление кучей Java - сборка мусора. Следует отметить следующие моменты, которые могут использоваться в качестве рекомендаций при написании программ:
(1) Не пытайтесь предполагать время, когда происходит сборка мусора, причем все это неизвестно. Например, временный объект в методе становится бесполезным после вызова метода, и его память может быть освобождена в это время.
(2) Java предоставляет несколько классов, которые занимаются сборкой мусора, и предоставляет способ принудительного вызова функции сборки мусора System.gc (), но это также ненадежный метод. Java не гарантирует, что сборка мусора будет запускаться каждый раз при вызове этого метода. Она просто отправляет такой запрос в JVM. Неизвестно, выполняется ли сборка мусора на самом деле.
(3) Выберите подходящий вам сборщик мусора. Вообще говоря, если система не предъявляет особых требований к производительности, вы можете использовать параметры JVM по умолчанию. В противном случае вы можете рассмотреть возможность использования целевых сборщиков мусора.Например, инкрементные сборщики больше подходят для систем с высокими требованиями к работе в реальном времени. Система имеет более высокую конфигурацию и больше простаивающих ресурсов, вы можете рассмотреть возможность использования параллельного сборщика меток / разверток.
(4) Ключевая и сложная проблема - это утечки памяти. Хорошие навыки программирования и строгое отношение к программированию всегда являются самыми важными. Не позволяйте небольшой собственной ошибке вызвать большую дыру в памяти.
(5) Освободите ссылки на бесполезные объекты как можно скорее.
Когда большинство программистов используют временные переменные, они автоматически устанавливают для ссылочной переменной значение null после выхода из активной области (области), что означает, что сборщик мусора будет собирать объект. Вы должны обратить внимание на то, отслеживается ли объект, на который указывает ссылка, если да, удалите прослушиватель, а затем назначьте нулевое значение.
Другими словами, лучше контролировать операции частого обращения к памяти и освобождения памяти самостоятельно, но метод System.gc () может быть неприменим. Лучше использовать finalize для принудительного выполнения или написать свой собственный метод finalize.
Я обнаружил ошибку TOMCAT: java.lang.OutOfMemoryError: пространство кучи Java, поэтому я проверил информацию и нашел решение:
If Java runs out of memory, the following error occurs:
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
Java heap size can be increased as follows:
Если вы используете выигрыш
/tomcat/bin/catalina.bat плюс следующая команда:
set JAVA_OPTS=-Xms32m -Xmx256m
Если вы используете unix / linux
/tomcat/bin/catalina.sh плюс следующая команда:
JAVA_OPTS="-Xms32m -Xmx256m"
инструмент просмотра и анализа памяти jvm
В отрасли существует множество мощных инструментов для профилей Java, таких как Jporfiler и yourkit. Я не хочу говорить об этих платных вещах. Я хочу сказать, что сама java обеспечивает большой мониторинг памяти. Маленькие инструменты, перечисленные ниже инструменты - лишь небольшая часть. Все еще довольно интересно внимательно изучить инструменты jdk :)
1: вывод журнала gc
-verbose: gc и -XX: + PrintTenuringDistribution и т. д.
Код коллекции HTML-кода
Usage:
jmap -histo (to connect to running process and print histogram of java object heap
jmap -dump: (to connect to running process and dump java heap)
dump-options: format=b binary default file=
dump heap to
Example: jmap -dump:format=b,file=heap.bin
jmap -dump:file=c:\dump.txt 340
Обратите внимание, что 340 - это pid java-процесса моей машины. Размер выгруженного файла превышает 10 мегабайт, и я только что открыл tomcat и запустил очень простое приложение без какого-либо доступа. Его можно представить на большом и загруженном сервере. , Насколько большим должен быть файл дампа? Что вам нужно знать, так это то, что информация о файле дампа очень примитивна и определенно не подходит для просмотра людьми напрямую, а содержимое, отображаемое jmap -histo, слишком простое, например, оно только показывает, сколько памяти занимают определенные типы объектов и количество этих объектов. , Но нет более подробной информации, например, кто создал эти объекты. Итак, какая польза от файла дампа? Конечно полезно, потому что есть инструмент для анализа файла дампа памяти jvm.
6: анализатор памяти eclipse
S0 S1 E O P YGC YGCT FGC FGCT GCT
54.62 0.00 42.87 43.52 86.24 1792 5.093 33 7.670 12.763
S0 S1 E O P YGC YGCT FGC FGCT GCT
54.62 0.00 42.87 43.52 86.24 1792 5.093 33 7.670 12.763
S0: Зона susvivor0 нового поколения, коэффициент использования площадей 54 . 62%
S1: область susvivor1 нового поколения, коэффициент использования пространства составляет 0,00% (поскольку второй второстепенный сбор не был выполнен)
Upto my knowledge, Heap space is occupied by instance variables only. If this is correct, then why this error occurred after running fine for sometime as space for instance variables are alloted at the time of object creation.
Is there any way to increase the heap space?
What changes should I made to my program so that It will grab less heap space?
30 Answers 30
Ultimately you always have a finite max of heap to use no matter what platform you are running on. In Windows 32 bit this is around 2GB (not specifically heap but total amount of memory per process). It just happens that Java chooses to make the default smaller (presumably so that the programmer can't create programs that have runaway memory allocation without running into this problem and having to examine exactly what they are doing).
If you determine that you are allocating these objects for a reason and you need to keep around references (depending on what you are doing this might be the case), you will just need to increase the max heap size when you start the program. However, once you do the memory profiling and understand how your objects are getting allocated you should have a better idea about how much memory you need.
In general if you can't guarantee that your program will run in some finite amount of memory (perhaps depending on input size) you will always run into this problem. Only after exhausting all of this will you need to look into caching objects out to disk etc. At this point you should have a very good reason to say "I need Xgb of memory" for something and you can't work around it by improving your algorithms or memory allocation patterns. Generally this will only usually be the case for algorithms operating on large datasets (like a database or some scientific analysis program) and then techniques like caching and memory mapped IO become useful.
Если вы словили OutOfMemoryError, то это вовсе не значит, что ваше приложение создает много объектов, которые не могут почиститься сборщиком мусора и заполняют всю память, выделенную вами с помощью параметра -Xmx. Я, как минимум, могу придумать два других случая, когда вы можете увидеть эту ошибку. Дело в том, что память java процесса не ограничивается областью -Xmx, где ваше приложение программно создает объекты.
Область памяти, занимаемая 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-процесса.
12 Answers 12
If you want to increase your heap space, you can use java -Xms -Xmx on the command line. By default, the values are based on the JRE version and system configuration. You can find out more about the VM options on the Java website.
However, I would recommend profiling your application to find out why your heap size is being eaten. NetBeans has a very good profiler included with it. I believe it uses the jvisualvm under the hood. With a profiler, you can try to find where many objects are being created, when objects get garbage collected, and more.
I am using Netbeans but I don't know how to use profiler. I would like to know more about the profiler so that I can use it to find memory leaks in my application.
Default values change with java versions, it would be nice to include this information in your answer.
Just fixed similar problem and first tried: java -jar division.jar -Xmx512m -Xms512m - this gives me same error but when I do it like so: java -Xmx512m -Xms512m -jar division.jar - all is fine. So the order of params is also important.
1.- Yes, but it pretty much refers to the whole memory used by your program.
2.- Yes see Java VM options
java -Xmx2g assign 2 gigabytes of ram as maximum to your app
But you should see if you don't have a memory leak first.
3.- It depends on the program. Try spot memory leaks. This question would be to hard to answer. Lately you can profile using JConsole to try to find out where your memory is going to
I have found it useful to use visualgc to watch how the different parts of the memory model is filling up, to determine what to change.
It is difficult to determine which part of memory was filled up, hence visualgc, as you may want to just change the part that is having a problem, rather than just say,
Fine! I will give 1G of RAM to the JVM.
Try to be more precise about what you are doing, in the long run you will probably find the program better for it.
To determine where the memory leak may be you can use unit tests for that, by testing what was the memory before the test, and after, and if there is too big a change then you may want to examine it, but, you need to do the check while your test is still running.
I am writing a client-side Swing application (graphical font designer) on Java 5. Recently, I am running into java.lang.OutOfMemoryError: Java heap space error because I am not being conservative on memory usage. The user can open unlimited number of files, and the program keeps the opened objects in the memory. After a quick research I found Ergonomics in the 5.0 Java Virtual Machine and others saying on Windows machine the JVM defaults max heap size as 64MB .
Given this situation, how should I deal with this constraint?
I could increase the max heap size using command line option to java, but that would require figuring out available RAM and writing some launching program or script. Besides, increasing to some finite max does not ultimately get rid of the issue.
I could rewrite some of my code to persist objects to file system frequently (using database is the same thing) to free up the memory. It could work, but it's probably a lot work too.
If you could point me to details of above ideas or some alternatives like automatic virtual memory, extending heap size dynamically, that will be great.
The Sun/Oracle JVM has always been quite rigid about specifying the amount memory to use (and having some interesting defaults if left on its own). That was one of the nice things of the Microsoft JVM back then - it was fast and it could use whatever memory the machine had.
Читайте также: