监控 Java 应用程序自己的内存使用情况

Posted

技术标签:

【中文标题】监控 Java 应用程序自己的内存使用情况【英文标题】:Monitoring own memory usage by Java application 【发布时间】:2012-05-25 12:49:42 【问题描述】:

我想在一个 Java 进程中运行多个 REST Web 应用程序,以在 Akka 的帮助下节省内存并轻松扩展。我想估计每个请求处理程序消耗多少内存并检测这些对整个系统的危险。

    是否可以在该进程内几乎实时监控内存使用情况,并找出每个请求处理程序使用了多少内存?我需要什么来实现这一目标?有什么工具吗?

    是否可以捕获 out of memory exception 并根据内存使用情况做一些事情,例如仅崩溃请求处理程序超出假定的内存限制?如果是这样,那有什么不好的?

【问题讨论】:

这是一个棘手的问题。在此处查看更多信息:***.com/questions/52353/… 【参考方案1】:

一个程序的总已用/空闲内存可以通过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));
  
 

【讨论】:

【参考方案2】:

要回答您的第一个问题,您可以使用许多工具来监控内存使用情况,但是我不知道有任何应用程序可以“实时”将内存使用情况映射到线程。在应用程序中,您可以使用MemoryMXBean 和MemoryPoolMXBeans 来监控内存使用情况,

回答你的第二个问题:不,不是。除了捕获 OOME 通常是个坏主意之外,主要问题是接收异常的线程可能不是真正的罪魁祸首。 OOME 被抛出到发出最终分配请求的线程上。然而,一些 other 线程可能会占满大部分内存。另一个问题是,由于 OOME 可以随时抛出,它可能会被抛出到应用程序的一些关键代码中,使其处于瘫痪状态。长话短说,您几乎总是希望在收到 OOME 时重新启动您的应用程序。

【讨论】:

感谢您的回答。 1.所以我只能将内存映射到线程?不能做一些更复杂的事情吗? 2. 我想根据内存使用信息处理的OOME源问题,所以我可以知道问题是否在我的请求处理程序中。如果不是,我可以升级异常并重新启动整个 JVM。这还是个坏主意吗? 我不确定我是否理解您评论中的任何内容。 1. 正如我所说,我不知道有任何解决方案可以以编程方式或“实时”将内存使用映射到线程。 2. 我不明白你的意思。 啊,我误会你了。我假设可以跟踪单个组件的内存使用情况,并在捕获 OOME(谁抛出以及每个组件正在使用多少内存)时使用此信息来确定一个组件是否可以为其余组件安全地杀死。 所以在 java.lang.management 是我所能得到的。这些信息通过 JMX 与所有监控工具共享?还有什么?我对吗? docs.oracle.com/javase/6/docs/api/java/lang/management/… @RafałSobota - 您可以从 java.lang.management 获得的信息是您可以从标准 jdk 获得的所有信息(这些值可从 jvm 和任何外部 jmx 工具)。一个特定的 jvm 实现可能有其他 专有 监控能力,但我不知道有什么具体的。【参考方案3】:

VisualVM 是监控应用程序的一个简单易用的好工具。你可以试试:http://visualvm.java.net/

【讨论】:

这真的是为了外部监控。【参考方案4】:

您还可以添加代码语句来监控空闲内存,例如:

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

无法处理此异常。问题是,如果您在一个通用的应用服务器(例如 tomcat)中运行所有 Web 服务,那么如果出现“内存不足”异常,JVM 就会崩溃。尝试查看您的程序中是否存在任何内存泄漏或错误的内存处理。您可以在 Netbeans 或 Eclipse 中使用分析。此外,使用“findbugs”或“sonar”之类的工具进行代码分析可能会向您展示代码中可能存在的不良做法。

在任何情况下,使用有关垃圾收集或 JVM 内存的 java 选项(如 -Xmx)可以减少此类异常并提高性能。

【讨论】:

使用 Runtime.freeMemory() 时需要注意的重要一点是,它包含当前在堆上的垃圾,因此可能无法提供您想要的。 没错,你是对的。谢谢你的评论。但是,在许多不良内存处理的情况下,它可能具有指示性。

以上是关于监控 Java 应用程序自己的内存使用情况的主要内容,如果未能解决你的问题,请参考以下文章

如何使用JVisualVM远程监控和优化Tomcat和Java程序的内存和CPU

Linux—JVM等性能调优监控

Linux—JVM等性能调优监控

监控自身进程的内存使用情况

Java千百问_07JVM架构(018)_如何监控jvm的运行情况

监控每个线程的内存使用情况