Reputation: 406
I am writing a Java application where I am using Java GarbageCollectorMXBean
APIs to get the collection count at regular intervals (for every 5 seconds). Below is the program I have written to do the task.
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);
}
}
}
The program runs fine, but sometimes it starts giving following IOException repeatedly in every loop.
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)
Looking at the code, any exception will get caught in catch block where all fields will be initialized to null and in the next loop all the fields will be reinitialized. But, looking at the logs, once the exception starts coming, I get above exception only at getCollectionCount()
call in every loop. I wonder even though the objects are re-initialized, every time I get same exception.
I am looking at following things from the above information
java.io.IOException: The client has been closed.
in the above scenario. I know, if we call jmxConnector.close()
and then use the already created garbageCollectorMXBean
object to get the collection count, we get this. But my code does not follow that path. jmxserver
remote JMX server contributes? I tried to reproduce by stopping/restarting the remote JMX server, but could not do it.Upvotes: 5
Views: 1844
Reputation: 173
judging from the stack trace last line :
at com.sun.proxy.$Proxy112.getCollectionCount(Unknown Source)
at JMXTest.main(JMXTest.java:48)
it seems the problem is with line of code
if (jmxConnector != null)
{
try
{
jmxConnector.close();
} catch (IOException ioe) {}
jmxConnector = null; //...line no.48
}
mbsc = null; //......this is probably causing the issue
@raghavendra , as you acquire the "MBeanServerConnection" object from the "JMXConnector" , you should close the objects / nullify them in that order i.e. change your code to
if (jmxConnector != null)
{
try
{
mbsc = null; //...object handle assigned null before closing the connector
jmxConnector.close();
} catch (IOException ioe) {}
jmxConnector = null;
}
Upvotes: 0