Мониторинг использования собственной памяти с помощью приложения Java

Я хочу запустить несколько веб-приложений REST внутри одного Java-процесса, чтобы сэкономить память и масштабировать с помощью Akka. Я хотел бы оценить, сколько памяти каждый обработчик запросов потребляет и обнаруживает, что они опасны для всей системы.

  • Возможно ли отслеживать использование памяти почти в реальном времени внутри этого процесса и выяснить, сколько памяти используется для каждого обработчика запросов? Что мне нужно для этого? Есть ли какие-нибудь инструменты?

  • Можно ли поймать out of memory exception и на основе использования памяти сделать что-то, например, только обработчики запросов с превышением допустимого предела памяти? Если да, то что может быть плохо с этим?

Ответ 1

Чтобы ответить на ваш первый вопрос, есть много инструментов, которые вы можете использовать для мониторинга использования памяти, однако я не знаю ни одного приложения, которое отображает использование памяти в потоки в "реальном" времени. В приложении вы можете использовать MemoryMXBean и MemoryPoolMXBeans для мониторинга использования памяти,

Чтобы ответить на второй вопрос: нет, не совсем. Помимо того факта, что, как правило, плохой идеей ловить OOME, основная проблема заключается в том, что поток, который получает исключение, может быть не фактическим виновником. OOME выбрасывается в поток, который делает окончательный запрос на выделение. однако другой поток может быть тем, который заполняет большую часть памяти. Другая проблема заключается в том, что, поскольку OOME может быть брошен в любое время, он может быть брошен внутри некоторого критического кода в вашем приложении, оставив его в искаженном состоянии. Короче говоря, вы почти всегда хотите перезапустить приложение, когда получаете OOME.

Ответ 2

Общая используемая/свободная память программы может быть получена в программе через java.lang.Runtime.getRuntime();

Время выполнения имеет несколько методов, которые относятся к памяти. Следующий пример кодирования демонстрирует его использование.

package test;

import java.util.ArrayList;
import java.util.List;

public class PerformanceTest {
  private static final long MEGABYTE = 1024L * 1024L;

  public static long bytesToMegabytes(long bytes) {
    return bytes / MEGABYTE;
  }

  public static void main(String[] args) {
    // I assume you will know how to create a object Person yourself...
    List<Person> list = new ArrayList<Person>();
    for (int i = 0; i <= 100000; i++) {
      list.add(new Person("Jim", "Knopf"));
    }
    // Get the Java runtime
    Runtime runtime = Runtime.getRuntime();
    // Run the garbage collector
    runtime.gc();
    // Calculate the used memory
    long memory = runtime.totalMemory() - runtime.freeMemory();
    System.out.println("Used memory is bytes: " + memory);
    System.out.println("Used memory is megabytes: "
        + bytesToMegabytes(memory));
  }
} 

Ответ 3

Хорошим и легким инструментом для мониторинга вашего приложения является VisualVM. Вы можете попробовать: http://visualvm.java.net/

Ответ 4

Вы также можете добавить в свои инструкции кода для контроля свободной памяти, например:

Runtime runtime = Runtime.getRuntime();
System.out.println("Free memory: " + runtime.freeMemory() + " bytes.");

Невозможно обработать это исключение. Проблема в том, что если вы используете все свои веб-службы на общем сервере приложений (например, tomcat), то, если есть исключение из памяти, JVM будет работать. Попытайтесь увидеть, есть ли утечка памяти или неправильная обработка памяти в вашей программе. Вы можете использовать профилирование внутри Netbeans или Eclipse. Кроме того, анализ кода с помощью инструмента, такого как "findbugs" или "sonar", может показать вам возможные неправильные методы внутри вашего кода.

В любом случае использование java-параметров в отношении коллекции мусора или памяти JVM (например, -Xmx) может уменьшить такие исключения и повысить производительность.