如何监控Java内存使用情况?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1058991/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to monitor Java memory usage?
提问by Oleg Pavliv
We have a j2ee application running on Jboss and we want to monitor its memory usage. Currently we use the following code
我们有一个在 Jboss 上运行的 j2ee 应用程序,我们想监控它的内存使用情况。目前我们使用以下代码
System.gc();
Runtime rt = Runtime.getRuntime();
long usedMB = (rt.totalMemory() - rt.freeMemory()) / 1024 / 1024;
logger.information(this, "memory usage" + usedMB);
This code works fine. That means it shows memory curve which corresponds to reality. When we create a big xml file from a DB a curve goes up, after the extraction is finished it goes down.
这段代码工作正常。这意味着它显示了与现实相对应的记忆曲线。当我们从数据库创建一个大的 xml 文件时,曲线上升,提取完成后曲线下降。
A consultant told us that calling gc() explicitly is wrong, "let jvm decide when to run gc". Basically his arguments were the same as disscussed here. But I still don't understand:
一位顾问告诉我们,明确调用 gc() 是错误的,“让 jvm 决定何时运行 gc”。基本上他的论点与这里讨论的相同。但我还是不明白:
- how can I have my memory usage curve?
- what is wrong with the explicit gc()? I don't care about small performance issues which can happen with explicit gc() and which I would estimate in 1-3%. What I need is memory and thread monitor which helps me in analysis of our system on customer site.
- 我怎样才能得到我的内存使用曲线?
- 显式 gc() 有什么问题?我不关心显式 gc() 可能发生的小性能问题,我估计会出现 1-3% 的问题。我需要的是内存和线程监视器,它可以帮助我分析客户站点上的系统。
采纳答案by amischiefr
If you want to really look at what is going on in the VM memory you should use a good tool like VisualVM. This is Free Software and it's a great way to see what is going on.
如果您想真正了解 VM 内存中发生的情况,您应该使用像VisualVM这样的好工具。这是自由软件,它是了解正在发生的事情的好方法。
Nothing is really "wrong" with explicit gc()
calls. However, remember that when you call gc()
you are "suggesting" that the garbage collector run. There is no guarantee that it will run at the exact time you run that command.
显式gc()
调用没有什么是真正的“错误” 。但是,请记住,当您调用时,gc()
您是在“建议”垃圾收集器运行。无法保证它会在您运行该命令的确切时间运行。
回答by Yishai
I would say that the consultant is right in the theory, and you are right in practice. As the saying goes:
我会说顾问在理论上是正确的,而您在实践中是正确的。正如俗话说:
In theory, theory and practice are the same. In practice, they are not.
在理论上,理论和实践是相同的。在实践中,他们不是。
The Java spec says that System.gc suggests to call garbage collection. In practice, it just spawns a thread and runs right away on the Sun JVM.
Java 规范说 System.gc 建议调用垃圾收集。实际上,它只是生成一个线程并立即在 Sun JVM 上运行。
Although in theory you could be messing up some finely tuned JVM implementation of garbage collection, unless you are writing generic code intended to be deployed on any JVM out there, don't worry about it. If it works for you, do it.
尽管理论上您可能会搞乱一些经过微调的 JVM 垃圾收集实现,除非您正在编写打算部署在任何 JVM 上的通用代码,否则不要担心。如果它对你有用,那就去做吧。
回答by Tom
Have you tried JMX?
你试过 JMX 吗?
http://java.sun.com/developer/technicalArticles/J2SE/jconsole.html
http://java.sun.com/developer/technicalArticles/J2SE/jconsole.html
(source: sun.com)
(来源:sun.com)
回答by Nick Holt
Take a look at the JVM args: http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp#DebuggingOptions
看看 JVM 参数:http: //java.sun.com/javase/technologies/hotspot/vmoptions.jsp#DebuggingOptions
XX:-PrintGC Print messages at garbage collection. Manageable.
-XX:-PrintGCDetails Print more details at garbage collection. Manageable. (Introduced in 1.4.0.)
-XX:-PrintGCTimeStamps Print timestamps at garbage collection. Manageable (Introduced in 1.4.0.)
-XX:-PrintTenuringDistribution Print tenuring age information.
XX:-PrintGC 在垃圾收集时打印消息。可管理。
-XX:-PrintGCDetails 在垃圾收集时打印更多详细信息。可管理。(在 1.4.0 中引入。)
-XX:-PrintGCTimeStamps 在垃圾回收时打印时间戳。可管理(在 1.4.0 中引入。)
-XX:-PrintTenuringDistribution 打印任期年龄信息。
While you're not going to upset the JVM with explicit calls to System.gc()
they may not have the effect you are expecting. To really understand what's going on with the memory in a JVM with read anything and everything the Brian Goetzwrites.
虽然您不会通过显式调用来扰乱 JVM,System.gc()
但它们可能不会达到您期望的效果。要真正了解 JVM 中的内存发生了什么,并读取Brian Goetz写的所有内容和所有内容。
回答by Zoukaye
If you use java 1.5, you can look at ManagementFactory.getMemoryMXBean() which give you numbers on all kinds of memory. heap and non-heap, perm-gen.
如果您使用 java 1.5,您可以查看 ManagementFactory.getMemoryMXBean() ,它为您提供各种内存的数字。堆和非堆,永久代。
A good example can be found there http://www.freshblurbs.com/explaining-java-lang-outofmemoryerror-permgen-space
一个很好的例子可以在那里找到 http://www.freshblurbs.com/explaining-java-lang-outofmemoryerror-permgen-space
回答by u7867
There are tools that let you monitor the VM's memory usage. The VM can expose memory statistics using JMX. You can also print GC statisticsto see how the memory is performing over time.
有一些工具可让您监控 VM 的内存使用情况。该VM可以公开使用JMX内存统计信息。您还可以打印 GC 统计信息以查看内存随时间的运行情况。
Invoking System.gc() can harm the GC's performance because objects will be prematurely moved from the new to old generations, and weak references will be cleared prematurely. This can result in decreased memory efficiency, longer GC times, and decreased cache hits (for caches that use weak refs). I agree with your consultant: System.gc() is bad. I'd go as far as to disable itusing the command line switch.
调用 System.gc() 会损害 GC 的性能,因为对象会过早地从新生代移到老年代,并且弱引用会过早清除。这会导致内存效率降低、GC 时间延长和缓存命中减少(对于使用弱引用的缓存)。我同意你的顾问:System.gc() 不好。我会尽可能使用命令行开关禁用它。
回答by Steve B.
Explicitly running System.gc() on a production system is a terrible idea. If the memory gets to any size at all, the entire system can freeze while a full GC is running. On a multi-gigabyte-sized server, this can easily be very noticeable, depending on how the jvm is configured, and how much headroom it has, etc etc - I've seen pauses of more than 30 seconds.
在生产系统上显式运行 System.gc() 是一个糟糕的主意。如果内存达到任何大小,整个系统可能会在 full GC 运行时冻结。在一个多 GB 大小的服务器上,这很容易变得非常明显,这取决于 jvm 的配置方式,以及它有多少净空等等——我见过超过 30 秒的停顿。
Another issue is that by explicitly calling GC you're not actually monitoring how the JVM is running the GC, you're actually altering it - depending on how you've configured the JVM, it's going to garbage collect when appropriate, and usually incrementally (It doesn't just run a full GC when it runs out of memory). What you'll be printing out will be nothing like what the JVM will do on it's own - for one thing you'll probably see fewer automatic / incremental GC's as you'll be clearing the memory manually.
另一个问题是,通过显式调用 GC,您实际上并没有监视 JVM 如何运行 GC,您实际上是在更改它 - 取决于您如何配置 JVM,它会在适当的时候进行垃圾收集,并且通常是递增的(它不只是在内存不足时运行完整的 GC)。您将打印出来的内容与 JVM 自己做的事情完全不同 - 一方面,您可能会看到更少的自动/增量 GC,因为您将手动清除内存。
As Nick Holt's post points out, options to print GC activity already exist as JVM flags.
正如 Nick Holt 的帖子所指出的,打印 GC 活动的选项已经作为 JVM 标志存在。
You could have a thread that just prints out free and available at reasonable intervals, this will show you actual mem useage.
您可以有一个线程,它可以在合理的时间间隔内免费打印出来并可用,这将显示您实际的内存使用情况。
回答by Aakash
As has been suggested, try VisualVM to get a basic view.
正如所建议的,尝试 VisualVM 以获得基本视图。
You can also use Eclipse MAT, to do a more detailed memory analysis.
您还可以使用 Eclipse MAT,进行更详细的内存分析。
It's ok to do a System.gc() as long as you dont depend on it, for the correctness of your program.
为了程序的正确性,只要不依赖 System.gc() 就可以。
回答by Pablojim
If you like a nice way to do this from the command line use jstat:
如果您喜欢从命令行执行此操作的好方法,请使用 jstat:
http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jstat.html
http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jstat.html
It gives raw information at configurable intervals which is very useful for logging and graphing purposes.
它以可配置的时间间隔提供原始信息,这对于记录和绘图目的非常有用。
回答by bgw
The problem with system.gc, is that the JVM already automatically allocates time to the garbage collector based on memory usage.
system.gc 的问题在于 JVM 已经根据内存使用情况自动为垃圾收集器分配时间。
However, if you are, for instance, working in a very memory limited condition, like a mobile device, System.gc allows you to manually allocate more time towards this garbage collection, but at the cost of cpu time (but, as you said, you aren't that concerned about performance issues of gc).
但是,例如,如果您在内存非常有限的情况下工作,例如移动设备,System.gc 允许您手动为此垃圾收集分配更多时间,但以 CPU 时间为代价(但是,正如您所说,您并不那么关心 gc 的性能问题)。
Best practice would probablybe to only use it where you might be doing large amounts of deallocation (like flushing a large array).
最佳实践可能是仅在您可能进行大量释放(例如刷新大型数组)的地方使用它。
All considered, since you are simply concerned about memory usage, feel free to call gc, or, better yet, see if it makes much of a memory difference in your case, and then decide.
考虑到所有因素,因为您只关心内存使用情况,请随时调用 gc,或者更好的是,看看它是否对您的情况产生很大的内存差异,然后再决定。