Java:GarbageCollectorMXBean getCollectionCount 抛出 java.io.IOException:客户端已关闭

标签 java garbage-collection jmx mxbean

我正在编写一个 Java 应用程序,我在其中使用 Java GarbageCollectorMXBean API 定期(每 5 秒)获取收集计数。下面是我为完成任务而编写的程序。

import java.io.IOException;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.util.HashMap;
import java.util.Map;

import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class JMXTest {
    public static final String GC_NAME = "java.lang:name=MarkSweepCompact,type=GarbageCollector";
    private static GarbageCollectorMXBean garbageCollectorMXBean;
    private static JMXConnector jmxConnector;
    private static MBeanServerConnection mbsc;

    public static void main(String[] args) throws Exception {
        String rmiHostname = "jmxserver";
        String defaultUrl = "service:jmx:rmi:///jndi/rmi://" + rmiHostname + ":1999/jmxrmi";
        JMXServiceURL jmxServiceURL = new JMXServiceURL(defaultUrl);

        Map<String,Object> jmxCredentials = new HashMap<String,Object>();
        String[] credentials = new String[]{"jmxusername", "jmxpassword"};
        jmxCredentials.put("jmx.remote.credentials", credentials);

       boolean run = true;
       while(run){
         try {
            if(garbageCollectorMXBean == null){
                if (mbsc == null){
                    jmxConnector = JMXConnectorFactory.connect(jmxServiceURL, jmxCredentials);
                    mbsc = jmxConnector.getMBeanServerConnection();
                }
                garbageCollectorMXBean = ManagementFactory.newPlatformMXBeanProxy(mbsc, GC_NAME,GarbageCollectorMXBean.class);
            }
            long count = garbageCollectorMXBean.getCollectionCount();
            System.out.println("Garbage Collector count = " + count);
        } catch (Exception e) {
            e.printStackTrace();
            garbageCollectorMXBean = null;
            if (jmxConnector != null)
            {
                try
                {
                    jmxConnector.close();
                } catch (IOException ioe) {}
                jmxConnector = null;
            }
            mbsc = null;
        }
        Thread.currentThread().sleep(5000);
    }
}

程序运行良好,但有时它会在每个循环中重复出现以下 IOException。

Exception in thread "main" java.io.IOException: The client has been closed.
at java.util.TimerThread.run(Timer.java:505)
at com.sun.jmx.remote.internal.ClientCommunicatorAdmin.restart(ClientCommunicatorAdmin.java:94)
at com.sun.jmx.remote.internal.ClientCommunicatorAdmin.gotIOException(ClientCommunicatorAdmin.java:54)
at javax.management.remote.rmi.RMIConnector$RMIClientCommunicatorAdmin.gotIOException(RMIConnector.java:1470)
at javax.management.remote.rmi.RMIConnector$RemoteMBeanServerConnection.getAttribute(RMIConnector.java:906)
at com.ibm.lang.management.OpenTypeMappingIHandler$6.run(OpenTypeMappingIHandler.java:506)
at java.security.AccessController.doPrivileged(AccessController.java:330)
at com.ibm.lang.management.OpenTypeMappingIHandler.invokeAttributeGetter(OpenTypeMappingIHandler.java:501)
at com.ibm.lang.management.OpenTypeMappingIHandler.invoke(OpenTypeMappingIHandler.java:121)
at com.sun.proxy.$Proxy112.getCollectionCount(Unknown Source)
at JMXTest.main(JMXTest.java:48)

查看代码,任何异常都将在 catch block 中捕获,其中所有字段都将初始化为 null,并且在下一个循环中所有字段将被重新初始化。但是,查看日志,一旦异常开始出现,我只会在每个循环中的 getCollectionCount() 调用中获得上述异常。我想知道即使对象被重新初始化,每次我都会遇到相同的异常。

我正在从以上信息中查看以下内容

  1. 在所有情况下,我们都会收到此异常 java.io.IOException: The client has been closed. 在上述场景中。我知道,如果我们调用 jmxConnector.close() 然后使用已经创建的 garbageCollectorMXBean 对象来获取集合计数,我们就会得到这个。但是我的代码不遵循该路径。
  2. 对于上述问题,jmxserver远程JMX服务器有贡献吗?我试图通过停止/重新启动远程 JMX 服务器来重现,但无法做到。

最佳答案

从堆栈跟踪最后一行判断:

at com.sun.proxy.$Proxy112.getCollectionCount(Unknown Source)
at JMXTest.main(JMXTest.java:48)

看来问题出在代码行上

if (jmxConnector != null)
            {
                try
                {
                    jmxConnector.close();
                } catch (IOException ioe) {}
                jmxConnector = null;   //...line no.48
            }
            mbsc = null;    //......this is probably causing the issue

@raghavendra,当您从 "JMXConnector"获取 "MBeanServerConnection"对象时,您应该按顺序关闭对象/使它们无效,即将代码更改为

if (jmxConnector != null)
            {
                try
                {
                    mbsc = null;    //...object handle assigned null before closing the connector 
                    jmxConnector.close();
                } catch (IOException ioe) {}
                jmxConnector = null;
            }

关于Java:GarbageCollectorMXBean getCollectionCount 抛出 java.io.IOException:客户端已关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25367634/

相关文章:

java - 导出到 jar 时如何包含 opencv native 库

java - 不使用 StringBuffer.reverse() 反转字符串

javascript - promise 垃圾的解决/拒绝功能是否在解决/拒绝后被收集?

java - 如何通过JMX暴露Hystrix的断路器状态

java - 如何更新主要 Activity 以了解首选项已更改?

java - 尝试将 JSON 字符串发送到 Android 客户端时出现 500 内部服务器错误 GAE?

java - 关于递归存储的二叉搜索树问题

c# - 我如何识别未被垃圾收集的不需要的 .NET 对象?

java - 如何在Activemq中暂停队列

java - Hazelcast MBean 丢失