8004213: JDP packet needs pid, broadcast interval and rmi server hostname fields
Summary: Add some extra fileds to jdp packet
Reviewed-by: allwin, sla, hirt
--- a/jdk/src/share/classes/sun/management/jdp/JdpController.java Fri Oct 18 16:28:35 2013 +0100
+++ b/jdk/src/share/classes/sun/management/jdp/JdpController.java Sat Oct 19 00:05:42 2013 +0400
@@ -29,6 +29,12 @@
import java.net.UnknownHostException;
import java.util.UUID;
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import sun.management.VMManagement;
+
/**
* JdpController is responsible to create and manage a broadcast loop
*
@@ -126,6 +132,25 @@
}
}
+ // Get the process id of the current running Java process
+ private static Integer getProcessId() {
+ try {
+ // Get the current process id using a reflection hack
+ RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
+ Field jvm = runtime.getClass().getDeclaredField("jvm");
+ jvm.setAccessible(true);
+
+ VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime);
+ Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId");
+ pid_method.setAccessible(true);
+ Integer pid = (Integer) pid_method.invoke(mgmt);
+ return pid;
+ } catch(Exception ex) {
+ return null;
+ }
+ }
+
+
/**
* Starts discovery service
*
@@ -173,6 +198,20 @@
// it the key is skipped. PacketWriter is responsible to skip keys having null value.
packet.setInstanceName(instanceName);
+ // Set rmi server hostname if it explicitly specified by user with
+ // java.rmi.server.hostname
+ String rmiHostname = System.getProperty("java.rmi.server.hostname");
+ packet.setRmiHostname(rmiHostname);
+
+ // Set broadcast interval
+ packet.setBroadcastInterval(new Integer(pause).toString());
+
+ // Set process id
+ Integer pid = getProcessId();
+ if (pid != null) {
+ packet.setProcessId(pid.toString());
+ }
+
JdpBroadcaster bcast = new JdpBroadcaster(address, sourceAddress, port, ttl);
// Stop discovery service if it's already running
--- a/jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java Fri Oct 18 16:28:35 2013 +0100
+++ b/jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java Sat Oct 19 00:05:42 2013 +0400
@@ -64,11 +64,27 @@
* Name of Java instance
*/
public final static String INSTANCE_NAME_KEY = "INSTANCE_NAME";
+ /**
+ * PID of java process, optional presented if it could be obtained
+ */
+ public final static String PROCESS_ID_KEY = "PROCESS_ID";
+ /**
+ * Hostname of rmi server, optional presented if user overrides rmi server
+ * hostname by java.rmi.server.hostname property
+ */
+ public final static String RMI_HOSTNAME_KEY = "RMI_HOSTNAME";
+ /**
+ * Configured broadcast interval, optional
+ */
+ public final static String BROADCAST_INTERVAL_KEY = "BROADCAST_INTERVAL";
private UUID id;
private String mainClass;
private String jmxServiceUrl;
private String instanceName;
+ private String processId;
+ private String rmiHostname;
+ private String broadcastInterval;
/**
* Create new instance from user provided data. Set mandatory fields
@@ -99,6 +115,9 @@
this.jmxServiceUrl = p.get(JMX_SERVICE_URL_KEY);
this.mainClass = p.get(MAIN_CLASS_KEY);
this.instanceName = p.get(INSTANCE_NAME_KEY);
+ this.processId = p.get(PROCESS_ID_KEY);
+ this.rmiHostname = p.get(RMI_HOSTNAME_KEY);
+ this.broadcastInterval = p.get(BROADCAST_INTERVAL_KEY);
}
/**
@@ -150,6 +169,30 @@
return instanceName;
}
+ public String getProcessId() {
+ return processId;
+ }
+
+ public void setProcessId(String processId) {
+ this.processId = processId;
+ }
+
+ public String getRmiHostname() {
+ return rmiHostname;
+ }
+
+ public void setRmiHostname(String rmiHostname) {
+ this.rmiHostname = rmiHostname;
+ }
+
+ public String getBroadcastInterval() {
+ return broadcastInterval;
+ }
+
+ public void setBroadcastInterval(String broadcastInterval) {
+ this.broadcastInterval = broadcastInterval;
+ }
+
/**
*
* @return assembled packet ready to be sent across a Net
@@ -164,6 +207,10 @@
writer.addEntry(MAIN_CLASS_KEY, mainClass);
writer.addEntry(JMX_SERVICE_URL_KEY, jmxServiceUrl);
writer.addEntry(INSTANCE_NAME_KEY, instanceName);
+ writer.addEntry(PROCESS_ID_KEY, processId);
+ writer.addEntry(RMI_HOSTNAME_KEY, rmiHostname);
+ writer.addEntry(BROADCAST_INTERVAL_KEY, broadcastInterval);
+
return writer.getPacketBytes();
}
--- a/jdk/test/sun/management/jdp/JdpClient.java Fri Oct 18 16:28:35 2013 +0100
+++ b/jdk/test/sun/management/jdp/JdpClient.java Sat Oct 19 00:05:42 2013 +0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,8 +35,10 @@
import java.nio.channels.Selector;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.Map;
import sun.management.jdp.JdpException;
import sun.management.jdp.JdpJmxPacket;
+import sun.management.jdp.JdpPacketReader;
public class JdpClient {
@@ -47,6 +49,31 @@
private static int maxPacketCount = 1;
private static int maxEmptyPacketCount = 10;
+ private void get(Map<?,?> map, String key)
+ throws JdpException {
+
+ if (map.get(key) == null) {
+ throw new JdpException("Test failed, packet field " + key + " missed");
+ }
+ }
+
+ private void checkFieldPresence(JdpJmxPacket p)
+ throws IOException, JdpException {
+
+ byte[] b = p.getPacketData();
+
+ JdpPacketReader reader = new JdpPacketReader(b);
+ Map<String,String> pMap = reader.getDiscoveryDataAsMap();
+
+ get(pMap, JdpJmxPacket.UUID_KEY);
+ get(pMap, JdpJmxPacket.MAIN_CLASS_KEY);
+ get(pMap, JdpJmxPacket.JMX_SERVICE_URL_KEY);
+ // get(pMap, JdpJmxPacket.INSTANCE_NAME_KEY);
+ get(pMap, JdpJmxPacket.PROCESS_ID_KEY);
+ get(pMap, JdpJmxPacket.BROADCAST_INTERVAL_KEY);
+ get(pMap, JdpJmxPacket.RMI_HOSTNAME_KEY);
+ }
+
PacketListener(DatagramChannel channel) {
this.channel = channel;
@@ -67,6 +94,8 @@
try {
while (true) {
+ // Use tcpdump -U -w - -s 1400 -c 2 -vv port 7095
+ // to verify that correct packet being sent
sel.selectedKeys().clear();
buf.rewind();
@@ -87,10 +116,10 @@
buf.flip();
byte[] dgramData = new byte[buf.remaining()];
buf.get(dgramData);
-
try {
JdpJmxPacket packet = new JdpJmxPacket(dgramData);
JdpDoSomething.printJdpPacket(packet);
+ checkFieldPresence(packet);
if(++count > maxPacketCount){
break;
}
--- a/jdk/test/sun/management/jdp/JdpDoSomething.java Fri Oct 18 16:28:35 2013 +0100
+++ b/jdk/test/sun/management/jdp/JdpDoSomething.java Sat Oct 19 00:05:42 2013 +0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
public class JdpDoSomething {
private static final String lockFileName = "JdpDoSomething.lck";
- private static final boolean verbose=false;
+ private static final boolean verbose = false;
public static boolean getVerbose(){
return verbose;
@@ -52,6 +52,9 @@
System.out.println("Jmx: " + p.getJmxServiceUrl());
System.out.println("Main: " + p.getMainClass());
System.out.println("InstanceName: " + p.getInstanceName());
+ System.out.println("ProccessId: " + p.getProcessId());
+ System.out.println("BroadcastInterval: " + p.getBroadcastInterval());
+ System.out.println("Rmi Hostname: " + p.getRmiHostname());
System.out.flush();
}
--- a/jdk/test/sun/management/jdp/JdpTest.sh Fri Oct 18 16:28:35 2013 +0100
+++ b/jdk/test/sun/management/jdp/JdpTest.sh Sat Oct 19 00:05:42 2013 +0400
@@ -1,6 +1,6 @@
#!/bin/sh -x
-# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -56,7 +56,7 @@
if [ ! -d ${_testclasses} ]
then
- mkdir -p ${_testclasses}
+ mkdir -p ${_testclasses}
fi
rm -f ${_testclasses}/*.class
@@ -64,7 +64,7 @@
# Compile testcase
${COMPILEJAVA}/bin/javac -XDignore.symbol.file -d ${_testclasses} \
JdpUnitTest.java \
- JdpDoSomething.java \
+ JdpDoSomething.java \
JdpClient.java
@@ -84,10 +84,10 @@
${TESTJAVA}/bin/java -server $* -cp ${_testclasses} ${testappname} >> ${_logname} 2>&1 &
_last_pid=$!
-# wait until VM is actually starts.
+# wait until VM is actually starts.
# please note, if vm doesn't start for some reason
# jtreg kills the test by timeout. Don't file a bug.
- cnt=1
+ cnt=1
while true
do
npid=`_get_pid`
@@ -135,7 +135,6 @@
-Dcom.sun.management.jdp.port=${_port} \
-Dcom.sun.management.jdp.address=${_ip} \
JdpClient
-
}
@@ -156,18 +155,20 @@
_echo "**** Test one ****"
_app_start JdpUnitTest \
- -Dcom.sun.management.jdp.port=${_port} \
- -Dcom.sun.management.jdp.address=${_ip} \
- -Dcom.sun.management.jdp.pause=5
+ -Dcom.sun.management.jdp.port=${_port} \
+ -Dcom.sun.management.jdp.address=${_ip} \
+ -Dcom.sun.management.jdp.name=testme \
+ -Djava.rmi.server.hostname=localhost \
+ -Dcom.sun.management.jdp.pause=5
res=`_testme`
case "${res}" in
OK*)
- _echo "Passed"
+ _echo "Passed"
;;
*)
- _echo "Failed!"
+ _echo "Failed!"
;;
esac
@@ -179,21 +180,23 @@
_echo "**** Test two ****"
_app_start JdpDoSomething \
- -Dcom.sun.management.jdp.port=${_port} \
- -Dcom.sun.management.jdp.address=${_ip} \
- -Dcom.sun.management.jdp.pause=5 \
- -Dcom.sun.management.jmxremote.port=${_jmxport} \
- -Dcom.sun.management.jmxremote.authenticate=false \
- -Dcom.sun.management.jmxremote.ssl=false
+ -Dcom.sun.management.jdp.port=${_port} \
+ -Dcom.sun.management.jdp.address=${_ip} \
+ -Dcom.sun.management.jdp.pause=5 \
+ -Dcom.sun.management.jdp.name=testme \
+ -Djava.rmi.server.hostname=localhost \
+ -Dcom.sun.management.jmxremote.port=${_jmxport} \
+ -Dcom.sun.management.jmxremote.authenticate=false \
+ -Dcom.sun.management.jmxremote.ssl=false
res=`_testme`
case "${res}" in
OK*)
- _echo "Passed"
+ _echo "Passed"
;;
*)
- _echo "Failed!"
+ _echo "Failed!"
;;
esac
@@ -218,10 +221,10 @@
case "${res}" in
OK*)
- _echo "Passed"
+ _echo "Passed"
;;
*)
- _echo "Failed!"
+ _echo "Failed!"
;;
esac
@@ -233,19 +236,21 @@
_echo "**** Test four ****"
_app_start JdpDoSomething \
- -Dcom.sun.management.jmxremote.autodiscovery=true \
- -Dcom.sun.management.jmxremote.port=${_jmxport} \
- -Dcom.sun.management.jmxremote.authenticate=false \
- -Dcom.sun.management.jmxremote.ssl=false
+ -Dcom.sun.management.jmxremote.autodiscovery=true \
+ -Dcom.sun.management.jdp.name=testme \
+ -Djava.rmi.server.hostname=localhost \
+ -Dcom.sun.management.jmxremote.port=${_jmxport} \
+ -Dcom.sun.management.jmxremote.authenticate=false \
+ -Dcom.sun.management.jmxremote.ssl=false
res=`_testme`
case "${res}" in
OK*)
- _echo "Passed"
+ _echo "Passed"
;;
*)
- _echo "Failed!"
+ _echo "Failed!"
;;
esac
@@ -269,10 +274,10 @@
case "${res}" in
OK*)
- _echo "Passed"
+ _echo "Passed"
;;
*)
- _echo "Failed!"
+ _echo "Failed!"
;;
esac
@@ -300,28 +305,28 @@
for parm in "$@"
do
- case $parm in
- --verbose) _verbose=yes ;;
- --jtreg) _jtreg=yes ;;
- --no-compile) _compile=no ;;
- --testsuite=*) _testsuite=`_echo $parm | sed "s,^--.*=\(.*\),\1,"` ;;
- *)
- echo "Undefined parameter $parm. Try --help for help"
- exit
- ;;
- esac
+ case $parm in
+ --verbose) _verbose=yes ;;
+ --jtreg) _jtreg=yes ;;
+ --no-compile) _compile=no ;;
+ --testsuite=*) _testsuite=`_echo $parm | sed "s,^--.*=\(.*\),\1,"` ;;
+ *)
+ echo "Undefined parameter $parm. Try --help for help"
+ exit
+ ;;
+ esac
done
if [ "${_compile}" = "yes" ]
then
- _do_compile
+ _do_compile
fi
if [ "${_jtreg}" = "yes" ]
then
- _testclasses=${TESTCLASSES}
- _testsrc=${TESTSRC}
- _logname="output.txt"
+ _testclasses=${TESTCLASSES}
+ _testsrc=${TESTSRC}
+ _logname="output.txt"
fi
# Make sure _tesclasses is absolute path