4

当我的 Java 应用程序 (Oracle JVM v1.6.0) 启用了 GC 日志记录时,它通常会在退出时打印以下输出:

PSYoungGen      total 6429824K, used 5483163K [0x0000000640000000, 0x0000000800000000, 0x0000000800000000)
  eden space 5483456K, 99% used [0x0000000640000000,0x000000078eaa6cc0,0x000000078eaf0000)
  from space 946368K, 0% used [0x00000007c63d0000,0x00000007c63d0000,0x0000000800000000)
  to   space 910208K, 0% used [0x000000078eaf0000,0x000000078eaf0000,0x00000007c63d0000)
 ParOldGen       total 3145728K, used 3145724K [0x0000000580000000, 0x0000000640000000, 0x0000000640000000)
  object space 3145728K, 99% used [0x0000000580000000,0x000000063ffff3a0,0x0000000640000000)
 PSPermGen       total 57984K, used 57686K [0x000000057ac00000, 0x000000057e4a0000, 0x0000000580000000)
  object space 57984K, 99% used [0x000000057ac00000,0x000000057e455ae0,0x000000057e4a0000)

有没有一种方法可以在应用程序运行期间定期生成此输出?我知道如何通过 JMX 以编程方式访问内存使用情况?但坦率地说,我希望有一条捷径,而不是重新实现生成上述代码的代码。例如,也许向 JVM 发送终止信号会强制上述输出?

4

2 回答 2

4

MXBean 有什么问题?实施并不难。

我用过类似的东西:

    List<GarbageCollectorMXBean> gcList = ManagementFactory.getGarbageCollectorMXBeans();
    for(GarbageCollectorMXBean tmpGC : gcList){

        System.out.println("\nName: " + tmpGC.getName());
        System.out.println("Collection count: " + tmpGC.getCollectionCount());
        System.out.println("Collection time: " + tmpGC.getCollectionTime());
        System.out.println("Memory Pools: ");

        String[] memoryPoolNames = tmpGC.getMemoryPoolNames();
        for(String mpnTmp : memoryPoolNames){
            System.out.println("\t" + mpnTmp);
        }

    }

    System.out.println( "Memory Pools Info" );
    List<MemoryPoolMXBean> memoryList = ManagementFactory.getMemoryPoolMXBeans();
    for(MemoryPoolMXBean tmpMem : memoryList){

        System.out.println("\nName: " + tmpMem.getName());
        System.out.println("Usage: " + tmpMem.getUsage());
        System.out.println("Collection Usage: " + tmpMem.getCollectionUsage());
        System.out.println("Peak Usage: " + tmpMem.getPeakUsage());
        System.out.println("Type: " + tmpMem.getType());
        System.out.println("Memory Manager Names: ") ;

        String[] memManagerNames = tmpMem.getMemoryManagerNames();
        for(String mmnTmp : memManagerNames){
            System.out.println("\t" + mmnTmp);
        }
        System.out.println("\n");
    }

    MemoryUsage mu =ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
    MemoryUsage muNH =ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage();
    System.out.println(
            "Init :"+mu.getInit()+
            "\nMax :"+mu.getMax()+
            "\nUsed :"+mu.getUsed()+
            "\nCommited :"+mu.getCommitted()+
            "\nInit NH :"+muNH.getInit()+
            "\nMax NH :"+muNH.getMax()+
            "\nUsed NH:"+muNH.getUsed()+
            "\nCommited NH:"+muNH.getCommitted());
于 2012-06-12T19:38:24.350 回答
2

您可以使用选项启动 JVM,以控制此类信息的运行时输出。

请参阅java 工具文档

例如输出到控制台:

java -verbose:gc

或输出到文件:

java -Xloggc:your.log.file

使用这些选项中的任何一个,JVM 都会在 VM 运行时记录每个 GC 事件(而不仅仅是在它退出时)。

于 2012-06-12T14:55:11.267 回答