您如何从Shell强制垃圾收集?


106

因此,我正在远程容器上查看带有jmap的堆,并且我想对其进行强制垃圾收集。如何在不弹出jvisualvm或jconsole和朋友的情况下执行此操作?

我知道您不应该进行强制垃圾回收的实践-您应该弄清楚为什么堆很大/越来越大。

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

话虽如此,有没有一种方法可以轻松地做到这一点?我缺少一些命令行应用程序?


Answers:


25

您可以通过免费的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​​ / other脚本中的信息。我已经在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

346

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

jcmd <pid> GC.run


22
你们为什么不告诉我这些事?:)
noahlz 2014年

2
如果您收到“ AttachNotSupportedException:无法打开套接字文件”的信息,请参阅我对此答案的补充
Thomas Rebele,

而且,如果得到的话Explicit GC is disabled, no GC has been performed,可能是由于-XX:+DisableExplicitGCVM参数引起的。请参阅:mail.openjdk.java.net/pipermail/serviceability-dev/2017-August/...
的Eyal罗斯

这仅适用于Oracle JDK,不适用于open-jdk。
Ali Saleh

104

如果运行jmap -histo:live <pid>,这将在堆中打印出所有内容之前在堆上强制使用完整的GC。


3
在所有javas上强制进行垃圾回收:ps axf | grep Java | grep -v grep | awk'{print“ jmap -histo:live” $ 1}'| sh
gtrak

1
在哪里记录?没有:live怎么办(例如,当需要-F时)?
2014年

7
您好,2014年神秘的未来。 jcmd现在是完成工作的正确工具。
noahlz 2014年

16

除了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>?您可以从tophtop


那下面呢?一样? java.io.IOException: Operation not permitted
dhockey

我还没有遇到此错误消息。也许它可以使用sudo -u <process_owner> jcmd <pid> GC.run,您可以尝试吗?该命令应该是安全的
Thomas Rebele '18

我可以,但是我在那台机器上没有sudo访问权限。
dhockey '18

该工具正常工作。您只是在操作系统中没有正确的权限来执行它。这同样适用于其他应用程序,即使不使用Java。
9/3

6

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

以下示例适用于cmdline-jmxclient:

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

很好,因为它只有一行,您可以非常轻松地将其放入脚本中。


5

对于Linux:

$ jcmd $(pgrep java) GC.run

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


看来只有在运行一个Java进程时,这才起作用。否则,它将把第二个PID解释为jcmd的命令,这显然无法识别,并引发错误。
CasEliëns

0

我认为没有相同的命令行选项。

您将需要使用jvisualvm / jconsole。

我宁愿建议您使用这些工具进行身份识别,为什么您的程序会占用大量内存。

无论如何,您都不应该强行使用GC,因为它肯定会干扰GC算法并降低程序运行速度。


0

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.