查找Java堆大小和使用的内存的命令行工具(Linux)?


171

是否有命令行工具(Linux)检查Java应用程序的堆大小(和已用内存)?

我已经尝试通过jmap。但是它提供了信息。关于内部存储器区域,例如Eden / PermGen等,这对我没有用。

我正在寻找类似的东西:

  • 最大内存:1GB
  • 最小内存:256 MB
  • 堆内存:700 MB
  • 使用的内存:460 MB

就这样。我知道我可以在JConsole等中看到它,但是我需要一个命令行工具(无法启用JMX等)。

您知道这样的工具/命令吗?

Answers:


149

每个Java进程都有一个pid,您首先需要通过jps命令找到它。

有了pid后,就可以jstat -gc [insert-pid-here]用来查找垃圾收集堆行为的统计信息。

  • jstat -gccapacity [insert-pid-here] 将介绍有关内存池生成和空间功能的信息。

  • jstat -gcutil [insert-pid-here]将以容量的百分比表示每一代的利用率。有助于快速了解使用情况。

请参阅Oracle网站上的jstat文档


11
是否有建议jstat使用一个选项,以便仅验证JVM的整体内存使用情况?假设您使用Xms=4g和启动JVM,并且Xmx=4g想知道已经使用了多少内存?
basZero 2014年

1
“ jstat -gcutil <pid> 250 N”对于以250ms的间隔获取N个样本并将输出显示为相应空格的百分比非常有用。谢谢。
凯雷姆

3
值得指出的报价jstat甲骨文的Java 8手册This command is experimental and unsupported
patryk.beza 2015年

1
awk 'print {$3+$4+$6+$8}'可以在Java 8的jstat列上打印摘要用法
cybersoft '17

在其他答案上遇到了麻烦,但有一个基本操作ps -ef | grep java向我显示了vm args,在我的情况下,该参数包括-Xmx值,这是我所需要的。
xdhmoore

66

jvmtop是一个命令行工具,可提供多种指标(包括堆)的实时视图。

VM概述模式的示例输出:

 JvmTop 0.3 alpha (expect bugs)  amd64  8 cpus, Linux 2.6.32-27, load avg 0.12
 http://code.google.com/p/jvmtop

  PID MAIN-CLASS      HPCUR HPMAX NHCUR NHMAX    CPU     GC    VM USERNAME   #T DL
 3370 rapperSimpleApp  165m  455m  109m  176m  0.12%  0.00% S6U37 web        21
11272 ver.resin.Resin [ERROR: Could not attach to VM]
27338 WatchdogManager   11m   28m   23m  130m  0.00%  0.00% S6U37 web        31
19187 m.jvmtop.JvmTop   20m 3544m   13m  130m  0.93%  0.47% S6U37 web        20
16733 artup.Bootstrap  159m  455m  166m  304m  0.12%  0.00% S6U37 web        46

它确实是一个很棒的工具,有点htop,但是带有jstat的指标。感谢您的建议,@MRalwasser。
oski86

65

此命令以字节为单位显示配置的堆大小。

java -XX:+PrintFlagsFinal -version | grep HeapSize

它也适用于EC2上的Amazon AMI。


26
这不能回答问题,该问题专门询问如何检查进程的堆使用情况。此处的命令列出了所有进程的JVM默认值。
Madbreaks '16

10
但是,这对我来说是非常有用的答案,它通过google搜索如何找到全局堆大小来到达此页面。
约翰(Johan)

@jumping_monkey不是间接的,不正确的。如果您说的是真的,则应编辑答案,或者您可以随时添加新答案。
Madbreaks

42

尝试在Ubuntu和RedHat中工作的方法:

java -XX:+PrintFlagsFinal -version | grep -iE 'HeapSize|PermSize|ThreadStackSize'

对于Windows:

java -XX:+PrintFlagsFinal -version | findstr /i "HeapSize PermSize ThreadStackSize"

对于Mac

java -XX:+PrintFlagsFinal -version | grep -iE 'heapsize|permsize|threadstacksize'

所有这些命令的输出类似于以下输出:

uintx InitialHeapSize                          := 20655360        {product}
uintx MaxHeapSize                              := 331350016       {product}
uintx PermSize                                  = 21757952        {pd product}
uintx MaxPermSize                               = 85983232        {pd product}
intx ThreadStackSize                           = 1024            {pd product}
java version "1.7.0_05"
Java(TM) SE Runtime Environment (build 1.7.0_05-b05)
Java HotSpot(TM) 64-Bit Server VM (build 23.1-b03, mixed mode)

要找到以MB为单位的大小,请将该值除以(1024 * 1024)。


如何通过pid查找特定java进程的堆,permsize,...分隔的内存使用情况?
加里·高

3
@GaryGauh这是默认的堆大小。要找到正在运行的应用程序的用法,您应该在代码中进行操作,或者可以使用jconsole。我知道这也应该有许多其他方式。
padippist

2
使用jstat -gc <vmid>用于运行应用程序。
米查·维登曼

27

不使用大多数工具使用的JMX,您所能做的就是使用

jps -lvm

并推断该设置将来自命令行选项。

默认情况下,没有JMX,您将无法获得动态信息,但是您可以编写自己的服务来做到这一点。

顺便说一句:我更喜欢使用VisualVM而不是JConsole。


25

有一个具有可视外观的命令行工具-jvm-mon。它是用于以下方面的命令行的JVM监视工具:

  • 堆使用情况,大小和最大值
  • jvm进程
  • cpu和GC使用情况
  • 顶线

打开工具后,指标和图表会更新。

样品: 吉蒙


1
请注意,jvm-mon仅针对Java8运行
tmanolatos

1
^有一个新的版本,现在还支持Java 11
安德烈斯

11

晚会晚了,但是一个非常简单的解决方案是使用jpsstat.sh脚本。它提供了简单的实时当前内存最大内存cpu使用详细信息。

  • 转到GitHub项目并下载jpsstat.sh文件
  • 右键单击jpsstat.sh并转到“ 权限”选项卡,使其可执行
  • 现在使用以下命令运行脚本./jpsstat.sh

这是脚本的示例输出-

=====  ======  =======  =======  =====
 PID    Name   CurHeap  MaxHeap  %_CPU
=====  ======  =======  =======  =====
2777   Test3      1.26     1.26    5.8
2582   Test1      2.52     2.52    8.3
2562   Test2      2.52     2.52    6.4

在SUSE Linux上似乎无法立即使用(第38行:声明:-A:无效选项)
克里斯(Chris

听起来好像您在需要bash> = 4的关联数组声明中遇到错误。另外,另一个问题可能是由于将脚本运行为“ sh jpsstat.sh”所致。如果是这样,请尝试以“ ./jpsstat.sh”运行脚本。
amarjeetAnand '17

9

就我而言,我需要检查没有大多数基本实用程序(ps,pstree ...)的docker容器内的标志。

通过使用,jps我得到了正在运行的JVM的PID(在我的情况1中),然后jcmd 1 VM.flags得到了来自正在运行的JVM的标志。

这取决于您可用的命令,但这可能会对某人有所帮助。:)


8

Java8及更高版本中,您可以使用以下命令:

jcmd JAVA_PROCESS_IDGC.heap_info

您可以从输出中引用总内存,总内存和已用内存。

Sample Command And Output: jcmd 9758 GC.heap_info

PSYoungGen  total 1579520K, used 487543K [0x0000000751d80000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 1354240K, 36% used [0x0000000751d80000,0x000000076f99dc40,0x00000007a4800000)
  from space 225280K, 0% used [0x00000007b2400000,0x00000007b2400000,0x00000007c0000000)
  to   space 225280K, 0% used [0x00000007a4800000,0x00000007a4800000,0x00000007b2400000)
ParOldGen       total 3610112K, used 0K [0x0000000675800000, 0x0000000751d80000, 0x0000000751d80000)
  object space 3610112K, 0% used [0x0000000675800000,0x0000000675800000,0x0000000751d80000)
Metaspace       used 16292K, capacity 16582K, committed 16896K, reserved 1064960K
  class space    used 1823K, capacity 1936K, committed 2048K, reserved 1048576K

有关jcmd命令的更多详细信息,请访问链接:https ://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr006.html


1
您需要更正您的评论。GC.heap_info在Java 9及更高版本中可用。这是不可用在Java 8中看到的另一个线程在这里:stackoverflow.com/questions/41891127/...
帕维尔·莫尔恰诺夫

@PavelMolchanov我能够使用jdk1.8.0_172中的命令。/Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/bin/jcmd 98270 GC.heap_info。请(如果可以)将信息添加到引用的线程中,以及我目前没有足够的声誉在此添加评论。
vaibhav gupta

您使用Mac吗?您是否使用Oracle JDK?我不知道如何在您的jdk1.8.0_172中使用它,Oracle仅在Java 9及更高版本中记录了此功能:docs.oracle.com/javase/9​​/tools/jcmd.htm。它不在Java 8的Oracle JDK文档中。在底部提供的链接中未提及:docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot / ...
Pavel Molchanov,

还有一个问题。请检查示例中运行过程98270的JDK版本。jcmd从进程的JVM(在您的情况下为98270)获取可用命令。如果使用不同的JDK(JDK 9或更高版本)执行进程98270进程,则即使JCMD本身是Java 8,您也会看到GC.heap_info命令可用。要获取可用命令,请执行:jcmp <PID>帮助。
Pavel Molchanov,

1
FWIW GC.heap_info在OpenJDK 8中也绝对可用。也许只有最新版本?我正在使用这个:8u191-b12-2ubuntu0.18.04.1
Per Lundberg

7

任何方法都应该给您大致相同的数字。分配-X..m -X..x所有代使用的堆总是一个好主意。然后,您可以保证也可以执行ps来查看已传递并因此使用了哪些参数。

对于实际的内存使用情况,您还可以将VIRT(已分配和共享)和RES(实际使用)与jstat值进行粗略比较:

对于Java 8,请参阅jstat了解这些值的实际含义。假设您运行一个没有mmap或文件处理的简单类。

$ jstat -gccapacity 32277
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC
215040.0 3433472.0  73728.0  512.0  512.0  67072.0   430080.0  6867968.0   392704.0   392704.0      0.0 1083392.0  39680.0      0.0 1048576.0   4864.0   7225     2
$ jstat -gcutil 32277
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
  6.25   0.00   7.96  18.21  98.01  95.29   7228   30.859     2    0.173   31.032

最大值

     NGCMX + S0C + S1C + EC    + OGCMX   + MCMX    + CCSMX
   3433472 + 512 + 512 + 67072 + 6867968 + 1083392 + 1048576 = 12 GB

(大约和低于VIRT内存)

最大值(最小值,已使用):

215040 + 512 + 512 + 67072 + 430080  + 39680    +  4864  = ~ 1GB

(大致接近RES内存)

“不要在此引用我的信息”,但是VIRT mem大约接近或大于分配的最大内存,但是只要正在使用的内存在物理内存中是可用的/可用的,JVM就不会抛出内存异常。实际上,即使在OS上关闭了交换,在JVM启动时也不会针对物理内存检查最大内存。真正使用由Java程序什么的虚拟内存更好的解释是讨论在这里


4

首先从以下其中一项获取进程ID,即列出的进程的第一个数字:(或使用ps aux | grep java,如果愿意的话)

jps -lvm

然后在此处使用进程ID:

jmap -heap $MY_PID 2>/dev/null | sed -ne '/Heap Configuration/,$p';
jmap -permstat $MY_PID

2

使用top命令是检查程序内存使用情况的最简单方法。RES列显示进程占用的实际物理内存。

就我而言,我有一个10g的文件在java中读取,每次我退出outOfMemory异常。当RES列中的值达到-Xmx选项中设置的值时,就会发生这种情况。然后通过使用-Xmx选项增加内存,一切正常。


3
top命令显示给JVM多少操作系统。这个家伙在问我们如何看到JVM内部的堆空间使用情况。JVM使用10g并不意味着真正的堆空间中充满了10g数据,因为jvm几乎永远不会从堆中将内存返回给OS,直到您杀死该进程。
linehrr

2

就Java堆大小而言,在Linux中,您可以使用

ps aux | grep java

要么

ps -ef | grep java

并查找-Xms,-Xmx以找出指定的初始堆大小和最大堆大小。

但是,如果您感兴趣的Java进程不存在-Xms或-Xmx,则表明您的Java进程正在使用默认堆大小。您可以使用以下命令找出默认大小。

java -XX:+PrintFlagsFinal -version | grep HeapSize

或特定的jvm,例如,

/path/to/jdk1.8.0_102/bin/java -XX:+PrintFlagsFinal -version | grep HeapSize

并查找InitialHeapSize和MaxHeapSize(以字节为单位)。


1

如果使用jrockit,请尝试使用jrcmd命令行工具。例如:

$ jrcmd 5127 print_memusage
5127:
Total mapped                  1074596KB           (reserved=3728KB)
-              Java heap       786432KB           (reserved=0KB)
-              GC tables        26316KB          
-          Thread stacks        13452KB           (#threads=34)
-          Compiled code         9856KB           (used=9761KB)
-               Internal          840KB          
-                     OS        15036KB          
-                  Other       146632KB          
-        Java class data        75008KB           (malloced=74861KB #103221 in 18709 classes)
- Native memory tracking         1024KB           (malloced=102KB #8)

对于更多命令,例如heap_diagnostics,请使用“ jrcmd帮助”将其列出。

https://blogs.oracle.com/jrockit/entry/why_is_my_jvm_process_larger_t


1
jstat -gccapacity javapid  (ex. stat -gccapacity 28745)
jstat -gccapacity javapid gaps frames (ex.  stat -gccapacity 28745 550 10 )

上面命令的样本O / P

NGCMN    NGCMX     NGC     S0C  
87040.0 1397760.0 1327616.0 107520.0 

NGCMN   Minimum new generation capacity (KB).
NGCMX   Maximum new generation capacity (KB).
NGC Current new generation capacity (KB).

http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstat.html上获得有关此内容的更多详细信息


1

到目前为止,还没有这种工具可以按照您要求的格式打印堆内存 。唯一且唯一的打印方法是借助Runtime Class编写Java程序

public class TestMemory {

public static void main(String [] args) {

    int MB = 1024*1024;

    //Getting the runtime reference from system
    Runtime runtime = Runtime.getRuntime();

    //Print used memory
    System.out.println("Used Memory:" 
        + (runtime.totalMemory() - runtime.freeMemory()) / MB);

    //Print free memory
    System.out.println("Free Memory:" 
        + runtime.freeMemory() / mb);

    //Print total available memory
    System.out.println("Total Memory:" + runtime.totalMemory() / MB);

    //Print Maximum available memory
    System.out.println("Max Memory:" + runtime.maxMemory() / MB);
}

}

参考:https : //viralpatel.net/blogs/getting-jvm-heap-size-used-memory-total-memory-using-java-runtime/


这是错误的。jmap -heap <pid>给出了此信息
vsingh

0

从顶部找到您的webapp / java进程的进程ID。使用jmap heap获取堆分配。我在AWS-Ec2上测试了弹性beantalk

您可以在下面的图像中看到该应用程序的最大堆空间为3GB

在此处输入图片说明

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.