Java Heap Space Memory с Runtime API

1. Общ преглед

В тази статия ще обсъдим приложните програмни интерфейси (API), предоставени от Java, които могат да ни помогнат да разберем няколко аспекта, свързани с Java купчината пространство.

Това може да бъде полезно за разбиране на текущото състояние на паметта на JVM и възлагането му на услуги за наблюдение като StatsD и Datadog, които след това могат да бъдат конфигурирани да предприемат превантивни действия и да избягват неуспехите на приложенията.

2. Достъп до параметрите на паметта

Всяко приложение на Java има един екземпляр на java.lang.Runtime, който може да ни помогне да разберем текущото състояние на паметта на приложението. Статичният метод Runtime # getRuntime може да бъде извикан, за да се получи екземпляр на Runtime за еднократно изпълнение .

2.1. Обща памет

Методът на изпълнение # getTotalMemory връща общото пространство на купчината, запазено в момента от JVM в байтове. Включва паметта, запазена за настоящи и бъдещи обекти. Следователно не е гарантирано, че ще бъде постоянен по време на изпълнението на програмата, тъй като пространството на купчина Java може да бъде разширено или намалено, тъй като са разпределени повече обекти.

Освен това тази стойност не е непременно това, което се използва, или максималната налична памет.

2.2. Свободна памет

Методът Runtime # freeMemory връща свободното пространство за купчина, налично за разпределение на нови обекти в байтове. Той може да се увеличи в резултат на операция за събиране на боклук, където след това е налице повече свободна памет.

2.3. Максимална памет

Методът Runtime # maxMemory връща максималната памет, която JVM ще се опита да използва. След като използването на паметта на JVM достигне тази стойност, тогава тя няма да разпределя повече памет и вместо това ще събира по-често боклука.

Ако обектите на JVM все още се нуждаят от повече памет дори след стартиране на събирача на боклук, тогава JVM може да хвърли изключение по време на изпълнение java.lang.OutOfMemoryErro r.

3. Пример

В примера по-долу инициализираме ArrayList и добавяме елементи към него, като същевременно следим пространството на купчина JVM, използвайки горните три метода:

ArrayList arrayList = new ArrayList(); System.out.println("i \t Free Memory \t Total Memory \t Max Memory"); for (int i = 0; i < 1000000; i++) { arrayList.add(i); System.out.println(i + " \t " + Runtime.getRuntime().freeMemory() + " \t \t " + Runtime.getRuntime().totalMemory() + " \t \t " + Runtime.getRuntime().maxMemory()); } // ...
Output: i Free Memory Total Memory Max Memory 0 254741016 257425408 3817865216 1 254741016 257425408 3817865216 ... 1498 254741016 257425408 3817865216 1499 253398840 257425408 3817865216 1500 253398840 257425408 3817865216 ... 900079 179608120 260046848 3817865216 900080 302140152 324534272 3817865216 900081 302140152 324534272 3817865216 ...
  • Ред 1498: Стойността Runtime # freeMemory намалява, когато на достатъчно обекти се разпредели място в Java купчината.
  • Ред 900080: Към този момент JVM разполага с повече място, тъй като GC е изпълнил, следователно стойностите на Runtime # freeMemory и Runtime # totalMemory се увеличават.

Стойностите, показани по-горе, се очаква да бъдат различни при всяко изпълнение на Java приложение.

4. Персонализиране на параметрите на паметта

Можем да заменим стойностите по подразбиране за параметрите на паметта на JVM, като зададем персонализирани стойности на определени флагове при стартиране на нашата програма Java, за да постигнем необходимата производителност на паметта:

  • -Xms: Стойността, присвоена на флаг -Xms, задава началната и минималната стойност на Java купчината. Може да се използва в случаите, когато нашето приложение изисква повече памет от минималния по подразбиране при стартиране на JVM
  • -Xmx: По същия начин можем да зададем максималната стойност за пространството на купчината, като го присвоим на флаг -Xmx . Може да се използва, когато искаме нарочно да ограничим обема памет, който ще използва нашето приложение.

Моля, имайте предвид също, че стойността -Xms трябва да бъде равна или по-малка от стойността -Xmx .

4.1. Употреба

java -Xms32M -Xmx64M Main Free Memory : 31792664 bytes Total Memory : 32505856 bytes Max Memory : 59768832 bytes java -Xms64M -Xmx64M Main Free Memory : 63480640 bytes Total Memory : 64487424 bytes Max Memory : 64487424 bytes java -Xms64M -Xmx32M Main Error occurred during initialization of VM Initial heap size set to a larger value than the maximum heap size

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

В тази статия видяхме как да извлечем метрики на JVM паметта чрез класа Runtime . Тези методи могат да бъдат полезни при разследване на изтичане на памет на JVM и други проблеми, свързани с производителността на JVM паметта.

Също така показахме как да присвоите персонализирани стойности за определени флагове, водещи до различно поведение на JVM паметта за различни сценарии.