linux-notes.org
Узнать размер Java Heap Memory Size
Есть проблема с Java Heap Memory Size, ее нужно нормально указать для того чтобы все нормально работало ( например, веб- сервер tomcat, liferay, OpenMRS и так далее) и в данной статье «Узнать размер Java Heap Memory Size» расскажу как можно найти оптимальное значение для java.
Сейчас я покажу вам, как использовать-XX:+PrintFlagsFinal чтобы узнать ваш размер кучи «heap size». В Java, по умолчанию и максимальный размер кучи распределяются на основании алгоритма — эргономики (ergonomics algorithm).
Как же рассчитывается Heap sizes?
Начальный размер кучи — это соотношение 1/64 физической памяти к 1 Гб. (Initial heap size of 1/64 of physical memory up to 1Gbyte)
Максимальный размер кучи — это соотношение 1/4 физической памяти до 1 Гб. (Maximum heap size of 1/4 of physical memory up to 1Gbyte)
Тем не менее, алгоритм что выше, как раз для справки, могут варьироваться в разных VM.
Обзор памяти Java
Краткий обзор структуры памяти Java:
1. Java Heap Size
Место для хранения объектов, созданных приложением Java, это где Garbage Collection берет память для приложений Java. Для «тяжелого процесса Java», недостаточный размер кучи вызовет популярную ошибку: java.lang.OutOfMemoryError: Java heap space.
-Xms — Установить начальный размер Java куча «Java heap size»
-Xmx — Установить максимальный размер Java куча «Java heap size»
2. Размер Perm Gen (Perm Gen Size).
Место для хранения определение загруженного класса и метаданных. Если большой кодовый, базовый проект загружен, имеет недостаточный размер Perm Gen size то это вызовит ошибку: Java.Lang.OutOfMemoryError: PermGen.
-XX:PermSize — Установить начальный размер для параметра «PermGen Size».
-XX:MaxPermSize — Установить максимальный размер для параметра «PermGen Size».
3. Размер java стека «Java Stack Size»
Размер java нитей (Size of a Java thread). Если проект имеет много обработки нитей, попробуйте уменьшить этот размер стека, чтобы избежать нехватки памяти.
-Xss = Установить размер стека Java (java thread stack size).
ЗАМЕТКА
Значение по умолчанию для heap size, perm gen, или stack size отличаются от различных JVM. Лучшие практически всегда определить собственные значение для сервера.
ТЕСТЫ или ГОТОВЫЕ примеры
Приведу различные тесты на разных ОС.
Ubuntu
Среда тестирования имеет такие характеристики:
ОС : Ubuntu 13 (64 битная) (Под управлением VirtualBox)
RAM : 4Гб оперативной памяти
CPU : 1 x Процессор
JDK : 1.7
Выполним команду для отображения необходимой информации:
Для JVM выделено следующие значения по умолчанию:
Java heap size
InitialHeapSize = 64781184 байт (61.7 Мб) и MaxHeapSize = 1038090240 байт (990Мб).
PermGen Size
PermSize = 21757952 байт (20.75 Мб), MaxPermSize = 174063616 байт (166 Мб)
Thread Stack Size
ThreadStackSize = 1024 кб (1 Мб)
Выделенный размер кучи (heap memory size) довольно близок к результатам эргономики.
#ergonomics algorithm
Initial heap size = 4096M/64 = 64 Мб
Maximum heap size = 4096M/4 = 1024 Мб
Mac OS X
Среда тестирования имеет такие характеристики:
ОС : Mac OSX 10.9
RAM : 8 Гб оперативной памяти
CPU : 4 x Поцессор
JDK : 1.7
Запускаем команду чтобы проверить:
Узнать размер Java Heap Memory Size в macOS X
Для JVM выделено следующие значения по умолчанию:
Java heap size
InitialHeapSize = 20655360 байт (19.69M) и MaxHeapSize = 331350016 bytes (316 Мб).
PermGen Size
PermSize = 21757952 байт (20.75 Мб), MaxPermSize = 85983232 байт (82 Мб).
Java Stack Size
ThreadStackSize = 1024 Кб (1 Мб)
Выделенный размер кучи памяти (heap memory size) не имеют никакого значения, если сравнить со следующий результат по алгоритму эргономики.
#ergonomics algorithm
Initial heap size = 8192M/64 = 128 Мб
Maximum heap size = 8192M/4 = 2048 Мб
Windows
Grep нет в Windows, вместо этого, мы используем Findstr.
Среда тестирования имеет такие характеристики:
ОС : Windows 8
RAM : 16 Гб
CPU : 8 x процессор
JDK : 1.7
Узнать размер Java Heap Memory Size в windows
Для JVM в Windows ОС выделено следующие значения по умолчанию:
Java heap size
InitialHeapSize = 266634176 байт (256 Мб) и MaxHeapSize = 4266146816 байт (4068 Мб).
PermGen Size
PermSize = 21757952 байт (20.75 Мб), MaxPermSize = 85983232 bytes (823 Мб).
Java Stack Size
ThreadStackSize = 0 kilobytes. (weird…)
Выделенный размер кучи памяти почти такой же как и по алгоритму эргономика:
#ergonomics algorithm
Initial heap size = 16384/64 = 256 Мб
Maximum heap size = 16384/4 = 4096 Мб
Предлагаемые для Java Memory
Ниже, я привел мою рекомендацию (параметры) для малой и средней нагрузки приложений Java 🙂
P.S: Для большинства проектов Java, 512k памяти для потока (thread) более чем достаточно.
оптимаьные значения для Java Heap Memory Size
Часто задаваемые вопросы.
Вывод
Наконец, значения по умолчанию для heap memory, perm gem и stack size отличается от JVM, не ожидайте что JVM будет использовать оптимальные значения для вашего приложения Java.
На этом, я завершаю «Узнать размер Java Heap Memory Size». Надеюсь, было познавательно.
Узнайте свой объем памяти кучи Java
Размеры кучи
Начальный размер кучи от 1/64 физической памяти до 1 Гбайт
Максимальный размер кучи от 1/4 физической памяти до 1 Гбайт
Однако вышеприведенные алгоритмы приведены только для справки, они могут различаться в разных ВМ.
1. Обзор памяти Java
Краткий обзор структуры памяти Java:
3. Размер стека Java
Размер потока Java. Если в проекте выполняется много потоков, попробуйте уменьшить этот размер стека, чтобы избежать нехватки памяти.
-Xss = установить размер стека Java-потока
Заметка
Значение по умолчанию для размера кучи, perm gen или размера стека отличается от разных JVM. Лучшая практика всегда определяет вашу собственную ценность.
2. Убунту
Это среда тестирования:
В вышеуказанной среде JVM выделяет следующие значения по умолчанию:
Выделенный объем памяти кучи довольно близок к результату эргономики.
3. Mac OSX
Это среда тестирования:
Выделенный объем памяти кучи совершенно не имеет значения, если сравнивать со следующим эргономическим результатом.
4. Windows
Это среда тестирования:
Выделенный объем памяти кучи практически одинаков с результатом эргономики:
5. Рекомендуемая память Java
Ниже мое рекомендуемое значение для небольшого и среднего Java-приложения 🙂
PS Для большинства Java-проектов достаточно 512 КБ для потока.
6. Часто задаваемые вопросы
7. Заключение
Наконец, значения по умолчанию для динамической памяти, гемов Perm и размера стека отличаются для каждой JVM, не ожидайте, что JVM назначит оптимальные значения для вашего Java-приложения. Лучше всего выяснить детали вашей памяти, а затем точно настроить значения.
Просто некоторые узнают и поделятся, дайте мне знать ваш комментарий.
Управление памятью Java
Это глубокое погружение в управление памятью Java позволит расширить ваши знания о том, как работает куча, ссылочные типы и сборка мусора.
Вероятно, вы могли подумать, что если вы программируете на Java, то вам незачем знать о том, как работает память. В Java есть автоматическое управление памятью, красивый и тихий сборщик мусора, который работает в фоновом режиме для очистки неиспользуемых объектов и освобождения некоторой памяти.
Поэтому вам, как программисту на Java, не нужно беспокоиться о таких проблемах, как уничтожение объектов, поскольку они больше не используются. Однако, даже если в Java этот процесс выполняется автоматически, он ничего не гарантирует. Не зная, как устроен сборщик мусора и память Java, вы можете создать объекты, которые не подходят для сбора мусора, даже если вы их больше не используете.
Для начала давайте посмотрим, как обычно организована память в Java:

Стек (Stack)
Стековая память отвечает за хранение ссылок на объекты кучи и за хранение типов значений (также известных в Java как примитивные типы), которые содержат само значение, а не ссылку на объект из кучи.
Кроме того, переменные в стеке имеют определенную видимость, также называемую областью видимости. Используются только объекты из активной области. Например, предполагая, что у нас нет никаких глобальных переменных (полей) области видимости, а только локальные переменные, если компилятор выполняет тело метода, он может получить доступ только к объектам из стека, которые находятся внутри тела метода. Он не может получить доступ к другим локальным переменным, так как они не выходят в область видимости. Когда метод завершается и возвращается, верхняя часть стека выталкивается, и активная область видимости изменяется.
Возможно, вы заметили, что на картинке выше отображено несколько стеков памяти. Это связано с тем, что стековая память в Java выделяется для каждого потока. Следовательно, каждый раз, когда поток создается и запускается, он имеет свою собственную стековую память и не может получить доступ к стековой памяти другого потока.
Куча (Heap)
Эта часть памяти хранит в памяти фактические объекты, на которые ссылаются переменные из стека. Например, давайте проанализируем, что происходит в следующей строке кода:
Ключевое слово new несет ответственность за обеспечение того, достаточно ли свободного места на куче, создавая объект типа StringBuilder в памяти и обращаясь к нему через «Builder» ссылки, которая попадает в стек.
Для каждого запущенного процесса JVM существует только одна область памяти в куче. Следовательно, это общая часть памяти независимо от того, сколько потоков выполняется. На самом деле структура кучи немного отличается от того, что показано на картинке выше. Сама куча разделена на несколько частей, что облегчает процесс сборки мусора.
Типы ссылок
Если вы внимательно посмотрите на изображение структуры памяти, вы, вероятно, заметите, что стрелки, представляющие ссылки на объекты из кучи, на самом деле относятся к разным типам. Это потому, что в языке программирования Java используются разные типы ссылок: сильные, слабые, мягкие и фантомные ссылки. Разница между типами ссылок заключается в том, что объекты в куче, на которые они ссылаются, имеют право на сборку мусора по различным критериям. Рассмотрим подробнее каждую из них.
1. Сильная ссылка
Это самые популярные ссылочные типы, к которым мы все привыкли. В приведенном выше примере со StringBuilder мы фактически храним сильную ссылку на объект из кучи. Объект в куче не удаляется сборщиком мусора, пока на него указывает сильная ссылка или если он явно доступен через цепочку сильных ссылок.
2. Слабая ссылка
Попросту говоря, слабая ссылка на объект из кучи, скорее всего, не сохранится после следующего процесса сборки мусора. Слабая ссылка создается следующим образом:
После сбора мусора ключа из WeakHashMap вся запись удаляется из карты.
3. Мягкая ссылка
Подобно слабым ссылкам, мягкая ссылка создается следующим образом:
4. Фантомная ссылка
Ссылки на String
Ссылки на тип String в Java обрабатываются немного по- другому. Строки неизменяемы, что означает, что каждый раз, когда вы делаете что-то со строкой, в куче фактически создается другой объект. Для строк Java управляет пулом строк в памяти. Это означает, что Java сохраняет и повторно использует строки, когда это возможно. В основном это верно для строковых литералов. Например:
При запуске этот код распечатывает следующее:
Следовательно, оказывается, что две ссылки типа String на одинаковые строковые литералы фактически указывают на одни и те же объекты в куче. Однако это не действует для вычисляемых строк. Предположим, что у нас есть следующее изменение в строке // 1 приведенного выше кода.
Strings are different
При добавлении вышеуказанного изменения создается следующий результат:
Процесс сборки мусора
Как обсуждалось ранее, в зависимости от типа ссылки, которую переменная из стека содержит на объект из кучи, в определенный момент времени этот объект становится подходящим для сборщика мусора.

Например, все объекты, отмеченные красным цветом, могут быть собраны сборщиком мусора. Вы можете заметить, что в куче есть объект, который имеет строгие ссылки на другие объекты, которые также находятся в куче (например, это может быть список, который имеет ссылки на его элементы, или объект, имеющий два поля типа, на которые есть ссылки). Однако, поскольку ссылка из стека потеряна, к ней больше нельзя получить доступ, так что это тоже мусор.
Чтобы углубиться в детали, давайте сначала упомянем несколько вещей:
Этот процесс запускается автоматически Java, и Java решает, запускать или нет этот процесс.
На самом деле это дорогостоящий процесс. При запуске сборщика мусора все потоки в вашем приложении приостанавливаются (в зависимости от типа GC, который будет обсуждаться позже).
На самом деле это более сложный процесс, чем просто сбор мусора и освобождение памяти.
Несмотря на то, что Java решает, когда запускать сборщик мусора, вы можете явно вызвать System.gc() и ожидать, что сборщик мусора будет запускаться при выполнении этой строки кода, верно?
Это ошибочное предположение.
Вы только как бы просите Java запустить сборщик мусора, но, опять же, Java решать, делать это или нет. В любом случае явно вызывать System.gc() не рекомендуется.
Поскольку это довольно сложный процесс и может повлиять на вашу производительность, он реализован разумно. Для этого используется так называемый процесс «Mark and Sweep». Java анализирует переменные из стека и «отмечает» все объекты, которые необходимо поддерживать в рабочем состоянии. Затем все неиспользуемые объекты очищаются.
Так что на самом деле Java не собирает мусор. Фактически, чем больше мусора и чем меньше объектов помечены как живые, тем быстрее идет процесс. Чтобы сделать это еще более оптимизированным, память кучи на самом деле состоит из нескольких частей. Мы можем визуализировать использование памяти и другие полезные вещи с помощью JVisualVM, инструмента, поставляемого с Java JDK. Единственное, что вам нужно сделать, это установить плагин с именем Visual GC, который позволяет увидеть, как на самом деле структурирована память. Давайте немного увеличим масштаб и разберем общую картину:

Когда объект создается, он размещается в пространстве Eden (1). Поскольку пространство Eden не такое уж большое, оно заполняется довольно быстро. Сборщик мусора работает в пространстве Eden и помечает объекты как живые.
Если объект выживает в процессе сборки мусора, он перемещается в так называемое пространство выжившего S0(2). Во второй раз, когда сборщик мусора запускается в пространстве Eden, он перемещает все уцелевшие объекты в пространство S1(3). Кроме того, все, что в настоящее время находится на S0(2), перемещается в пространство S1(3).
Если объект выживает в течение X раундов сборки мусора (X зависит от реализации JVM, в моем случае это 8), скорее всего, он выживет вечно и перемещается в пространство Old(4).
Принимая все сказанное выше, если вы посмотрите на график сборщика мусора (6), каждый раз, когда он запускается, вы можете увидеть, что объекты переключаются на пространство выживших и что пространство Эдема увеличивалось. И так далее. Старое поколение также может быть обработано сборщиком мусора, но, поскольку это большая часть памяти по сравнению с пространством Eden, это происходит не так часто. Метапространство (5) используется для хранения метаданных о ваших загруженных классах в JVM.
Представленное изображение на самом деле является приложением Java 8. До Java 8 структура памяти была немного другой. Метапространство на самом деле называется PermGen область. Например, в Java 6 это пространство также хранит память для пула строк. Поэтому, если в вашем приложении Java 6 слишком много строк, оно может аварийно завершить работу.
Типы сборщиков мусора
Фактически, JVM имеет три типа сборщиков мусора, и программист может выбрать, какой из них следует использовать. По умолчанию Java выбирает используемый тип сборщика мусора в зависимости от базового оборудования.
3. Mostly concurrent GC (В основном параллельный сборщик мусора). Если вы помните, ранее в этой статье упоминалось, что процесс сбора мусора на самом деле довольно дорогостоящий, и когда он выполняется, все потоки приостанавливаются. Однако у нас есть в основном параллельный тип GC, который утверждает, что он работает одновременно с приложением. Однако есть причина, по которой он «в основном» параллелен. Он не работает на 100% одновременно с приложением. Есть период времени, на который цепочки приостанавливаются. Тем не менее, пауза делается как можно короче для достижения наилучшей производительности сборщика мусора. На самом деле существует 2 типа в основном параллельных сборщиков мусора:
Примечание переводчика. Информация про сборщики мусора для различных версий Java приведена в переводе:
Советы и приемы
Чтобы минимизировать объем памяти, максимально ограничьте область видимости переменных. Помните, что каждый раз, когда выскакивает верхняя область видимости из стека, ссылки из этой области теряются, и это может сделать объекты пригодными для сбора мусора.
Явно устанавливайте в null устаревшие ссылки. Это сделает объекты, на которые ссылаются, подходящими для сбора мусора.
Избегайте финализаторов (finalizer). Они замедляют процесс и ничего не гарантируют. Фантомные ссылки предпочтительны для работы по очистке памяти.
JVisualVM также имеет функцию создания дампа кучи в определенный момент, чтобы вы могли анализировать для каждого класса, сколько памяти он занимает.
Настройте JVM в соответствии с требованиями вашего приложения. Явно укажите размер кучи для JVM при запуске приложения. Процесс выделения памяти также является дорогостоящим, поэтому выделите разумный начальный и максимальный объем памяти для кучи. Если вы знаете его, то не имеет смысла начинать с небольшого начального размера кучи с самого начала, JVM расширит это пространство памяти. Указание параметров памяти выполняется с помощью следующих параметров:
Если приложение Java выдает ошибку OutOfMemoryError и вам нужна дополнительная информация для обнаружения утечки, запустите процесс с –XX:HeapDumpOnOutOfMemory параметром, который создаст файл дампа кучи, когда эта ошибка произойдет в следующий раз.
Заключение
Что такое Heap и Stack память в Java?
В Java есть такие понятия как Heap и Stack память. Сегодня мы узнаем разницу между ними и зачем они нужны. Как всегда, сначала в теории и затем на практике разберем эту сложную тему.
Java Heap память
Java Heap (куча) используется Java Runtime для выделения памяти под объекты и JRE классы. Создание нового объекта также происходит в куче. Здесь работает сборщик мусора: освобождает память путем удаления объектов, на которые нет каких-либо ссылок. Любой объект, созданный в куче, имеет глобальный доступ и на него могут ссылаться с любой части приложения.
Stack память в Java
Стековая память в Java работает по схеме LIFO (Последний-зашел-Первый-вышел). Всякий раз, когда вызывается метод, в памяти стека создается новый блок, который содержит примитивы и ссылки на другие объекты в методе. Как только метод заканчивает работу, блок также перестает использоваться, тем самым предоставляя доступ для следующего метода.
Размер стековой памяти намного меньше объема памяти в куче.
Давайте рассмотрим отличия стековой памяти и кучи на примере простой программы.
На картинке ниже представлена память стека и кучи для программы выше
А теперь рассмотри шаги выполнения нашей программы:
Разница между Stack и Heap памятью в Java
На основании приведенных выше объяснений, мы можем легко подытожить следующие различия между Heap и Stack памятью в Java.
Вот и все, что нужно знать о Stack и Heap памяти в Java. Следите за обновлениями в разделе Полезности.
How to control Java heap size (memory) allocation (xmx, xms)
Java memory FAQ: How do I control the amount of memory my Java program uses (i.e., Java RAM usage)?
The short answer
The short answer is that you use these java command-line parameters to help control the RAM use of application:
Use this syntax to specify the amount of memory the JVM should use:
A complete java command looks like this:
See the rest of this article for more details. Also see my Java heap and stack definitions if you’re not comfortable with those terms.
The longer answer
As a bit of background, I’m running a Java application on a Raspberry Pi device where memory is limited. Unfortunately, every time I try to run the program I get this Java heap size error message:
“Error occurred during initialization of VM. Could not reserve enough space for object heap. Could not create the Java virtual machine.”
I knew my program doesn’t need a lot of memory — it was just hitting a database and generating some files and reports — so I got around this memory limit problem by specifying the maximum Java heap size my program was allowed to allocate. In my case I didn’t think about it too hard and just chose a heap size limit of 64 MB RAM, and after I set this RAM limit my program ran fine.
Setting the maximum Java heap size (Xmx)
Using that memory limit setting, the Java command I use in my shell script to start my Java program looks like this:
More Java memory-related command line arguments
From that list, the command-line arguments specifically related to Java application memory use are:
Java heap size descriptions (xms, xmx, xmn)
Java memory arguments (xms, xmx, xmn) formatting (MB, GB)
When setting the Java heap size, you should specify your memory argument using one of the letters “m” or “M” for MB, or “g” or “G” for GB. Your setting won’t work if you specify “MB” or “GB.” Valid arguments look like this:







