如何监控Java的内存使用情况?如何监控Java的内存使用情况?(How to monitor Ja

2019-05-14 02:51发布

我们在JBoss上运行的J2EE应用程序,我们需要监控其内存使用情况。 目前,我们使用下面的代码

    System.gc();
    Runtime rt = Runtime.getRuntime();
    long usedMB = (rt.totalMemory() - rt.freeMemory()) / 1024 / 1024;
    logger.information(this, "memory usage" + usedMB);

此代码工作正常。 这意味着它示出了对应于现实记忆曲线。 当我们创建一个从DB一个大的XML文件的曲线上升,提取结束后,它的股价下跌。

一位顾问告诉我们,调用GC()明确地是错误的,“让JVM决定何时运行GC”。 基本上他的论点一样在这里disscussed 。 但我还是不明白:

  • 我怎么能有我的内存使用情况的曲线?
  • 什么是错的明确GC()? 我不在乎能有明确的GC()和我将在1-3%估计发生小的性能问题。 我需要的是内存和线程监视器,它帮助我在我们的客户现场系统的分析。

Answer 1:

如果你想真正了解一下什么是虚拟机的内存怎么回事,你应该使用这样的好工具VisualVM的 。 这个软件是免费的,它看到正在发生的事情的好方法。

没有什么是真正的“错误”有明确的GC()的调用。 但是,请记住,当你调用GC()你“暗示”垃圾收集器运行。 没有保证,它会在你运行该命令的确切时间运行。



Answer 2:

有迹象表明,让你监视虚拟机的内存使用的工具。 该VM可以公开使用JMX内存统计信息 。 您也可以打印GC统计看内存是如何执行一段时间。

调用System.gc()的可能会损害GC的性能,因为对象将从新被过早地转移到老一代人,而弱引用会被过早清除。 这可能会导致记忆力减退效率,更长的GC时间,降低缓存命中率(对于使用弱裁判高速缓存)。 我同意你的顾问:System.gc()的是坏的。 我会去尽可能以禁用它使用命令行开关。



Answer 3:

你可以看看stagemonitor 。 它是一个开源的Java(网络)应用程序性能监控。 它捕获响应时间度量,JVM度量,请求细节(包括由该请求剖析器捕获的调用堆栈)越来越。 开销是非常低的。

或者,您可以用伟大的时间序列数据库石墨它来存储数据点,你可以看看花哨的仪表盘很长的历史。

例:

看看该项目的网站上看到的截图,功能描述和文档。

注:我stagemonitor开发商



Answer 4:

我要说的是,顾问是正确的理论,你是正确的做法。 正如俗话说 :

从理论上讲,理论和实践上都是一样的。 在实践中,他们都没有。

Java的规范说的System.gc建议调用垃圾收集。 在实践中,它只是产生一个线程,运行马上在Sun JVM。

虽然在理论上可以被搞乱了一些微调JVM执行垃圾收集的,除非你正在写意图在任何JVM将被部署在那里的通用代码,不用担心。 如果是为你工作,做到这一点。



Answer 5:

您是否尝试过JMX?

http://java.sun.com/developer/technicalArticles/J2SE/jconsole.html


(来源: sun.com )



Answer 6:

窥视到里面是什么tomcat的通过Visual VM发生。 http://www.skill-guru.com/blog/2010/10/05/increasing-permgen-size-in-your-server/



Answer 7:

看看JVM的ARGS: http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp#DebuggingOptions

XX:在垃圾收集-PrintGC打印的消息。 管理。

-XX:-PrintGCDetails在垃圾收集打印更多的细节。 管理。 (介绍了在1.4.0。)

-XX:在垃圾收集-PrintGCTimeStamps打印时间戳。 可管理(介绍了在1.4.0。)

-XX:-PrintTenuringDistribution打印tenuring年龄信息。

虽然你不会打乱用显式调用到JVM System.gc()他们可能没有您所期待的效果。 要真正了解发生了什么事情,在与读什么,一切都在一个JVM内存布赖恩戈茨写道。



Answer 8:

在生产系统上运行的明确System.gc()的是一个可怕的想法。 如果内存获取到任何大小可言,整个系统可以冻结,而一个完整的GC运行。 在多千兆字节大小的服务器,这很容易被非常明显,这取决于JVM是如何配置的,多少净空它,等等等等 - 我见过的超过30秒的停顿。

另一个问题是,通过显式调用GC您实际上并不监视JVM是如何运行GC,你实际上改变它 - 这取决于你如何配置的JVM,这将垃圾回收适当的时候,通常递增(它不只是运行一个完整的GC,当它运行的内存)。 你会被打印出来会有什么什么像什么的JVM会做它自己 - 一件事,你可能会看到更少的自动/增量GC的,你会被手动清除内存。

正如尼克·霍尔特的帖子指出,选择打印GC活动已经存在的JVM标志。

你可以有一个线程,只是打印出免费的,可以在合理的时间间隔,这将显示您的实际MEM使用率。



Answer 9:

如果你喜欢一个很好的方式,在命令行中使用jstat做到这一点:

http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jstat.html

它提供了可配置的间隔原始信息是用于记录和绘图的目的是非常有用的。



Answer 10:

如果你使用的Java 1.5,你可以看看ManagementFactory.getMemoryMXBean(),它给你的所有种类的内存数量。 堆和非堆,烫发根。

一个很好的例子在那里可以找到http://www.freshblurbs.com/explaining-java-lang-outofmemoryerror-permgen-space



Answer 11:

如果你使用JMX提供GC的历史运行时,您可以使用相同的前/后的数字,你就是没有强制GC。

你只需要记住,那些GC运行(通常是一个老人和一个新的一代)不是定期intervalls,所以你需要提取的开始时间以及密谋(或你暗算的序列号,对于大多数实用的目的,这将是足够的策划)。

例如在Oracle HotSpot虚拟机与ParNewGC,还有的JMX MBean所谓java.lang:type=GarbageCollector,name=PS Scavenge ,它有一个属性LastGCInfo,它返回最后YG清道夫运行的CompositeData。 它记录duration ,绝对的startTimememoryUsageBeforememoryUsageAfter

只需用一个定时器来读取属性。 每当一个新的开始时间显示出来,你知道,它描述了一个新的GC事件后,你解压存储信息,并保持轮询下一次更新。 (不知道是否AttributeChangeNotification某种程度上都可以使用。)

提示:在计时器您可能测量到最后GC运行的距离,如果这是你绘制的resulution太长,你可以()有条件地调用的System.gc。 但是我不会做,在一个OLTP实例。



Answer 12:

正如已经建议,尝试的VisualVM得到一个基本观点。

您也可以使用Eclipse MAT,做了更详细的内存分析。

这是确定做一个System.gc()的,只要你不依赖于它,为你的程序的正确性。



Answer 13:

用的System.gc的问题,就是JVM已经自动分配时间根据内存使用的垃圾收集器。

但是,如果你是,例如,在一个非常有限的内存的工作状态,比如移动设备,的System.gc允许你手动朝着这个垃圾收集分配更多的时间,但在CPU时间成本(但是,如你所说,你是不是担心GC的性能问题)。

最好的做法很可能是只使用它,你可能会做大量释放的(如冲洗大阵)。

所有的考虑,因为你只是担心内存使用情况,随时来电GC,或者更好的,看它是否太大的内存差别在你的情况,然后再决定。



文章来源: How to monitor Java memory usage?