changeset 767:5eab86fc2ea8

Merge
author tbell
date Fri, 17 Oct 2008 16:45:36 -0700
parents cc5f810b5af8 214ebdcf7252
children 889050324044 7df3f9183f67
files
diffstat 16 files changed, 522 insertions(+), 157 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java	Fri Oct 17 08:41:15 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java	Fri Oct 17 16:45:36 2008 -0700
@@ -32,6 +32,7 @@
 import java.lang.reflect.GenericArrayType;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.util.Map;
 import java.util.WeakHashMap;
@@ -390,7 +391,31 @@
         if (type instanceof Class)
             return ((Class) type).getName();
         else
-            return type.toString();
+            return genericTypeString(type);
+    }
+
+    private static String genericTypeString(Type type) {
+        if (type instanceof Class<?>) {
+            Class<?> c = (Class<?>) type;
+            if (c.isArray())
+                return genericTypeString(c.getComponentType()) + "[]";
+            else
+                return c.getName();
+        } else if (type instanceof GenericArrayType) {
+            GenericArrayType gat = (GenericArrayType) type;
+            return genericTypeString(gat.getGenericComponentType()) + "[]";
+        } else if (type instanceof ParameterizedType) {
+            ParameterizedType pt = (ParameterizedType) type;
+            StringBuilder sb = new StringBuilder();
+            sb.append(genericTypeString(pt.getRawType())).append("<");
+            String sep = "";
+            for (Type t : pt.getActualTypeArguments()) {
+                sb.append(sep).append(genericTypeString(t));
+                sep = ", ";
+            }
+            return sb.append(">").toString();
+        } else
+            return "???";
     }
 
     private final PerInterfaceMap<ConvertingMethod>
--- a/src/share/classes/java/nio/channels/SelectableChannel.java	Fri Oct 17 08:41:15 2008 -0700
+++ b/src/share/classes/java/nio/channels/SelectableChannel.java	Fri Oct 17 16:45:36 2008 -0700
@@ -191,6 +191,9 @@
      * @throws  ClosedChannelException
      *          If this channel is closed
      *
+     * @throws  ClosedSelectorException
+     *          If the selector is closed
+     *
      * @throws  IllegalBlockingModeException
      *          If this channel is in blocking mode
      *
@@ -246,6 +249,9 @@
      * @throws  ClosedChannelException
      *          If this channel is closed
      *
+     * @throws  ClosedSelectorException
+     *          If the selector is closed
+     *
      * @throws  IllegalBlockingModeException
      *          If this channel is in blocking mode
      *
--- a/src/share/classes/java/nio/channels/spi/AbstractSelectableChannel.java	Fri Oct 17 08:41:15 2008 -0700
+++ b/src/share/classes/java/nio/channels/spi/AbstractSelectableChannel.java	Fri Oct 17 16:45:36 2008 -0700
@@ -175,6 +175,16 @@
      * the selector is invoked while holding the appropriate locks.  The
      * resulting key is added to this channel's key set before being returned.
      * </p>
+     *
+     * @throws  ClosedSelectorException {@inheritDoc}
+     *
+     * @throws  IllegalBlockingModeException {@inheritDoc}
+     *
+     * @throws  IllegalSelectorException {@inheritDoc}
+     *
+     * @throws  CancelledKeyException {@inheritDoc}
+     *
+     * @throws  IllegalArgumentException {@inheritDoc}
      */
     public final SelectionKey register(Selector sel, int ops,
                                        Object att)
--- a/src/share/classes/javax/management/event/EventClient.java	Fri Oct 17 08:41:15 2008 -0700
+++ b/src/share/classes/javax/management/event/EventClient.java	Fri Oct 17 16:45:36 2008 -0700
@@ -265,12 +265,20 @@
             public ScheduledThreadPoolExecutor createThreadPool(ThreadGroup group) {
                 ThreadFactory daemonThreadFactory = new DaemonThreadFactory(
                         "JMX EventClient lease renewer %d");
-                ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(
-                        20, daemonThreadFactory);
-                exec.setKeepAliveTime(1, TimeUnit.SECONDS);
-                exec.allowCoreThreadTimeOut(true);
-                exec.setRemoveOnCancelPolicy(true);
-                return exec;
+                ScheduledThreadPoolExecutor executor =
+                        new ScheduledThreadPoolExecutor(20, daemonThreadFactory);
+                executor.setKeepAliveTime(1, TimeUnit.SECONDS);
+                executor.allowCoreThreadTimeOut(true);
+                executor.setRemoveOnCancelPolicy(true);
+                // By default, a ScheduledThreadPoolExecutor will keep jobs
+                // in its queue even after they have been cancelled.  They
+                // will only be removed when their scheduled time arrives.
+                // Since the job references the LeaseRenewer which references
+                // this EventClient, this can lead to a moderately large number
+                // of objects remaining referenced until the renewal time
+                // arrives.  Hence the above call, which removes the job from
+                // the queue as soon as it is cancelled.
+                return executor;
             }
         };
         return leaseRenewerThreadPool.getThreadPoolExecutor(create);
@@ -381,7 +389,7 @@
             listenerId =
                     eventClientDelegate.addListener(clientId, name, filter);
         } catch (EventClientNotFoundException ecnfe) {
-            final IOException ioe = new IOException();
+            final IOException ioe = new IOException(ecnfe.getMessage());
             ioe.initCause(ecnfe);
             throw ioe;
         }
@@ -488,7 +496,7 @@
             listenerId =
                     eventClientDelegate.addSubscriber(clientId, name, filter);
         } catch (EventClientNotFoundException ecnfe) {
-            final IOException ioe = new IOException();
+            final IOException ioe = new IOException(ecnfe.getMessage());
             ioe.initCause(ecnfe);
             throw ioe;
         }
--- a/src/share/classes/javax/management/event/FetchingEventRelay.java	Fri Oct 17 08:41:15 2008 -0700
+++ b/src/share/classes/javax/management/event/FetchingEventRelay.java	Fri Oct 17 16:45:36 2008 -0700
@@ -91,7 +91,7 @@
      * the fetching.
      *
      * @param delegate The {@code EventClientDelegateMBean} to work with.
-     * @param executor Used to do the fetching. A new thread is created if
+     * @param fetchExecutor Used to do the fetching. A new thread is created if
      * {@code null}.
      * @throws IOException If failed to work with the {@code delegate}.
      * @throws MBeanException if unable to add a client to the remote
@@ -101,12 +101,12 @@
      * @throws IllegalArgumentException If {@code delegate} is {@code null}.
      */
     public FetchingEventRelay(EventClientDelegateMBean delegate,
-            Executor executor) throws IOException, MBeanException {
+            Executor fetchExecutor) throws IOException, MBeanException {
         this(delegate,
                 DEFAULT_BUFFER_SIZE,
                 DEFAULT_WAITING_TIMEOUT,
                 DEFAULT_MAX_NOTIFICATIONS,
-                executor);
+                fetchExecutor);
     }
 
     /**
@@ -120,7 +120,7 @@
      * @param timeout The waiting time in millseconds when fetching
      * notifications from an {@code EventClientDelegateMBean}.
      * @param maxNotifs The maximum notifications to fetch every time.
-     * @param executor Used to do the fetching. A new thread is created if
+     * @param fetchExecutor Used to do the fetching. A new thread is created if
      * {@code null}.
      * @throws IOException if failed to communicate with the {@code delegate}.
      * @throws MBeanException if unable to add a client to the remote
@@ -133,12 +133,12 @@
             int bufferSize,
             long timeout,
             int maxNotifs,
-            Executor executor) throws IOException, MBeanException {
+            Executor fetchExecutor) throws IOException, MBeanException {
         this(delegate,
                 bufferSize,
                 timeout,
                 maxNotifs,
-                executor,
+                fetchExecutor,
                 FetchingEventForwarder.class.getName(),
                 new Object[] {bufferSize},
                 new String[] {int.class.getName()});
@@ -155,7 +155,7 @@
      * @param timeout The waiting time in millseconds when fetching
      * notifications from an {@code EventClientDelegateMBean}.
      * @param maxNotifs The maximum notifications to fetch every time.
-     * @param executor Used to do the fetching.
+     * @param fetchExecutor Used to do the fetching.
      * @param forwarderName the class name of a user specific EventForwarder
      * to create in server to forward notifications to this object. The class
      * should be a subclass of the class {@link FetchingEventForwarder}.
@@ -174,7 +174,7 @@
             int bufferSize,
             long timeout,
             int maxNotifs,
-            Executor executor,
+            Executor fetchExecutor,
             String forwarderName,
             Object[] params,
             String[] sig) throws IOException, MBeanException {
@@ -184,11 +184,11 @@
                     bufferSize+" "+
                     timeout+" "+
                     maxNotifs+" "+
-                    executor+" "+
+                    fetchExecutor+" "+
                     forwarderName+" ");
         }
 
-        if(delegate == null) {
+        if (delegate == null) {
             throw new NullPointerException("Null EventClientDelegateMBean!");
         }
 
@@ -212,16 +212,16 @@
         this.timeout = timeout;
         this.maxNotifs = maxNotifs;
 
-        if (executor == null) {
-            ScheduledThreadPoolExecutor stpe = new ScheduledThreadPoolExecutor(1,
-                    daemonThreadFactory);
-            stpe.setKeepAliveTime(1, TimeUnit.SECONDS);
-            stpe.allowCoreThreadTimeOut(true);
-            executor = stpe;
-            this.defaultExecutor = stpe;
+        if (fetchExecutor == null) {
+            ScheduledThreadPoolExecutor executor =
+                    new ScheduledThreadPoolExecutor(1, daemonThreadFactory);
+            executor.setKeepAliveTime(1, TimeUnit.SECONDS);
+            executor.allowCoreThreadTimeOut(true);
+            fetchExecutor = executor;
+            this.defaultExecutor = executor;
         } else
             this.defaultExecutor = null;
-        this.executor = executor;
+        this.fetchExecutor = fetchExecutor;
 
         startSequenceNumber = 0;
         fetchingJob = new MyJob();
@@ -258,7 +258,7 @@
 
     private class MyJob extends RepeatedSingletonJob {
         public MyJob() {
-            super(executor);
+            super(fetchExecutor);
         }
 
         public boolean isSuspended() {
@@ -368,7 +368,7 @@
     private String clientId;
     private boolean stopped = false;
 
-    private final Executor executor;
+    private final Executor fetchExecutor;
     private final ExecutorService defaultExecutor;
     private final MyJob fetchingJob;
 
--- a/src/share/classes/javax/management/monitor/Monitor.java	Fri Oct 17 08:41:15 2008 -0700
+++ b/src/share/classes/javax/management/monitor/Monitor.java	Fri Oct 17 16:45:36 2008 -0700
@@ -181,7 +181,7 @@
     /**
      * Executor Service.
      */
-    private static final ExecutorService executor;
+    private static final ThreadPoolExecutor executor;
     static {
         final String maximumPoolSizeSysProp = "jmx.x.monitor.maximum.pool.size";
         final String maximumPoolSizeStr = AccessController.doPrivileged(
@@ -218,7 +218,7 @@
                 TimeUnit.SECONDS,
                 new LinkedBlockingQueue<Runnable>(),
                 new DaemonThreadFactory("Executor"));
-        ((ThreadPoolExecutor)executor).allowCoreThreadTimeOut(true);
+        executor.allowCoreThreadTimeOut(true);
     }
 
     /**
--- a/src/share/classes/javax/management/remote/rmi/RMIConnector.java	Fri Oct 17 08:41:15 2008 -0700
+++ b/src/share/classes/javax/management/remote/rmi/RMIConnector.java	Fri Oct 17 16:45:36 2008 -0700
@@ -71,9 +71,8 @@
 import java.util.Properties;
 import java.util.Set;
 import java.util.WeakHashMap;
-import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.Executor;
-import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
@@ -421,12 +420,12 @@
             public ThreadPoolExecutor createThreadPool(ThreadGroup group) {
                 ThreadFactory daemonThreadFactory = new DaemonThreadFactory(
                         "JMX RMIConnector listener dispatch %d");
-                ThreadPoolExecutor exec = new ThreadPoolExecutor(
+                ThreadPoolExecutor executor = new ThreadPoolExecutor(
                         1, 10, 1, TimeUnit.SECONDS,
-                        new LinkedBlockingDeque<Runnable>(),
+                        new LinkedBlockingQueue<Runnable>(),
                         daemonThreadFactory);
-                exec.allowCoreThreadTimeOut(true);
-                return exec;
+                executor.allowCoreThreadTimeOut(true);
+                return executor;
             }
         };
         return listenerDispatchThreadPool.getThreadPoolExecutor(create);
@@ -1503,7 +1502,7 @@
             super(period);
         }
 
-        public void gotIOException (IOException ioe) throws IOException {
+        public void gotIOException(IOException ioe) throws IOException {
             if (ioe instanceof NoSuchObjectException) {
                 // need to restart
                 super.gotIOException(ioe);
--- a/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java	Fri Oct 17 08:41:15 2008 -0700
+++ b/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java	Fri Oct 17 16:45:36 2008 -0700
@@ -80,7 +80,7 @@
 import static sun.management.AgentConfigurationError.*;
 import sun.management.ConnectorAddressLink;
 import sun.management.FileSystem;
-import sun.management.snmp.util.MibLogger;
+import com.sun.jmx.remote.util.ClassLogger;
 
 import com.sun.jmx.remote.internal.RMIExporter;
 import com.sun.jmx.remote.security.JMXPluggableAuthenticator;
@@ -99,6 +99,7 @@
         public static final String PORT = "0";
         public static final String CONFIG_FILE_NAME = "management.properties";
         public static final String USE_SSL = "true";
+        public static final String USE_LOCAL_ONLY = "true";
         public static final String USE_REGISTRY_SSL = "false";
         public static final String USE_AUTHENTICATION = "true";
         public static final String PASSWORD_FILE_NAME = "jmxremote.password";
@@ -115,6 +116,8 @@
                 "com.sun.management.jmxremote.port";
         public static final String CONFIG_FILE_NAME =
                 "com.sun.management.config.file";
+        public static final String USE_LOCAL_ONLY =
+                "com.sun.management.jmxremote.local.only";
         public static final String USE_SSL =
                 "com.sun.management.jmxremote.ssl";
         public static final String USE_REGISTRY_SSL =
@@ -384,7 +387,7 @@
             checkAccessFile(accessFileName);
         }
 
-        if (log.isDebugOn()) {
+        if (log.debugOn()) {
             log.debug("initialize",
                     Agent.getText("jmxremote.ConnectorBootstrap.initialize") +
                     "\n\t" + PropertyNames.PORT + "=" + port +
@@ -477,6 +480,18 @@
         MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
         try {
             JMXServiceURL url = new JMXServiceURL("rmi", localhost, 0);
+            // Do we accept connections from local interfaces only?
+            Properties props = Agent.getManagementProperties();
+            if (props ==  null) {
+                props = new Properties();
+            }
+            String useLocalOnlyStr = props.getProperty(
+                    PropertyNames.USE_LOCAL_ONLY, DefaultValues.USE_LOCAL_ONLY);
+            boolean useLocalOnly = Boolean.valueOf(useLocalOnlyStr).booleanValue();
+            if (useLocalOnly) {
+                env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,
+                        new LocalRMIServerSocketFactory());
+            }
             JMXConnectorServer server =
                     JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
             server.start();
@@ -764,7 +779,7 @@
     private ConnectorBootstrap() {
     }
 
-    // XXX Revisit: should probably clone this MibLogger....
-    private static final MibLogger log =
-            new MibLogger(ConnectorBootstrap.class);
+    private static final ClassLogger log =
+        new ClassLogger(ConnectorBootstrap.class.getPackage().getName(),
+                        "ConnectorBootstrap");
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/management/jmxremote/LocalRMIServerSocketFactory.java	Fri Oct 17 16:45:36 2008 -0700
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.management.jmxremote;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.rmi.server.RMIServerSocketFactory;
+import java.util.Enumeration;
+
+/**
+ * This RMI server socket factory creates server sockets that
+ * will only accept connection requests from clients running
+ * on the host where the RMI remote objects have been exported.
+ */
+public final class LocalRMIServerSocketFactory implements RMIServerSocketFactory {
+    /**
+     * Creates a server socket that only accepts connection requests from
+     * clients running on the host where the RMI remote objects have been
+     * exported.
+     */
+    public ServerSocket createServerSocket(int port) throws IOException {
+        return new ServerSocket(port) {
+            @Override
+            public Socket accept() throws IOException {
+                Socket socket = super.accept();
+                InetAddress remoteAddr = socket.getInetAddress();
+                final String msg = "The server sockets created using the " +
+                        "LocalRMIServerSocketFactory only accept connections " +
+                        "from clients running on the host where the RMI " +
+                        "remote objects have been exported.";
+                if (remoteAddr.isAnyLocalAddress()) {
+                    // local address: accept the connection.
+                    return socket;
+                }
+                // Retrieve all the network interfaces on this host.
+                Enumeration<NetworkInterface> nis;
+                try {
+                    nis = NetworkInterface.getNetworkInterfaces();
+                } catch (SocketException e) {
+                    try {
+                        socket.close();
+                    } catch (IOException ioe) {
+                        // Ignore...
+                    }
+                    throw new IOException(msg, e);
+                }
+                // Walk through the network interfaces to see
+                // if any of them matches the client's address.
+                // If true, then the client's address is local.
+                while (nis.hasMoreElements()) {
+                    NetworkInterface ni = nis.nextElement();
+                    Enumeration<InetAddress> addrs = ni.getInetAddresses();
+                    while (addrs.hasMoreElements()) {
+                        InetAddress localAddr = addrs.nextElement();
+                        if (localAddr.equals(remoteAddr)) {
+                            return socket;
+                        }
+                    }
+                }
+                // The client's address is remote so refuse the connection.
+                try {
+                    socket.close();
+                } catch (IOException ioe) {
+                    // Ignore...
+                }
+                throw new IOException(msg);
+            }
+        };
+    }
+
+    /**
+     * Two LocalRMIServerSocketFactory objects
+     * are equal if they are of the same type.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        return (obj instanceof LocalRMIServerSocketFactory);
+    }
+
+    /**
+     * Returns a hash code value for this LocalRMIServerSocketFactory.
+     */
+    @Override
+    public int hashCode() {
+        return getClass().hashCode();
+    }
+}
--- a/src/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java	Fri Oct 17 08:41:15 2008 -0700
+++ b/src/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java	Fri Oct 17 16:45:36 2008 -0700
@@ -58,6 +58,9 @@
     // True if this Selector has been closed
     private boolean closed = false;
 
+    // Lock for close and cleanup
+    private Object closeLock = new Object();
+
     AbstractPollSelectorImpl(SelectorProvider sp, int channels, int offset) {
         super(sp);
         this.totalChannels = channels;
@@ -65,7 +68,11 @@
     }
 
     void putEventOps(SelectionKeyImpl sk, int ops) {
-        pollWrapper.putEventOps(sk.getIndex(), ops);
+        synchronized (closeLock) {
+            if (closed)
+                throw new ClosedSelectorException();
+            pollWrapper.putEventOps(sk.getIndex(), ops);
+        }
     }
 
     public Selector wakeup() {
@@ -76,7 +83,9 @@
     protected abstract int doSelect(long timeout) throws IOException;
 
     protected void implClose() throws IOException {
-        if (!closed) {
+        synchronized (closeLock) {
+            if (closed)
+                return;
             closed = true;
             // Deregister channels
             for(int i=channelOffset; i<totalChannels; i++) {
@@ -129,23 +138,28 @@
     }
 
     protected void implRegister(SelectionKeyImpl ski) {
-        // Check to see if the array is large enough
-        if (channelArray.length == totalChannels) {
-            // Make a larger array
-            int newSize = pollWrapper.totalChannels * 2;
-            SelectionKeyImpl temp[] = new SelectionKeyImpl[newSize];
-            // Copy over
-            for (int i=channelOffset; i<totalChannels; i++)
-                temp[i] = channelArray[i];
-            channelArray = temp;
-            // Grow the NativeObject poll array
-            pollWrapper.grow(newSize);
+        synchronized (closeLock) {
+            if (closed)
+                throw new ClosedSelectorException();
+
+            // Check to see if the array is large enough
+            if (channelArray.length == totalChannels) {
+                // Make a larger array
+                int newSize = pollWrapper.totalChannels * 2;
+                SelectionKeyImpl temp[] = new SelectionKeyImpl[newSize];
+                // Copy over
+                for (int i=channelOffset; i<totalChannels; i++)
+                    temp[i] = channelArray[i];
+                channelArray = temp;
+                // Grow the NativeObject poll array
+                pollWrapper.grow(newSize);
+            }
+            channelArray[totalChannels] = ski;
+            ski.setIndex(totalChannels);
+            pollWrapper.addEntry(ski.channel);
+            totalChannels++;
+            keys.add(ski);
         }
-        channelArray[totalChannels] = ski;
-        ski.setIndex(totalChannels);
-        pollWrapper.addEntry(ski.channel);
-        totalChannels++;
-        keys.add(ski);
     }
 
     protected void implDereg(SelectionKeyImpl ski) throws IOException {
--- a/src/share/lib/management/management.properties	Fri Oct 17 08:41:15 2008 -0700
+++ b/src/share/lib/management/management.properties	Fri Oct 17 16:45:36 2008 -0700
@@ -82,7 +82,7 @@
 #
 # com.sun.management.snmp.interface=<InetAddress>
 #      Specifies the local interface on which the SNMP agent will bind.
-#      This is usefull when running on machines which have several
+#      This is useful when running on machines which have several
 #      interfaces defined. It makes it possible to listen to a specific
 #      subnet accessible through that interface.
 #      Default for this property is "localhost".
@@ -144,6 +144,26 @@
 #
 
 #
+# ########## RMI connector settings for local management ##########
+#
+# com.sun.management.jmxremote.local.only=true|false
+#      Default for this property is true. (Case for true/false ignored)
+#      If this property is specified as true then the local JMX RMI connector
+#      server will only accept connection requests from clients running on
+#      the host where the out-of-the-box JMX management agent is running.
+#      In order to ensure backwards compatibility this property could be
+#      set to false. However, deploying the local management agent in this
+#      way is discouraged because the local JMX RMI connector server will
+#      accept connection requests from any client either local or remote.
+#      For remote management the remote JMX RMI connector server should
+#      be used instead with authentication and SSL/TLS encryption enabled.
+#
+
+# For allowing the local management agent accept local
+# and remote connection requests use the following line
+# com.sun.management.jmxremote.local.only=false
+
+#
 # ###################### RMI SSL #############################
 #
 # com.sun.management.jmxremote.ssl=true|false
--- a/src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java	Fri Oct 17 08:41:15 2008 -0700
+++ b/src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java	Fri Oct 17 16:45:36 2008 -0700
@@ -46,15 +46,15 @@
     // The poll object
     DevPollArrayWrapper pollWrapper;
 
-    // The number of valid channels in this Selector's poll array
-    private int totalChannels;
-
     // Maps from file descriptors to keys
     private Map<Integer,SelectionKeyImpl> fdToKey;
 
     // True if this Selector has been closed
     private boolean closed = false;
 
+    // Lock for close/cleanup
+    private Object closeLock = new Object();
+
     // Lock for interrupt triggering and clearing
     private Object interruptLock = new Object();
     private boolean interruptTriggered = false;
@@ -72,7 +72,6 @@
         pollWrapper = new DevPollArrayWrapper();
         pollWrapper.initInterrupt(fd0, fd1);
         fdToKey = new HashMap<Integer,SelectionKeyImpl>();
-        totalChannels = 1;
     }
 
     protected int doSelect(long timeout)
@@ -131,45 +130,39 @@
     }
 
     protected void implClose() throws IOException {
-        if (!closed) {
-            closed = true;
+        if (closed)
+            return;
+        closed = true;
 
-            // prevent further wakeup
-            synchronized (interruptLock) {
-                interruptTriggered = true;
-            }
+        // prevent further wakeup
+        synchronized (interruptLock) {
+            interruptTriggered = true;
+        }
 
-            FileDispatcher.closeIntFD(fd0);
-            FileDispatcher.closeIntFD(fd1);
-            if (pollWrapper != null) {
+        FileDispatcher.closeIntFD(fd0);
+        FileDispatcher.closeIntFD(fd1);
 
-                pollWrapper.release(fd0);
-                pollWrapper.closeDevPollFD();
-                pollWrapper = null;
-                selectedKeys = null;
+        pollWrapper.release(fd0);
+        pollWrapper.closeDevPollFD();
+        selectedKeys = null;
 
-                // Deregister channels
-                Iterator i = keys.iterator();
-                while (i.hasNext()) {
-                    SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
-                    deregister(ski);
-                    SelectableChannel selch = ski.channel();
-                    if (!selch.isOpen() && !selch.isRegistered())
-                        ((SelChImpl)selch).kill();
-                    i.remove();
-                }
-                totalChannels = 0;
-
-            }
-            fd0 = -1;
-            fd1 = -1;
+        // Deregister channels
+        Iterator i = keys.iterator();
+        while (i.hasNext()) {
+            SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
+            deregister(ski);
+            SelectableChannel selch = ski.channel();
+            if (!selch.isOpen() && !selch.isRegistered())
+                ((SelChImpl)selch).kill();
+            i.remove();
         }
+        fd0 = -1;
+        fd1 = -1;
     }
 
     protected void implRegister(SelectionKeyImpl ski) {
         int fd = IOUtil.fdVal(ski.channel.getFD());
         fdToKey.put(Integer.valueOf(fd), ski);
-        totalChannels++;
         keys.add(ski);
     }
 
@@ -179,7 +172,6 @@
         int fd = ski.channel.getFDVal();
         fdToKey.remove(Integer.valueOf(fd));
         pollWrapper.release(fd);
-        totalChannels--;
         ski.setIndex(-1);
         keys.remove(ski);
         selectedKeys.remove(ski);
@@ -190,6 +182,8 @@
     }
 
     void putEventOps(SelectionKeyImpl sk, int ops) {
+        if (closed)
+            throw new ClosedSelectorException();
         int fd = IOUtil.fdVal(sk.channel.getFD());
         pollWrapper.setInterest(fd, ops);
     }
--- a/src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java	Fri Oct 17 08:41:15 2008 -0700
+++ b/src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java	Fri Oct 17 16:45:36 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-2007 Sun Microsystems, Inc.  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
@@ -31,7 +31,6 @@
 import java.util.*;
 import sun.misc.*;
 
-
 /**
  * An implementation of Selector for Linux 2.6+ kernels that uses
  * the epoll event notification facility.
@@ -51,7 +50,7 @@
     private Map<Integer,SelectionKeyImpl> fdToKey;
 
     // True if this Selector has been closed
-    private boolean closed = false;
+    private volatile boolean closed = false;
 
     // Lock for interrupt triggering and clearing
     private Object interruptLock = new Object();
@@ -128,40 +127,41 @@
     }
 
     protected void implClose() throws IOException {
-        if (!closed) {
-            closed = true;
+        if (closed)
+            return;
+        closed = true;
 
-            // prevent further wakeup
-            synchronized (interruptLock) {
-                interruptTriggered = true;
-            }
+        // prevent further wakeup
+        synchronized (interruptLock) {
+            interruptTriggered = true;
+        }
 
-            FileDispatcher.closeIntFD(fd0);
-            FileDispatcher.closeIntFD(fd1);
-            if (pollWrapper != null) {
+        FileDispatcher.closeIntFD(fd0);
+        FileDispatcher.closeIntFD(fd1);
 
-                pollWrapper.release(fd0);
-                pollWrapper.closeEPollFD();
-                pollWrapper = null;
-                selectedKeys = null;
+        pollWrapper.release(fd0);
+        pollWrapper.closeEPollFD();
+        // it is possible
+        selectedKeys = null;
 
-                // Deregister channels
-                Iterator i = keys.iterator();
-                while (i.hasNext()) {
-                    SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
-                    deregister(ski);
-                    SelectableChannel selch = ski.channel();
-                    if (!selch.isOpen() && !selch.isRegistered())
-                        ((SelChImpl)selch).kill();
-                    i.remove();
-                }
-            }
-            fd0 = -1;
-            fd1 = -1;
+        // Deregister channels
+        Iterator i = keys.iterator();
+        while (i.hasNext()) {
+            SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
+            deregister(ski);
+            SelectableChannel selch = ski.channel();
+            if (!selch.isOpen() && !selch.isRegistered())
+                ((SelChImpl)selch).kill();
+            i.remove();
         }
+
+        fd0 = -1;
+        fd1 = -1;
     }
 
     protected void implRegister(SelectionKeyImpl ski) {
+        if (closed)
+            throw new ClosedSelectorException();
         int fd = IOUtil.fdVal(ski.channel.getFD());
         fdToKey.put(Integer.valueOf(fd), ski);
         pollWrapper.add(fd);
@@ -183,6 +183,8 @@
     }
 
     void putEventOps(SelectionKeyImpl sk, int ops) {
+        if (closed)
+            throw new ClosedSelectorException();
         int fd = IOUtil.fdVal(sk.channel.getFD());
         pollWrapper.setInterest(fd, ops);
     }
--- a/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java	Fri Oct 17 08:41:15 2008 -0700
+++ b/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java	Fri Oct 17 16:45:36 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2002-2007 Sun Microsystems, Inc.  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
@@ -80,6 +80,9 @@
     // File descriptors corresponding to source and sink
     private final int wakeupSourceFd, wakeupSinkFd;
 
+    // Lock for close cleanup
+    private Object closeLock = new Object();
+
     // Maps file descriptors to their indices in  pollArray
     private final static class FdMap extends HashMap<Integer, MapEntry> {
         static final long serialVersionUID = 0L;
@@ -473,42 +476,48 @@
     }
 
     protected void implClose() throws IOException {
-        if (channelArray != null) {
-            if (pollWrapper != null) {
-                // prevent further wakeup
-                synchronized (interruptLock) {
-                    interruptTriggered = true;
-                }
-                wakeupPipe.sink().close();
-                wakeupPipe.source().close();
-                for(int i = 1; i < totalChannels; i++) { // Deregister channels
-                    if (i % MAX_SELECTABLE_FDS != 0) { // skip wakeupEvent
-                        deregister(channelArray[i]);
-                        SelectableChannel selch = channelArray[i].channel();
-                        if (!selch.isOpen() && !selch.isRegistered())
-                            ((SelChImpl)selch).kill();
+        synchronized (closeLock) {
+            if (channelArray != null) {
+                if (pollWrapper != null) {
+                    // prevent further wakeup
+                    synchronized (interruptLock) {
+                        interruptTriggered = true;
                     }
-                }
-                pollWrapper.free();
-                pollWrapper = null;
-                selectedKeys = null;
-                channelArray = null;
-                threads.clear();
-                // Call startThreads. All remaining helper threads now exit,
-                // since threads.size() = 0;
-                startLock.startThreads();
+                    wakeupPipe.sink().close();
+                    wakeupPipe.source().close();
+                    for(int i = 1; i < totalChannels; i++) { // Deregister channels
+                        if (i % MAX_SELECTABLE_FDS != 0) { // skip wakeupEvent
+                            deregister(channelArray[i]);
+                            SelectableChannel selch = channelArray[i].channel();
+                            if (!selch.isOpen() && !selch.isRegistered())
+                                ((SelChImpl)selch).kill();
+                        }
+                    }
+                    pollWrapper.free();
+                    pollWrapper = null;
+                     selectedKeys = null;
+                     channelArray = null;
+                     threads.clear();
+                     // Call startThreads. All remaining helper threads now exit,
+                     // since threads.size() = 0;
+                     startLock.startThreads();
+                 }
             }
         }
     }
 
     protected void implRegister(SelectionKeyImpl ski) {
-        growIfNeeded();
-        channelArray[totalChannels] = ski;
-        ski.setIndex(totalChannels);
-        fdMap.put(ski);
-        keys.add(ski);
-        pollWrapper.addEntry(totalChannels, ski);
-        totalChannels++;
+        synchronized (closeLock) {
+            if (pollWrapper == null)
+                throw new ClosedSelectorException();
+            growIfNeeded();
+            channelArray[totalChannels] = ski;
+            ski.setIndex(totalChannels);
+            fdMap.put(ski);
+            keys.add(ski);
+            pollWrapper.addEntry(totalChannels, ski);
+            totalChannels++;
+        }
     }
 
     private void growIfNeeded() {
@@ -554,7 +563,11 @@
     }
 
     void putEventOps(SelectionKeyImpl sk, int ops) {
-        pollWrapper.putEventOps(sk.getIndex(), ops);
+        synchronized (closeLock) {
+            if (pollWrapper == null)
+                throw new ClosedSelectorException();
+            pollWrapper.putEventOps(sk.getIndex(), ops);
+        }
     }
 
     public Selector wakeup() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/nio/channels/Selector/CloseThenRegister.java	Fri Oct 17 16:45:36 2008 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @bug 5025260
+ * @summary ClosedSelectorException is expected when register after close
+ */
+
+import java.net.*;
+import java.nio.channels.*;
+
+public class CloseThenRegister {
+
+    public static void main (String [] args) throws Exception {
+        try {
+            Selector s = Selector.open();
+            s.close();
+            ServerSocketChannel c = ServerSocketChannel.open();
+            c.socket().bind(new InetSocketAddress(40000));
+            c.configureBlocking(false);
+            c.register(s, SelectionKey.OP_ACCEPT);
+        } catch (ClosedSelectorException cse) {
+            return;
+        }
+        throw new RuntimeException("register after close does not cause CSE!");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/mxbean/TypeNameTest.java	Fri Oct 17 16:45:36 2008 -0700
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6757225
+ * @summary Test that type names in MXBeans match their spec.
+ * @author Eamonn McManus
+ */
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.List;
+import java.util.Map;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+import javax.management.StandardMBean;
+
+public class TypeNameTest {
+    public static interface TestMXBean {
+        public int getInt();
+        public String IntName = "int";
+
+        public Map<String, Integer> getMapSI();
+        public String MapSIName = "java.util.Map<java.lang.String, java.lang.Integer>";
+
+        public Map<String, int[]> getMapSInts();
+        public String MapSIntsName = "java.util.Map<java.lang.String, int[]>";
+
+        public List<List<int[]>> getListListInts();
+        public String ListListIntsName = "java.util.List<java.util.List<int[]>>";
+    }
+
+    private static InvocationHandler nullIH = new InvocationHandler() {
+        public Object invoke(Object proxy, Method method, Object[] args)
+                throws Throwable {
+            return null;
+        }
+    };
+
+    static String failure;
+
+    public static void main(String[] args) throws Exception {
+        TestMXBean testImpl = (TestMXBean) Proxy.newProxyInstance(
+                TestMXBean.class.getClassLoader(), new Class<?>[] {TestMXBean.class}, nullIH);
+        Object mxbean = new StandardMBean(testImpl, TestMXBean.class, true);
+        MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+        ObjectName name = new ObjectName("a:b=c");
+        mbs.registerMBean(mxbean, name);
+        MBeanInfo mbi = mbs.getMBeanInfo(name);
+        MBeanAttributeInfo[] mbais = mbi.getAttributes();
+        for (MBeanAttributeInfo mbai : mbais) {
+            String attrName = mbai.getName();
+            String attrTypeName = (String) mbai.getDescriptor().getFieldValue("originalType");
+            String fieldName = attrName + "Name";
+            Field nameField = TestMXBean.class.getField(fieldName);
+            String expectedTypeName = (String) nameField.get(null);
+            if (expectedTypeName.equals(attrTypeName)) {
+                System.out.println("OK: " + attrName + ": " + attrTypeName);
+            } else {
+                failure = "For attribute " + attrName + " expected type name \"" +
+                        expectedTypeName + "\", found type name \"" + attrTypeName +
+                        "\"";
+                System.out.println("FAIL: " + failure);
+            }
+        }
+        if (failure == null)
+            System.out.println("TEST PASSED");
+        else
+            throw new Exception("TEST FAILED: " + failure);
+    }
+}