我该如何查看Java正在使用哪个垃圾收集器

16

Java虚拟机支持多种垃圾收集策略。

文章对其进行了解释。

现在我想知道我的应用程序使用的是哪种(自动选定的)策略,是否有办法让JVM(版本1.6)打印出此信息?

编辑:JVM会检测其是否处于客户端或服务器模式。所以问题实际上是如何查看已检测到的模式?


2
请注意,本文讨论的是一个具体的实现(具体来说是Sun JRE中的HotSpot JVM)。 - Joachim Sauer
请注意,您不一定只使用一个GC。通常针对不同的区域有不同的策略。如果您使用CMS,我认为默认情况下会在年轻区域使用“新并行”策略。 - Fredrik
7个回答

18

这正是我需要的,不幸的是它在 Windows 上不可用(不知道为什么)。 - Thirler
或许你应该在问题中添加那些关于 Windows 的信息 ;) - fglez

16

http://java.sun.com/j2se/1.5.0/docs/guide/vm/gc-ergonomics.html。该链接适用于J2SE 6,指出默认使用的是Parallel Collector。

我们曾经在JVM 1.5上进行过测试,只设置了

-server -Xms3g -Xmx3g -XX:PermSize=128m -XX:LargePageSizeInBytes=4m -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps

输出结果为:

41359.597: [GC [PSYoungGen:90499K->32K(377344K)] 268466K->181862K(2474496K),0.0183138秒]
41359.615:[Full GC [PSYoungGen:32K->0K(377344K)] [PSOldGen:181830K->129760K(2097152K)] 181862K->129760K(2474496K)[PSPermGen:115335K->115335K(131072K)],4.4590942秒]

其中PS代表并行清理。


9
把这个加入到JAVA_OPTS中:
-XX:+UseSerialGC -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps

对于UseSerialGC,我们将在日志中看到:

 7.732: [GC 7.732: [DefNew: 419456K->47174K(471872K), 0.1321800 secs] 419456K->47174K(1520448K), 0.1322500 secs] [Times: user=0.10 sys=0.03, real=0.14 secs]

对于UseConcMarkSweepGC,我们在日志中会看到:

 5.630: [GC 5.630: ['ParNew: 37915K->3941K(38336K), 0.0123210 secs] 78169K->45163K(1568640K), 0.0124030 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]

对于 UseParallelGC,我们将在日志中看到:

30.250: [GC [PSYoungGen: 441062K->65524K(458752K)] 441062K->76129K(1507328K), 0.1870880 secs] [Times: user=0.33 sys=0.03, real=0.19 secs]

6
看起来,我们有更方便的方法在运行时定义GC版本。建议始终使用工具。要定义GC版本,我们需要两个随JVM一起提供的工具(位于jdk/bin目录下):
  1. VisualVM - 启动它并尝试对某个进程进行分析(例如,您可以对VisualVM本身进行分析)。您的分析将向您显示进程的PID(请参见截图中的绿色矩形)。
  2. jMap - 使用-heap <PID>选项启动此工具,并查找专用于垃圾收集器类型的字符串(请参见截图中的粉色线条)。

enter image description here


5
如Joachim所指出的那样,您提到的文章描述了Sun VM提供的VM策略。VM规范本身并不强制使用特定的GC算法,因此在API中为这些算法列举枚举值是没有意义的。
但是,您可以从Management API中获取一些信息:
List<GarbageCollectorMXBean> beans = 
    ManagementFactory.getGarbageCollectorMXBeans();

遍历这些bean,您可以获取GC的名称(仅作为字符串)和不同GC管理的内存池的名称。


3

获取此信息的最佳方式是:

打开命令行并输入以下命令。

java -XX:+PrintCommandLineFlags -version

它将显示如下结果:

C:\windows\system32>java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=132968640 -XX:MaxHeapSize=2127498240 -XX:+PrintCommandLineFl
ags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesInd
**ividualAllocation -XX:+UseParallelGC**
java version "1.8.0_66"
Java(TM) SE Runtime Environment (build 1.8.0_66-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode)`enter code here`

1
你可以编写一个简单的程序,通过jmx连接到你的Java进程:
public class PrintJMX {
  public static void main(String[] args) throws Exception {
    String rmiHostname = "localhost";
    String defaultUrl = "service:jmx:rmi:///jndi/rmi://" + rmiHostname + ":1099/jmxrmi";
    JMXServiceURL jmxServiceURL = new JMXServiceURL(defaultUrl);

    JMXConnector jmxConnector = JMXConnectorFactory.connect(jmxServiceURL);
    MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection();


    ObjectName gcName = new ObjectName(ManagementFactory.GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + ",*");

    for (ObjectName name : mbsc.queryNames(gcName, null)) {
      GarbageCollectorMXBean gc = ManagementFactory.newPlatformMXBeanProxy(mbsc,
        name.getCanonicalName(),
        GarbageCollectorMXBean.class);

      System.out.println(gc.getName());
    }

  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接