128

所以我在一个远程盒子上查看一个带有 jmap 的堆,我想对其进行强制垃圾收集。你如何在不进入 jvisualvm 或 jconsole 和朋友的情况下做到这一点?

我知道您不应该进行强制垃圾收集的做法——您应该弄清楚为什么堆很大/正在增长。

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

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

4

12 回答 12

386

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

jcmd <pid> GC.run

于 2014-01-15T14:10:44.210 回答
107

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

于 2010-08-19T16:39:45.023 回答
26

您可以通过免费的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
于 2010-08-19T16:33:06.277 回答
18

除了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

于 2018-02-06T15:22:11.393 回答
9

对于 Linux:

$ jcmd $(pgrep java) GC.run

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

于 2019-09-25T20:06:27.033 回答
7

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

以下示例适用于 cmdline-jmxclient:

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

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

于 2010-08-19T16:37:27.437 回答
1

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

您将需要使用 jvisualvm/jconsole 来做同样的事情。

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

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

于 2010-08-19T16:30:05.683 回答
0

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

curl http://localhost:8558/jolokia/exec/java.lang:type=Memory/gc
于 2017-12-22T19:21:19.223 回答
0

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

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

于 2021-04-06T04:00:46.067 回答
0

除了user3198490 的回答之外,如果您运行后没有任何变化jcmd <pid> GC.run,原因可能是:

GC.run本质上是调用java.lang.System.gc(),这只是对 gc 的提示,JVM 可以随意忽略它。

如果要确保强制执行完整的 GC,可以选择使用:

jcmd <pid> GC.heap_dump filename.hprof

此命令的最初目的是创建一个名为filename.hprof. 但作为副作用,为了到达所有活动对象,它“除非指定 -all 选项,否则请求完整的 GC ”。

此答案jmap -histo:live <PID>中提到的其他一些命令以相同的方式触发 GC 作为副作用。

于 2021-07-14T07:19:30.787 回答
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
于 2021-08-03T00:54:42.790 回答
-15

只是:

kill -SIGQUIT <PID>
于 2013-01-17T03:05:49.403 回答