我正在使用远程jmap查看堆栈,我想在其中强制进行垃圾回收。不使用jvisualvm或jconsole等工具如何实现?
我知道不应该频繁强制进行垃圾回收,而是要找出为什么堆栈会变得如此庞大。
同时我也明白System.GC()并不能真正强制进行垃圾回收,它只是通知垃圾回收器你希望进行回收。
那么是否有一种简单的方法来实现强制进行垃圾回收呢?有没有我遗漏的命令行应用程序?
我正在使用远程jmap查看堆栈,我想在其中强制进行垃圾回收。不使用jvisualvm或jconsole等工具如何实现?
我知道不应该频繁强制进行垃圾回收,而是要找出为什么堆栈会变得如此庞大。
同时我也明白System.GC()并不能真正强制进行垃圾回收,它只是通知垃圾回收器你希望进行回收。
那么是否有一种简单的方法来实现强制进行垃圾回收呢?有没有我遗漏的命令行应用程序?
jcmd <pid> GC.run
Explicit GC is disabled, no GC has been performed
的错误,这可能是由于-XX:+DisableExplicitGC
虚拟机参数引起的。参见:http://mail.openjdk.java.net/pipermail/serviceability-dev/2017-August/021763.html - Eyal Rothsudo apt install openjdk-11-jdk-headless
进行安装,然后使用jcmd 0 GC.run
运行(进程ID“0”表示:“对所有Java进程执行”),所有的java
进程都分配了更少的RAM(Resident Set Size RSS;请参见此处https://dev59.com/oGsz5IYBdhLWcg3weHkA#21049737)。虚拟内存大小(VSZ)仍然与以前相同(使用`ps -A u或
ps -A u | grep java`进行检查)。 - user14972917如果你运行jmap -histo:live <pid>
,那么它会在打印任何内容之前强制对堆进行一次完整的GC。
jcmd
现在是正确的工具。 - noahlz你可以通过免费的jmxterm程序实现此操作。
这样启动:
java -jar jmxterm-1.0-alpha-4-uber.jar
从那里,您可以连接到主机并触发垃圾回收:
$>open host:jmxport
#Connection to host:jmxport is opened
$>bean java.lang:type=Memory
#bean is set to java.lang:type=Memory
$>run gc
#calling operation gc of mbean java.lang:type=Memory
#operation returns:
null
$>quit
#bye
查看jmxterm网站上的文档,了解将其嵌入bash/perl/ruby/其他脚本中的信息。 我已经在Python中使用popen2或在Perl中使用open3来执行此操作。
更新:这是使用jmxterm的一行命令:
echo run -b java.lang:type=Memory gc | java -jar jmxterm-1.0-alpha-4-uber.jar -n -l host:port
除了user3198490的回答之外,还需要注意一点。运行这个命令可能会出现以下错误信息:
$ jcmd 1805 GC.run
[16:08:01]
1805:
com.sun.tools.attach.AttachNotSupportedException: Unable to open socket file: target process not responding or HotSpot VM not loaded
...
使用这个stackoverflow答案的帮助可以解决这个问题。
sudo -u <process_owner> jcmd <pid> GC.run
其中<process_owner>
是使用PID<pid>
运行该进程的用户。您可以从top
或htop
中获取两个值。
java.io.IOException: 操作不允许
- dhockeysudo -u<process_owner> jcmd<pid> GC.run
可以解决,你可以试一下吗? 这个命令应该是安全的。 - Thomas Rebele对于 Linux:
$ jcmd $(pgrep java) GC.run
jcmd
与JDK捆绑,$(pgrep java)
获取java进程的ID
还有一些其他的解决方案(这里已经有很多好的解决方案了):
gc()
。gc()
操作。以下示例是针对cmdline-jmxclient的:
$ java -jar cmdline-jmxclient-0.10.3.jar - localhost:3812 'java.lang:type=Memory' gc
jcmd <pid> GC.run
后仍然没有任何变化,原因可能是:
GC.run
本质上调用了java.lang.System.gc()
, 这只是给gc的一个提示,JVM可以选择忽略它。jcmd <pid> GC.heap_dump filename.hprof
该命令的原始目的是创建一个名为filename.hprof
的堆转储文件。但是作为副作用,为了达到所有活动对象,它会 "请求进行完整的GC,除非指定了-all选项".
还有一些其他命令,如jmap -histo:live <PID>
在此答案中提到,以同样的方式触发GC。
如果您正在使用jolokia与您的应用程序,您可以使用此命令触发垃圾回收:
curl http://localhost:8558/jolokia/exec/java.lang:type=Memory/gc
我认为没有相应的命令行选项。
你需要使用jvisualvm/jconsole。
我建议你使用这些工具来确定为什么你的程序占用了很多内存。
无论如何,你不应该强制进行垃圾回收,因为这肯定会干扰垃圾回收算法并使你的程序变慢。