Merge
authorlana
Mon, 28 Nov 2011 15:15:50 -0800
changeset 11041 64fbc4786179
parent 11008 cc30ba2655b8 (current diff)
parent 11040 bba8493895c2 (diff)
child 11042 465818f87eea
Merge
jdk/test/java/io/FileDescriptor/FileChannelFDTest.java
jdk/test/java/io/etc/FileDescriptorSharing.java
--- a/jdk/make/docs/Makefile	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/make/docs/Makefile	Mon Nov 28 15:15:50 2011 -0800
@@ -71,7 +71,7 @@
 ifeq ($(ARCH_DATA_MODEL),64)
   MAX_VM_MEMORY = 1024
 else
-  MAX_VM_MEMORY = 512
+  MAX_VM_MEMORY = 612
 endif
 
 # List of all possible directories for javadoc to look for sources
--- a/jdk/src/share/classes/java/io/FileInputStream.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/java/io/FileInputStream.java	Mon Nov 28 15:15:50 2011 -0800
@@ -124,7 +124,7 @@
             throw new NullPointerException();
         }
         fd = new FileDescriptor();
-        fd.incrementAndGetUseCount();
+        fd.attach(this);
         open(name);
     }
 
@@ -164,10 +164,9 @@
 
         /*
          * FileDescriptor is being shared by streams.
-         * Ensure that it's GC'ed only when all the streams/channels are done
-         * using it.
+         * Register this stream with FileDescriptor tracker.
          */
-        fd.incrementAndGetUseCount();
+        fd.attach(this);
     }
 
     /**
@@ -294,27 +293,14 @@
             closed = true;
         }
         if (channel != null) {
-            /*
-             * Decrement the FD use count associated with the channel
-             * The use count is incremented whenever a new channel
-             * is obtained from this stream.
-             */
-           fd.decrementAndGetUseCount();
            channel.close();
         }
 
-        /*
-         * Decrement the FD use count associated with this stream
-         */
-        int useCount = fd.decrementAndGetUseCount();
-
-        /*
-         * If FileDescriptor is still in use by another stream, we
-         * will not close it.
-         */
-        if (useCount <= 0) {
-            close0();
-        }
+        fd.closeAll(new Closeable() {
+            public void close() throws IOException {
+               close0();
+           }
+        });
     }
 
     /**
@@ -328,7 +314,9 @@
      * @see        java.io.FileDescriptor
      */
     public final FileDescriptor getFD() throws IOException {
-        if (fd != null) return fd;
+        if (fd != null) {
+            return fd;
+        }
         throw new IOException();
     }
 
@@ -352,13 +340,6 @@
         synchronized (this) {
             if (channel == null) {
                 channel = FileChannelImpl.open(fd, true, false, this);
-
-                /*
-                 * Increment fd's use count. Invoking the channel's close()
-                 * method will result in decrementing the use count set for
-                 * the channel.
-                 */
-                fd.incrementAndGetUseCount();
             }
             return channel;
         }
@@ -381,7 +362,12 @@
      */
     protected void finalize() throws IOException {
         if ((fd != null) &&  (fd != FileDescriptor.in)) {
-                close();
+            /* if fd is shared, the references in FileDescriptor
+             * will ensure that finalizer is only called when
+             * safe to do so. All references using the fd have
+             * become unreachable. We can call close()
+             */
+            close();
         }
     }
 }
--- a/jdk/src/share/classes/java/io/FileOutputStream.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/java/io/FileOutputStream.java	Mon Nov 28 15:15:50 2011 -0800
@@ -197,9 +197,9 @@
             throw new NullPointerException();
         }
         this.fd = new FileDescriptor();
+        fd.attach(this);
         this.append = append;
 
-        fd.incrementAndGetUseCount();
         open(name, append);
     }
 
@@ -237,12 +237,7 @@
         this.fd = fdObj;
         this.append = false;
 
-        /*
-         * FileDescriptor is being shared by streams.
-         * Ensure that it's GC'ed only when all the streams/channels are done
-         * using it.
-         */
-        fd.incrementAndGetUseCount();
+        fd.attach(this);
     }
 
     /**
@@ -331,27 +326,14 @@
         }
 
         if (channel != null) {
-            /*
-             * Decrement FD use count associated with the channel
-             * The use count is incremented whenever a new channel
-             * is obtained from this stream.
-             */
-            fd.decrementAndGetUseCount();
             channel.close();
         }
 
-        /*
-         * Decrement FD use count associated with this stream
-         */
-        int useCount = fd.decrementAndGetUseCount();
-
-        /*
-         * If FileDescriptor is still in use by another stream, we
-         * will not close it.
-         */
-        if (useCount <= 0) {
-            close0();
-        }
+        fd.closeAll(new Closeable() {
+            public void close() throws IOException {
+               close0();
+           }
+        });
     }
 
     /**
@@ -365,7 +347,9 @@
      * @see        java.io.FileDescriptor
      */
      public final FileDescriptor getFD()  throws IOException {
-        if (fd != null) return fd;
+        if (fd != null) {
+            return fd;
+        }
         throw new IOException();
      }
 
@@ -390,13 +374,6 @@
         synchronized (this) {
             if (channel == null) {
                 channel = FileChannelImpl.open(fd, false, true, append, this);
-
-                /*
-                 * Increment fd's use count. Invoking the channel's close()
-                 * method will result in decrementing the use count set for
-                 * the channel.
-                 */
-                fd.incrementAndGetUseCount();
             }
             return channel;
         }
@@ -415,7 +392,12 @@
             if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
                 flush();
             } else {
-                    close();
+                /* if fd is shared, the references in FileDescriptor
+                 * will ensure that finalizer is only called when
+                 * safe to do so. All references using the fd have
+                 * become unreachable. We can call close()
+                 */
+                close();
             }
         }
     }
--- a/jdk/src/share/classes/java/io/RandomAccessFile.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/java/io/RandomAccessFile.java	Mon Nov 28 15:15:50 2011 -0800
@@ -229,7 +229,7 @@
             throw new NullPointerException();
         }
         fd = new FileDescriptor();
-        fd.incrementAndGetUseCount();
+        fd.attach(this);
         open(name, imode);
     }
 
@@ -242,7 +242,9 @@
      * @see        java.io.FileDescriptor
      */
     public final FileDescriptor getFD() throws IOException {
-        if (fd != null) return fd;
+        if (fd != null) {
+            return fd;
+        }
         throw new IOException();
     }
 
@@ -268,17 +270,6 @@
         synchronized (this) {
             if (channel == null) {
                 channel = FileChannelImpl.open(fd, true, rw, this);
-
-                /*
-                 * FileDescriptor could be shared by FileInputStream or
-                 * FileOutputStream.
-                 * Ensure that FD is GC'ed only when all the streams/channels
-                 * are done using it.
-                 * Increment fd's use count. Invoking the channel's close()
-                 * method will result in decrementing the use count set for
-                 * the channel.
-                 */
-                fd.incrementAndGetUseCount();
             }
             return channel;
         }
@@ -577,28 +568,14 @@
             closed = true;
         }
         if (channel != null) {
-            /*
-             * Decrement FD use count associated with the channel. The FD use
-             * count is incremented whenever a new channel is obtained from
-             * this stream.
-             */
-            fd.decrementAndGetUseCount();
             channel.close();
         }
 
-        /*
-         * Decrement FD use count associated with this stream.
-         * The count got incremented by FileDescriptor during its construction.
-         */
-        int useCount = fd.decrementAndGetUseCount();
-
-        /*
-         * If FileDescriptor is still in use by another stream, we
-         * will not close it.
-         */
-        if (useCount <= 0) {
-            close0();
-        }
+        fd.closeAll(new Closeable() {
+            public void close() throws IOException {
+               close0();
+           }
+        });
     }
 
     //
--- a/jdk/src/share/classes/java/io/Writer.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/java/io/Writer.java	Mon Nov 28 15:15:50 2011 -0800
@@ -57,7 +57,7 @@
     /**
      * Size of writeBuffer, must be >= 1
      */
-    private final int writeBufferSize = 1024;
+    private static final int WRITE_BUFFER_SIZE = 1024;
 
     /**
      * The object used to synchronize operations on this stream.  For
@@ -107,7 +107,7 @@
     public void write(int c) throws IOException {
         synchronized (lock) {
             if (writeBuffer == null){
-                writeBuffer = new char[writeBufferSize];
+                writeBuffer = new char[WRITE_BUFFER_SIZE];
             }
             writeBuffer[0] = (char) c;
             write(writeBuffer, 0, 1);
@@ -180,9 +180,9 @@
     public void write(String str, int off, int len) throws IOException {
         synchronized (lock) {
             char cbuf[];
-            if (len <= writeBufferSize) {
+            if (len <= WRITE_BUFFER_SIZE) {
                 if (writeBuffer == null) {
-                    writeBuffer = new char[writeBufferSize];
+                    writeBuffer = new char[WRITE_BUFFER_SIZE];
                 }
                 cbuf = writeBuffer;
             } else {    // Don't permanently allocate very large buffers.
--- a/jdk/src/share/classes/java/lang/AssertionError.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/java/lang/AssertionError.java	Mon Nov 28 15:15:50 2011 -0800
@@ -71,7 +71,7 @@
      * @see   Throwable#getCause()
      */
     public AssertionError(Object detailMessage) {
-        this("" +  detailMessage);
+        this(String.valueOf(detailMessage));
         if (detailMessage instanceof Throwable)
             initCause((Throwable) detailMessage);
     }
@@ -85,7 +85,7 @@
      * @param detailMessage value to be used in constructing detail message
      */
     public AssertionError(boolean detailMessage) {
-        this("" +  detailMessage);
+        this(String.valueOf(detailMessage));
     }
 
     /**
@@ -97,7 +97,7 @@
      * @param detailMessage value to be used in constructing detail message
      */
     public AssertionError(char detailMessage) {
-        this("" +  detailMessage);
+        this(String.valueOf(detailMessage));
     }
 
     /**
@@ -109,7 +109,7 @@
      * @param detailMessage value to be used in constructing detail message
      */
     public AssertionError(int detailMessage) {
-        this("" +  detailMessage);
+        this(String.valueOf(detailMessage));
     }
 
     /**
@@ -121,7 +121,7 @@
      * @param detailMessage value to be used in constructing detail message
      */
     public AssertionError(long detailMessage) {
-        this("" +  detailMessage);
+        this(String.valueOf(detailMessage));
     }
 
     /**
@@ -133,7 +133,7 @@
      * @param detailMessage value to be used in constructing detail message
      */
     public AssertionError(float detailMessage) {
-        this("" +  detailMessage);
+        this(String.valueOf(detailMessage));
     }
 
     /**
@@ -145,7 +145,7 @@
      * @param detailMessage value to be used in constructing detail message
      */
     public AssertionError(double detailMessage) {
-        this("" +  detailMessage);
+        this(String.valueOf(detailMessage));
     }
 
     /**
--- a/jdk/src/share/classes/java/lang/Class.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/java/lang/Class.java	Mon Nov 28 15:15:50 2011 -0800
@@ -3008,7 +3008,7 @@
 
     /**
      * Casts this {@code Class} object to represent a subclass of the class
-     * represented by the specified class object.  Checks that that the cast
+     * represented by the specified class object.  Checks that the cast
      * is valid, and throws a {@code ClassCastException} if it is not.  If
      * this method succeeds, it always returns a reference to this class object.
      *
--- a/jdk/src/share/classes/java/lang/Double.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/java/lang/Double.java	Mon Nov 28 15:15:50 2011 -0800
@@ -607,8 +607,7 @@
      * @see       java.lang.Double#valueOf(java.lang.String)
      */
     public Double(String s) throws NumberFormatException {
-        // REMIND: this is inefficient
-        this(valueOf(s).doubleValue());
+        value = parseDouble(s);
     }
 
     /**
--- a/jdk/src/share/classes/java/lang/Float.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/java/lang/Float.java	Mon Nov 28 15:15:50 2011 -0800
@@ -529,8 +529,7 @@
      * @see        java.lang.Float#valueOf(java.lang.String)
      */
     public Float(String s) throws NumberFormatException {
-        // REMIND: this is inefficient
-        this(valueOf(s).floatValue());
+        value = parseFloat(s);
     }
 
     /**
--- a/jdk/src/share/classes/java/security/Policy.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/java/security/Policy.java	Mon Nov 28 15:15:50 2011 -0800
@@ -28,6 +28,7 @@
 
 import java.util.Enumeration;
 import java.util.WeakHashMap;
+import java.util.concurrent.atomic.AtomicReference;
 import sun.security.jca.GetInstance;
 import sun.security.util.Debug;
 import sun.security.util.SecurityConstants;
@@ -60,8 +61,8 @@
  * with a standard type.  The default policy type is "JavaPolicy".
  *
  * <p> Once a Policy instance has been installed (either by default, or by
- * calling <code>setPolicy</code>),
- * the Java runtime invokes its <code>implies</code> when it needs to
+ * calling <code>setPolicy</code>), the Java runtime invokes its
+ * <code>implies</code> method when it needs to
  * determine whether executing code (encapsulated in a ProtectionDomain)
  * can perform SecurityManager-protected operations.  How a Policy object
  * retrieves its policy data is up to the Policy implementation itself.
@@ -94,18 +95,33 @@
     public static final PermissionCollection UNSUPPORTED_EMPTY_COLLECTION =
                         new UnsupportedEmptyCollection();
 
-    /** the system-wide policy. */
-    private static Policy policy; // package private for AccessControlContext
+    // Information about the system-wide policy.
+    private static class PolicyInfo {
+        // the system-wide policy
+        final Policy policy;
+        // a flag indicating if the system-wide policy has been initialized
+        final boolean initialized;
+
+        PolicyInfo(Policy policy, boolean initialized) {
+            this.policy = policy;
+            this.initialized = initialized;
+        }
+    }
+
+    // PolicyInfo is stored in an AtomicReference
+    private static AtomicReference<PolicyInfo> policy =
+        new AtomicReference<>(new PolicyInfo(null, false));
 
     private static final Debug debug = Debug.getInstance("policy");
 
     // Cache mapping ProtectionDomain.Key to PermissionCollection
     private WeakHashMap<ProtectionDomain.Key, PermissionCollection> pdMapping;
 
-    /** package private for AccessControlContext */
+    /** package private for AccessControlContext and ProtectionDomain */
     static boolean isSet()
     {
-        return policy != null;
+        PolicyInfo pi = policy.get();
+        return pi.policy != null && pi.initialized == true;
     }
 
     private static void checkPermission(String type) {
@@ -143,80 +159,92 @@
 
     /**
      * Returns the installed Policy object, skipping the security check.
-     * Used by SecureClassLoader and getPolicy.
+     * Used by ProtectionDomain and getPolicy.
      *
      * @return the installed Policy.
-     *
      */
-    static synchronized Policy getPolicyNoCheck()
+    static Policy getPolicyNoCheck()
     {
-        if (policy == null) {
-            String policy_class = null;
-            policy_class = AccessController.doPrivileged(
-                new PrivilegedAction<String>() {
-                    public String run() {
-                        return Security.getProperty("policy.provider");
-                    }
-                });
-            if (policy_class == null) {
-                policy_class = "sun.security.provider.PolicyFile";
-            }
-
-            try {
-                policy = (Policy)
-                    Class.forName(policy_class).newInstance();
-            } catch (Exception e) {
-                /*
-                 * The policy_class seems to be an extension
-                 * so we have to bootstrap loading it via a policy
-                 * provider that is on the bootclasspath
-                 * If it loads then shift gears to using the configured
-                 * provider.
-                 */
-
-                // install the bootstrap provider to avoid recursion
-                policy = new sun.security.provider.PolicyFile();
-
-                final String pc = policy_class;
-                Policy p = AccessController.doPrivileged(
-                    new PrivilegedAction<Policy>() {
-                        public Policy run() {
-                            try {
-                                ClassLoader cl =
-                                        ClassLoader.getSystemClassLoader();
-                                // we want the extension loader
-                                ClassLoader extcl = null;
-                                while (cl != null) {
-                                    extcl = cl;
-                                    cl = cl.getParent();
-                                }
-                                return (extcl != null ? (Policy)Class.forName(
-                                        pc, true, extcl).newInstance() : null);
-                            } catch (Exception e) {
-                                if (debug != null) {
-                                    debug.println("policy provider " +
-                                                pc +
-                                                " not available");
-                                    e.printStackTrace();
-                                }
-                                return null;
-                            }
+        PolicyInfo pi = policy.get();
+        // Use double-check idiom to avoid locking if system-wide policy is
+        // already initialized
+        if (pi.initialized == false || pi.policy == null) {
+            synchronized (Policy.class) {
+                PolicyInfo pinfo = policy.get();
+                if (pinfo.policy == null) {
+                    String policy_class = AccessController.doPrivileged(
+                        new PrivilegedAction<String>() {
+                        public String run() {
+                            return Security.getProperty("policy.provider");
                         }
                     });
-                /*
-                 * if it loaded install it as the policy provider. Otherwise
-                 * continue to use the system default implementation
-                 */
-                if (p != null) {
-                    policy = p;
-                } else {
-                    if (debug != null) {
-                        debug.println("using sun.security.provider.PolicyFile");
+                    if (policy_class == null) {
+                        policy_class = "sun.security.provider.PolicyFile";
                     }
+
+                    try {
+                        pinfo = new PolicyInfo(
+                            (Policy) Class.forName(policy_class).newInstance(),
+                            true);
+                    } catch (Exception e) {
+                        /*
+                         * The policy_class seems to be an extension
+                         * so we have to bootstrap loading it via a policy
+                         * provider that is on the bootclasspath.
+                         * If it loads then shift gears to using the configured
+                         * provider.
+                         */
+
+                        // install the bootstrap provider to avoid recursion
+                        Policy polFile = new sun.security.provider.PolicyFile();
+                        pinfo = new PolicyInfo(polFile, false);
+                        policy.set(pinfo);
+
+                        final String pc = policy_class;
+                        Policy pol = AccessController.doPrivileged(
+                            new PrivilegedAction<Policy>() {
+                            public Policy run() {
+                                try {
+                                    ClassLoader cl =
+                                            ClassLoader.getSystemClassLoader();
+                                    // we want the extension loader
+                                    ClassLoader extcl = null;
+                                    while (cl != null) {
+                                        extcl = cl;
+                                        cl = cl.getParent();
+                                    }
+                                    return (extcl != null ? (Policy)Class.forName(
+                                            pc, true, extcl).newInstance() : null);
+                                } catch (Exception e) {
+                                    if (debug != null) {
+                                        debug.println("policy provider " +
+                                                    pc +
+                                                    " not available");
+                                        e.printStackTrace();
+                                    }
+                                    return null;
+                                }
+                            }
+                        });
+                        /*
+                         * if it loaded install it as the policy provider. Otherwise
+                         * continue to use the system default implementation
+                         */
+                        if (pol != null) {
+                            pinfo = new PolicyInfo(pol, true);
+                        } else {
+                            if (debug != null) {
+                                debug.println("using sun.security.provider.PolicyFile");
+                            }
+                            pinfo = new PolicyInfo(polFile, true);
+                        }
+                    }
+                    policy.set(pinfo);
                 }
+                return pinfo.policy;
             }
         }
-        return policy;
+        return pi.policy;
     }
 
     /**
@@ -245,7 +273,7 @@
             initPolicy(p);
         }
         synchronized (Policy.class) {
-            Policy.policy = p;
+            policy.set(new PolicyInfo(p, p != null));
         }
     }
 
@@ -292,14 +320,14 @@
         PermissionCollection policyPerms = null;
         synchronized (p) {
             if (p.pdMapping == null) {
-                p.pdMapping =
-                    new WeakHashMap<ProtectionDomain.Key, PermissionCollection>();
+                p.pdMapping = new WeakHashMap<>();
            }
         }
 
         if (policyDomain.getCodeSource() != null) {
-            if (Policy.isSet()) {
-                policyPerms = policy.getPermissions(policyDomain);
+            Policy pol = policy.get().policy;
+            if (pol != null) {
+                policyPerms = pol.getPermissions(policyDomain);
             }
 
             if (policyPerms == null) { // assume it has all
@@ -434,7 +462,7 @@
                                                         type,
                                                         params);
         } catch (NoSuchAlgorithmException nsae) {
-            return handleException (nsae);
+            return handleException(nsae);
         }
     }
 
@@ -494,7 +522,7 @@
                                                         type,
                                                         params);
         } catch (NoSuchAlgorithmException nsae) {
-            return handleException (nsae);
+            return handleException(nsae);
         }
     }
 
@@ -808,7 +836,7 @@
          *
          * @param permission the Permission object to compare.
          *
-         * @return true if "permission" is implied by the  permissions in
+         * @return true if "permission" is implied by the permissions in
          * the collection, false if not.
          */
         @Override public boolean implies(Permission permission) {
--- a/jdk/src/share/classes/java/sql/PreparedStatement.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/java/sql/PreparedStatement.java	Mon Nov 28 15:15:50 2011 -0800
@@ -767,7 +767,7 @@
 
 
     /**
-     * Sets the designated paramter to the given <code>String</code> object.
+     * Sets the designated parameter to the given <code>String</code> object.
      * The driver converts this to a SQL <code>NCHAR</code> or
      * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code> value
      * (depending on the argument's
--- a/jdk/src/share/classes/java/sql/Statement.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/java/sql/Statement.java	Mon Nov 28 15:15:50 2011 -0800
@@ -991,7 +991,7 @@
         /**
          * Requests that a <code>Statement</code> be pooled or not pooled.  The value
          * specified is a hint to the statement pool implementation indicating
-         * whether the applicaiton wants the statement to be pooled.  It is up to
+         * whether the application wants the statement to be pooled.  It is up to
          * the statement pool manager as to whether the hint is used.
          * <p>
          * The poolable value of a statement is applicable to both internal
--- a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java	Mon Nov 28 15:15:50 2011 -0800
@@ -742,6 +742,8 @@
             throw new NullPointerException();
         if (c == this)
             throw new IllegalArgumentException();
+        if (maxElements <= 0)
+            return 0;
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
--- a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java	Mon Nov 28 15:15:50 2011 -0800
@@ -332,7 +332,7 @@
         // Note: convention in all put/take/etc is to preset local var
         // holding count negative to indicate failure unless set.
         int c = -1;
-        Node<E> node = new Node(e);
+        Node<E> node = new Node<E>(e);
         final ReentrantLock putLock = this.putLock;
         final AtomicInteger count = this.count;
         putLock.lockInterruptibly();
@@ -412,7 +412,7 @@
         if (count.get() == capacity)
             return false;
         int c = -1;
-        Node<E> node = new Node(e);
+        Node<E> node = new Node<E>(e);
         final ReentrantLock putLock = this.putLock;
         putLock.lock();
         try {
@@ -728,6 +728,8 @@
             throw new NullPointerException();
         if (c == this)
             throw new IllegalArgumentException();
+        if (maxElements <= 0)
+            return 0;
         boolean signalNotFull = false;
         final ReentrantLock takeLock = this.takeLock;
         takeLock.lock();
--- a/jdk/src/share/classes/java/util/jar/Attributes.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/java/util/jar/Attributes.java	Mon Nov 28 15:15:50 2011 -0800
@@ -629,7 +629,7 @@
         public static final Name IMPLEMENTATION_VENDOR_ID = new Name("Implementation-Vendor-Id");
 
        /**
-         * <code>Name</code> object for <code>Implementation-Vendor-URL</code>
+         * <code>Name</code> object for <code>Implementation-URL</code>
          * manifest attribute used for package versioning.
          * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779">
          *      Java Product Versioning Specification</a>
--- a/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java	Mon Nov 28 15:15:50 2011 -0800
@@ -402,10 +402,10 @@
                 } catch (IOException e) {
                     logger.log (Level.FINER, "Dispatcher (4)", e);
                 } catch (Exception e) {
-                    e.printStackTrace();
                     logger.log (Level.FINER, "Dispatcher (7)", e);
                 }
             }
+            try {selector.close(); } catch (Exception e) {}
         }
 
         private void handleException (SelectionKey key, Exception e) {
--- a/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java	Mon Nov 28 15:15:50 2011 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2011, 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
@@ -29,6 +29,7 @@
 import java.util.Hashtable;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
+import java.io.FilePermission;
 import java.io.IOException;
 import java.net.*;
 import java.rmi.*;
@@ -54,7 +55,6 @@
 import sun.rmi.transport.LiveRef;
 import sun.rmi.transport.ObjectTable;
 import sun.rmi.transport.Target;
-import sun.security.action.GetPropertyAction;
 
 /**
  * A "registry" exists on every node that allows RMI connections to
@@ -335,19 +335,6 @@
             URL[] urls = sun.misc.URLClassPath.pathToURLs(envcp);
             ClassLoader cl = new URLClassLoader(urls);
 
-            String codebaseProperty = null;
-            String prop = java.security.AccessController.doPrivileged(
-                new GetPropertyAction("java.rmi.server.codebase"));
-            if (prop != null && prop.trim().length() > 0) {
-                codebaseProperty = prop;
-            }
-            URL[] codebaseURLs = null;
-            if (codebaseProperty != null) {
-                codebaseURLs = sun.misc.URLClassPath.pathToURLs(codebaseProperty);
-            } else {
-                codebaseURLs = new URL[0];
-            }
-
             /*
              * Fix bugid 4242317: Classes defined by this class loader should
              * be annotated with the value of the "java.rmi.server.codebase"
@@ -365,7 +352,7 @@
                         public RegistryImpl run() throws RemoteException {
                             return new RegistryImpl(regPort);
                         }
-                    }, getAccessControlContext(codebaseURLs));
+                    }, getAccessControlContext());
             } catch (PrivilegedActionException ex) {
                 throw (RemoteException) ex.getException();
             }
@@ -391,11 +378,11 @@
     }
 
     /**
-     * Generates an AccessControlContext from several URLs.
+     * Generates an AccessControlContext with minimal permissions.
      * The approach used here is taken from the similar method
      * getAccessControlContext() in the sun.applet.AppletPanel class.
      */
-    private static AccessControlContext getAccessControlContext(URL[] urls) {
+    private static AccessControlContext getAccessControlContext() {
         // begin with permissions granted to all code in current policy
         PermissionCollection perms = AccessController.doPrivileged(
             new java.security.PrivilegedAction<PermissionCollection>() {
@@ -420,17 +407,15 @@
 
         perms.add(new RuntimePermission("accessClassInPackage.sun.*"));
 
-        // add permissions required to load from codebase URL path
-        LoaderHandler.addPermissionsForURLs(urls, perms, false);
+        perms.add(new FilePermission("<<ALL FILES>>", "read"));
 
         /*
          * Create an AccessControlContext that consists of a single
          * protection domain with only the permissions calculated above.
          */
         ProtectionDomain pd = new ProtectionDomain(
-            new CodeSource((urls.length > 0 ? urls[0] : null),
-                (java.security.cert.Certificate[]) null),
-            perms);
+            new CodeSource(null,
+                (java.security.cert.Certificate[]) null), perms);
         return new AccessControlContext(new ProtectionDomain[] { pd });
     }
 }
--- a/jdk/src/share/classes/sun/rmi/server/LoaderHandler.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/sun/rmi/server/LoaderHandler.java	Mon Nov 28 15:15:50 2011 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2011, 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
@@ -1031,7 +1031,7 @@
      * loader.  A given permission is only added to the collection if
      * it is not already implied by the collection.
      */
-    public static void addPermissionsForURLs(URL[] urls,
+    private static void addPermissionsForURLs(URL[] urls,
                                              PermissionCollection perms,
                                              boolean forLoader)
     {
--- a/jdk/src/share/classes/sun/security/krb5/internal/KerberosTime.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/KerberosTime.java	Mon Nov 28 15:15:50 2011 -0800
@@ -68,8 +68,8 @@
     private int  microSeconds; // the last three digits of the microsecond value
 
     // The time when this class is loaded. Used in setNow()
-    private static final long initMilli = System.currentTimeMillis();
-    private static final long initMicro = System.nanoTime() / 1000;
+    private static long initMilli = System.currentTimeMillis();
+    private static long initMicro = System.nanoTime() / 1000;
 
     private static long syncTime;
     private static boolean DEBUG = Krb5.DEBUG;
@@ -212,9 +212,22 @@
     }
 
     public void setNow() {
-        long microElapsed = System.nanoTime() / 1000 - initMicro;
-        setTime(initMilli + microElapsed/1000);
-        microSeconds = (int)(microElapsed % 1000);
+        long newMilli = System.currentTimeMillis();
+        long newMicro = System.nanoTime() / 1000;
+        long microElapsed = newMicro - initMicro;
+        long calcMilli = initMilli + microElapsed/1000;
+        if (calcMilli - newMilli > 100 || newMilli - calcMilli > 100) {
+            if (DEBUG) {
+                System.out.println("System time adjusted");
+            }
+            initMilli = newMilli;
+            initMicro = newMicro;
+            setTime(newMilli);
+            microSeconds = 0;
+        } else {
+            setTime(calcMilli);
+            microSeconds = (int)(microElapsed % 1000);
+        }
     }
 
     public int getMicroSeconds() {
--- a/jdk/src/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java	Mon Nov 28 15:15:50 2011 -0800
@@ -375,7 +375,7 @@
         }
         AuthorizationDataEntry[] auDataEntry = readAuth();
         AuthorizationData auData = null;
-        if (auData != null) {
+        if (auDataEntry != null) {
             auData = new AuthorizationData(auDataEntry);
         }
         byte[] ticketData = readData();
--- a/jdk/src/share/classes/sun/security/krb5/internal/ccache/Credentials.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ccache/Credentials.java	Mon Nov 28 15:15:50 2011 -0800
@@ -209,10 +209,24 @@
     }
 
     public sun.security.krb5.Credentials setKrbCreds() {
+        // Note: We will not pass authorizationData to s.s.k.Credentials. The
+        // field in that class will be passed to Krb5Context as the return
+        // value of ExtendedGSSContext.inquireSecContext(KRB5_GET_AUTHZ_DATA),
+        // which is documented as the authData in the service ticket. That
+        // is on the acceptor side.
+        //
+        // This class is for the initiator side. Also, authdata inside a ccache
+        // is most likely to be the one in Authenticator in PA-TGS-REQ encoded
+        // in TGS-REQ, therefore only stored with a service ticket. Currently
+        // in Java, we only reads TGTs.
         return new sun.security.krb5.Credentials(ticket,
                 cname, sname, key, flags, authtime, starttime, endtime, renewTill, caddr);
     }
 
+    public KerberosTime getStartTime() {
+        return starttime;
+    }
+
     public KerberosTime getAuthTime() {
         return authtime;
     }
@@ -221,6 +235,10 @@
         return endtime;
     }
 
+    public KerberosTime getRenewTill() {
+        return renewTill;
+    }
+
     public TicketFlags getTicketFlags() {
         return flags;
     }
@@ -228,4 +246,8 @@
     public int getEType() {
         return key.getEType();
     }
+
+    public int getTktEType() {
+        return ticket.encPart.getEType();
+    }
 }
--- a/jdk/src/share/classes/sun/security/ssl/SSLContextImpl.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/SSLContextImpl.java	Mon Nov 28 15:15:50 2011 -0800
@@ -771,10 +771,15 @@
 final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
             implements X509TrustManager {
 
+    // the delegated trust manager
     private final X509TrustManager tm;
 
+    // Cache the trusted certificate to optimize the performance.
+    private final Collection<X509Certificate> trustedCerts = new HashSet<>();
+
     AbstractTrustManagerWrapper(X509TrustManager tm) {
         this.tm = tm;
+        Collections.addAll(trustedCerts, tm.getAcceptedIssuers());
     }
 
     @Override
@@ -863,20 +868,7 @@
                 constraints = new SSLAlgorithmConstraints(sslSocket, true);
             }
 
-            AlgorithmChecker checker = new AlgorithmChecker(constraints);
-            try {
-                checker.init(false);
-
-                // a forward checker, need to check from trust to target
-                for (int i = chain.length - 1; i >= 0; i--) {
-                    Certificate cert = chain[i];
-                    // We don't care about the unresolved critical extensions.
-                    checker.check(cert, Collections.<String>emptySet());
-                }
-            } catch (CertPathValidatorException cpve) {
-                throw new CertificateException(
-                    "Certificates does not conform to algorithm constraints");
-            }
+            checkAlgorithmConstraints(chain, constraints);
         }
     }
 
@@ -918,20 +910,33 @@
                 constraints = new SSLAlgorithmConstraints(engine, true);
             }
 
-            AlgorithmChecker checker = new AlgorithmChecker(constraints);
-            try {
+            checkAlgorithmConstraints(chain, constraints);
+        }
+    }
+
+    private void checkAlgorithmConstraints(X509Certificate[] chain,
+            AlgorithmConstraints constraints) throws CertificateException {
+
+        try {
+            // Does the certificate chain end with a trusted certificate?
+            int checkedLength = chain.length - 1;
+            if (trustedCerts.contains(chain[checkedLength])) {
+                    checkedLength--;
+            }
+
+            // A forward checker, need to check from trust to target
+            if (checkedLength >= 0) {
+                AlgorithmChecker checker = new AlgorithmChecker(constraints);
                 checker.init(false);
-
-                // A forward checker, need to check from trust to target
-                for (int i = chain.length - 1; i >= 0; i--) {
+                for (int i = checkedLength; i >= 0; i--) {
                     Certificate cert = chain[i];
                     // We don't care about the unresolved critical extensions.
                     checker.check(cert, Collections.<String>emptySet());
                 }
-            } catch (CertPathValidatorException cpve) {
-                throw new CertificateException(
-                    "Certificates does not conform to algorithm constraints");
             }
+        } catch (CertPathValidatorException cpve) {
+            throw new CertificateException(
+                "Certificates does not conform to algorithm constraints");
         }
     }
 }
--- a/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java	Mon Nov 28 15:15:50 2011 -0800
@@ -1485,7 +1485,8 @@
 
     private void closeSocket(boolean selfInitiated) throws IOException {
         if ((debug != null) && Debug.isOn("ssl")) {
-            System.out.println(threadName() + ", called closeSocket(selfInitiated)");
+            System.out.println(threadName() +
+                ", called closeSocket(" + selfInitiated + ")");
         }
         if (self == this) {
             super.close();
--- a/jdk/src/share/classes/sun/security/tools/CertAndKeyGen.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/sun/security/tools/CertAndKeyGen.java	Mon Nov 28 15:15:50 2011 -0800
@@ -33,18 +33,7 @@
 import java.util.Date;
 
 import sun.security.pkcs10.PKCS10;
-import sun.security.x509.AlgorithmId;
-import sun.security.x509.CertificateAlgorithmId;
-import sun.security.x509.CertificateIssuerName;
-import sun.security.x509.CertificateSerialNumber;
-import sun.security.x509.CertificateSubjectName;
-import sun.security.x509.CertificateValidity;
-import sun.security.x509.CertificateVersion;
-import sun.security.x509.CertificateX509Key;
-import sun.security.x509.X500Name;
-import sun.security.x509.X509CertImpl;
-import sun.security.x509.X509CertInfo;
-import sun.security.x509.X509Key;
+import sun.security.x509.*;
 
 
 /**
@@ -165,6 +154,13 @@
 
         publicKey = pair.getPublic();
         privateKey = pair.getPrivate();
+
+        // publicKey's format must be X.509 otherwise
+        // the whole CertGen part of this class is broken.
+        if (!"X.509".equalsIgnoreCase(publicKey.getFormat())) {
+            throw new IllegalArgumentException("publicKey's is not X.509, but "
+                    + publicKey.getFormat());
+        }
     }
 
 
@@ -186,6 +182,16 @@
         return (X509Key)publicKey;
     }
 
+    /**
+     * Always returns the public key of the generated key pair. Used
+     * by KeyTool only.
+     *
+     * The publicKey is not necessarily to be an instance of
+     * X509Key in some JCA/JCE providers, for example SunPKCS11.
+     */
+    public PublicKey getPublicKeyAnyway() {
+        return publicKey;
+    }
 
     /**
      * Returns the private key of the generated key pair.
@@ -200,7 +206,6 @@
         return privateKey;
     }
 
-
     /**
      * Returns a self-signed X.509v3 certificate for the public key.
      * The certificate is immediately valid. No extensions.
@@ -225,6 +230,15 @@
     throws CertificateException, InvalidKeyException, SignatureException,
         NoSuchAlgorithmException, NoSuchProviderException
     {
+        return getSelfCertificate(myname, firstDate, validity, null);
+    }
+
+    // Like above, plus a CertificateExtensions argument, which can be null.
+    public X509Certificate getSelfCertificate (X500Name myname, Date firstDate,
+            long validity, CertificateExtensions ext)
+    throws CertificateException, InvalidKeyException, SignatureException,
+        NoSuchAlgorithmException, NoSuchProviderException
+    {
         X509CertImpl    cert;
         Date            lastDate;
 
@@ -248,6 +262,7 @@
             info.set(X509CertInfo.KEY, new CertificateX509Key(publicKey));
             info.set(X509CertInfo.VALIDITY, interval);
             info.set(X509CertInfo.ISSUER, new CertificateIssuerName(myname));
+            if (ext != null) info.set(X509CertInfo.EXTENSIONS, ext);
 
             cert = new X509CertImpl(info);
             cert.sign(privateKey, this.sigAlg);
--- a/jdk/src/share/classes/sun/security/tools/KeyTool.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/classes/sun/security/tools/KeyTool.java	Mon Nov 28 15:15:50 2011 -0800
@@ -1518,9 +1518,16 @@
         keypair.generate(keysize);
         PrivateKey privKey = keypair.getPrivateKey();
 
+        CertificateExtensions ext = createV3Extensions(
+                null,
+                null,
+                v3ext,
+                keypair.getPublicKeyAnyway(),
+                null);
+
         X509Certificate[] chain = new X509Certificate[1];
         chain[0] = keypair.getSelfCertificate(
-                x500Name, getStartDate(startDate), validity*24L*60L*60L);
+                x500Name, getStartDate(startDate), validity*24L*60L*60L, ext);
 
         if (verbose) {
             MessageFormat form = new MessageFormat(rb.getString
@@ -1537,9 +1544,6 @@
             keyPass = promptForKeyPass(alias, null, storePass);
         }
         keyStore.setKeyEntry(alias, privKey, keyPass, chain);
-
-        // resign so that -ext are applied.
-        doSelfCert(alias, null, sigAlgName);
     }
 
     /**
--- a/jdk/src/share/native/sun/awt/medialib/mlib_types.h	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/share/native/sun/awt/medialib/mlib_types.h	Mon Nov 28 15:15:50 2011 -0800
@@ -59,13 +59,8 @@
 
 #if defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined(__GNUC__)
 
-#if defined(__linux__)
-#include <stdint.h>                     /* for uintptr_t */
-#include <malloc.h>                     /* for ptrdiff_t */
-#else
-#include <link.h>                       /* for uintptr_t */
-#include <stddef.h>                     /* for ptrdiff_t */
-#endif  /* __linux__ */
+#include <stdint.h>
+#include <stddef.h>
 
 #ifdef MLIB_OS64BIT
 
--- a/jdk/src/solaris/classes/java/io/FileDescriptor.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/solaris/classes/java/io/FileDescriptor.java	Mon Nov 28 15:15:50 2011 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2011, 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
@@ -25,7 +25,8 @@
 
 package java.io;
 
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Instances of the file descriptor class serve as an opaque handle
@@ -46,12 +47,9 @@
 
     private int fd;
 
-    /**
-     * A counter for tracking the FIS/FOS/RAF instances that
-     * use this FileDescriptor. The FIS/FOS.finalize() will not release
-     * the FileDescriptor if it is still under user by a stream.
-     */
-    private AtomicInteger useCount;
+    private Closeable parent;
+    private List<Closeable> otherParents;
+    private boolean closed;
 
     /**
      * Constructs an (invalid) FileDescriptor
@@ -59,12 +57,10 @@
      */
     public /**/ FileDescriptor() {
         fd = -1;
-        useCount = new AtomicInteger();
     }
 
     private /* */ FileDescriptor(int fd) {
         this.fd = fd;
-        useCount = new AtomicInteger();
     }
 
     /**
@@ -164,13 +160,67 @@
         );
     }
 
-    // package private methods used by FIS, FOS and RAF
+    /*
+     * Package private methods to track referents.
+     * If multiple streams point to the same FileDescriptor, we cycle
+     * through the list of all referents and call close()
+     */
 
-    int incrementAndGetUseCount() {
-        return useCount.incrementAndGet();
+    /**
+     * Attach a Closeable to this FD for tracking.
+     * parent reference is added to otherParents when
+     * needed to make closeAll simpler.
+     */
+    synchronized void attach(Closeable c) {
+        if (parent == null) {
+            // first caller gets to do this
+            parent = c;
+        } else if (otherParents == null) {
+            otherParents = new ArrayList<>();
+            otherParents.add(parent);
+            otherParents.add(c);
+        } else {
+            otherParents.add(c);
+        }
     }
 
-    int decrementAndGetUseCount() {
-        return useCount.decrementAndGet();
+    /**
+     * Cycle through all Closeables sharing this FD and call
+     * close() on each one.
+     *
+     * The caller closeable gets to call close0().
+     */
+    @SuppressWarnings("try")
+    synchronized void closeAll(Closeable releaser) throws IOException {
+        if (!closed) {
+            closed = true;
+            IOException ioe = null;
+            try (Closeable c = releaser) {
+                if (otherParents != null) {
+                    for (Closeable referent : otherParents) {
+                        try {
+                            referent.close();
+                        } catch(IOException x) {
+                            if (ioe == null) {
+                                ioe = x;
+                            } else {
+                                ioe.addSuppressed(x);
+                            }
+                        }
+                    }
+                }
+            } catch(IOException ex) {
+                /*
+                 * If releaser close() throws IOException
+                 * add other exceptions as suppressed.
+                 */
+                if (ioe != null)
+                    ex.addSuppressed(ioe);
+                ioe = ex;
+            } finally {
+                if (ioe != null)
+                    throw ioe;
+            }
+        }
     }
 }
--- a/jdk/src/solaris/native/java/net/Inet4AddressImpl.c	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/solaris/native/java/net/Inet4AddressImpl.c	Mon Nov 28 15:15:50 2011 -0800
@@ -43,8 +43,9 @@
 #include "java_net_Inet4AddressImpl.h"
 
 /* the initial size of our hostent buffers */
-#define HENT_BUF_SIZE 1024
-#define BIG_HENT_BUF_SIZE 10240  /* a jumbo-sized one */
+#ifndef NI_MAXHOST
+#define NI_MAXHOST 1025
+#endif
 
 /************************************************************************
  * Inet4AddressImpl
@@ -57,60 +58,36 @@
  */
 JNIEXPORT jstring JNICALL
 Java_java_net_Inet4AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
-    char hostname[MAXHOSTNAMELEN+1];
+    char hostname[NI_MAXHOST+1];
 
     hostname[0] = '\0';
     if (JVM_GetHostName(hostname, sizeof(hostname))) {
         /* Something went wrong, maybe networking is not setup? */
         strcpy(hostname, "localhost");
     } else {
-#ifdef __linux__
-        /* On Linux gethostname() says "host.domain.sun.com".  On
-         * Solaris gethostname() says "host", so extra work is needed.
-         */
-#else
-        /* Solaris doesn't want to give us a fully qualified domain name.
-         * We do a reverse lookup to try and get one.  This works
-         * if DNS occurs before NIS in /etc/resolv.conf, but fails
-         * if NIS comes first (it still gets only a partial name).
-         * We use thread-safe system calls.
-         */
-#endif /* __linux__ */
-        struct hostent res, res2, *hp;
-        // these buffers must be pointer-aligned so they are declared
-        // with pointer type
-        char *buf[HENT_BUF_SIZE/(sizeof (char *))];
-        char *buf2[HENT_BUF_SIZE/(sizeof (char *))];
-        int h_error=0;
+        struct addrinfo hints, *res;
+        int error;
 
-        // ensure null-terminated
-        hostname[MAXHOSTNAMELEN] = '\0';
+        hostname[NI_MAXHOST] = '\0';
+        memset(&hints, 0, sizeof(hints));
+        hints.ai_flags = AI_CANONNAME;
+        hints.ai_family = AF_INET;
+
+        error = getaddrinfo(hostname, NULL, &hints, &res);
 
-#ifdef __GLIBC__
-        gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &hp, &h_error);
-#else
-        hp = gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &h_error);
-#endif
-        if (hp) {
-#ifdef __GLIBC__
-            gethostbyaddr_r(hp->h_addr, hp->h_length, AF_INET,
-                            &res2, (char*)buf2, sizeof(buf2), &hp, &h_error);
-#else
-            hp = gethostbyaddr_r(hp->h_addr, hp->h_length, AF_INET,
-                                 &res2, (char*)buf2, sizeof(buf2), &h_error);
-#endif
-            if (hp) {
-                /*
-                 * If gethostbyaddr_r() found a fully qualified host name,
-                 * returns that name. Otherwise, returns the hostname
-                 * found by gethostname().
-                 */
-                char *p = hp->h_name;
-                if ((strlen(hp->h_name) > strlen(hostname))
-                    && (strncmp(hostname, hp->h_name, strlen(hostname)) == 0)
-                    && (*(p + strlen(hostname)) == '.'))
-                    strcpy(hostname, hp->h_name);
-            }
+        if (error == 0) {/* host is known to name service */
+            getnameinfo(res->ai_addr,
+                        res->ai_addrlen,
+                        hostname,
+                        NI_MAXHOST,
+                        NULL,
+                        0,
+                        NI_NAMEREQD);
+
+            /* if getnameinfo fails hostname is still the value
+               from gethostname */
+
+            freeaddrinfo(res);
         }
     }
     return (*env)->NewStringUTF(env, hostname);
@@ -140,14 +117,9 @@
                                                 jstring host) {
     const char *hostname;
     jobjectArray ret = 0;
-    struct hostent res, *hp = 0;
-    // this buffer must be pointer-aligned so is declared
-    // with pointer type
-    char *buf[HENT_BUF_SIZE/(sizeof (char *))];
-
-    /* temporary buffer, on the off chance we need to expand */
-    char *tmp = NULL;
-    int h_error=0;
+    int retLen = 0;
+    int error = 0;
+    struct addrinfo hints, *res, *resNew = NULL;
 
     if (!initialized) {
       ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
@@ -168,6 +140,11 @@
     hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
     CHECK_NULL_RETURN(hostname, NULL);
 
+    /* Try once, with our static buffer. */
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_flags = AI_CANONNAME;
+    hints.ai_family = AF_INET;
+
 #ifdef __solaris__
     /*
      * Workaround for Solaris bug 4160367 - if a hostname contains a
@@ -181,69 +158,93 @@
     }
 #endif
 
-    /* Try once, with our static buffer. */
-#ifdef __GLIBC__
-    gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &hp, &h_error);
-#else
-    hp = gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &h_error);
-#endif
+    error = getaddrinfo(hostname, NULL, &hints, &res);
+
+    if (error) {
+        /* report error */
+        ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
+        JNU_ReleaseStringPlatformChars(env, host, hostname);
+        return NULL;
+    } else {
+        int i = 0;
+        struct addrinfo *itr, *last = NULL, *iterator = res;
 
-    /* With the re-entrant system calls, it's possible that the buffer
-     * we pass to it is not large enough to hold an exceptionally
-     * large DNS entry.  This is signaled by errno->ERANGE.  We try once
-     * more, with a very big size.
-     */
-    if (hp == NULL && errno == ERANGE) {
-        if ((tmp = (char*)malloc(BIG_HENT_BUF_SIZE))) {
-#ifdef __GLIBC__
-            gethostbyname_r(hostname, &res, tmp, BIG_HENT_BUF_SIZE,
-                            &hp, &h_error);
-#else
-            hp = gethostbyname_r(hostname, &res, tmp, BIG_HENT_BUF_SIZE,
-                                 &h_error);
-#endif
-        }
-    }
-    if (hp != NULL) {
-        struct in_addr **addrp = (struct in_addr **) hp->h_addr_list;
-        int i = 0;
+        while (iterator != NULL) {
+            // remove the duplicate one
+            int skip = 0;
+            itr = resNew;
+            while (itr != NULL) {
+                struct sockaddr_in *addr1, *addr2;
+                addr1 = (struct sockaddr_in *)iterator->ai_addr;
+                addr2 = (struct sockaddr_in *)itr->ai_addr;
+                if (addr1->sin_addr.s_addr ==
+                    addr2->sin_addr.s_addr) {
+                    skip = 1;
+                    break;
+                }
+                itr = itr->ai_next;
+            }
 
-        while (*addrp != (struct in_addr *) 0) {
-            i++;
-            addrp++;
+            if (!skip) {
+                struct addrinfo *next
+                    = (struct addrinfo*) malloc(sizeof(struct addrinfo));
+                if (!next) {
+                    JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
+                    ret = NULL;
+                    goto cleanupAndReturn;
+                }
+                memcpy(next, iterator, sizeof(struct addrinfo));
+                next->ai_next = NULL;
+                if (resNew == NULL) {
+                    resNew = next;
+                } else {
+                    last->ai_next = next;
+                }
+                last = next;
+                i++;
+            }
+            iterator = iterator->ai_next;
         }
 
-        ret = (*env)->NewObjectArray(env, i, ni_iacls, NULL);
+        retLen = i;
+        iterator = resNew;
+
+        ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL);
+
         if (IS_NULL(ret)) {
             /* we may have memory to free at the end of this */
             goto cleanupAndReturn;
         }
-        addrp = (struct in_addr **) hp->h_addr_list;
+
         i = 0;
-        while (*addrp) {
-          jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
-          if (IS_NULL(iaObj)) {
-            ret = NULL;
-            goto cleanupAndReturn;
-          }
-          (*env)->SetIntField(env, iaObj, ni_iaaddressID,
-                              ntohl((*addrp)->s_addr));
-          (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
-          (*env)->SetObjectArrayElement(env, ret, i, iaObj);
-          addrp++;
-          i++;
+        while (iterator != NULL) {
+            jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
+            if (IS_NULL(iaObj)) {
+                ret = NULL;
+                goto cleanupAndReturn;
+            }
+            (*env)->SetIntField(env, iaObj, ni_iaaddressID,
+                                ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
+            (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
+            (*env)->SetObjectArrayElement(env, ret, i++, iaObj);
+            iterator = iterator->ai_next;
         }
-    } else {
-        JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
-                        (char *)hostname);
-        ret = NULL;
     }
 
-cleanupAndReturn:
-    JNU_ReleaseStringPlatformChars(env, host, hostname);
-    if (tmp != NULL) {
-        free(tmp);
+ cleanupAndReturn:
+    {
+        struct addrinfo *iterator, *tmp;
+        iterator = resNew;
+        while (iterator != NULL) {
+            tmp = iterator;
+            iterator = iterator->ai_next;
+            free(tmp);
+        }
+        JNU_ReleaseStringPlatformChars(env, host, hostname);
     }
+
+    freeaddrinfo(res);
+
     return ret;
 }
 
@@ -256,63 +257,38 @@
 Java_java_net_Inet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
                                             jbyteArray addrArray) {
     jstring ret = NULL;
-    jint addr;
-    struct hostent hent, *hp = 0;
-    // this buffer must be pointer-aligned so is declared
-    // with pointer type
-    char *buf[HENT_BUF_SIZE/(sizeof (char *))];
-    int h_error = 0;
-    char *tmp = NULL;
 
-    /*
-     * We are careful here to use the reentrant version of
-     * gethostbyname because at the Java level this routine is not
-     * protected by any synchronization.
-     *
-     * Still keeping the reentrant platform dependent calls temporarily
-     * We should probably conform to one interface later.
-     *
-     */
+    char host[NI_MAXHOST+1];
+    int error = 0;
+    int len = 0;
     jbyte caddr[4];
+
+    struct sockaddr_in him4;
+    struct sockaddr *sa;
+
+    jint addr;
     (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
     addr = ((caddr[0]<<24) & 0xff000000);
     addr |= ((caddr[1] <<16) & 0xff0000);
     addr |= ((caddr[2] <<8) & 0xff00);
     addr |= (caddr[3] & 0xff);
-    addr = htonl(addr);
-#ifdef __GLIBC__
-    gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET, &hent,
-                    (char*)buf, sizeof(buf), &hp, &h_error);
-#else
-    hp = gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET, &hent,
-                         (char*)buf, sizeof(buf), &h_error);
-#endif
-    /* With the re-entrant system calls, it's possible that the buffer
-     * we pass to it is not large enough to hold an exceptionally
-     * large DNS entry.  This is signaled by errno->ERANGE.  We try once
-     * more, with a very big size.
-     */
-    if (hp == NULL && errno == ERANGE) {
-        if ((tmp = (char*)malloc(BIG_HENT_BUF_SIZE))) {
-#ifdef __GLIBC__
-            gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET,
-                            &hent, tmp, BIG_HENT_BUF_SIZE, &hp, &h_error);
-#else
-            hp = gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET,
-                                 &hent, tmp, BIG_HENT_BUF_SIZE, &h_error);
-#endif
-        } else {
-            JNU_ThrowOutOfMemoryError(env, "getHostByAddr");
-        }
+    memset((void *) &him4, 0, sizeof(him4));
+    him4.sin_addr.s_addr = (uint32_t) htonl(addr);
+    him4.sin_family = AF_INET;
+    sa = (struct sockaddr *) &him4;
+    len = sizeof(him4);
+
+    error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
+                        NI_NAMEREQD);
+
+    if (!error) {
+        ret = (*env)->NewStringUTF(env, host);
     }
-    if (hp == NULL) {
+
+    if (ret == NULL) {
         JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL);
-    } else {
-        ret = (*env)->NewStringUTF(env, hp->h_name);
     }
-    if (tmp) {
-        free(tmp);
-    }
+
     return ret;
 }
 
--- a/jdk/src/solaris/native/java/net/Inet6AddressImpl.c	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/solaris/native/java/net/Inet6AddressImpl.c	Mon Nov 28 15:15:50 2011 -0800
@@ -82,31 +82,29 @@
          * We use thread-safe system calls.
          */
 #ifdef AF_INET6
-        if (NET_addrtransAvailable()) {
-            struct addrinfo  hints, *res;
-            int error;
+        struct addrinfo  hints, *res;
+        int error;
 
-            bzero(&hints, sizeof(hints));
-            hints.ai_flags = AI_CANONNAME;
-            hints.ai_family = AF_UNSPEC;
+        memset(&hints, 0, sizeof(hints));
+        hints.ai_flags = AI_CANONNAME;
+        hints.ai_family = AF_UNSPEC;
 
-            error = (*getaddrinfo_ptr)(hostname, NULL, &hints, &res);
+        error = getaddrinfo(hostname, NULL, &hints, &res);
 
-            if (error == 0) {
-                /* host is known to name service */
-                error = (*getnameinfo_ptr)(res->ai_addr,
-                                           res->ai_addrlen,
-                                           hostname,
-                                           NI_MAXHOST,
-                                           NULL,
-                                           0,
-                                           NI_NAMEREQD);
+        if (error == 0) {
+            /* host is known to name service */
+            error = getnameinfo(res->ai_addr,
+                                res->ai_addrlen,
+                                hostname,
+                                NI_MAXHOST,
+                                NULL,
+                                0,
+                                NI_NAMEREQD);
 
-                /* if getnameinfo fails hostname is still the value
-                   from gethostname */
+            /* if getnameinfo fails hostname is still the value
+               from gethostname */
 
-                (*freeaddrinfo_ptr)(res);
-            }
+            freeaddrinfo(res);
         }
 #endif /* AF_INET6 */
 #endif /* __linux__ */
@@ -173,193 +171,191 @@
     CHECK_NULL_RETURN(hostname, NULL);
 
 #ifdef AF_INET6
-    if (NET_addrtransAvailable()) {
-        static jfieldID ia_preferIPv6AddressID;
-        if (ia_preferIPv6AddressID == NULL) {
-            jclass c = (*env)->FindClass(env,"java/net/InetAddress");
-            if (c)  {
-                ia_preferIPv6AddressID =
-                    (*env)->GetStaticFieldID(env, c, "preferIPv6Address", "Z");
-            }
-            if (ia_preferIPv6AddressID == NULL) {
-                JNU_ReleaseStringPlatformChars(env, host, hostname);
-                return NULL;
-            }
+    static jfieldID ia_preferIPv6AddressID;
+    if (ia_preferIPv6AddressID == NULL) {
+        jclass c = (*env)->FindClass(env,"java/net/InetAddress");
+        if (c)  {
+            ia_preferIPv6AddressID =
+                (*env)->GetStaticFieldID(env, c, "preferIPv6Address", "Z");
         }
-        /* get the address preference */
-        preferIPv6Address
-            = (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID);
-
-        /* Try once, with our static buffer. */
-        bzero(&hints, sizeof(hints));
-        hints.ai_flags = AI_CANONNAME;
-        hints.ai_family = AF_UNSPEC;
-
-#ifdef __solaris__
-        /*
-         * Workaround for Solaris bug 4160367 - if a hostname contains a
-         * white space then 0.0.0.0 is returned
-         */
-        if (isspace((unsigned char)hostname[0])) {
-            JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
-                            hostname);
+        if (ia_preferIPv6AddressID == NULL) {
             JNU_ReleaseStringPlatformChars(env, host, hostname);
             return NULL;
         }
+    }
+    /* get the address preference */
+    preferIPv6Address
+        = (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID);
+
+    /* Try once, with our static buffer. */
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_flags = AI_CANONNAME;
+    hints.ai_family = AF_UNSPEC;
+
+#ifdef __solaris__
+    /*
+     * Workaround for Solaris bug 4160367 - if a hostname contains a
+     * white space then 0.0.0.0 is returned
+     */
+    if (isspace((unsigned char)hostname[0])) {
+        JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
+                        hostname);
+        JNU_ReleaseStringPlatformChars(env, host, hostname);
+        return NULL;
+    }
 #endif
 
-        error = (*getaddrinfo_ptr)(hostname, NULL, &hints, &res);
+    error = getaddrinfo(hostname, NULL, &hints, &res);
 
-        if (error) {
-            /* report error */
-            ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
-            JNU_ReleaseStringPlatformChars(env, host, hostname);
-            return NULL;
-        } else {
-            int i = 0;
-            int inetCount = 0, inet6Count = 0, inetIndex, inet6Index;
-            struct addrinfo *itr, *last = NULL, *iterator = res;
-            while (iterator != NULL) {
-                int skip = 0;
-                itr = resNew;
-                while (itr != NULL) {
-                    if (iterator->ai_family == itr->ai_family &&
-                        iterator->ai_addrlen == itr->ai_addrlen) {
-                        if (itr->ai_family == AF_INET) { /* AF_INET */
-                            struct sockaddr_in *addr1, *addr2;
-                            addr1 = (struct sockaddr_in *)iterator->ai_addr;
-                            addr2 = (struct sockaddr_in *)itr->ai_addr;
-                            if (addr1->sin_addr.s_addr ==
-                                addr2->sin_addr.s_addr) {
-                                skip = 1;
-                                break;
-                            }
-                        } else {
-                            int t;
-                            struct sockaddr_in6 *addr1, *addr2;
-                            addr1 = (struct sockaddr_in6 *)iterator->ai_addr;
-                            addr2 = (struct sockaddr_in6 *)itr->ai_addr;
+    if (error) {
+        /* report error */
+        ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
+        JNU_ReleaseStringPlatformChars(env, host, hostname);
+        return NULL;
+    } else {
+        int i = 0;
+        int inetCount = 0, inet6Count = 0, inetIndex, inet6Index;
+        struct addrinfo *itr, *last = NULL, *iterator = res;
+        while (iterator != NULL) {
+            int skip = 0;
+            itr = resNew;
+            while (itr != NULL) {
+                if (iterator->ai_family == itr->ai_family &&
+                    iterator->ai_addrlen == itr->ai_addrlen) {
+                    if (itr->ai_family == AF_INET) { /* AF_INET */
+                        struct sockaddr_in *addr1, *addr2;
+                        addr1 = (struct sockaddr_in *)iterator->ai_addr;
+                        addr2 = (struct sockaddr_in *)itr->ai_addr;
+                        if (addr1->sin_addr.s_addr ==
+                            addr2->sin_addr.s_addr) {
+                            skip = 1;
+                            break;
+                        }
+                    } else {
+                        int t;
+                        struct sockaddr_in6 *addr1, *addr2;
+                        addr1 = (struct sockaddr_in6 *)iterator->ai_addr;
+                        addr2 = (struct sockaddr_in6 *)itr->ai_addr;
 
-                            for (t = 0; t < 16; t++) {
-                                if (addr1->sin6_addr.s6_addr[t] !=
-                                    addr2->sin6_addr.s6_addr[t]) {
-                                    break;
-                                }
-                            }
-                            if (t < 16) {
-                                itr = itr->ai_next;
-                                continue;
-                            } else {
-                                skip = 1;
+                        for (t = 0; t < 16; t++) {
+                            if (addr1->sin6_addr.s6_addr[t] !=
+                                addr2->sin6_addr.s6_addr[t]) {
                                 break;
                             }
                         }
-                    } else if (iterator->ai_family != AF_INET &&
-                               iterator->ai_family != AF_INET6) {
-                        /* we can't handle other family types */
-                        skip = 1;
-                        break;
-                    }
-                    itr = itr->ai_next;
-                }
-
-                if (!skip) {
-                    struct addrinfo *next
-                        = (struct addrinfo*) malloc(sizeof(struct addrinfo));
-                    if (!next) {
-                        JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
-                        ret = NULL;
-                        goto cleanupAndReturn;
+                        if (t < 16) {
+                            itr = itr->ai_next;
+                            continue;
+                        } else {
+                            skip = 1;
+                            break;
+                        }
                     }
-                    memcpy(next, iterator, sizeof(struct addrinfo));
-                    next->ai_next = NULL;
-                    if (resNew == NULL) {
-                        resNew = next;
-                    } else {
-                        last->ai_next = next;
-                    }
-                    last = next;
-                    i++;
-                    if (iterator->ai_family == AF_INET) {
-                        inetCount ++;
-                    } else if (iterator->ai_family == AF_INET6) {
-                        inet6Count ++;
-                    }
+                } else if (iterator->ai_family != AF_INET &&
+                           iterator->ai_family != AF_INET6) {
+                    /* we can't handle other family types */
+                    skip = 1;
+                    break;
                 }
-                iterator = iterator->ai_next;
-            }
-            retLen = i;
-            iterator = resNew;
-
-            ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL);
-
-            if (IS_NULL(ret)) {
-                /* we may have memory to free at the end of this */
-                goto cleanupAndReturn;
+                itr = itr->ai_next;
             }
 
-            if (preferIPv6Address) {
-                /* AF_INET addresses will be offset by inet6Count */
-                inetIndex = inet6Count;
-                inet6Index = 0;
-            } else {
-                /* AF_INET6 addresses will be offset by inetCount */
-                inetIndex = 0;
-                inet6Index = inetCount;
+            if (!skip) {
+                struct addrinfo *next
+                    = (struct addrinfo*) malloc(sizeof(struct addrinfo));
+                if (!next) {
+                    JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
+                    ret = NULL;
+                    goto cleanupAndReturn;
+                }
+                memcpy(next, iterator, sizeof(struct addrinfo));
+                next->ai_next = NULL;
+                if (resNew == NULL) {
+                    resNew = next;
+                } else {
+                    last->ai_next = next;
+                }
+                last = next;
+                i++;
+                if (iterator->ai_family == AF_INET) {
+                    inetCount ++;
+                } else if (iterator->ai_family == AF_INET6) {
+                    inet6Count ++;
+                }
             }
+            iterator = iterator->ai_next;
+        }
+        retLen = i;
+        iterator = resNew;
 
-            while (iterator != NULL) {
-              if (iterator->ai_family == AF_INET) {
+        ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL);
+
+        if (IS_NULL(ret)) {
+            /* we may have memory to free at the end of this */
+            goto cleanupAndReturn;
+        }
+
+        if (preferIPv6Address) {
+            /* AF_INET addresses will be offset by inet6Count */
+            inetIndex = inet6Count;
+            inet6Index = 0;
+        } else {
+            /* AF_INET6 addresses will be offset by inetCount */
+            inetIndex = 0;
+            inet6Index = inetCount;
+        }
+
+        while (iterator != NULL) {
+            if (iterator->ai_family == AF_INET) {
                 jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
                 if (IS_NULL(iaObj)) {
-                  ret = NULL;
-                  goto cleanupAndReturn;
+                    ret = NULL;
+                    goto cleanupAndReturn;
                 }
                 (*env)->SetIntField(env, iaObj, ni_iaaddressID,
                                     ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
                 (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
                 (*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
                 inetIndex++;
-              } else if (iterator->ai_family == AF_INET6) {
+            } else if (iterator->ai_family == AF_INET6) {
                 jint scope = 0;
                 jbyteArray ipaddress;
 
                 jobject iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
                 if (IS_NULL(iaObj)) {
-                  ret = NULL;
-                  goto cleanupAndReturn;
+                    ret = NULL;
+                    goto cleanupAndReturn;
                 }
                 ipaddress = (*env)->NewByteArray(env, 16);
                 if (IS_NULL(ipaddress)) {
-                  ret = NULL;
-                  goto cleanupAndReturn;
+                    ret = NULL;
+                    goto cleanupAndReturn;
                 }
                 (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
                                            (jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
 #ifdef __linux__
                 if (!kernelIsV22()) {
-                  scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
+                    scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
                 }
 #else
                 scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
 #endif
                 if (scope != 0) { /* zero is default value, no need to set */
-                  (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
-                  (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
+                    (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
+                    (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
                 }
                 (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
                 (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
                 (*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
                 inet6Index++;
-              }
-              iterator = iterator->ai_next;
             }
+            iterator = iterator->ai_next;
         }
     }
 
-cleanupAndReturn:
+ cleanupAndReturn:
     {
-        struct addrinfo *iterator, *tmp;
+      struct addrinfo *iterator, *tmp;
         iterator = resNew;
         while (iterator != NULL) {
             tmp = iterator;
@@ -369,8 +365,7 @@
         JNU_ReleaseStringPlatformChars(env, host, hostname);
     }
 
-    if (NET_addrtransAvailable())
-        (*freeaddrinfo_ptr)(res);
+    freeaddrinfo(res);
 #endif /* AF_INET6 */
 
     return ret;
@@ -393,44 +388,42 @@
     int len = 0;
     jbyte caddr[16];
 
-    if (NET_addrtransAvailable()) {
-        struct sockaddr_in him4;
-        struct sockaddr_in6 him6;
-        struct sockaddr *sa;
+    struct sockaddr_in him4;
+    struct sockaddr_in6 him6;
+    struct sockaddr *sa;
 
+    /*
+     * For IPv4 addresses construct a sockaddr_in structure.
+     */
+    if ((*env)->GetArrayLength(env, addrArray) == 4) {
+        jint addr;
+        (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
+        addr = ((caddr[0]<<24) & 0xff000000);
+        addr |= ((caddr[1] <<16) & 0xff0000);
+        addr |= ((caddr[2] <<8) & 0xff00);
+        addr |= (caddr[3] & 0xff);
+        memset((void *) &him4, 0, sizeof(him4));
+        him4.sin_addr.s_addr = (uint32_t) htonl(addr);
+        him4.sin_family = AF_INET;
+        sa = (struct sockaddr *) &him4;
+        len = sizeof(him4);
+    } else {
         /*
-         * For IPv4 addresses construct a sockaddr_in structure.
+         * For IPv6 address construct a sockaddr_in6 structure.
          */
-        if ((*env)->GetArrayLength(env, addrArray) == 4) {
-            jint addr;
-            (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
-            addr = ((caddr[0]<<24) & 0xff000000);
-            addr |= ((caddr[1] <<16) & 0xff0000);
-            addr |= ((caddr[2] <<8) & 0xff00);
-            addr |= (caddr[3] & 0xff);
-            memset((void *) &him4, 0, sizeof(him4));
-            him4.sin_addr.s_addr = (uint32_t) htonl(addr);
-            him4.sin_family = AF_INET;
-            sa = (struct sockaddr *) &him4;
-            len = sizeof(him4);
-        } else {
-            /*
-             * For IPv6 address construct a sockaddr_in6 structure.
-             */
-            (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
-            memset((void *) &him6, 0, sizeof(him6));
-            memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
-            him6.sin6_family = AF_INET6;
-            sa = (struct sockaddr *) &him6 ;
-            len = sizeof(him6) ;
-        }
+        (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
+        memset((void *) &him6, 0, sizeof(him6));
+        memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
+        him6.sin6_family = AF_INET6;
+        sa = (struct sockaddr *) &him6 ;
+        len = sizeof(him6) ;
+    }
 
-        error = (*getnameinfo_ptr)(sa, len, host, NI_MAXHOST, NULL, 0,
-                                   NI_NAMEREQD);
+    error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
+                        NI_NAMEREQD);
 
-        if (!error) {
-            ret = (*env)->NewStringUTF(env, host);
-        }
+    if (!error) {
+        ret = (*env)->NewStringUTF(env, host);
     }
 #endif /* AF_INET6 */
 
--- a/jdk/src/solaris/native/java/net/net_util_md.c	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/solaris/native/java/net/net_util_md.c	Mon Nov 28 15:15:50 2011 -0800
@@ -377,37 +377,12 @@
      *  we should also check if the APIs are available.
      */
     ipv6_fn = JVM_FindLibraryEntry(RTLD_DEFAULT, "inet_pton");
+    close(fd);
     if (ipv6_fn == NULL ) {
-        close(fd);
         return JNI_FALSE;
+    } else {
+        return JNI_TRUE;
     }
-
-    /*
-     * We've got the library, let's get the pointers to some
-     * IPV6 specific functions. We have to do that because, at least
-     * on Solaris we may build on a system without IPV6 networking
-     * libraries, therefore we can't have a hard link to these
-     * functions.
-     */
-    getaddrinfo_ptr = (getaddrinfo_f)
-        JVM_FindLibraryEntry(RTLD_DEFAULT, "getaddrinfo");
-
-    freeaddrinfo_ptr = (freeaddrinfo_f)
-        JVM_FindLibraryEntry(RTLD_DEFAULT, "freeaddrinfo");
-
-    gai_strerror_ptr = (gai_strerror_f)
-        JVM_FindLibraryEntry(RTLD_DEFAULT, "gai_strerror");
-
-    getnameinfo_ptr = (getnameinfo_f)
-        JVM_FindLibraryEntry(RTLD_DEFAULT, "getnameinfo");
-
-    if (freeaddrinfo_ptr == NULL || getnameinfo_ptr == NULL) {
-        /* We need all 3 of them */
-        getaddrinfo_ptr = NULL;
-    }
-
-    close(fd);
-    return JNI_TRUE;
 #endif /* AF_INET6 */
 }
 
@@ -920,10 +895,6 @@
     return 1;
 }
 
-jboolean NET_addrtransAvailable() {
-    return (jboolean)(getaddrinfo_ptr != NULL);
-}
-
 /*
  * Map the Java level socket option to the platform specific
  * level and option name.
--- a/jdk/src/solaris/native/java/net/net_util_md.h	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/solaris/native/java/net/net_util_md.h	Mon Nov 28 15:15:50 2011 -0800
@@ -102,10 +102,6 @@
                                            const char* hostname,
                                            int gai_error);
 
-/* do we have address translation support */
-
-extern jboolean NET_addrtransAvailable();
-
 #define NET_WAIT_READ   0x01
 #define NET_WAIT_WRITE  0x02
 #define NET_WAIT_CONNECT        0x04
--- a/jdk/src/windows/classes/java/io/FileDescriptor.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/windows/classes/java/io/FileDescriptor.java	Mon Nov 28 15:15:50 2011 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, 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
@@ -25,7 +25,8 @@
 
 package java.io;
 
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Instances of the file descriptor class serve as an opaque handle
@@ -45,13 +46,9 @@
 
     private long handle;
 
-    /**
-     * A use counter for tracking the FIS/FOS/RAF instances that
-     * use this FileDescriptor. The FIS/FOS.finalize() will not release
-     * the FileDescriptor if it is still under use by any stream.
-     */
-    private AtomicInteger useCount;
-
+    private Closeable parent;
+    private List<Closeable> otherParents;
+    private boolean closed;
 
     /**
      * Constructs an (invalid) FileDescriptor
@@ -60,7 +57,6 @@
     public /**/ FileDescriptor() {
         fd = -1;
         handle = -1;
-        useCount = new AtomicInteger();
     }
 
     static {
@@ -168,13 +164,67 @@
         return desc;
     }
 
-    // package private methods used by FIS, FOS and RAF.
+    /*
+     * Package private methods to track referents.
+     * If multiple streams point to the same FileDescriptor, we cycle
+     * through the list of all referents and call close()
+     */
 
-    int incrementAndGetUseCount() {
-        return useCount.incrementAndGet();
+    /**
+     * Attach a Closeable to this FD for tracking.
+     * parent reference is added to otherParents when
+     * needed to make closeAll simpler.
+     */
+    synchronized void attach(Closeable c) {
+        if (parent == null) {
+            // first caller gets to do this
+            parent = c;
+        } else if (otherParents == null) {
+            otherParents = new ArrayList<>();
+            otherParents.add(parent);
+            otherParents.add(c);
+        } else {
+            otherParents.add(c);
+        }
     }
 
-    int decrementAndGetUseCount() {
-        return useCount.decrementAndGet();
+    /**
+     * Cycle through all Closeables sharing this FD and call
+     * close() on each one.
+     *
+     * The caller closeable gets to call close0().
+     */
+    @SuppressWarnings("try")
+    synchronized void closeAll(Closeable releaser) throws IOException {
+        if (!closed) {
+            closed = true;
+            IOException ioe = null;
+            try (Closeable c = releaser) {
+                if (otherParents != null) {
+                    for (Closeable referent : otherParents) {
+                        try {
+                            referent.close();
+                        } catch(IOException x) {
+                            if (ioe == null) {
+                                ioe = x;
+                            } else {
+                                ioe.addSuppressed(x);
+                            }
+                        }
+                    }
+                }
+            } catch(IOException ex) {
+                /*
+                 * If releaser close() throws IOException
+                 * add other exceptions as suppressed.
+                 */
+                if (ioe != null)
+                    ex.addSuppressed(ioe);
+                ioe = ex;
+            } finally {
+                if (ioe != null)
+                    throw ioe;
+            }
+        }
     }
 }
--- a/jdk/src/windows/classes/java/net/PlainSocketImpl.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/windows/classes/java/net/PlainSocketImpl.java	Mon Nov 28 15:15:50 2011 -0800
@@ -314,7 +314,7 @@
 
     void socketSetOption(int cmd, boolean on, Object value)
         throws SocketException {
-        socketSetOption(cmd, on, value);
+        impl.socketSetOption(cmd, on, value);
     }
 
     int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
--- a/jdk/src/windows/classes/sun/security/krb5/internal/tools/Klist.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/windows/classes/sun/security/krb5/internal/tools/Klist.java	Mon Nov 28 15:15:50 2011 -0800
@@ -207,7 +207,7 @@
                 }
                 if (options[2] == 't') {
                     System.out.println("\t Time stamp: " +
-                            reformat(entries[i].getTimeStamp().toDate().toString()));
+                            format(entries[i].getTimeStamp()));
                 }
             }
         }
@@ -234,30 +234,39 @@
             System.out.println("\nDefault principal: " +
                                defaultPrincipal + ", " +
                                creds.length + " entries found.\n");
-        String starttime = null;
-        String endtime = null;
-        String servicePrincipal = null;
-        String etype = null;
         if (creds != null) {
             for (int i = 0; i < creds.length; i++) {
                 try {
-                    starttime =
-                        reformat(creds[i].getAuthTime().toDate().toString());
-                    endtime =
-                        reformat(creds[i].getEndTime().toDate().toString());
+                    String starttime;
+                    String endtime;
+                    String renewTill;
+                    String servicePrincipal;
+                    if (creds[i].getStartTime() != null) {
+                        starttime = format(creds[i].getStartTime());
+                    } else {
+                        starttime = format(creds[i].getAuthTime());
+                    }
+                    endtime = format(creds[i].getEndTime());
                     servicePrincipal =
                         creds[i].getServicePrincipal().toString();
                     System.out.println("[" + (i + 1) + "] " +
                                        " Service Principal:  " +
                                        servicePrincipal);
-                    System.out.println("     Valid starting:  " + starttime);
-                    System.out.println("     Expires:         " + endtime);
+                    System.out.println("     Valid starting:     " + starttime);
+                    System.out.println("     Expires:            " + endtime);
+                    if (creds[i].getRenewTill() != null) {
+                        renewTill = format(creds[i].getRenewTill());
+                        System.out.println(
+                                "     Renew until:        " + renewTill);
+                    }
                     if (options[0] == 'e') {
-                        etype = EType.toString(creds[i].getEType());
-                        System.out.println("     Encryption type: " + etype);
+                        String eskey = EType.toString(creds[i].getEType());
+                        String etkt = EType.toString(creds[i].getTktEType());
+                        System.out.println("     EType (skey, tkt):  "
+                                + eskey + ", " + etkt);
                     }
                     if (options[1] == 'f') {
-                        System.out.println("     Flags:           " +
+                        System.out.println("     Flags:              " +
                                            creds[i].getTicketFlags().toString());
                     }
                     if (options[2] == 'a') {
@@ -312,13 +321,14 @@
      * and yyyy is the year.
      * @param date the string form of Date object.
      */
-    String reformat(String date) {
+    private String format(KerberosTime kt) {
+        String date = kt.toDate().toString();
         return (date.substring(4, 7) + " " + date.substring(8, 10) +
                 ", " + date.substring(24)
-                + " " + date.substring(11, 16));
+                + " " + date.substring(11, 19));
     }
     /**
-     * Printes out the help information.
+     * Prints out the help information.
      */
     void printHelp() {
         System.out.println("\nUsage: klist " +
--- a/jdk/src/windows/lib/tzmappings	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/src/windows/lib/tzmappings	Mon Nov 28 15:15:50 2011 -0800
@@ -167,7 +167,7 @@
 Argentina Standard Time:900,900::America/Buenos_Aires:
 Azerbaijan Standard Time:901,901:AZ:Asia/Baku:
 Bangladesh Standard Time:902,902::Asia/Dhaka:
-Central Brazilian Standard Time:903,903:BR:America/Manaus:
+Central Brazilian Standard Time:903,903:BR:America/Cuiaba:
 Central Standard Time (Mexico):904,904::America/Mexico_City:
 Georgian Standard Time:905,905:GE:Asia/Tbilisi:
 Jordan Standard Time:906,906:JO:Asia/Amman:
@@ -189,5 +189,7 @@
 Ulaanbaatar Standard Time:922,922::Asia/Ulaanbaatar:
 Venezuela Standard Time:923,923::America/Caracas:
 Magadan Standard Time:924,924::Asia/Magadan:
-Western Brazilian Standard Time:925,925:BR:America/Rio_Branco:
-Armenian Standard Time:926,926:AM:Asia/Yerevan:
+Kaliningrad Standard Time:925,925:RU:Europe/Kaliningrad:
+Turkey Standard Time:926,926::Asia/Istanbul:
+Western Brazilian Standard Time:927,927:BR:America/Rio_Branco:
+Armenian Standard Time:928,928:AM:Asia/Yerevan:
--- a/jdk/test/java/io/FileDescriptor/FileChannelFDTest.java	Fri Nov 18 16:57:01 2011 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2006, 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
- * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- *
- * @test
- * @bug 6322678
- * @summary Test for making sure that fd is closed during
- *          finalization of a stream, when an associated
- *          file channel is not available
- */
-
-import java.io.*;
-import java.nio.*;
-import java.nio.channels.*;
-
-public class FileChannelFDTest {
-
-    static byte data[] = new byte[] {48, 49, 50, 51, 52, 53, 54, 55, 56, 57,};
-    static String inFileName = "fd-in-test.txt";
-    static String outFileName = "fd-out-test.txt";
-    static File inFile;
-    static File outFile;
-
-    private static void writeToInFile() throws IOException {
-        FileOutputStream out = new FileOutputStream(inFile);
-        out.write(data);
-        out.close();
-    }
-
-    public static void main(String[] args)
-                throws Exception {
-
-        inFile= new File(System.getProperty("test.dir", "."),
-                        inFileName);
-        inFile.createNewFile();
-        inFile.deleteOnExit();
-        writeToInFile();
-
-        outFile  = new File(System.getProperty("test.dir", "."),
-                        outFileName);
-        outFile.createNewFile();
-        outFile.deleteOnExit();
-
-        doFileChannel();
-    }
-
-     private static void doFileChannel() throws Exception {
-
-        FileInputStream fis = new FileInputStream(inFile);
-        FileDescriptor fd = fis.getFD();
-        FileChannel fc = fis.getChannel();
-        System.out.println("Created fis:" + fis);
-
-        /**
-         * Encourage the GC
-         */
-        fis = null;
-        fc = null;
-        System.gc();
-        Thread.sleep(500);
-
-        if (fd.valid()) {
-            throw new Exception("Finalizer either didn't run --" +
-                "try increasing the Thread's sleep time after System.gc();" +
-                "or the finalizer didn't close the file");
-        }
-
-        System.out.println("File Closed successfully");
-        System.out.println();
-  }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/io/FileDescriptor/Sharing.java	Mon Nov 28 15:15:50 2011 -0800
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2011, 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
+ * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7105952 6322678 7082769
+ * @summary Improve finalisation for FileInputStream/FileOutputStream/RandomAccessFile
+ * @run main/othervm Sharing
+ */
+
+import java.io.*;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.util.concurrent.CountDownLatch;
+
+public class Sharing {
+
+    final static int numFiles = 10;
+    volatile static boolean fail;
+
+    public static void main(String[] args) throws Exception {
+        TestFinalizer();
+        TestMultipleFD();
+        TestIsValid();
+        MultiThreadedFD();
+        TestCloseAll();
+    }
+
+    /**
+     * Finalizer shouldn't discard a file descriptor until all streams have
+     * finished with it.
+     */
+    private static void TestFinalizer() throws Exception {
+        FileDescriptor fd = null;
+        File tempFile = new File("TestFinalizer1.txt");
+        tempFile.deleteOnExit();
+        try (Writer writer = new FileWriter(tempFile)) {
+            for (int i=0; i<5; i++) {
+                writer.write("test file content test file content");
+            }
+        }
+
+        FileInputStream fis1 = new FileInputStream(tempFile);
+        fd = fis1.getFD();
+        // Create a new FIS based on the existing FD (so the two FIS's share the same native fd)
+        try (FileInputStream fis2 = new FileInputStream(fd)) {
+            // allow fis1 to be gc'ed
+            fis1 = null;
+            int ret = 0;
+            while(ret >= 0) {
+                // encourage gc
+                System.gc();
+                // read from fis2 - when fis1 is gc'ed and finalizer is run, read will fail
+                System.out.print(".");
+                ret = fis2.read();
+            }
+        }
+
+        // variation of above. Use RandomAccessFile to obtain a filedescriptor
+        File testFinalizerFile = new File("TestFinalizer");
+        RandomAccessFile raf = new RandomAccessFile(testFinalizerFile, "rw");
+        raf.writeBytes("test file content test file content");
+        raf.seek(0L);
+        fd = raf.getFD();
+        try (FileInputStream fis3 = new FileInputStream(fd)) {
+            // allow raf to be gc'ed
+            raf = null;
+            int ret = 0;
+            while (ret >= 0) {
+                // encourage gc
+                System.gc();
+                /*
+                 * read from fis3 - when raf is gc'ed and finalizer is run,
+                 * fd should still be valid.
+                 */
+                System.out.print(".");
+                ret = fis3.read();
+            }
+        } finally {
+            testFinalizerFile.delete();
+        }
+    }
+
+    /**
+     * Exercise FileDispatcher close()/preClose()
+     */
+    private static void TestMultipleFD() throws Exception {
+        RandomAccessFile raf = null;
+        FileOutputStream fos = null;
+        FileInputStream fis = null;
+        FileChannel fc = null;
+        FileLock fileLock = null;
+
+        File test1 = new File("test1");
+        try {
+            raf = new RandomAccessFile(test1, "rw");
+            fos = new FileOutputStream(raf.getFD());
+            fis = new FileInputStream(raf.getFD());
+            fc = raf.getChannel();
+            fileLock = fc.lock();
+            raf.setLength(0L);
+            fos.flush();
+            fos.write("TEST".getBytes());
+        } finally {
+            if (fileLock != null) fileLock.release();
+            if (fis != null) fis.close();
+            if (fos != null) fos.close();
+            if (raf != null) raf.close();
+            test1.delete();
+        }
+
+        /*
+         * Close out in different order to ensure FD is not
+         * closed out too early
+         */
+        File test2 = new File("test2");
+        try {
+            raf = new RandomAccessFile(test2, "rw");
+            fos = new FileOutputStream(raf.getFD());
+            fis = new FileInputStream(raf.getFD());
+            fc = raf.getChannel();
+            fileLock = fc.lock();
+            raf.setLength(0L);
+            fos.flush();
+            fos.write("TEST".getBytes());
+        } finally {
+            if (fileLock != null) fileLock.release();
+            if (raf != null) raf.close();
+            if (fos != null) fos.close();
+            if (fis != null) fis.close();
+            test2.delete();
+        }
+
+        // one more time, fos first this time
+        File test3 = new File("test3");
+        try {
+            raf = new RandomAccessFile(test3, "rw");
+            fos = new FileOutputStream(raf.getFD());
+            fis = new FileInputStream(raf.getFD());
+            fc = raf.getChannel();
+            fileLock = fc.lock();
+            raf.setLength(0L);
+            fos.flush();
+            fos.write("TEST".getBytes());
+        } finally {
+            if (fileLock != null) fileLock.release();
+            if (fos != null) fos.close();
+            if (raf != null) raf.close();
+            if (fis != null) fis.close();
+            test3.delete();
+        }
+    }
+
+    /**
+     * Similar to TestMultipleFD() but this time we
+     * just get and use FileDescriptor.valid() for testing.
+     */
+    private static void TestIsValid() throws Exception {
+        FileDescriptor fd = null;
+        RandomAccessFile raf = null;
+        FileOutputStream fos = null;
+        FileInputStream fis = null;
+        FileChannel fc = null;
+
+        File test1 = new File("test1");
+        try {
+            raf = new RandomAccessFile(test1, "rw");
+            fd = raf.getFD();
+            fos = new FileOutputStream(fd);
+            fis = new FileInputStream(fd);
+        } finally {
+            try {
+                if (fis != null) fis.close();
+                if (fd.valid()) {
+                    throw new RuntimeException("[FIS close()] FileDescriptor shouldn't be valid");
+                }
+                if (fos != null) fos.close();
+                if (raf != null) raf.close();
+            } finally {
+                test1.delete();
+            }
+        }
+
+        /*
+         * Close out in different order to ensure FD is
+         * closed correctly.
+         */
+        File test2 = new File("test2");
+        try {
+            raf = new RandomAccessFile(test2, "rw");
+            fd = raf.getFD();
+            fos = new FileOutputStream(fd);
+            fis = new FileInputStream(fd);
+        } finally {
+            try {
+                if (raf != null) raf.close();
+                if (fd.valid()) {
+                    throw new RuntimeException("[RAF close()] FileDescriptor shouldn't be valid");
+                }
+                if (fos != null) fos.close();
+                if (fis != null) fis.close();
+            } finally {
+                test2.delete();
+            }
+        }
+
+        // one more time, fos first this time
+        File test3 = new File("test3");
+        try {
+            raf = new RandomAccessFile(test3, "rw");
+            fd = raf.getFD();
+            fos = new FileOutputStream(fd);
+            fis = new FileInputStream(fd);
+        } finally {
+            try {
+                if (fos != null) fos.close();
+                if (fd.valid()) {
+                    throw new RuntimeException("[FOS close()] FileDescriptor shouldn't be valid");
+                }
+                if (raf != null) raf.close();
+                if (fis != null) fis.close();
+            } finally {
+                test3.delete();
+            }
+        }
+    }
+
+    /**
+     * Test concurrent access to the same FileDescriptor
+     */
+    private static void MultiThreadedFD() throws Exception {
+        RandomAccessFile raf = null;
+        FileDescriptor fd = null;
+        int numThreads = 2;
+        CountDownLatch done = new CountDownLatch(numThreads);
+        OpenClose[] fileOpenClose = new OpenClose[numThreads];
+        File MultipleThreadedFD = new File("MultipleThreadedFD");
+        try {
+            raf = new RandomAccessFile(MultipleThreadedFD, "rw");
+            fd = raf.getFD();
+            for(int count=0;count<numThreads;count++) {
+                fileOpenClose[count] = new OpenClose(fd, done);
+                fileOpenClose[count].start();
+            }
+            done.await();
+        } finally {
+            try {
+                if(raf != null) raf.close();
+                // fd should now no longer be valid
+                if(fd.valid()) {
+                    throw new RuntimeException("FileDescriptor should not be valid");
+                }
+                // OpenClose thread tests failed
+                if(fail) {
+                    throw new RuntimeException("OpenClose thread tests failed.");
+                }
+            } finally {
+                MultipleThreadedFD.delete();
+            }
+        }
+    }
+
+    /**
+     * Test closeAll handling in FileDescriptor
+     */
+    private static void TestCloseAll() throws Exception {
+        File testFile = new File("test");
+        testFile.deleteOnExit();
+        RandomAccessFile raf = new RandomAccessFile(testFile, "rw");
+        FileInputStream fis = new FileInputStream(raf.getFD());
+        fis.close();
+        if (raf.getFD().valid()) {
+             throw new RuntimeException("FD should not be valid.");
+        }
+
+        // Test the suppressed exception handling - FileInputStream
+
+        raf = new RandomAccessFile(testFile, "rw");
+        fis = new FileInputStream(raf.getFD());
+        BadFileInputStream bfis1 = new BadFileInputStream(raf.getFD());
+        BadFileInputStream bfis2 = new BadFileInputStream(raf.getFD());
+        BadFileInputStream bfis3 = new BadFileInputStream(raf.getFD());
+        // extra test - set bfis3 to null
+        bfis3 = null;
+        try {
+            fis.close();
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+            if (ioe.getSuppressed().length != 2) {
+                throw new RuntimeException("[FIS]Incorrect number of suppressed " +
+                          "exceptions received : " + ioe.getSuppressed().length);
+            }
+        }
+        if (raf.getFD().valid()) {
+            // we should still have closed the FD
+            // even with the exception.
+            throw new RuntimeException("[FIS]TestCloseAll : FD still valid.");
+        }
+
+        // Now test with FileOutputStream
+
+        raf = new RandomAccessFile(testFile, "rw");
+        FileOutputStream fos = new FileOutputStream(raf.getFD());
+        BadFileOutputStream bfos1 = new BadFileOutputStream(raf.getFD());
+        BadFileOutputStream bfos2 = new BadFileOutputStream(raf.getFD());
+        BadFileOutputStream bfos3 = new BadFileOutputStream(raf.getFD());
+        // extra test - set bfos3 to null
+        bfos3 = null;
+        try {
+            fos.close();
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+            if (ioe.getSuppressed().length != 2) {
+                throw new RuntimeException("[FOS]Incorrect number of suppressed " +
+                          "exceptions received : " + ioe.getSuppressed().length);
+            }
+        }
+        if (raf.getFD().valid()) {
+            // we should still have closed the FD
+            // even with the exception.
+            throw new RuntimeException("[FOS]TestCloseAll : FD still valid.");
+        }
+    }
+
+    /**
+     * A thread which will open and close a number of FileInputStreams and
+     * FileOutputStreams referencing the same native file descriptor.
+     */
+    private static class OpenClose extends Thread {
+        private FileDescriptor fd = null;
+        private CountDownLatch done;
+        FileInputStream[] fisArray = new FileInputStream[numFiles];
+        FileOutputStream[] fosArray = new FileOutputStream[numFiles];
+
+        OpenClose(FileDescriptor filedescriptor, CountDownLatch done) {
+            this.fd = filedescriptor;
+            this.done = done;
+        }
+
+        public void run() {
+             try {
+                 for(int i=0;i<numFiles;i++) {
+                     fisArray[i] = new FileInputStream(fd);
+                     fosArray[i] = new FileOutputStream(fd);
+                 }
+
+                 // Now close out
+                 for(int i=0;i<numFiles;i++) {
+                     if(fisArray[i] != null) fisArray[i].close();
+                     if(fosArray[i] != null) fosArray[i].close();
+                 }
+
+             } catch(IOException ioe) {
+                 System.out.println("OpenClose encountered IO issue :" + ioe);
+                 fail = true;
+             } finally {
+                 if (fd.valid()) { // fd should not be valid after first close() call
+                     System.out.println("OpenClose: FileDescriptor shouldn't be valid");
+                     fail = true;
+                 }
+                 done.countDown();
+             }
+         }
+    }
+
+    private static class BadFileInputStream extends FileInputStream {
+
+        BadFileInputStream(FileDescriptor fd) {
+            super(fd);
+        }
+
+        public void close() throws IOException {
+            throw new IOException("Bad close operation");
+        }
+    }
+
+    private static class BadFileOutputStream extends FileOutputStream {
+
+        BadFileOutputStream(FileDescriptor fd) {
+            super(fd);
+        }
+
+        public void close() throws IOException {
+            throw new IOException("Bad close operation");
+        }
+    }
+
+}
--- a/jdk/test/java/io/etc/FileDescriptorSharing.java	Fri Nov 18 16:57:01 2011 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,336 +0,0 @@
-/*
- * Copyright (c) 2011, 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
- * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 6322678 7082769
- * @summary FileInputStream/FileOutputStream/RandomAccessFile allow file descriptor
- *          to be closed while still in use.
- * @run main/othervm FileDescriptorSharing
- */
-
-import java.io.*;
-import java.nio.channels.FileChannel;
-import java.nio.channels.FileLock;
-import java.util.concurrent.CountDownLatch;
-
-public class FileDescriptorSharing {
-
-    final static int numFiles = 10;
-    volatile static boolean fail;
-
-    public static void main(String[] args) throws Exception {
-        TestFinalizer();
-        TestMultipleFD();
-        TestIsValid();
-        MultiThreadedFD();
-    }
-
-    /**
-     * We shouldn't discard a file descriptor until all streams have
-     * finished with it
-     */
-    private static void TestFinalizer() throws Exception {
-        FileDescriptor fd = null;
-        File tempFile = new File("TestFinalizer1.txt");
-        tempFile.deleteOnExit();
-        try (Writer writer = new FileWriter(tempFile)) {
-            for (int i=0; i<5; i++) {
-                writer.write("test file content test file content");
-            }
-        }
-
-        FileInputStream fis1 = new FileInputStream(tempFile);
-        fd = fis1.getFD();
-        // Create a new FIS based on the existing FD (so the two FIS's share the same native fd)
-        try (FileInputStream fis2 = new FileInputStream(fd)) {
-            // allow fis1 to be gc'ed
-            fis1 = null;
-            int ret = 0;
-            while(ret >= 0) {
-                // encourage gc
-                System.gc();
-                // read from fis2 - when fis1 is gc'ed and finalizer is run, read will fail
-                System.out.print(".");
-                ret = fis2.read();
-            }
-        }
-
-        // variation of above. Use RandomAccessFile to obtain a filedescriptor
-        File testFinalizerFile = new File("TestFinalizer");
-        RandomAccessFile raf = new RandomAccessFile(testFinalizerFile, "rw");
-        raf.writeBytes("test file content test file content");
-        raf.seek(0L);
-        fd = raf.getFD();
-        try (FileInputStream fis3 = new FileInputStream(fd)) {
-            // allow raf to be gc'ed
-            raf = null;
-            int ret = 0;
-            while (ret >= 0) {
-                // encourage gc
-                System.gc();
-                /*
-                 * read from fis3 - when raf is gc'ed and finalizer is run,
-                 * fd should still be valid.
-                 */
-                System.out.print(".");
-                ret = fis3.read();
-            }
-            if(!fd.valid()) {
-                throw new RuntimeException("TestFinalizer() : FileDescriptor should be valid");
-            }
-        } finally {
-            testFinalizerFile.delete();
-        }
-    }
-
-    /**
-     * Exercise FileDispatcher close()/preClose()
-     */
-    private static void TestMultipleFD() throws Exception {
-        RandomAccessFile raf = null;
-        FileOutputStream fos = null;
-        FileInputStream fis = null;
-        FileChannel fc = null;
-        FileLock fileLock = null;
-
-        File test1 = new File("test1");
-        try {
-            raf = new RandomAccessFile(test1, "rw");
-            fos = new FileOutputStream(raf.getFD());
-            fis = new FileInputStream(raf.getFD());
-            fc = raf.getChannel();
-            fileLock = fc.lock();
-            raf.setLength(0L);
-            fos.flush();
-            fos.write("TEST".getBytes());
-        } finally {
-            if (fileLock != null) fileLock.release();
-            if (fis != null) fis.close();
-            if (fos != null) fos.close();
-            if (raf != null) raf.close();
-            test1.delete();
-        }
-
-        /*
-         * Close out in different order to ensure FD is not
-         * closed out too early
-         */
-        File test2 = new File("test2");
-        try {
-            raf = new RandomAccessFile(test2, "rw");
-            fos = new FileOutputStream(raf.getFD());
-            fis = new FileInputStream(raf.getFD());
-            fc = raf.getChannel();
-            fileLock = fc.lock();
-            raf.setLength(0L);
-            fos.flush();
-            fos.write("TEST".getBytes());
-        } finally {
-            if (fileLock != null) fileLock.release();
-            if (raf != null) raf.close();
-            if (fos != null) fos.close();
-            if (fis != null) fis.close();
-            test2.delete();
-        }
-
-        // one more time, fos first this time
-        File test3 = new File("test3");
-        try {
-            raf = new RandomAccessFile(test3, "rw");
-            fos = new FileOutputStream(raf.getFD());
-            fis = new FileInputStream(raf.getFD());
-            fc = raf.getChannel();
-            fileLock = fc.lock();
-            raf.setLength(0L);
-            fos.flush();
-            fos.write("TEST".getBytes());
-        } finally {
-            if (fileLock != null) fileLock.release();
-            if (fos != null) fos.close();
-            if (raf != null) raf.close();
-            if (fis != null) fis.close();
-            test3.delete();
-        }
-    }
-
-    /**
-     * Similar to TestMultipleFD() but this time we
-     * just get and use FileDescriptor.valid() for testing.
-     */
-    private static void TestIsValid() throws Exception {
-        FileDescriptor fd = null;
-        RandomAccessFile raf = null;
-        FileOutputStream fos = null;
-        FileInputStream fis = null;
-        FileChannel fc = null;
-
-        File test1 = new File("test1");
-        try {
-            raf = new RandomAccessFile(test1, "rw");
-            fd = raf.getFD();
-            fos = new FileOutputStream(fd);
-            fis = new FileInputStream(fd);
-        } finally {
-            try {
-                if (fis != null) fis.close();
-                if (fos != null) fos.close();
-                if (!fd.valid()) {
-                    throw new RuntimeException("FileDescriptor should be valid");
-                }
-                if (raf != null) raf.close();
-                if (fd.valid()) {
-                    throw new RuntimeException("close() called and FileDescriptor still valid");
-                }
-            } finally {
-                if (raf != null) raf.close();
-                test1.delete();
-            }
-        }
-
-        /*
-         * Close out in different order to ensure FD is not
-         * closed out too early
-         */
-        File test2 = new File("test2");
-        try {
-            raf = new RandomAccessFile(test2, "rw");
-            fd = raf.getFD();
-            fos = new FileOutputStream(fd);
-            fis = new FileInputStream(fd);
-        } finally {
-            try {
-                if (raf != null) raf.close();
-                if (fos != null) fos.close();
-                if (!fd.valid()) {
-                    throw new RuntimeException("FileDescriptor should be valid");
-                }
-                if (fis != null) fis.close();
-                if (fd.valid()) {
-                    throw new RuntimeException("close() called and FileDescriptor still valid");
-                }
-            } finally {
-                test2.delete();
-            }
-        }
-
-        // one more time, fos first this time
-        File test3 = new File("test3");
-        try {
-            raf = new RandomAccessFile(test3, "rw");
-            fd = raf.getFD();
-            fos = new FileOutputStream(fd);
-            fis = new FileInputStream(fd);
-        } finally {
-            try {
-                if (fos != null) fos.close();
-                if (raf != null) raf.close();
-                if (!fd.valid()) {
-                    throw new RuntimeException("FileDescriptor should be valid");
-                }
-                if (fis != null) fis.close();
-                if (fd.valid()) {
-                    throw new RuntimeException("close() called and FileDescriptor still valid");
-                }
-            } finally {
-                test3.delete();
-            }
-        }
-    }
-
-    /**
-     * Test concurrent access to the same fd.useCount field
-     */
-    private static void MultiThreadedFD() throws Exception {
-        RandomAccessFile raf = null;
-        FileDescriptor fd = null;
-        int numThreads = 2;
-        CountDownLatch done = new CountDownLatch(numThreads);
-        OpenClose[] fileOpenClose = new OpenClose[numThreads];
-        File MultipleThreadedFD = new File("MultipleThreadedFD");
-        try {
-            raf = new RandomAccessFile(MultipleThreadedFD, "rw");
-            fd = raf.getFD();
-            for(int count=0;count<numThreads;count++) {
-                fileOpenClose[count] = new OpenClose(fd, done);
-                fileOpenClose[count].start();
-            }
-            done.await();
-        } finally {
-            try {
-                if(raf != null) raf.close();
-                // fd should now no longer be valid
-                if(fd.valid()) {
-                    throw new RuntimeException("FileDescriptor should not be valid");
-                }
-                // OpenClose thread tests failed
-                if(fail) {
-                    throw new RuntimeException("OpenClose thread tests failed.");
-                }
-            } finally {
-                MultipleThreadedFD.delete();
-            }
-        }
-    }
-
-    /**
-     * A thread which will open and close a number of FileInputStreams and
-     * FileOutputStreams referencing the same native file descriptor.
-     */
-    private static class OpenClose extends Thread {
-        private FileDescriptor fd = null;
-        private CountDownLatch done;
-        FileInputStream[] fisArray = new FileInputStream[numFiles];
-        FileOutputStream[] fosArray = new FileOutputStream[numFiles];
-
-        OpenClose(FileDescriptor filedescriptor, CountDownLatch done) {
-            this.fd = filedescriptor;
-            this.done = done;
-        }
-
-        public void run() {
-             try {
-                 for(int i=0;i<numFiles;i++) {
-                     fisArray[i] = new FileInputStream(fd);
-                     fosArray[i] = new FileOutputStream(fd);
-                 }
-
-                 // Now close out
-                 for(int i=0;i<numFiles;i++) {
-                     if(fisArray[i] != null) fisArray[i].close();
-                     if(fosArray[i] != null) fosArray[i].close();
-                 }
-
-             } catch(IOException ioe) {
-                 System.out.println("OpenClose encountered IO issue :" + ioe);
-                 fail = true;
-             } finally {
-                 if (!fd.valid()) { // fd should still be valid given RAF reference
-                     System.out.println("OpenClose: FileDescriptor should be valid");
-                     fail = true;
-                 }
-                 done.countDown();
-             }
-         }
-    }
-}
--- a/jdk/test/java/lang/Runtime/exec/StreamsSurviveDestroy.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/test/java/lang/Runtime/exec/StreamsSurviveDestroy.java	Mon Nov 28 15:15:50 2011 -0800
@@ -28,6 +28,7 @@
  */
 
 import java.io.*;
+import java.util.concurrent.*;
 
 
 public class StreamsSurviveDestroy {
@@ -40,15 +41,17 @@
         boolean wantInterrupt;
         boolean acceptException;
         Exception exc = null;
+        CountDownLatch latch;
 
         Copier(String name, InputStream in, OutputStream out,
-               boolean ae, boolean wi)
+               boolean ae, boolean wi, CountDownLatch l)
         {
             this.name = name;
             this.in = in;
             this.out = out;
             this.acceptException = ae;
             this.wantInterrupt = wi;
+            this.latch = l;
             setName(name);
             start();
         }
@@ -59,6 +62,7 @@
 
         public void run() {
             byte[] buf = new byte[4242];
+            latch.countDown();
             for (;;) {
                 try {
                     int n = in.read(buf);
@@ -95,13 +99,17 @@
     }
 
     static void test() throws Exception {
+        CountDownLatch latch = new CountDownLatch(2);
+
         System.err.println("test");
         Process p = Runtime.getRuntime().exec("/bin/cat");
         Copier cp1 = new Copier("out", p.getInputStream(), System.err,
-                               false, false);
+                                false, false, latch);
         Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
-                               false, false);
-        Thread.sleep(100);
+                                false, false, latch);
+        latch.await();    // Wait till both Copiers about to read
+        Thread.sleep(100);// Give both Copiers a chance to start read
+
         p.destroy();
         System.err.println("  exit: " + p.waitFor());
         cp1.join();
@@ -111,13 +119,17 @@
     }
 
     static void testCloseBeforeDestroy() throws Exception {
+        CountDownLatch latch = new CountDownLatch(2);
+
         System.err.println("testCloseBeforeDestroy");
         Process p = Runtime.getRuntime().exec("/bin/cat");
         Copier cp1 = new Copier("out", p.getInputStream(), System.err,
-                                true, false);
+                                true, false, latch);
         Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
-                                true, false);
-        Thread.sleep(100);
+                                true, false, latch);
+        latch.await();    // Wait till both Copiers about to read
+        Thread.sleep(100);// Give both Copiers a chance to start read
+
         p.getInputStream().close();
         p.getErrorStream().close();
         p.destroy();
@@ -129,13 +141,17 @@
     }
 
     static void testCloseAfterDestroy() throws Exception {
+        CountDownLatch latch = new CountDownLatch(2);
         System.err.println("testCloseAfterDestroy");
         Process p = Runtime.getRuntime().exec("/bin/cat");
         Copier cp1 = new Copier("out", p.getInputStream(), System.err,
-                                true, false);
+                                true, false,latch);
         Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
-                                true, false);
-        Thread.sleep(100);
+                                true, false, latch);
+
+        latch.await();    // Wait till both Copiers about to read
+        Thread.sleep(100);// Give both Copiers a chance to start read
+
         p.destroy();
         p.getInputStream().close();
         p.getErrorStream().close();
@@ -147,13 +163,16 @@
     }
 
     static void testInterrupt() throws Exception {
+        CountDownLatch latch = new CountDownLatch(2);
         System.err.println("testInterrupt");
         Process p = Runtime.getRuntime().exec("/bin/cat");
         Copier cp1 = new Copier("out", p.getInputStream(), System.err,
-                                false, true);
+                                false, true, latch);
         Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
-                                false, true);
-        Thread.sleep(100);
+                                false, true, latch);
+        latch.await();    // Wait till both Copiers about to read
+        Thread.sleep(100);// Give both Copiers a chance to start read
+
         cp1.interrupt();
         cp2.interrupt();
         Thread.sleep(100);
@@ -176,7 +195,5 @@
         testCloseBeforeDestroy();
         testCloseAfterDestroy();
         testInterrupt();
-
     }
-
 }
--- a/jdk/test/java/lang/ThreadGroup/NullThreadName.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/test/java/lang/ThreadGroup/NullThreadName.java	Mon Nov 28 15:15:50 2011 -0800
@@ -24,7 +24,6 @@
 /*
  * @test
  * @bug 6576763
- * @ignore until hotspot 6776144 bug is resolved
  * @summary (thread) Thread constructors throw undocumented NPE for null name
  */
 
@@ -64,8 +63,8 @@
             try { Thread.sleep(2000); }
             catch (InterruptedException unused) {}
 
-            /* do not wait forever */
-            if (count++ > 5)
+            /* do not wait forever - allow 120 seconds same as jtreg default timeout. */
+            if (count++ > 60)
                 throw new AssertionError("GoodThread is still alive!");
         }
 
--- a/jdk/test/java/lang/ThreadGroup/Stop.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/test/java/lang/ThreadGroup/Stop.java	Mon Nov 28 15:15:50 2011 -0800
@@ -29,37 +29,58 @@
  */
 
 public class Stop implements Runnable {
-    private static Thread first=null;
-    private static Thread second=null;
-    private static ThreadGroup group = new ThreadGroup("");
+    private static boolean groupStopped = false ;
+    private static final Object lock = new Object();
 
-    Stop() {
-        Thread thread = new Thread(group, this);
-        if (first == null)
-            first = thread;
-        else
-            second = thread;
-
-        thread.start();
-    }
+    private static final ThreadGroup group = new ThreadGroup("");
+    private static final Thread first = new Thread(group, new Stop());
+    private static final Thread second = new Thread(group, new Stop());
 
     public void run() {
         while (true) {
+            // Give the other thread a chance to start
             try {
-                Thread.sleep(1000); // Give other thread a chance to start
-                if (Thread.currentThread() == first)
-                    group.stop();
-            } catch(InterruptedException e){
+                Thread.sleep(1000);
+            } catch (InterruptedException e) {
+            }
+
+            // When the first thread runs, it will stop the group.
+            if (Thread.currentThread() == first) {
+                synchronized (lock) {
+                    try {
+                        group.stop();
+                    } finally {
+                        // Signal the main thread it is time to check
+                        // that the stopped thread group was successful
+                        groupStopped = true;
+                        lock.notifyAll();
+                    }
+                }
             }
         }
     }
 
     public static void main(String[] args) throws Exception {
-        for (int i=0; i<2; i++)
-            new Stop();
-        Thread.sleep(3000);
+        // Launch two threads as part of the same thread group
+        first.start();
+        second.start();
+
+        // Wait for the thread group stop to be issued
+        synchronized(lock){
+            while (!groupStopped) {
+                lock.wait();
+                // Give the other thread a chance to stop
+                Thread.sleep(1000);
+            }
+        }
+
+        // Check that the second thread is terminated when the
+        // first thread terminates the thread group.
         boolean failed = second.isAlive();
-        first.stop(); second.stop();
+
+        // Clean up any threads that may have not been terminated
+        first.stop();
+        second.stop();
         if (failed)
             throw new RuntimeException("Failure.");
     }
--- a/jdk/test/java/lang/management/PlatformLoggingMXBean/LoggingMXBeanTest.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/test/java/lang/management/PlatformLoggingMXBean/LoggingMXBeanTest.java	Mon Nov 28 15:15:50 2011 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 7024172
+ * @bug 7024172 7067691
  * @summary Test if proxy for PlatformLoggingMXBean is equivalent
  *          to proxy for LoggingMXBean
  *
@@ -43,6 +43,13 @@
     static String LOGGER_NAME_2 = "com.sun.management.Logger.Logger2";
     static String UNKNOWN_LOGGER_NAME = "com.sun.management.Unknown";
 
+    // These instance variables prevent premature logger garbage collection
+    // See getLogger() weak reference warnings.
+    Logger logger1;
+    Logger logger2;
+
+    static LoggingMXBeanTest test;
+
     public static void main(String[] argv) throws Exception {
         MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
         LoggingMXBean proxy =
@@ -51,7 +58,7 @@
                 LoggingMXBean.class);
 
         // test LoggingMXBean proxy
-        LoggingMXBeanTest p = new LoggingMXBeanTest(proxy);
+        test = new LoggingMXBeanTest(proxy);
 
         // check if the attributes implemented by PlatformLoggingMXBean
         // and LoggingMXBean return the same value
@@ -64,9 +71,9 @@
     // same verification as in java/util/logging/LoggingMXBeanTest2
     public LoggingMXBeanTest(LoggingMXBean mbean) throws Exception {
 
-        Logger logger1 = Logger.getLogger( LOGGER_NAME_1 );
+        logger1 = Logger.getLogger( LOGGER_NAME_1 );
         logger1.setLevel(Level.FINE);
-        Logger logger2 = Logger.getLogger( LOGGER_NAME_2 );
+        logger2 = Logger.getLogger( LOGGER_NAME_2 );
         logger2.setLevel(null);
 
         /*
@@ -207,6 +214,7 @@
         // verify logger names
         List<String> loggers1 = mxbean1.getLoggerNames();
         List<String> loggers2 = mxbean2.getLoggerNames();
+
         if (loggers1.size() != loggers2.size())
             throw new RuntimeException("LoggerNames: unmatched number of entries");
         List<String> loggers3 = new ArrayList<>(loggers1);
@@ -219,7 +227,10 @@
             if (!mxbean1.getLoggerLevel(logger)
                     .equals(mxbean2.getLoggerLevel(logger)))
                 throw new RuntimeException(
-                    "LoggerLevel: unmatched level for " + logger);
+                    "LoggerLevel: unmatched level for " + logger
+                    + ", " + mxbean1.getLoggerLevel(logger)
+                    + ", " + mxbean2.getLoggerLevel(logger));
+
             if (!mxbean1.getParentLoggerName(logger)
                     .equals(mxbean2.getParentLoggerName(logger)))
                 throw new RuntimeException(
--- a/jdk/test/java/lang/management/PlatformLoggingMXBean/PlatformLoggingMXBeanTest.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/test/java/lang/management/PlatformLoggingMXBean/PlatformLoggingMXBeanTest.java	Mon Nov 28 15:15:50 2011 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug     6876135 7024172
+ * @bug     6876135 7024172 7067691
  *
  * @summary Test PlatformLoggingMXBean
  *          This test performs similar testing as
@@ -41,11 +41,15 @@
 
 public class PlatformLoggingMXBeanTest
 {
-
     ObjectName objectName = null;
     static String LOGGER_NAME_1 = "com.sun.management.Logger1";
     static String LOGGER_NAME_2 = "com.sun.management.Logger2";
 
+    // Use Logger instance variables to prevent premature garbage collection
+    // of weak references.
+    Logger logger1;
+    Logger logger2;
+
     public PlatformLoggingMXBeanTest() throws Exception {
     }
 
@@ -135,8 +139,8 @@
         System.out.println( "*********** Phase 3 ***********" );
         System.out.println( "*******************************" );
         System.out.println( " Create and test new Loggers" );
-        Logger logger1 = Logger.getLogger( LOGGER_NAME_1 );
-        Logger logger2 = Logger.getLogger( LOGGER_NAME_2 );
+        logger1 = Logger.getLogger( LOGGER_NAME_1 );
+        logger2 = Logger.getLogger( LOGGER_NAME_2 );
 
         // check that Level object are returned properly
         try {
@@ -187,6 +191,7 @@
         System.out.println( " Set and Check the Logger Level" );
         log1 = false;
         log2 = false;
+
         try {
             // Set the level of logger1 to ALL
             params = new Object[2];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/registry/readTest/readTest.java	Mon Nov 28 15:15:50 2011 -0800
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011, 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
+ * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.rmi.registry.Registry;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+
+public class readTest {
+
+    public static void main(String args[]) throws Exception {
+        int port = 7491;
+        try {
+            testPkg.Server obj = new testPkg.Server();
+            testPkg.Hello stub = (testPkg.Hello) UnicastRemoteObject.exportObject(obj, 0);
+            // Bind the remote object's stub in the registry
+            Registry registry = LocateRegistry.getRegistry(port);
+            registry.bind("Hello", stub);
+
+            System.err.println("Server ready");
+
+            // now, let's test client
+            testPkg.Client client = new testPkg.Client(port);
+            String testStubReturn = client.testStub();
+            if(!testStubReturn.equals(obj.hello)) {
+                throw new RuntimeException("Test Fails : unexpected string from stub call");
+            } else {
+                System.out.println("Test passed");
+            }
+            registry.unbind("Hello");
+
+        } catch (Exception e) {
+            System.err.println("Server exception: " + e.toString());
+            e.printStackTrace();
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/registry/readTest/readTest.sh	Mon Nov 28 15:15:50 2011 -0800
@@ -0,0 +1,95 @@
+#
+# Copyright (c) 2011, 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
+# 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# @test
+# @bug 7102369 7094468 7100592
+# @summary remove java.rmi.server.codebase property parsing from registyimpl
+# @run shell readTest.sh
+
+OS=`uname -s`
+case "$OS" in
+  SunOS | Linux )
+    PS=":"
+    FS="/"
+    FILEURL="file:"
+    ;;
+  Windows* | CYGWIN* )
+    PS=";"
+    FS="\\"
+    FILEURL="file:/"
+    ;;
+  * )
+    echo "Unrecognized system!"
+    exit 1;
+    ;;
+esac
+
+cp -r ${TESTSRC}${FS}* .
+${TESTJAVA}${FS}bin${FS}javac testPkg${FS}*java
+${TESTJAVA}${FS}bin${FS}javac readTest.java
+
+mkdir rmi_tmp
+RMIREG_OUT=rmi.out
+#start rmiregistry without any local classes on classpath
+cd rmi_tmp
+${TESTJAVA}${FS}bin${FS}rmiregistry 7491 > ..${FS}${RMIREG_OUT} 2>&1 &
+RMIREG_PID=$!
+# allow some time to start
+sleep 3
+cd ..
+
+# trailing / after code base is important for rmi codebase property.
+${TESTJAVA}${FS}bin${FS}java -Djava.rmi.server.codebase=${FILEURL}`pwd`/ readTest > OUT.TXT 2>&1 &
+TEST_PID=$!
+#bulk of testcase - let it run for a while
+sleep 5
+
+#we're done, kill processes first
+kill -9 ${RMIREG_PID} ${TEST_PID}
+sleep 3
+
+echo "Test output : "
+
+cat OUT.TXT
+echo "=============="
+echo "rmiregistry output  : "
+cat ${RMIREG_OUT}
+echo "=============="
+
+grep "Server ready" OUT.TXT
+result1=$?
+grep "Test passed" OUT.TXT
+result2=$?
+
+if [ $result1 -eq 0  -a $result2 -eq 0 ]
+then 
+    echo "Passed"
+    exitCode=0;
+else
+    echo "Failed"
+    exitCode=1
+fi
+rm -rf OUT.TXT ${RMIREG_OUT} rmi_tmp
+exit ${exitCode}    
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/registry/readTest/testPkg/Client.java	Mon Nov 28 15:15:50 2011 -0800
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011, 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
+ * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package testPkg;
+
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+
+public class Client {
+    int port;
+
+    public Client(int p) {
+        port = p;
+    }
+
+    public String testStub() throws Exception {
+        try {
+            Registry registry = LocateRegistry.getRegistry(port);
+            Hello stub = (Hello) registry.lookup("Hello");
+            String response = stub.sayHello();
+            return response;
+            } catch (Exception e) {
+                System.err.println("Client exception: " + e.toString());
+                throw e;
+            }
+        }
+    }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/registry/readTest/testPkg/Hello.java	Mon Nov 28 15:15:50 2011 -0800
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011, 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
+ * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package testPkg;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface Hello extends Remote {
+    String sayHello() throws RemoteException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/registry/readTest/testPkg/Server.java	Mon Nov 28 15:15:50 2011 -0800
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011, 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
+ * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package testPkg;
+
+public class Server implements Hello {
+
+    public String hello = "Hello, world!";
+
+    public Server() {}
+
+    public String sayHello() {
+        return hello;
+    }
+
+}
--- a/jdk/test/java/util/Timer/Args.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/test/java/util/Timer/Args.java	Mon Nov 28 15:15:50 2011 -0800
@@ -92,19 +92,22 @@
                new F(){void f(){ t.scheduleAtFixedRate(x, (Date)null, 42); }}
                );
 
-        final long start = System.currentTimeMillis();
-        final Date past = new Date(start - 10500);
         final CountDownLatch y1 = new CountDownLatch(1);
         final CountDownLatch y2 = new CountDownLatch(1);
         final CountDownLatch y3 = new CountDownLatch(11);
+        final long start = System.currentTimeMillis();
+        final Date past = new Date(start - 10500);
+
         schedule(           t, counter(y1), past);
         schedule(           t, counter(y2), past, 1000);
         scheduleAtFixedRate(t, counter(y3), past, 1000);
         y3.await();
         y1.await();
         y2.await();
-        System.out.printf("elapsed=%d%n", System.currentTimeMillis() - start);
-        check(System.currentTimeMillis() - start < 500);
+
+        final long elapsed = System.currentTimeMillis() - start;
+        System.out.printf("elapsed=%d%n", elapsed);
+        check(elapsed < 500);
 
         t.cancel();
 
--- a/jdk/test/java/util/Timer/KillThread.java	Fri Nov 18 16:57:01 2011 -0800
+++ b/jdk/test/java/util/Timer/KillThread.java	Mon Nov 28 15:15:50 2011 -0800
@@ -31,21 +31,26 @@
 import java.util.*;
 
 public class KillThread {
+    static volatile Thread tdThread;
     public static void main (String[] args) throws Exception  {
         Timer t = new Timer();
 
         // Start a mean event that kills the timer thread
         t.schedule(new TimerTask() {
             public void run() {
+                tdThread = Thread.currentThread();
                 throw new ThreadDeath();
             }
         }, 0);
 
         // Wait for mean event to do the deed and thread to die.
         try {
-            Thread.sleep(100);
+            do {
+                Thread.sleep(100);
+            } while(tdThread == null);
         } catch(InterruptedException e) {
         }
+        tdThread.join();
 
         // Try to start another event
         try {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/MD2InTrustAnchor.java	Mon Nov 28 15:15:50 2011 -0800
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 2011, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7113275
+ * @summary compatibility issue with MD2 trust anchor and old X509TrustManager
+ *
+ *     SunJSSE does not support dynamic system properties, no way to re-use
+ *     system properties in samevm/agentvm mode.
+ * @run main/othervm MD2InTrustAnchor PKIX TLSv1.1
+ * @run main/othervm MD2InTrustAnchor SunX509 TLSv1.1
+ * @run main/othervm MD2InTrustAnchor PKIX TLSv1.2
+ * @run main/othervm MD2InTrustAnchor SunX509 TLSv1.2
+ */
+
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import javax.net.ssl.*;
+import java.security.KeyStore;
+import java.security.KeyFactory;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.*;
+import java.security.interfaces.*;
+import sun.misc.BASE64Decoder;
+
+
+public class MD2InTrustAnchor {
+
+    /*
+     * =============================================================
+     * Set the various variables needed for the tests, then
+     * specify what tests to run on each side.
+     */
+
+    /*
+     * Should we run the client or server in a separate thread?
+     * Both sides can throw exceptions, but do you have a preference
+     * as to which side should be the main thread.
+     */
+    static boolean separateServerThread = false;
+
+    /*
+     * Certificates and key used in the test.
+     */
+
+    // It's a trust anchor signed with MD2 hash function.
+    static String trustedCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQIFADA7MQswCQYDVQQGEwJVUzEN\n" +
+        "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
+        "MTExMTE4MTExNDA0WhcNMzIxMDI4MTExNDA0WjA7MQswCQYDVQQGEwJVUzENMAsG\n" +
+        "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" +
+        "KoZIhvcNAQEBBQADgY0AMIGJAoGBAPGyB9tugUGgxtdeqe0qJEwf9x1Gy4BOi1yR\n" +
+        "wzDZY4H5LquvIfQ2V3J9X1MQENVsFvkvp65ZcFcy+ObOucXUUPFcd/iw2DVb5QXA\n" +
+        "ffyeVqWD56GPi8Qe37wrJO3L6fBhN9oxp/BbdRLgjU81zx8qLEyPODhPMxV4OkcA\n" +
+        "SDwZTSxxAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLOAtr/YrYj9H04EDLA0fd14jisF\n" +
+        "MGMGA1UdIwRcMFqAFLOAtr/YrYj9H04EDLA0fd14jisFoT+kPTA7MQswCQYDVQQG\n" +
+        "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" +
+        "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEC\n" +
+        "BQADgYEAr8ExpXu/FTIRiMzPm0ubqwME4lniilwQUiEOD/4DbksNjEIcUyS2hIk1\n" +
+        "qsmjJz3SHBnwhxl9dhJVwk2tZLkPGW86Zn0TPVRsttK4inTgCC9GFGeqQBdrU/uf\n" +
+        "lipBzXWljrfbg4N/kK8m2LabtKUMMnGysM8rN0Fx2PYm5xxGvtM=\n" +
+        "-----END CERTIFICATE-----";
+
+    // The certificate issued by above trust anchor, signed with MD5
+    static String targetCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICeDCCAeGgAwIBAgIBAjANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
+        "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
+        "MTExMTE4MTExNDA2WhcNMzEwODA1MTExNDA2WjBPMQswCQYDVQQGEwJVUzENMAsG\n" +
+        "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n" +
+        "BAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwDnm96mw\n" +
+        "fXCH4bgXk1US0VcJsQVxUtGMyncAveMuzBzNzOmKZPeqyYX1Fuh4q+cuza03WTJd\n" +
+        "G9nOkNr364e3Rn1aaHjCMcBmFflObnGnhhufNmIGYogJ9dJPmhUVPEVAXrMG+Ces\n" +
+        "NKy2E8woGnLMrqu6yiuTClbLBPK8fWzTXrECAwEAAaN4MHYwCwYDVR0PBAQDAgPo\n" +
+        "MB0GA1UdDgQWBBSdRrpocLPJXyGfDmMWJrcEf29WGDAfBgNVHSMEGDAWgBSzgLa/\n" +
+        "2K2I/R9OBAywNH3deI4rBTAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIG\n" +
+        "CCsGAQUFBwMDMA0GCSqGSIb3DQEBBAUAA4GBAKJ71ZiCUykkJrCLYUxlFlhvUcr9\n" +
+        "sTcOc67QdroW5f412NI15SXWDiley/JOasIiuIFPjaJBjOKoHOvTjG/snVu9wEgq\n" +
+        "YNR8dPsO+NM8r79C6jO+Jx5fYAC7os2XxS75h3NX0ElJcbwIXGBJ6xRrsFh/BGYH\n" +
+        "yvudOlX4BkVR0l1K\n" +
+        "-----END CERTIFICATE-----";
+
+    // Private key in the format of PKCS#8.
+    static String targetPrivateKey =
+        "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMA55vepsH1wh+G4\n" +
+        "F5NVEtFXCbEFcVLRjMp3AL3jLswczczpimT3qsmF9RboeKvnLs2tN1kyXRvZzpDa\n" +
+        "9+uHt0Z9Wmh4wjHAZhX5Tm5xp4YbnzZiBmKICfXST5oVFTxFQF6zBvgnrDSsthPM\n" +
+        "KBpyzK6rusorkwpWywTyvH1s016xAgMBAAECgYEAn9bF3oRkdDoBU0i/mcww5I+K\n" +
+        "SH9tFt+WQbiojjz9ac49trkvUfu7MO1Jui2+QbrvaSkyj+HYGFOJd1wMsPXeB7ck\n" +
+        "5mOIYV4uZK8jfNMSQ8v0tFEeIPp5lKdw1XnrQfSe+abo2eL5Lwso437Y4s3w37+H\n" +
+        "aY3d76hR5qly+Ys+Ww0CQQDjeOoX89d/xhRqGXKjCx8ImE/dPmsI8O27cwtKrDYJ\n" +
+        "6t0v/xryVIdvOYcRBvKnqEogOH7T1kI+LnWKUTJ2ehJ7AkEA2FVloPVqCehXcc7e\n" +
+        "z3TDpU9w1B0JXklcV5HddYsRqp9RukN/VK4szKE7F1yoarIUtfE9Lr9082Jwyp3M\n" +
+        "L11xwwJBAKsZ+Hur3x0tUY29No2Nf/pnFyvEF57SGwA0uPmiL8Ol9lpz+UDudDEl\n" +
+        "hIM6Rqv12kwCMuQE9i7vo1o3WU3k5KECQEqhg1L49yD935TqiiFFpe0Ur9btQXse\n" +
+        "kdXAA4d2d5zGI7q/aGD9SYU6phkUJSHR16VA2RuUfzMrpb+wmm1IrmMCQFtLoKRT\n" +
+        "A5kokFb+E3Gplu29tJvCUpfwgBFRS+wmkvtiaU/tiyDcVgDO+An5DwedxxdVzqiE\n" +
+        "njWHoKY3axDQ8OU=\n";
+
+
+    static char passphrase[] = "passphrase".toCharArray();
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    /*
+     * Define the server side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doServerSide() throws Exception {
+        SSLContext context = generateSSLContext(trustedCertStr, targetCertStr,
+                                            targetPrivateKey);
+        SSLServerSocketFactory sslssf = context.getServerSocketFactory();
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket)sslssf.createServerSocket(serverPort);
+        sslServerSocket.setNeedClientAuth(true);
+        serverPort = sslServerSocket.getLocalPort();
+
+        /*
+         * Signal Client, we're ready for his connect.
+         */
+        serverReady = true;
+
+        SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept();
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslIS.read();
+        sslOS.write('A');
+        sslOS.flush();
+
+        sslSocket.close();
+    }
+
+    /*
+     * Define the client side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doClientSide() throws Exception {
+
+        /*
+         * Wait for server to get started.
+         */
+        while (!serverReady) {
+            Thread.sleep(50);
+        }
+
+        SSLContext context = generateSSLContext(trustedCertStr, targetCertStr,
+                                            targetPrivateKey);
+        SSLSocketFactory sslsf = context.getSocketFactory();
+
+        SSLSocket sslSocket =
+            (SSLSocket)sslsf.createSocket("localhost", serverPort);
+
+        // enable the specified TLS protocol
+        sslSocket.setEnabledProtocols(new String[] {tlsProtocol});
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslOS.write('B');
+        sslOS.flush();
+        sslIS.read();
+
+        sslSocket.close();
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+    private static String tmAlgorithm;        // trust manager
+    private static String tlsProtocol;        // trust manager
+
+    private static void parseArguments(String[] args) {
+        tmAlgorithm = args[0];
+        tlsProtocol = args[1];
+    }
+
+    private static SSLContext generateSSLContext(String trustedCertStr,
+            String keyCertStr, String keySpecStr) throws Exception {
+
+        // generate certificate from cert string
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+        // create a key store
+        KeyStore ks = KeyStore.getInstance("JKS");
+        ks.load(null, null);
+
+        // import the trused cert
+        Certificate trusedCert = null;
+        ByteArrayInputStream is = null;
+        if (trustedCertStr != null) {
+            is = new ByteArrayInputStream(trustedCertStr.getBytes());
+            trusedCert = cf.generateCertificate(is);
+            is.close();
+
+            ks.setCertificateEntry("RSA Export Signer", trusedCert);
+        }
+
+        if (keyCertStr != null) {
+            // generate the private key.
+            PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
+                                new BASE64Decoder().decodeBuffer(keySpecStr));
+            KeyFactory kf = KeyFactory.getInstance("RSA");
+            RSAPrivateKey priKey =
+                    (RSAPrivateKey)kf.generatePrivate(priKeySpec);
+
+            // generate certificate chain
+            is = new ByteArrayInputStream(keyCertStr.getBytes());
+            Certificate keyCert = cf.generateCertificate(is);
+            is.close();
+
+            // It's not allowed to send MD2 signed certificate to peer,
+            // even it may be a trusted certificate. Then we will not
+            // place the trusted certficate in the chain.
+            Certificate[] chain = new Certificate[1];
+            chain[0] = keyCert;
+
+            // import the key entry.
+            ks.setKeyEntry("Whatever", priKey, passphrase, chain);
+        }
+
+        // create SSL context
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm);
+        tmf.init(ks);
+
+        SSLContext ctx = SSLContext.getInstance(tlsProtocol);
+        if (keyCertStr != null && !keyCertStr.isEmpty()) {
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
+            kmf.init(ks, passphrase);
+
+            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+            ks = null;
+        } else {
+            ctx.init(null, tmf.getTrustManagers(), null);
+        }
+
+        return ctx;
+    }
+
+
+    // use any free port by default
+    volatile int serverPort = 0;
+
+    volatile Exception serverException = null;
+    volatile Exception clientException = null;
+
+    public static void main(String[] args) throws Exception {
+        if (debug)
+            System.setProperty("javax.net.debug", "all");
+
+        /*
+         * Get the customized arguments.
+         */
+        parseArguments(args);
+
+        /*
+         * Start the tests.
+         */
+        new MD2InTrustAnchor();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    MD2InTrustAnchor() throws Exception {
+        try {
+            if (separateServerThread) {
+                startServer(true);
+                startClient(false);
+            } else {
+                startClient(true);
+                startServer(false);
+            }
+        } catch (Exception e) {
+            // swallow for now.  Show later
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            serverThread.join();
+        } else {
+            clientThread.join();
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         * Which side threw the error?
+         */
+        Exception local;
+        Exception remote;
+        String whichRemote;
+
+        if (separateServerThread) {
+            remote = serverException;
+            local = clientException;
+            whichRemote = "server";
+        } else {
+            remote = clientException;
+            local = serverException;
+            whichRemote = "client";
+        }
+
+        /*
+         * If both failed, return the curthread's exception, but also
+         * print the remote side Exception
+         */
+        if ((local != null) && (remote != null)) {
+            System.out.println(whichRemote + " also threw:");
+            remote.printStackTrace();
+            System.out.println();
+            throw local;
+        }
+
+        if (remote != null) {
+            throw remote;
+        }
+
+        if (local != null) {
+            throw local;
+        }
+    }
+
+    void startServer(boolean newThread) throws Exception {
+        if (newThread) {
+            serverThread = new Thread() {
+                public void run() {
+                    try {
+                        doServerSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our server thread just died.
+                         *
+                         * Release the client, if not active already...
+                         */
+                        System.err.println("Server died...");
+                        serverReady = true;
+                        serverException = e;
+                    }
+                }
+            };
+            serverThread.start();
+        } else {
+            try {
+                doServerSide();
+            } catch (Exception e) {
+                serverException = e;
+            } finally {
+                serverReady = true;
+            }
+        }
+    }
+
+    void startClient(boolean newThread) throws Exception {
+        if (newThread) {
+            clientThread = new Thread() {
+                public void run() {
+                    try {
+                        doClientSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our client thread just died.
+                         */
+                        System.err.println("Client died...");
+                        clientException = e;
+                    }
+                }
+            };
+            clientThread.start();
+        } else {
+            try {
+                doClientSide();
+            } catch (Exception e) {
+                clientException = e;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/TrustTrustedCert.java	Mon Nov 28 15:15:50 2011 -0800
@@ -0,0 +1,475 @@
+/*
+ * Copyright (c) 2011, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7113275
+ * @summary compatibility issue with MD2 trust anchor and old X509TrustManager
+ *
+ *     SunJSSE does not support dynamic system properties, no way to re-use
+ *     system properties in samevm/agentvm mode.
+ * @run main/othervm TrustTrustedCert PKIX TLSv1.1
+ * @run main/othervm TrustTrustedCert SunX509 TLSv1.1
+ * @run main/othervm TrustTrustedCert PKIX TLSv1.2
+ * @run main/othervm TrustTrustedCert SunX509 TLSv1.2
+ */
+
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import javax.net.ssl.*;
+import java.security.*;
+import java.security.cert.*;
+import java.security.spec.*;
+import java.security.interfaces.*;
+import sun.misc.BASE64Decoder;
+
+
+public class TrustTrustedCert {
+
+    /*
+     * =============================================================
+     * Set the various variables needed for the tests, then
+     * specify what tests to run on each side.
+     */
+
+    /*
+     * Should we run the client or server in a separate thread?
+     * Both sides can throw exceptions, but do you have a preference
+     * as to which side should be the main thread.
+     */
+    static boolean separateServerThread = false;
+
+    /*
+     * Certificates and key used in the test.
+     */
+
+    // It's a trust anchor signed with MD2 hash function.
+    static String trustedCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQIFADA7MQswCQYDVQQGEwJVUzEN\n" +
+        "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
+        "MTExMTE4MTExNDA0WhcNMzIxMDI4MTExNDA0WjA7MQswCQYDVQQGEwJVUzENMAsG\n" +
+        "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" +
+        "KoZIhvcNAQEBBQADgY0AMIGJAoGBAPGyB9tugUGgxtdeqe0qJEwf9x1Gy4BOi1yR\n" +
+        "wzDZY4H5LquvIfQ2V3J9X1MQENVsFvkvp65ZcFcy+ObOucXUUPFcd/iw2DVb5QXA\n" +
+        "ffyeVqWD56GPi8Qe37wrJO3L6fBhN9oxp/BbdRLgjU81zx8qLEyPODhPMxV4OkcA\n" +
+        "SDwZTSxxAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLOAtr/YrYj9H04EDLA0fd14jisF\n" +
+        "MGMGA1UdIwRcMFqAFLOAtr/YrYj9H04EDLA0fd14jisFoT+kPTA7MQswCQYDVQQG\n" +
+        "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" +
+        "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEC\n" +
+        "BQADgYEAr8ExpXu/FTIRiMzPm0ubqwME4lniilwQUiEOD/4DbksNjEIcUyS2hIk1\n" +
+        "qsmjJz3SHBnwhxl9dhJVwk2tZLkPGW86Zn0TPVRsttK4inTgCC9GFGeqQBdrU/uf\n" +
+        "lipBzXWljrfbg4N/kK8m2LabtKUMMnGysM8rN0Fx2PYm5xxGvtM=\n" +
+        "-----END CERTIFICATE-----";
+
+    // The certificate issued by above trust anchor, signed with MD5
+    static String targetCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICeDCCAeGgAwIBAgIBAjANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
+        "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
+        "MTExMTE4MTExNDA2WhcNMzEwODA1MTExNDA2WjBPMQswCQYDVQQGEwJVUzENMAsG\n" +
+        "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n" +
+        "BAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwDnm96mw\n" +
+        "fXCH4bgXk1US0VcJsQVxUtGMyncAveMuzBzNzOmKZPeqyYX1Fuh4q+cuza03WTJd\n" +
+        "G9nOkNr364e3Rn1aaHjCMcBmFflObnGnhhufNmIGYogJ9dJPmhUVPEVAXrMG+Ces\n" +
+        "NKy2E8woGnLMrqu6yiuTClbLBPK8fWzTXrECAwEAAaN4MHYwCwYDVR0PBAQDAgPo\n" +
+        "MB0GA1UdDgQWBBSdRrpocLPJXyGfDmMWJrcEf29WGDAfBgNVHSMEGDAWgBSzgLa/\n" +
+        "2K2I/R9OBAywNH3deI4rBTAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIG\n" +
+        "CCsGAQUFBwMDMA0GCSqGSIb3DQEBBAUAA4GBAKJ71ZiCUykkJrCLYUxlFlhvUcr9\n" +
+        "sTcOc67QdroW5f412NI15SXWDiley/JOasIiuIFPjaJBjOKoHOvTjG/snVu9wEgq\n" +
+        "YNR8dPsO+NM8r79C6jO+Jx5fYAC7os2XxS75h3NX0ElJcbwIXGBJ6xRrsFh/BGYH\n" +
+        "yvudOlX4BkVR0l1K\n" +
+        "-----END CERTIFICATE-----";
+
+    // Private key in the format of PKCS#8.
+    static String targetPrivateKey =
+        "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMA55vepsH1wh+G4\n" +
+        "F5NVEtFXCbEFcVLRjMp3AL3jLswczczpimT3qsmF9RboeKvnLs2tN1kyXRvZzpDa\n" +
+        "9+uHt0Z9Wmh4wjHAZhX5Tm5xp4YbnzZiBmKICfXST5oVFTxFQF6zBvgnrDSsthPM\n" +
+        "KBpyzK6rusorkwpWywTyvH1s016xAgMBAAECgYEAn9bF3oRkdDoBU0i/mcww5I+K\n" +
+        "SH9tFt+WQbiojjz9ac49trkvUfu7MO1Jui2+QbrvaSkyj+HYGFOJd1wMsPXeB7ck\n" +
+        "5mOIYV4uZK8jfNMSQ8v0tFEeIPp5lKdw1XnrQfSe+abo2eL5Lwso437Y4s3w37+H\n" +
+        "aY3d76hR5qly+Ys+Ww0CQQDjeOoX89d/xhRqGXKjCx8ImE/dPmsI8O27cwtKrDYJ\n" +
+        "6t0v/xryVIdvOYcRBvKnqEogOH7T1kI+LnWKUTJ2ehJ7AkEA2FVloPVqCehXcc7e\n" +
+        "z3TDpU9w1B0JXklcV5HddYsRqp9RukN/VK4szKE7F1yoarIUtfE9Lr9082Jwyp3M\n" +
+        "L11xwwJBAKsZ+Hur3x0tUY29No2Nf/pnFyvEF57SGwA0uPmiL8Ol9lpz+UDudDEl\n" +
+        "hIM6Rqv12kwCMuQE9i7vo1o3WU3k5KECQEqhg1L49yD935TqiiFFpe0Ur9btQXse\n" +
+        "kdXAA4d2d5zGI7q/aGD9SYU6phkUJSHR16VA2RuUfzMrpb+wmm1IrmMCQFtLoKRT\n" +
+        "A5kokFb+E3Gplu29tJvCUpfwgBFRS+wmkvtiaU/tiyDcVgDO+An5DwedxxdVzqiE\n" +
+        "njWHoKY3axDQ8OU=\n";
+
+
+    static char passphrase[] = "passphrase".toCharArray();
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    /*
+     * Define the server side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doServerSide() throws Exception {
+        SSLContext context = generateSSLContext();
+        SSLServerSocketFactory sslssf = context.getServerSocketFactory();
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket)sslssf.createServerSocket(serverPort);
+        sslServerSocket.setNeedClientAuth(true);
+        serverPort = sslServerSocket.getLocalPort();
+
+        /*
+         * Signal Client, we're ready for his connect.
+         */
+        serverReady = true;
+
+        SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept();
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslIS.read();
+        sslOS.write('A');
+        sslOS.flush();
+
+        sslSocket.close();
+    }
+
+    /*
+     * Define the client side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doClientSide() throws Exception {
+
+        /*
+         * Wait for server to get started.
+         */
+        while (!serverReady) {
+            Thread.sleep(50);
+        }
+
+        SSLContext context = generateSSLContext();
+        SSLSocketFactory sslsf = context.getSocketFactory();
+
+        SSLSocket sslSocket =
+            (SSLSocket)sslsf.createSocket("localhost", serverPort);
+
+        // enable the specified TLS protocol
+        sslSocket.setEnabledProtocols(new String[] {tlsProtocol});
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslOS.write('B');
+        sslOS.flush();
+        sslIS.read();
+
+        sslSocket.close();
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+    private static String tmAlgorithm;        // trust manager
+    private static String tlsProtocol;        // trust manager
+
+    private static void parseArguments(String[] args) {
+        tmAlgorithm = args[0];
+        tlsProtocol = args[1];
+    }
+
+    private static SSLContext generateSSLContext() throws Exception {
+
+        // generate certificate from cert string
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+        // create a key store
+        KeyStore ks = KeyStore.getInstance("JKS");
+        ks.load(null, null);
+
+        // import the trused cert
+        X509Certificate trusedCert = null;
+        ByteArrayInputStream is =
+                new ByteArrayInputStream(trustedCertStr.getBytes());
+        trusedCert = (X509Certificate)cf.generateCertificate(is);
+        is.close();
+
+        ks.setCertificateEntry("Trusted RSA Signer", trusedCert);
+
+        // generate the private key.
+        PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
+                            new BASE64Decoder().decodeBuffer(targetPrivateKey));
+        KeyFactory kf = KeyFactory.getInstance("RSA");
+        RSAPrivateKey priKey =
+                (RSAPrivateKey)kf.generatePrivate(priKeySpec);
+
+        // generate certificate chain
+        is = new ByteArrayInputStream(targetCertStr.getBytes());
+        X509Certificate keyCert = (X509Certificate)cf.generateCertificate(is);
+        is.close();
+
+        X509Certificate[] chain = new X509Certificate[2];
+        chain[0] = keyCert;
+        chain[1] = trusedCert;
+
+        // import the key entry and the chain
+        ks.setKeyEntry("TheKey", priKey, passphrase, chain);
+
+        // create SSL context
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm);
+        tmf.init(ks);
+
+        // create the customized KM and TM
+        NoneExtendedX509TM myTM =
+            new NoneExtendedX509TM(tmf.getTrustManagers()[0]);
+        NoneExtendedX509KM myKM =
+            new NoneExtendedX509KM("TheKey", chain, priKey);
+
+        SSLContext ctx = SSLContext.getInstance(tlsProtocol);
+        // KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
+        // kmf.init(ks, passphrase);
+        // ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+        ctx.init(new KeyManager[]{myKM}, new TrustManager[]{myTM}, null);
+        ks = null;
+
+        return ctx;
+    }
+
+    static class NoneExtendedX509TM implements X509TrustManager {
+        X509TrustManager tm;
+
+        NoneExtendedX509TM(TrustManager tm) {
+            this.tm = (X509TrustManager)tm;
+        }
+
+        public void checkClientTrusted(X509Certificate chain[], String authType)
+                throws CertificateException {
+            tm.checkClientTrusted(chain, authType);
+        }
+
+        public void checkServerTrusted(X509Certificate chain[], String authType)
+                throws CertificateException {
+            tm.checkServerTrusted(chain, authType);
+        }
+
+        public X509Certificate[] getAcceptedIssuers() {
+            return tm.getAcceptedIssuers();
+        }
+    }
+
+    static class NoneExtendedX509KM implements X509KeyManager {
+        private String keyAlias;
+        private X509Certificate[] chain;
+        private PrivateKey privateKey;
+
+        NoneExtendedX509KM(String keyAlias, X509Certificate[] chain,
+                PrivateKey privateKey) {
+            this.keyAlias = keyAlias;
+            this.chain = chain;
+            this.privateKey = privateKey;
+        }
+
+        public String[] getClientAliases(String keyType, Principal[] issuers) {
+            return new String[] {keyAlias};
+        }
+
+        public String chooseClientAlias(String[] keyType, Principal[] issuers,
+                Socket socket) {
+            return keyAlias;
+        }
+
+        public String[] getServerAliases(String keyType, Principal[] issuers) {
+            return new String[] {keyAlias};
+        }
+
+        public String chooseServerAlias(String keyType, Principal[] issuers,
+                Socket socket) {
+            return keyAlias;
+        }
+
+        public X509Certificate[] getCertificateChain(String alias) {
+            return chain;
+        }
+
+        public PrivateKey getPrivateKey(String alias) {
+            return privateKey;
+        }
+    }
+
+
+    // use any free port by default
+    volatile int serverPort = 0;
+
+    volatile Exception serverException = null;
+    volatile Exception clientException = null;
+
+    public static void main(String[] args) throws Exception {
+        if (debug)
+            System.setProperty("javax.net.debug", "all");
+
+        /*
+         * Get the customized arguments.
+         */
+        parseArguments(args);
+
+        /*
+         * Start the tests.
+         */
+        new TrustTrustedCert();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    TrustTrustedCert() throws Exception {
+        try {
+            if (separateServerThread) {
+                startServer(true);
+                startClient(false);
+            } else {
+                startClient(true);
+                startServer(false);
+            }
+        } catch (Exception e) {
+            // swallow for now.  Show later
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            serverThread.join();
+        } else {
+            clientThread.join();
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         * Which side threw the error?
+         */
+        Exception local;
+        Exception remote;
+        String whichRemote;
+
+        if (separateServerThread) {
+            remote = serverException;
+            local = clientException;
+            whichRemote = "server";
+        } else {
+            remote = clientException;
+            local = serverException;
+            whichRemote = "client";
+        }
+
+        /*
+         * If both failed, return the curthread's exception, but also
+         * print the remote side Exception
+         */
+        if ((local != null) && (remote != null)) {
+            System.out.println(whichRemote + " also threw:");
+            remote.printStackTrace();
+            System.out.println();
+            throw local;
+        }
+
+        if (remote != null) {
+            throw remote;
+        }
+
+        if (local != null) {
+            throw local;
+        }
+    }
+
+    void startServer(boolean newThread) throws Exception {
+        if (newThread) {
+            serverThread = new Thread() {
+                public void run() {
+                    try {
+                        doServerSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our server thread just died.
+                         *
+                         * Release the client, if not active already...
+                         */
+                        System.err.println("Server died...");
+                        serverReady = true;
+                        serverException = e;
+                    }
+                }
+            };
+            serverThread.start();
+        } else {
+            try {
+                doServerSide();
+            } catch (Exception e) {
+                serverException = e;
+            } finally {
+                serverReady = true;
+            }
+        }
+    }
+
+    void startClient(boolean newThread) throws Exception {
+        if (newThread) {
+            clientThread = new Thread() {
+                public void run() {
+                    try {
+                        doClientSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our client thread just died.
+                         */
+                        System.err.println("Client died...");
+                        clientException = e;
+                    }
+                }
+            };
+            clientThread.start();
+        } else {
+            try {
+                doClientSide();
+            } catch (Exception e) {
+                clientException = e;
+            }
+        }
+    }
+}