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

eyb*_*erg 98 java garbage-collection jmx jmap

所以我在远程盒子上看着一个带有jmap的堆,我想强制垃圾收集.如果不突然进入jvisualvm或jconsole和朋友,你怎么做?

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

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

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

use*_*490 320

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

jcmd <pid> GC.run

  • 你们为什么不告诉我这些事情?!:) (19认同)
  • 这怎么不是公认的答案? (13认同)
  • 正是我在寻找,谢谢. (3认同)
  • 如果您收到"AttachNotSupportedException:无法打开套接字文件",请参阅[我对此答案的补充](/sf/answers/3405245161/) (2认同)
  • @AliSaleh:它还为我使用 openjdk(在 Debian 和 Ubuntu 中)。我用 `sudo apt install openjdk-11-jdk-headless` 安装了它,然后用 `jcmd 0 GC.run` 运行(进程 ID“0”表示:“对所有 java 进程执行此操作”)并且所有 `java` 进程都有分配的 RAM 较少(驻留集大小 RSS;请参阅此处 /sf/answers/1473481621/)。虚拟内存大小 (VSZ) 仍然与以前相同(使用 `ps -A u` 或 `ps -A u | grep java` 检查)。 (2认同)

Wil*_*ung 100

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

  • 你好,来自2014年的神秘未来.`jcmd`现在是这项工作的正确工具. (7认同)
  • 强制所有javas上的垃圾收集:ps axf | grep java | grep -v grep | awk'{print"jmap -histo:live"$ 1}'| sh (3认同)

Har*_*d L 22

您可以通过免费的jmxterm程序完成此操作.

把它点起来:

java -jar jmxterm-1.0-alpha-4-uber.jar
Run Code Online (Sandbox Code Playgroud)

从那里,您可以连接到主机并触发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
Run Code Online (Sandbox Code Playgroud)

查看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
Run Code Online (Sandbox Code Playgroud)


Tho*_*ele 14

除了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
...
Run Code Online (Sandbox Code Playgroud)

这可以通过这个stackoverflow答案来解决

sudo -u <process_owner> jcmd <pid> GC.run
Run Code Online (Sandbox Code Playgroud)

<process_owner>使用PID运行进程的用户在哪里<pid>.你可以从top或获得htop


小智 8

对于Linux:

$ jcmd $(pgrep java) GC.run
Run Code Online (Sandbox Code Playgroud)

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


The*_*ist 6

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

以下示例适用于cmdline-jmxclient:

$ java -jar cmdline-jmxclient-0.10.3.jar - localhost:3812 'java.lang:type=Memory' gc
Run Code Online (Sandbox Code Playgroud)

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