你如何从壳牌强制收集垃圾?

时间:2010-08-19 16:17:58

标签: java garbage-collection jmx jmap

所以我在远程盒子上查看带有jmap的堆,我想强制对它进行垃圾收集。如果没有弹出jvisualvm或jconsole和朋友你怎么做?

我知道你不应该在强制垃圾收集的实践中 - 你应该弄清楚为什么堆很大/正在增长。

我也意识到System.GC()实际上并没有强制进行垃圾收集 - 它只是告诉GC您希望它发生。

话虽如此,有办法轻松做到这一点吗?我失踪了一些命令行应用程序?

12 个答案:

答案 0 :(得分:290)

从JDK 7开始,您可以使用JDK命令工具'jcmd',例如:

jcmd <pid> GC.run

答案 1 :(得分:98)

如果您运行jmap -histo:live <pid>,那么在打印出任何内容之前,这将强制堆上的完整GC。

答案 2 :(得分:21)

您可以通过免费的jmxterm计划执行此操作。

像这样开火:

java -jar jmxterm-1.0-alpha-4-uber.jar

从那里,您可以连接到主机并触发GC:

$>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

答案 3 :(得分:11)

添加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
...

这可以在this stackoverflow answer

的帮助下解决
sudo -u <process_owner> jcmd <pid> GC.run

其中<process_owner>是使用PID <pid>运行进程的用户。您可以从tophtop

获取两者

答案 4 :(得分:6)

还有一些其他解决方案(这里有许多好的解决方案):

以下示例适用于cmdline-jmxclient:

$ java -jar cmdline-jmxclient-0.10.3.jar - localhost:3812 'java.lang:type=Memory' gc

这很好,因为它只有一行,你可以很容易地将它放在脚本中。

答案 5 :(得分:0)

我认为没有任何命令行选项。

您需要使用jvisualvm / jconsole。

我建议您使用这些工具来识别,为什么您的程序内存很高。

无论如何你不应该强迫GC,因为它肯定会扰乱GC算法并使你的程序变慢。

答案 6 :(得分:0)

如果您在应用程序中使用jolokia,则可以使用此命令触发垃圾回收:

curl http://localhost:8558/jolokia/exec/java.lang:type=Memory/gc

答案 7 :(得分:0)

对于Linux:

$ jcmd $(pgrep java) GC.run

jcmd与JDK打包在一起,$(pgrep java)获得了Java的进程ID

答案 8 :(得分:0)

考虑将 GNU 与 jcmd 并行使用,如下所示用于多个进程;

并行'jcmd {} GC.run' ::: $(pgrep java)

答案 9 :(得分:0)

除了user3198490's answer之外,如果运行jcmd <pid> GC.run后没有真正改变,原因可能是:

GC.run essentially calls java.lang.System.gc(),这只是给 gc 的一个提示,JVM 可以随意忽略它。

如果你想确保一个完整的 GC 是 FORCED,一个选择是使用:

jcmd <pid> GC.heap_dump filename.hprof

此命令的最初目的是创建一个名为 filename.hprof 的堆转储文件。但作为一个副作用,为了到达所有活动对象,它“request a full GC unless the -all option is specified”。

还有一些其他的命令,比如 this answer 中提到的 jmap -histo:live <PID> 会以同样的方式触发 GC 作为副作用。

答案 10 :(得分:0)

另外:

  • 使用相同的应用程序、jar 文件等为多进程运行 GC。使用:
jcmd your_application.jar GC.run
  • 要在 Windows 上运行 GC,请尝试:
cd C:\"Program Files"\Java\jdk-13.0.2\bin
.\jcmd.exe your_application.jar GC.run
  • MacOS/Linux:
jcmd your_application.jar GC.run
# or
/usr/bin/jcmd your_application.jar GC.run

答案 11 :(得分:-7)

只是:

kill -SIGQUIT <PID>