Пристрій пам’яті Java-процесу
Якщо ви читаєте цю статтю, значить, ви вже працюєте з Java і не хочете зупинятися на простому знанні синтаксису мови, стандартних бібліотек і популярних Java-фреймворків — ви дійсно хочете знати, як працює JVM, як виділяється пам'ять і відбувається процес складання сміття.
У цій статті я хочу познайомити вас з пристроєм пам'яті Java. Звідси ви дізнаєтеся, де в Java зберігаються локальні змінні, створюються об'єкти та як регулювати розмір різних областей пам'яті для Java-процесу.
Отже, давайте спочатку поглянемо з яких областей складається пам'ять, яку JVM виділяє для вашої програми.

Java Heap.
А тепер давайте докладніше. Пам'ять під об'єкти, які ви створюєте у своїй програмі JVM виділяє з області, званоїкупою (heap), яка розділена на частини - так званийYoungGeneration таOld Generation. Навіщо ділити усю пам'ять на дві частини?
Більш детально ми поговоримо про це у статті, присвяченій механізму збирання сміття в JVM. Зараз я поясню це зовсім коротко: складання сміття в Java ґрунтується на так званій слабкій гіпотезі про покоління, яка говорить про те, що більшість створюваних у програмі об'єктів вмирають рано: це всілякі локальні змінні, тимчасові об'єкти, які швидко відживають своє і більше не потрібні. Garbage collector'у (збиральнику сміття) потрібно підібрати їх в одному з наступних проходів та звільнити пам'ять.
Спочатку всі об'єкти знаходяться вYoung Generation. Але інші об'єкти (менша їх частина), які можуть існувати тривалий час або протягом всього додатку, не потрібно видаляти. На ці об'єкти завжди потрібні «живі» посилання. Складальник сміття не видаляє їх доПоки посилання на них ще існують. Вони переживають одну за одною складання сміття і нарешті переміщаються в другу частину Java-Heap'а —Old Generation, звідки з набагато меншою ймовірністю будуть колись видалені (звичайно, все залежить від специфіки вашої програми та розміру купи , див. нижче).
Що робити, якщо ви отрималиOut of Memory Error: java heap space і впевнені в тому, що ваша програма не страждає від витоку пам'яті або неефективного коду?
Ви можете регулювати розмір купи, запустивши вашу програму з наступними параметрами:-Xms (мінімальний розмір Java heap'а) абоXmx (максимальний розмір Java heap'a).
Permanent Generation.
При першому завантаженні класу JVM створює об'єктClass. Це метаінформація, необхідна для створення нових об'єктів в Java, зберігається якраз в області пам'яті, що називаєтьсяPermanent Generation. Код ваших методів також зберігається тут, як і всі статичні змінні та методи.
І ще: тепер, отримавши в процесі виконання вашої програми винятокOut of Memory Error: PermGen space, ви будете знати, розмір якої області пам'яті Java-процесу треба збільшити. Для цього використовуйте параметри запуску програми: -XX:PermSize (початковий розмір PermGen) або-XX:MaxPermSize (максимальний розмір PermGen).
Java Stack.
Java – це стікова віртуальна машина. Сподіваюся, вам не потрібно пояснювати, що таке стек. Якщо ви все ж таки потребуєте освіжити свої знання, зверніться до цієї статті.
Отже, JVM завантажує в стек всі локальні змінні та параметри методів, що викликаються. При подальшому виконанні програми вона їх звідти забирає, здійснює потрібні дії та кладе результат назад у стек чи просто витягуєнаступний операнд. Також потрібно знати, що стек ділиться на декілька областей, що відповідають кожному потоку, що виконується у вашій програмі.
Якщо всім потокам у вашій програмі потрібно більше пам'яті і ви хочете уникнутиStackOverflowError, то є сенс збільшити розмір стека, використовуючи параметр-Xss. Окремо слід приділити увагу потокам, де можливі рекурсивні виклики методів. Також, для більш точного регулювання розміру доступної пам'яті для кожного потоку, можна скористатися одним із конструкторів класуThread (ThreadGroup group, Runnable target, String name, long stackSize), що може виявитися більш розумним рішенням. Останній параметрstackSize говорить сам за себе.
Я сказав, що в стеку зберігаються всі локальні змінні та параметри. Але це зовсім так. Для об'єктів зберігаються лише посилання ними, тоді як самі об'єкти перебувають у купі. До речі, це вже не зовсім так завдяки функціїEscape Analysis з Java 6: ті об'єкти, які є виключно локальними і не повертаються за межі методу, що виконується, також зберігаються в стеку. Це зроблено для того, щоб збирач сміття згодом міг швидко їх видалити.