changeset 5781:d828938945af

Merge
author lana
date Tue, 03 Jul 2012 20:58:02 -0700
parents 8a284872ee2d (current diff) 3ae91286f313 (diff)
children 9957b4759354
files
diffstat 28 files changed, 1090 insertions(+), 238 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/jndi/cosnaming/CNCtx.java	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/share/classes/com/sun/jndi/cosnaming/CNCtx.java	Tue Jul 03 20:58:02 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
@@ -58,8 +58,22 @@
 
     private final static boolean debug = false;
 
+    /*
+     * Implement one shared ORB among all CNCtx.  However, there is a public constructor
+     * accepting an ORB, so we need the option of using a given ORB.
+     */
+    private static ORB _defaultOrb;
     ORB _orb;                   // used by ExceptionMapper and RMI/IIOP factory
     public NamingContext _nc;   // public for accessing underlying NamingContext
+
+    private synchronized static ORB getDefaultOrb() {
+        if (_defaultOrb == null) {
+            _defaultOrb = CorbaUtils.getOrb(null, -1,
+               new Hashtable<String, java.lang.Object>());
+        }
+        return _defaultOrb;
+    }
+
     private NameComponent[] _name = null;
 
     Hashtable<String, java.lang.Object> _env; // used by ExceptionMapper
@@ -114,8 +128,9 @@
         // rest is the INS name
         // Return the parsed form to prevent subsequent lookup
         // from parsing the string as a composite name
-        // The caller should be aware that a toString() of the name
-        // will yield its INS syntax, rather than a composite syntax
+        // The caller should be aware that a toString() of the name,
+        // which came from the environment will yield its INS syntax,
+        // rather than a composite syntax
         return new ResolveResult(ctx, parser.parse(rest));
     }
 
@@ -135,10 +150,10 @@
             if (orb == null || nctx == null)
                 throw new ConfigurationException(
                     "Must supply ORB or NamingContext");
-            _orb = orb;
-            orbTracker = tracker;
-            if (orbTracker != null) {
-                orbTracker.incRefCount();
+            if (orb != null) {
+                _orb = orb;
+            } else {
+                _orb = getDefaultOrb();
             }
             _nc = nctx;
             _env = env;
@@ -212,10 +227,13 @@
         org.omg.CORBA.ORB inOrb = null;
         String ncIor = null;
 
-        if (env != null) {
+        if (inOrb == null && env != null) {
             inOrb = (org.omg.CORBA.ORB) env.get("java.naming.corba.orb");
         }
 
+        if (inOrb == null)
+            inOrb = getDefaultOrb(); // will create a default ORB if none exists
+
         // Extract PROVIDER_URL from environment
         String provUrl = null;
         if (env != null) {
@@ -226,13 +244,6 @@
             // Initialize the root naming context by using the IOR supplied
             // in the PROVIDER_URL
             ncIor = getStringifiedIor(provUrl);
-
-            if (inOrb == null) {
-
-                // no ORB instance specified; create one using env and defaults
-                inOrb = CorbaUtils.getOrb(null, -1, env);
-                orbTracker = new OrbReuseTracker(inOrb);
-            }
             setOrbAndRootContext(inOrb, ncIor);
         } else if (provUrl != null) {
             // Initialize the root naming context by using the URL supplied
@@ -258,14 +269,8 @@
             }
         } else {
             // No PROVIDER_URL supplied; initialize using defaults
-            if (inOrb == null) {
-
-                // No ORB instance specified; create one using env and defaults
-                inOrb = CorbaUtils.getOrb(null, -1, env);
-                orbTracker = new OrbReuseTracker(inOrb);
-                if (debug) {
-                    System.err.println("Getting default ORB: " + inOrb + env);
-                }
+            if (debug) {
+                System.err.println("Getting default ORB: " + inOrb + env);
             }
             setOrbAndRootContext(inOrb, (String)null);
         }
@@ -286,6 +291,10 @@
      */
     private String initUsingIiopUrl(ORB defOrb, String url, Hashtable<?,?> env)
         throws NamingException {
+
+        if (defOrb == null)
+            defOrb = getDefaultOrb();
+
         try {
             IiopUrl parsedUrl = new IiopUrl(url);
 
@@ -294,19 +303,17 @@
             for (IiopUrl.Address addr : parsedUrl.getAddresses()) {
 
                 try {
-                    if (defOrb != null) {
-                        try {
-                            String tmpUrl = "corbaloc:iiop:" + addr.host
-                                + ":" + addr.port + "/NameService";
-                            if (debug) {
-                                System.err.println("Using url: " + tmpUrl);
-                            }
-                            org.omg.CORBA.Object rootCtx =
-                                defOrb.string_to_object(tmpUrl);
-                            setOrbAndRootContext(defOrb, rootCtx);
-                            return parsedUrl.getStringName();
-                        } catch (Exception e) {} // keep going
-                    }
+                    try {
+                        String tmpUrl = "corbaloc:iiop:" + addr.host
+                            + ":" + addr.port + "/NameService";
+                        if (debug) {
+                            System.err.println("Using url: " + tmpUrl);
+                        }
+                        org.omg.CORBA.Object rootCtx =
+                            defOrb.string_to_object(tmpUrl);
+                        setOrbAndRootContext(defOrb, rootCtx);
+                        return parsedUrl.getStringName();
+                    } catch (Exception e) {} // keep going
 
                     // Get ORB
                     if (debug) {
@@ -314,12 +321,8 @@
                             + " and port " + addr.port);
                     }
 
-                    // Get ORB
-                    ORB orb = CorbaUtils.getOrb(addr.host, addr.port, env);
-                    orbTracker = new OrbReuseTracker(orb);
-
                     // Assign to fields
-                    setOrbAndRootContext(orb, (String)null);
+                    setOrbAndRootContext(defOrb, (String)null);
                     return parsedUrl.getStringName();
 
                 } catch (NamingException ne) {
@@ -341,18 +344,16 @@
      */
     private String initUsingCorbanameUrl(ORB orb, String url, Hashtable<?,?> env)
         throws NamingException {
+
+        if (orb == null)
+                orb = getDefaultOrb();
+
         try {
             CorbanameUrl parsedUrl = new CorbanameUrl(url);
 
             String corbaloc = parsedUrl.getLocation();
             String cosName = parsedUrl.getStringName();
 
-            if (orb == null) {
-
-                // No ORB instance specified; create one using env and defaults
-                orb = CorbaUtils.getOrb(null, -1, env);
-                orbTracker = new OrbReuseTracker(orb);
-            }
             setOrbAndRootContext(orb, corbaloc);
 
             return parsedUrl.getStringName();
@@ -1117,9 +1118,6 @@
     }
 
     synchronized public void incEnumCount() {
-        if (orbTracker == null) {
-            return;
-        }
         enumCount++;
         if (debug) {
             System.out.println("incEnumCount, new count:" + enumCount);
@@ -1128,9 +1126,6 @@
 
     synchronized public void decEnumCount()
             throws NamingException {
-        if (orbTracker == null) {
-            return;
-        }
         enumCount--;
         if (debug) {
             System.out.println("decEnumCount, new count:" + enumCount +
@@ -1142,14 +1137,15 @@
     }
 
     synchronized public void close() throws NamingException {
-        if (orbTracker == null) {
-            return;
-        }
+
         if (enumCount > 0) {
             isCloseCalled = true;
             return;
         }
-        orbTracker.decRefCount();
+
+        // Never destroy an orb in CNCtx.
+        // The orb we have is either the shared/default orb, or one passed in to a constructor
+        // from elsewhere, so that orb is somebody else's reponsibility.
     }
 
     protected void finalize() {
--- a/src/share/classes/com/sun/jndi/ldap/Connection.java	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/share/classes/com/sun/jndi/ldap/Connection.java	Tue Jul 03 20:58:02 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
@@ -680,9 +680,11 @@
                         ldr = ldr.next;
                     }
                 }
-                parent.processConnectionClosure();
             }
         }
+        if (nparent) {
+            parent.processConnectionClosure();
+        }
     }
 
 
--- a/src/share/classes/com/sun/jndi/ldap/LdapClient.java	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/share/classes/com/sun/jndi/ldap/LdapClient.java	Tue Jul 03 20:58:02 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
@@ -488,14 +488,16 @@
      */
     void processConnectionClosure() {
         // Notify listeners
-        if (unsolicited.size() > 0) {
-            String msg;
-            if (conn != null) {
-                msg = conn.host + ":" + conn.port + " connection closed";
-            } else {
-                msg = "Connection closed";
+        synchronized (unsolicited) {
+            if (unsolicited.size() > 0) {
+                String msg;
+                if (conn != null) {
+                    msg = conn.host + ":" + conn.port + " connection closed";
+                } else {
+                    msg = "Connection closed";
+                }
+                notifyUnsolicited(new CommunicationException(msg));
             }
-            notifyUnsolicited(new CommunicationException(msg));
         }
 
         // Remove from pool
--- a/src/share/classes/java/lang/Process.java	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/share/classes/java/lang/Process.java	Tue Jul 03 20:58:02 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2012, 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
@@ -26,6 +26,7 @@
 package java.lang;
 
 import java.io.*;
+import java.util.concurrent.TimeUnit;
 
 /**
  * The {@link ProcessBuilder#start()} and
@@ -91,7 +92,7 @@
      * @return the output stream connected to the normal input of the
      *         subprocess
      */
-    abstract public OutputStream getOutputStream();
+    public abstract OutputStream getOutputStream();
 
     /**
      * Returns the input stream connected to the normal output of the
@@ -117,7 +118,7 @@
      * @return the input stream connected to the normal output of the
      *         subprocess
      */
-    abstract public InputStream getInputStream();
+    public abstract InputStream getInputStream();
 
     /**
      * Returns the input stream connected to the error output of the
@@ -138,7 +139,7 @@
      * @return the input stream connected to the error output of
      *         the subprocess
      */
-    abstract public InputStream getErrorStream();
+    public abstract InputStream getErrorStream();
 
     /**
      * Causes the current thread to wait, if necessary, until the
@@ -156,7 +157,51 @@
      *         thread while it is waiting, then the wait is ended and
      *         an {@link InterruptedException} is thrown.
      */
-    abstract public int waitFor() throws InterruptedException;
+    public abstract int waitFor() throws InterruptedException;
+
+    /**
+     * Causes the current thread to wait, if necessary, until the
+     * subprocess represented by this {@code Process} object has
+     * terminated, or the specified waiting time elapses.
+     *
+     * <p>If the subprocess has already terminated then this method returns
+     * immediately with the value {@code true}.  If the process has not
+     * terminated and the timeout value is less than, or equal to, zero, then
+     * this method returns immediately with the value {@code false}.
+     *
+     * <p>The default implementation of this methods polls the {@code exitValue}
+     * to check if the process has terminated. Concrete implementations of this
+     * class are strongly encouraged to override this method with a more
+     * efficient implementation.
+     *
+     * @param timeout the maximum time to wait
+     * @param unit the time unit of the {@code timeout} argument
+     * @return {@code true} if the subprocess has exited and {@code false} if
+     *         the waiting time elapsed before the subprocess has exited.
+     * @throws InterruptedException if the current thread is interrupted
+     *         while waiting.
+     * @throws NullPointerException if unit is null
+     * @since 1.8
+     */
+    public boolean waitFor(long timeout, TimeUnit unit)
+        throws InterruptedException
+    {
+        long startTime = System.nanoTime();
+        long rem = unit.toNanos(timeout);
+
+        do {
+            try {
+                exitValue();
+                return true;
+            } catch(IllegalThreadStateException ex) {
+                if (rem > 0)
+                    Thread.sleep(
+                        Math.min(TimeUnit.NANOSECONDS.toMillis(rem) + 1, 100));
+            }
+            rem = unit.toNanos(timeout) - (System.nanoTime() - startTime);
+        } while (rem > 0);
+        return false;
+    }
 
     /**
      * Returns the exit value for the subprocess.
@@ -167,11 +212,54 @@
      * @throws IllegalThreadStateException if the subprocess represented
      *         by this {@code Process} object has not yet terminated
      */
-    abstract public int exitValue();
+    public abstract int exitValue();
+
+    /**
+     * Kills the subprocess. Whether the subprocess represented by this
+     * {@code Process} object is forcibly terminated or not is
+     * implementation dependent.
+     */
+    public abstract void destroy();
 
     /**
      * Kills the subprocess. The subprocess represented by this
      * {@code Process} object is forcibly terminated.
+     *
+     * <p>The default implementation of this method invokes {@link #destroy}
+     * and so may not forcibly terminate the process. Concrete implementations
+     * of this class are strongly encouraged to override this method with a
+     * compliant implementation.  Invoking this method on {@code Process}
+     * objects returned by {@link ProcessBuilder#start} and
+     * {@link Runtime#exec} will forcibly terminate the process.
+     *
+     * <p>Note: The subprocess may not terminate immediately.
+     * i.e. {@code isAlive()} may return true for a brief period
+     * after {@code destroyForcibly()} is called. This method
+     * may be chained to {@code waitFor()} if needed.
+     *
+     * @return the {@code Process} object representing the
+     *         subprocess to be forcibly destroyed.
+     * @since 1.8
      */
-    abstract public void destroy();
+    public Process destroyForcibly() {
+        destroy();
+        return this;
+    }
+
+    /**
+     * Tests whether the subprocess represented by this {@code Process} is
+     * alive.
+     *
+     * @return {@code true} if the subprocess represented by this
+     *         {@code Process} object has not yet terminated.
+     * @since 1.8
+     */
+    public boolean isAlive() {
+        try {
+            exitValue();
+            return false;
+        } catch(IllegalThreadStateException e) {
+            return true;
+        }
+    }
 }
--- a/src/share/classes/java/lang/String.java	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/share/classes/java/lang/String.java	Tue Jul 03 20:58:02 2012 -0700
@@ -1921,17 +1921,17 @@
      * <blockquote><pre>
      * str.substring(begin,&nbsp;end)</pre></blockquote>
      *
-     * This method is defined so that the <tt>String</tt> class can implement
+     * This method is defined so that the {@code String} class can implement
      * the {@link CharSequence} interface. </p>
      *
-     * @param      beginIndex   the begin index, inclusive.
-     * @param      endIndex     the end index, exclusive.
-     * @return     the specified subsequence.
+     * @param   beginIndex   the begin index, inclusive.
+     * @param   endIndex     the end index, exclusive.
+     * @return  the specified subsequence.
      *
      * @throws  IndexOutOfBoundsException
-     *          if <tt>beginIndex</tt> or <tt>endIndex</tt> are negative,
-     *          if <tt>endIndex</tt> is greater than <tt>length()</tt>,
-     *          or if <tt>beginIndex</tt> is greater than <tt>startIndex</tt>
+     *          if {@code beginIndex} or {@code endIndex} is negative,
+     *          if {@code endIndex} is greater than {@code length()},
+     *          or if {@code beginIndex} is greater than {@code endIndex}
      *
      * @since 1.4
      * @spec JSR-51
--- a/src/share/classes/java/lang/StringBuffer.java	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/share/classes/java/lang/StringBuffer.java	Tue Jul 03 20:58:02 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2012, 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
@@ -39,29 +39,38 @@
  * that is consistent with the order of the method calls made by each of
  * the individual threads involved.
  * <p>
- * The principal operations on a <code>StringBuffer</code> are the
- * <code>append</code> and <code>insert</code> methods, which are
+ * The principal operations on a {@code StringBuffer} are the
+ * {@code append} and {@code insert} methods, which are
  * overloaded so as to accept data of any type. Each effectively
  * converts a given datum to a string and then appends or inserts the
  * characters of that string to the string buffer. The
- * <code>append</code> method always adds these characters at the end
- * of the buffer; the <code>insert</code> method adds the characters at
+ * {@code append} method always adds these characters at the end
+ * of the buffer; the {@code insert} method adds the characters at
  * a specified point.
  * <p>
- * For example, if <code>z</code> refers to a string buffer object
- * whose current contents are "<code>start</code>", then
- * the method call <code>z.append("le")</code> would cause the string
- * buffer to contain "<code>startle</code>", whereas
- * <code>z.insert(4, "le")</code> would alter the string buffer to
- * contain "<code>starlet</code>".
+ * For example, if {@code z} refers to a string buffer object
+ * whose current contents are {@code "start"}, then
+ * the method call {@code z.append("le")} would cause the string
+ * buffer to contain {@code "startle"}, whereas
+ * {@code z.insert(4, "le")} would alter the string buffer to
+ * contain {@code "starlet"}.
  * <p>
- * In general, if sb refers to an instance of a <code>StringBuffer</code>,
- * then <code>sb.append(x)</code> has the same effect as
- * <code>sb.insert(sb.length(),&nbsp;x)</code>.
+ * In general, if sb refers to an instance of a {@code StringBuffer},
+ * then {@code sb.append(x)} has the same effect as
+ * {@code sb.insert(sb.length(),&nbsp;x)}.
  * <p>
  * Whenever an operation occurs involving a source sequence (such as
- * appending or inserting from a source sequence) this class synchronizes
+ * appending or inserting from a source sequence), this class synchronizes
  * only on the string buffer performing the operation, not on the source.
+ * Note that while {@code StringBuffer} is designed to be safe to use
+ * concurrently from multiple threads, if the constructor or the
+ * {@code append} or {@code insert} operation is passed a source sequence
+ * that is shared across threads, the calling code must ensure
+ * that the operation has a consistent and unchanging view of the source
+ * sequence for the duration of the operation.
+ * This could be satisfied by the caller holding a lock during the
+ * operation's call, by using an immutable source sequence, or by not
+ * sharing the source sequence across threads.
  * <p>
  * Every string buffer has a capacity. As long as the length of the
  * character sequence contained in the string buffer does not exceed
@@ -101,8 +110,8 @@
      * the specified initial capacity.
      *
      * @param      capacity  the initial capacity.
-     * @exception  NegativeArraySizeException  if the <code>capacity</code>
-     *               argument is less than <code>0</code>.
+     * @exception  NegativeArraySizeException  if the {@code capacity}
+     *               argument is less than {@code 0}.
      */
     public StringBuffer(int capacity) {
         super(capacity);
@@ -111,10 +120,10 @@
     /**
      * Constructs a string buffer initialized to the contents of the
      * specified string. The initial capacity of the string buffer is
-     * <code>16</code> plus the length of the string argument.
+     * {@code 16} plus the length of the string argument.
      *
      * @param   str   the initial contents of the buffer.
-     * @exception NullPointerException if <code>str</code> is <code>null</code>
+     * @exception NullPointerException if {@code str} is {@code null}
      */
     public StringBuffer(String str) {
         super(str.length() + 16);
@@ -123,16 +132,16 @@
 
     /**
      * Constructs a string buffer that contains the same characters
-     * as the specified <code>CharSequence</code>. The initial capacity of
-     * the string buffer is <code>16</code> plus the length of the
-     * <code>CharSequence</code> argument.
+     * as the specified {@code CharSequence}. The initial capacity of
+     * the string buffer is {@code 16} plus the length of the
+     * {@code CharSequence} argument.
      * <p>
-     * If the length of the specified <code>CharSequence</code> is
+     * If the length of the specified {@code CharSequence} is
      * less than or equal to zero, then an empty buffer of capacity
-     * <code>16</code> is returned.
+     * {@code 16} is returned.
      *
      * @param      seq   the sequence to copy.
-     * @exception NullPointerException if <code>seq</code> is <code>null</code>
+     * @exception NullPointerException if {@code seq} is {@code null}
      * @since 1.5
      */
     public StringBuffer(CharSequence seq) {
@@ -253,10 +262,10 @@
      * the new character sequence is equal to the character at index <i>k</i>
      * in the old character sequence, if <i>k</i> is less than <i>n</i>;
      * otherwise, it is equal to the character at index <i>k-n</i> in the
-     * argument <code>sb</code>.
+     * argument {@code sb}.
      * <p>
-     * This method synchronizes on <code>this</code> (the destination)
-     * object but does not synchronize on the source (<code>sb</code>).
+     * This method synchronizes on {@code this}, the destination
+     * object, but does not synchronize on the source ({@code sb}).
      *
      * @param   sb   the <tt>StringBuffer</tt> to append.
      * @return  a reference to this object.
@@ -269,23 +278,23 @@
 
 
     /**
-     * Appends the specified <code>CharSequence</code> to this
+     * Appends the specified {@code CharSequence} to this
      * sequence.
      * <p>
-     * The characters of the <code>CharSequence</code> argument are appended,
+     * The characters of the {@code CharSequence} argument are appended,
      * in order, increasing the length of this sequence by the length of the
      * argument.
      *
      * <p>The result of this method is exactly the same as if it were an
      * invocation of this.append(s, 0, s.length());
      *
-     * <p>This method synchronizes on this (the destination)
-     * object but does not synchronize on the source (<code>s</code>).
+     * <p>This method synchronizes on {@code this}, the destination
+     * object, but does not synchronize on the source ({@code s}).
      *
-     * <p>If <code>s</code> is <code>null</code>, then the four characters
-     * <code>"null"</code> are appended.
+     * <p>If {@code s} is {@code null}, then the four characters
+     * {@code "null"} are appended.
      *
-     * @param   s the <code>CharSequence</code> to append.
+     * @param   s the {@code CharSequence} to append.
      * @return  a reference to this object.
      * @since 1.5
      */
--- a/src/share/classes/java/util/InvalidPropertiesFormatException.java	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/share/classes/java/util/InvalidPropertiesFormatException.java	Tue Jul 03 20:58:02 2012 -0700
@@ -44,6 +44,9 @@
  */
 
 public class InvalidPropertiesFormatException extends IOException {
+
+    private static final long serialVersionUID = 7763056076009360219L;
+
     /**
      * Constructs an InvalidPropertiesFormatException with the specified
      * cause.
--- a/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java	Tue Jul 03 20:58:02 2012 -0700
@@ -35,7 +35,8 @@
 
 package java.util.concurrent;
 
-import java.util.concurrent.locks.*;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.*;
 
 /**
@@ -111,7 +112,7 @@
      * java.util.PriorityQueue operations within a lock, as was done
      * in a previous version of this class. To maintain
      * interoperability, a plain PriorityQueue is still used during
-     * serialization, which maintains compatibility at the espense of
+     * serialization, which maintains compatibility at the expense of
      * transiently doubling overhead.
      */
 
@@ -308,14 +309,13 @@
     /**
      * Mechanics for poll().  Call only while holding lock.
      */
-    private E extract() {
-        E result;
+    private E dequeue() {
         int n = size - 1;
         if (n < 0)
-            result = null;
+            return null;
         else {
             Object[] array = queue;
-            result = (E) array[0];
+            E result = (E) array[0];
             E x = (E) array[n];
             array[n] = null;
             Comparator<? super E> cmp = comparator;
@@ -324,8 +324,8 @@
             else
                 siftDownUsingComparator(0, x, array, n, cmp);
             size = n;
+            return result;
         }
-        return result;
     }
 
     /**
@@ -382,39 +382,43 @@
      */
     private static <T> void siftDownComparable(int k, T x, Object[] array,
                                                int n) {
-        Comparable<? super T> key = (Comparable<? super T>)x;
-        int half = n >>> 1;           // loop while a non-leaf
-        while (k < half) {
-            int child = (k << 1) + 1; // assume left child is least
-            Object c = array[child];
-            int right = child + 1;
-            if (right < n &&
-                ((Comparable<? super T>) c).compareTo((T) array[right]) > 0)
-                c = array[child = right];
-            if (key.compareTo((T) c) <= 0)
-                break;
-            array[k] = c;
-            k = child;
+        if (n > 0) {
+            Comparable<? super T> key = (Comparable<? super T>)x;
+            int half = n >>> 1;           // loop while a non-leaf
+            while (k < half) {
+                int child = (k << 1) + 1; // assume left child is least
+                Object c = array[child];
+                int right = child + 1;
+                if (right < n &&
+                    ((Comparable<? super T>) c).compareTo((T) array[right]) > 0)
+                    c = array[child = right];
+                if (key.compareTo((T) c) <= 0)
+                    break;
+                array[k] = c;
+                k = child;
+            }
+            array[k] = key;
         }
-        array[k] = key;
     }
 
     private static <T> void siftDownUsingComparator(int k, T x, Object[] array,
                                                     int n,
                                                     Comparator<? super T> cmp) {
-        int half = n >>> 1;
-        while (k < half) {
-            int child = (k << 1) + 1;
-            Object c = array[child];
-            int right = child + 1;
-            if (right < n && cmp.compare((T) c, (T) array[right]) > 0)
-                c = array[child = right];
-            if (cmp.compare(x, (T) c) <= 0)
-                break;
-            array[k] = c;
-            k = child;
+        if (n > 0) {
+            int half = n >>> 1;
+            while (k < half) {
+                int child = (k << 1) + 1;
+                Object c = array[child];
+                int right = child + 1;
+                if (right < n && cmp.compare((T) c, (T) array[right]) > 0)
+                    c = array[child = right];
+                if (cmp.compare(x, (T) c) <= 0)
+                    break;
+                array[k] = c;
+                k = child;
+            }
+            array[k] = x;
         }
-        array[k] = x;
     }
 
     /**
@@ -520,13 +524,11 @@
     public E poll() {
         final ReentrantLock lock = this.lock;
         lock.lock();
-        E result;
         try {
-            result = extract();
+            return dequeue();
         } finally {
             lock.unlock();
         }
-        return result;
     }
 
     public E take() throws InterruptedException {
@@ -534,7 +536,7 @@
         lock.lockInterruptibly();
         E result;
         try {
-            while ( (result = extract()) == null)
+            while ( (result = dequeue()) == null)
                 notEmpty.await();
         } finally {
             lock.unlock();
@@ -548,7 +550,7 @@
         lock.lockInterruptibly();
         E result;
         try {
-            while ( (result = extract()) == null && nanos > 0)
+            while ( (result = dequeue()) == null && nanos > 0)
                 nanos = notEmpty.awaitNanos(nanos);
         } finally {
             lock.unlock();
@@ -559,13 +561,11 @@
     public E peek() {
         final ReentrantLock lock = this.lock;
         lock.lock();
-        E result;
         try {
-            result = size > 0 ? (E) queue[0] : null;
+            return (size == 0) ? null : (E) queue[0];
         } finally {
             lock.unlock();
         }
-        return result;
     }
 
     /**
@@ -649,32 +649,28 @@
      * @return {@code true} if this queue changed as a result of the call
      */
     public boolean remove(Object o) {
-        boolean removed = false;
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             int i = indexOf(o);
-            if (i != -1) {
-                removeAt(i);
-                removed = true;
-            }
+            if (i == -1)
+                return false;
+            removeAt(i);
+            return true;
         } finally {
             lock.unlock();
         }
-        return removed;
     }
 
-
     /**
      * Identity-based version for use in Itr.remove
      */
-    private void removeEQ(Object o) {
+    void removeEQ(Object o) {
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             Object[] array = queue;
-            int n = size;
-            for (int i = 0; i < n; i++) {
+            for (int i = 0, n = size; i < n; i++) {
                 if (o == array[i]) {
                     removeAt(i);
                     break;
@@ -694,15 +690,13 @@
      * @return {@code true} if this queue contains the specified element
      */
     public boolean contains(Object o) {
-        int index;
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            index = indexOf(o);
+            return indexOf(o) != -1;
         } finally {
             lock.unlock();
         }
-        return index != -1;
     }
 
     /**
@@ -728,7 +722,6 @@
         }
     }
 
-
     public String toString() {
         final ReentrantLock lock = this.lock;
         lock.lock();
@@ -739,7 +732,7 @@
             StringBuilder sb = new StringBuilder();
             sb.append('[');
             for (int i = 0; i < n; ++i) {
-                E e = (E)queue[i];
+                Object e = queue[i];
                 sb.append(e == this ? "(this Collection)" : e);
                 if (i != n - 1)
                     sb.append(',').append(' ');
@@ -757,23 +750,7 @@
      * @throws IllegalArgumentException      {@inheritDoc}
      */
     public int drainTo(Collection<? super E> c) {
-        if (c == null)
-            throw new NullPointerException();
-        if (c == this)
-            throw new IllegalArgumentException();
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            int n = 0;
-            E e;
-            while ( (e = extract()) != null) {
-                c.add(e);
-                ++n;
-            }
-            return n;
-        } finally {
-            lock.unlock();
-        }
+        return drainTo(c, Integer.MAX_VALUE);
     }
 
     /**
@@ -792,11 +769,10 @@
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            int n = 0;
-            E e;
-            while (n < maxElements && (e = extract()) != null) {
-                c.add(e);
-                ++n;
+            int n = Math.min(size, maxElements);
+            for (int i = 0; i < n; i++) {
+                c.add((E) queue[0]); // In this order, in case add() throws.
+                dequeue();
             }
             return n;
         } finally {
@@ -844,8 +820,7 @@
      * The following code can be used to dump the queue into a newly
      * allocated array of {@code String}:
      *
-     * <pre>
-     *     String[] y = x.toArray(new String[0]);</pre>
+     *  <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
      *
      * Note that {@code toArray(new Object[0])} is identical in function to
      * {@code toArray()}.
@@ -898,7 +873,7 @@
      */
     final class Itr implements Iterator<E> {
         final Object[] array; // Array of all elements
-        int cursor;           // index of next element to return;
+        int cursor;           // index of next element to return
         int lastRet;          // index of last element, or -1 if no such
 
         Itr(Object[] array) {
@@ -926,17 +901,18 @@
     }
 
     /**
-     * Saves the state to a stream (that is, serializes it).  For
-     * compatibility with previous version of this class,
-     * elements are first copied to a java.util.PriorityQueue,
-     * which is then serialized.
+     * Saves this queue to a stream (that is, serializes it).
+     *
+     * For compatibility with previous version of this class, elements
+     * are first copied to a java.util.PriorityQueue, which is then
+     * serialized.
      */
     private void writeObject(java.io.ObjectOutputStream s)
         throws java.io.IOException {
         lock.lock();
         try {
-            int n = size; // avoid zero capacity argument
-            q = new PriorityQueue<E>(n == 0 ? 1 : n, comparator);
+            // avoid zero capacity argument
+            q = new PriorityQueue<E>(Math.max(size, 1), comparator);
             q.addAll(this);
             s.defaultWriteObject();
         } finally {
@@ -946,10 +922,7 @@
     }
 
     /**
-     * Reconstitutes the {@code PriorityBlockingQueue} instance from a stream
-     * (that is, deserializes it).
-     *
-     * @param s the stream
+     * Reconstitutes this queue from a stream (that is, deserializes it).
      */
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
--- a/src/share/classes/java/util/regex/Pattern.java	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/share/classes/java/util/regex/Pattern.java	Tue Jul 03 20:58:02 2012 -0700
@@ -2026,6 +2026,7 @@
         }
     }
 
+    @SuppressWarnings("fallthrough")
     /**
      * Parsing of sequences between alternations.
      */
@@ -2140,6 +2141,7 @@
         return head;
     }
 
+    @SuppressWarnings("fallthrough")
     /**
      * Parse and add a new Single or Slice.
      */
@@ -2978,6 +2980,7 @@
         return head;
     }
 
+    @SuppressWarnings("fallthrough")
     /**
      * Parses inlined match flags and set them appropriately.
      */
@@ -3019,6 +3022,7 @@
         }
     }
 
+    @SuppressWarnings("fallthrough")
     /**
      * Parses the second part of inlined match flags and turns off
      * flags appropriately.
--- a/src/share/classes/java/util/zip/GZIPInputStream.java	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/share/classes/java/util/zip/GZIPInputStream.java	Tue Jul 03 20:58:02 2012 -0700
@@ -252,7 +252,7 @@
      */
     private int readUShort(InputStream in) throws IOException {
         int b = readUByte(in);
-        return ((int)readUByte(in) << 8) | b;
+        return (readUByte(in) << 8) | b;
     }
 
     /*
--- a/src/share/classes/sun/tools/jar/Main.java	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/share/classes/sun/tools/jar/Main.java	Tue Jul 03 20:58:02 2012 -0700
@@ -137,7 +137,7 @@
         File dir = file.getParentFile();
         if (dir == null)
             dir = new File(".");
-        return Files.createTempFile(dir.toPath(), "jartmp", null).toFile();
+        return File.createTempFile("jartmp", null, dir);
     }
 
     private boolean ok;
--- a/src/share/classes/sun/tools/native2ascii/Main.java	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/share/classes/sun/tools/native2ascii/Main.java	Tue Jul 03 20:58:02 2012 -0700
@@ -241,7 +241,9 @@
             if (tempDir == null)
                 tempDir = new File(System.getProperty("user.dir"));
 
-            tempFile = Files.createTempFile(tempDir.toPath(), "_N2A", ".TMP").toFile();
+            tempFile = File.createTempFile("_N2A",
+                                           ".TMP",
+                                            tempDir);
             tempFile.deleteOnExit();
 
             try {
@@ -291,7 +293,9 @@
             File tempDir = f.getParentFile();
             if (tempDir == null)
                 tempDir = new File(System.getProperty("user.dir"));
-            tempFile =  Files.createTempFile(tempDir.toPath(), "_N2A", ".TMP").toFile();
+            tempFile =  File.createTempFile("_N2A",
+                                            ".TMP",
+                                            tempDir);
             tempFile.deleteOnExit();
 
             try {
--- a/src/share/lib/security/java.security	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/share/lib/security/java.security	Tue Jul 03 20:58:02 2012 -0700
@@ -1,6 +1,28 @@
 #
 # This is the "master security properties file".
 #
+# An alternate java.security properties file may be specified
+# from the command line via the system property
+#
+#    -Djava.security.properties=<URL>
+#
+# This properties file appends to the master security properties file.
+# If both properties files specify values for the same key, the value
+# from the command-line properties file is selected, as it is the last
+# one loaded.
+#
+# Also, if you specify
+#
+#    -Djava.security.properties==<URL> (2 equals),
+#
+# then that properties file completely overrides the master security
+# properties file.
+#
+# To disable the ability to specify an additional properties file from
+# the command line, set the key security.overridePropertiesFile
+# to false in the master security properties file. It is set to true
+# by default.
+
 # In this file, various security properties are set for use by
 # java.security classes. This is where users can statically register
 # Cryptography Package Providers ("providers" for short). The term
--- a/src/share/lib/security/java.security-macosx	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/share/lib/security/java.security-macosx	Tue Jul 03 20:58:02 2012 -0700
@@ -1,6 +1,28 @@
 #
 # This is the "master security properties file".
 #
+# An alternate java.security properties file may be specified
+# from the command line via the system property
+#
+#    -Djava.security.properties=<URL>
+#
+# This properties file appends to the master security properties file.
+# If both properties files specify values for the same key, the value
+# from the command-line properties file is selected, as it is the last
+# one loaded.
+#
+# Also, if you specify
+#
+#    -Djava.security.properties==<URL> (2 equals),
+#
+# then that properties file completely overrides the master security
+# properties file.
+#
+# To disable the ability to specify an additional properties file from
+# the command line, set the key security.overridePropertiesFile
+# to false in the master security properties file. It is set to true
+# by default.
+
 # In this file, various security properties are set for use by
 # java.security classes. This is where users can statically register
 # Cryptography Package Providers ("providers" for short). The term
--- a/src/share/lib/security/java.security-solaris	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/share/lib/security/java.security-solaris	Tue Jul 03 20:58:02 2012 -0700
@@ -1,6 +1,28 @@
 #
 # This is the "master security properties file".
 #
+# An alternate java.security properties file may be specified
+# from the command line via the system property
+#
+#    -Djava.security.properties=<URL>
+#
+# This properties file appends to the master security properties file.
+# If both properties files specify values for the same key, the value
+# from the command-line properties file is selected, as it is the last
+# one loaded.
+#
+# Also, if you specify
+#
+#    -Djava.security.properties==<URL> (2 equals),
+#
+# then that properties file completely overrides the master security
+# properties file.
+#
+# To disable the ability to specify an additional properties file from
+# the command line, set the key security.overridePropertiesFile
+# to false in the master security properties file. It is set to true
+# by default.
+
 # In this file, various security properties are set for use by
 # java.security classes. This is where users can statically register
 # Cryptography Package Providers ("providers" for short). The term
--- a/src/share/lib/security/java.security-windows	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/share/lib/security/java.security-windows	Tue Jul 03 20:58:02 2012 -0700
@@ -1,6 +1,28 @@
 #
 # This is the "master security properties file".
 #
+# An alternate java.security properties file may be specified
+# from the command line via the system property
+#
+#    -Djava.security.properties=<URL>
+#
+# This properties file appends to the master security properties file.
+# If both properties files specify values for the same key, the value
+# from the command-line properties file is selected, as it is the last
+# one loaded.
+#
+# Also, if you specify
+#
+#    -Djava.security.properties==<URL> (2 equals),
+#
+# then that properties file completely overrides the master security
+# properties file.
+#
+# To disable the ability to specify an additional properties file from
+# the command line, set the key security.overridePropertiesFile
+# to false in the master security properties file. It is set to true
+# by default.
+
 # In this file, various security properties are set for use by
 # java.security classes. This is where users can statically register
 # Cryptography Package Providers ("providers" for short). The term
--- a/src/solaris/classes/java/lang/UNIXProcess.java.bsd	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/solaris/classes/java/lang/UNIXProcess.java.bsd	Tue Jul 03 20:58:02 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2012, 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
@@ -38,6 +38,7 @@
 import java.util.concurrent.Executors;
 import java.util.concurrent.Executor;
 import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
 import java.security.AccessController;
 import static java.security.AccessController.doPrivileged;
 import java.security.PrivilegedAction;
@@ -211,6 +212,24 @@
         }
         return exitcode;
     }
+    
+    @Override
+    public synchronized boolean waitFor(long timeout, TimeUnit unit) 
+        throws InterruptedException 
+    {
+        if (hasExited) return true;
+        if (timeout <= 0) return false;	
+
+        long timeoutAsNanos = unit.toNanos(timeout);
+        long startTime = System.nanoTime();
+        long rem = timeoutAsNanos;
+
+        while (!hasExited && (rem > 0)) {
+            wait(Math.max(TimeUnit.NANOSECONDS.toMillis(rem), 1));
+            rem = timeoutAsNanos - (System.nanoTime() - startTime);
+        }
+        return hasExited;
+    }
 
     public synchronized int exitValue() {
         if (!hasExited) {
@@ -219,8 +238,8 @@
         return exitcode;
     }
 
-    private static native void destroyProcess(int pid);
-    public void destroy() {
+    private static native void destroyProcess(int pid, boolean force);
+    private void destroy(boolean force) {
         // There is a risk that pid will be recycled, causing us to
         // kill the wrong process!  So we only terminate processes
         // that appear to still be running.  Even with this check,
@@ -229,13 +248,28 @@
         // soon, so this is quite safe.
         synchronized (this) {
             if (!hasExited)
-                destroyProcess(pid);
+                destroyProcess(pid, force);
         }
         try { stdin.close();  } catch (IOException ignored) {}
         try { stdout.close(); } catch (IOException ignored) {}
         try { stderr.close(); } catch (IOException ignored) {}
     }
 
+    public void destroy() {
+        destroy(false);
+    }
+
+    @Override
+    public Process destroyForcibly() {
+        destroy(true);
+        return this;
+    }
+
+    @Override
+    public synchronized boolean isAlive() {
+        return !hasExited;
+    }
+
     /* This routine initializes JNI field offsets for the class */
     private static native void initIDs();
 
--- a/src/solaris/classes/java/lang/UNIXProcess.java.linux	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/solaris/classes/java/lang/UNIXProcess.java.linux	Tue Jul 03 20:58:02 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2012, 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
@@ -38,6 +38,7 @@
 import java.util.concurrent.Executors;
 import java.util.concurrent.Executor;
 import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
 import java.security.AccessController;
 import static java.security.AccessController.doPrivileged;
 import java.security.PrivilegedAction;
@@ -212,6 +213,24 @@
         return exitcode;
     }
 
+    @Override
+    public synchronized boolean waitFor(long timeout, TimeUnit unit)
+        throws InterruptedException
+    {
+        if (hasExited) return true;
+        if (timeout <= 0) return false;
+
+        long timeoutAsNanos = unit.toNanos(timeout);
+        long startTime = System.nanoTime();
+        long rem = timeoutAsNanos;
+
+        while (!hasExited && (rem > 0)) {
+            wait(Math.max(TimeUnit.NANOSECONDS.toMillis(rem), 1));
+            rem = timeoutAsNanos - (System.nanoTime() - startTime);
+        }
+        return hasExited;
+    }
+
     public synchronized int exitValue() {
         if (!hasExited) {
             throw new IllegalThreadStateException("process hasn't exited");
@@ -219,8 +238,8 @@
         return exitcode;
     }
 
-    private static native void destroyProcess(int pid);
-    public void destroy() {
+    private static native void destroyProcess(int pid, boolean force);
+    private void destroy(boolean force) {
         // There is a risk that pid will be recycled, causing us to
         // kill the wrong process!  So we only terminate processes
         // that appear to still be running.  Even with this check,
@@ -229,13 +248,28 @@
         // soon, so this is quite safe.
         synchronized (this) {
             if (!hasExited)
-                destroyProcess(pid);
+                destroyProcess(pid, force);
         }
         try { stdin.close();  } catch (IOException ignored) {}
         try { stdout.close(); } catch (IOException ignored) {}
         try { stderr.close(); } catch (IOException ignored) {}
     }
 
+    public void destroy() {
+        destroy(false);
+    }
+
+    @Override
+    public Process destroyForcibly() {
+        destroy(true);
+        return this;
+    }
+
+    @Override
+    public synchronized boolean isAlive() {
+        return !hasExited;
+    }
+
     /* This routine initializes JNI field offsets for the class */
     private static native void initIDs();
 
--- a/src/solaris/classes/java/lang/UNIXProcess.java.solaris	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/solaris/classes/java/lang/UNIXProcess.java.solaris	Tue Jul 03 20:58:02 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2012, 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
@@ -26,6 +26,7 @@
 package java.lang;
 
 import java.io.*;
+import java.util.concurrent.TimeUnit;
 
 /* java.lang.Process subclass in the UNIX environment.
  *
@@ -158,6 +159,24 @@
         return exitcode;
     }
 
+    @Override
+    public synchronized boolean waitFor(long timeout, TimeUnit unit)
+        throws InterruptedException
+    {
+        if (hasExited) return true;
+        if (timeout <= 0) return false;
+
+        long timeoutAsNanos = unit.toNanos(timeout);
+        long startTime = System.nanoTime();
+        long rem = timeoutAsNanos;
+
+        while (!hasExited && (rem > 0)) {
+            wait(Math.max(TimeUnit.NANOSECONDS.toMillis(rem), 1));
+            rem = timeoutAsNanos - (System.nanoTime() - startTime);
+        }
+        return hasExited;
+    }
+
     public synchronized int exitValue() {
         if (!hasExited) {
             throw new IllegalThreadStateException("process hasn't exited");
@@ -165,8 +184,8 @@
         return exitcode;
     }
 
-    private static native void destroyProcess(int pid);
-    public synchronized void destroy() {
+    private static native void destroyProcess(int pid, boolean force);
+    private synchronized void destroy(boolean force) {
         // There is a risk that pid will be recycled, causing us to
         // kill the wrong process!  So we only terminate processes
         // that appear to still be running.  Even with this check,
@@ -174,7 +193,7 @@
         // is very small, and OSes try hard to not recycle pids too
         // soon, so this is quite safe.
         if (!hasExited)
-            destroyProcess(pid);
+            destroyProcess(pid, force);
         try {
             stdin_stream.close();
             if (stdout_inner_stream != null)
@@ -187,6 +206,21 @@
         }
     }
 
+    public void destroy() {
+        destroy(false);
+    }
+
+    @Override
+    public Process destroyForcibly() {
+        destroy(true);
+        return this;
+    }
+
+    @Override
+    public synchronized boolean isAlive() {
+        return !hasExited;
+    }
+
     // A FileInputStream that supports the deferment of the actual close
     // operation until the last pending I/O operation on the stream has
     // finished.  This is required on Solaris because we must close the stdin
--- a/src/solaris/native/java/lang/UNIXProcess_md.c	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/solaris/native/java/lang/UNIXProcess_md.c	Tue Jul 03 20:58:02 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2012, 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
@@ -955,7 +955,11 @@
 }
 
 JNIEXPORT void JNICALL
-Java_java_lang_UNIXProcess_destroyProcess(JNIEnv *env, jobject junk, jint pid)
+Java_java_lang_UNIXProcess_destroyProcess(JNIEnv *env,
+                                          jobject junk,
+                                          jint pid,
+                                          jboolean force)
 {
-    kill(pid, SIGTERM);
+    int sig = (force == JNI_TRUE) ? SIGKILL : SIGTERM;
+    kill(pid, sig);
 }
--- a/src/windows/classes/java/lang/ProcessImpl.java	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/windows/classes/java/lang/ProcessImpl.java	Tue Jul 03 20:58:02 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2012, 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
@@ -37,6 +37,7 @@
 import java.lang.ProcessBuilder.Redirect;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.concurrent.TimeUnit;
 
 /* This class is for the exclusive use of ProcessBuilder.start() to
  * create new processes.
@@ -254,11 +255,44 @@
             throw new InterruptedException();
         return exitValue();
     }
+
     private static native void waitForInterruptibly(long handle);
 
+    @Override
+    public boolean waitFor(long timeout, TimeUnit unit)
+        throws InterruptedException
+    {
+        if (getExitCodeProcess(handle) != STILL_ACTIVE) return true;
+        if (timeout <= 0) return false;
+
+        long msTimeout = unit.toMillis(timeout);
+
+        waitForTimeoutInterruptibly(handle, msTimeout);
+        if (Thread.interrupted())
+            throw new InterruptedException();
+        return (getExitCodeProcess(handle) != STILL_ACTIVE);
+    }
+
+    private static native void waitForTimeoutInterruptibly(
+        long handle, long timeout);
+
     public void destroy() { terminateProcess(handle); }
+
+    @Override
+    public Process destroyForcibly() {
+        destroy();
+        return this;
+    }
+
     private static native void terminateProcess(long handle);
 
+    @Override
+    public boolean isAlive() {
+        return isProcessAlive(handle);
+    }
+
+    private static native boolean isProcessAlive(long handle);
+
     /**
      * Create a process using the win32 function CreateProcess.
      *
--- a/src/windows/native/java/lang/ProcessImpl_md.c	Tue Jul 03 20:56:24 2012 -0700
+++ b/src/windows/native/java/lang/ProcessImpl_md.c	Tue Jul 03 20:58:02 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
@@ -299,18 +299,45 @@
 
     if (WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events,
                                FALSE,    /* Wait for ANY event */
-                               INFINITE) /* Wait forever */
+                               INFINITE)  /* Wait forever */
         == WAIT_FAILED)
         win32Error(env, "WaitForMultipleObjects");
 }
 
 JNIEXPORT void JNICALL
+Java_java_lang_ProcessImpl_waitForTimeoutInterruptibly(JNIEnv *env,
+                                                       jclass ignored,
+                                                       jlong handle,
+                                                       jlong timeout)
+{
+    HANDLE events[2];
+    DWORD dwTimeout = (DWORD)timeout;
+    DWORD result;
+    events[0] = (HANDLE) handle;
+    events[1] = JVM_GetThreadInterruptEvent();
+    result = WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events,
+                                    FALSE,    /* Wait for ANY event */
+                                    dwTimeout);  /* Wait for dwTimeout */
+
+    if (result == WAIT_FAILED)
+        win32Error(env, "WaitForMultipleObjects");
+}
+
+JNIEXPORT void JNICALL
 Java_java_lang_ProcessImpl_terminateProcess(JNIEnv *env, jclass ignored, jlong handle)
 {
     TerminateProcess((HANDLE) handle, 1);
 }
 
 JNIEXPORT jboolean JNICALL
+Java_java_lang_ProcessImpl_isProcessAlive(JNIEnv *env, jclass ignored, jlong handle)
+{
+    DWORD dwExitStatus;
+    GetExitCodeProcess(handle, &dwExitStatus);
+    return dwExitStatus == STILL_ACTIVE;
+}
+
+JNIEXPORT jboolean JNICALL
 Java_java_lang_ProcessImpl_closeHandle(JNIEnv *env, jclass ignored, jlong handle)
 {
     return CloseHandle((HANDLE) handle);
--- a/test/java/lang/ProcessBuilder/Basic.java	Tue Jul 03 20:56:24 2012 -0700
+++ b/test/java/lang/ProcessBuilder/Basic.java	Tue Jul 03 20:58:02 2012 -0700
@@ -26,7 +26,7 @@
  * @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689
  *      5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313
  *      6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958
- *      4947220 7018606 7034570
+ *      4947220 7018606 7034570 4244896
  * @summary Basic tests for Process and Environment Variable code
  * @run main/othervm/timeout=300 Basic
  * @author Martin Buchholz
@@ -38,6 +38,7 @@
 import java.io.*;
 import java.util.*;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import java.security.*;
 import java.util.regex.Pattern;
 import java.util.regex.Matcher;
@@ -636,6 +637,44 @@
         static boolean is() { return is; }
     }
 
+    static class DelegatingProcess extends Process {
+        final Process p;
+
+        DelegatingProcess(Process p) {
+            this.p = p;
+        }
+
+        @Override
+        public void destroy() {
+            p.destroy();
+        }
+
+        @Override
+        public int exitValue() {
+            return p.exitValue();
+        }
+
+        @Override
+        public int waitFor() throws InterruptedException {
+            return p.waitFor();
+        }
+
+        @Override
+        public OutputStream getOutputStream() {
+            return p.getOutputStream();
+        }
+
+        @Override
+        public InputStream getInputStream() {
+            return p.getInputStream();
+        }
+
+        @Override
+        public InputStream getErrorStream() {
+            return p.getErrorStream();
+        }
+    }
+
     private static boolean matches(String str, String regex) {
         return Pattern.compile(regex).matcher(str).find();
     }
@@ -2090,6 +2129,112 @@
         policy.setPermissions(new RuntimePermission("setSecurityManager"));
         System.setSecurityManager(null);
 
+        //----------------------------------------------------------------
+        // Check that Process.isAlive() &
+        // Process.waitFor(0, TimeUnit.MILLISECONDS) work as expected.
+        //----------------------------------------------------------------
+        try {
+            List<String> childArgs = new ArrayList<String>(javaChildArgs);
+            childArgs.add("sleep");
+            final Process p = new ProcessBuilder(childArgs).start();
+            long start = System.nanoTime();
+            if (!p.isAlive() || p.waitFor(0, TimeUnit.MILLISECONDS)) {
+                fail("Test failed: Process exited prematurely");
+            }
+            long end = System.nanoTime();
+            // give waitFor(timeout) a wide berth (100ms)
+            if ((end - start) > 100000000)
+                fail("Test failed: waitFor took too long");
+
+            p.destroy();
+            p.waitFor();
+
+            if (p.isAlive() ||
+                !p.waitFor(0, TimeUnit.MILLISECONDS))
+            {
+                fail("Test failed: Process still alive - please terminate " +
+                    p.toString() + " manually");
+            }
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Check that Process.waitFor(timeout, TimeUnit.MILLISECONDS)
+        // works as expected.
+        //----------------------------------------------------------------
+        try {
+            List<String> childArgs = new ArrayList<String>(javaChildArgs);
+            childArgs.add("sleep");
+            final Process p = new ProcessBuilder(childArgs).start();
+            long start = System.nanoTime();
+
+            p.waitFor(1000, TimeUnit.MILLISECONDS);
+
+            long end = System.nanoTime();
+            if ((end - start) < 500000000)
+                fail("Test failed: waitFor didn't take long enough");
+
+            p.destroy();
+
+            start = System.nanoTime();
+            p.waitFor(1000, TimeUnit.MILLISECONDS);
+            end = System.nanoTime();
+            if ((end - start) > 100000000)
+                fail("Test failed: waitFor took too long on a dead process.");
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Check that Process.waitFor(timeout, TimeUnit.MILLISECONDS)
+        // interrupt works as expected.
+        //----------------------------------------------------------------
+        try {
+            List<String> childArgs = new ArrayList<String>(javaChildArgs);
+            childArgs.add("sleep");
+            final Process p = new ProcessBuilder(childArgs).start();
+            final long start = System.nanoTime();
+
+            final Thread thread = new Thread() {
+                public void run() {
+                    try {
+                        try {
+                            p.waitFor(10000, TimeUnit.MILLISECONDS);
+                        } catch (InterruptedException e) {
+                            return;
+                        }
+                        fail("waitFor() wasn't interrupted");
+                    } catch (Throwable t) { unexpected(t); }}};
+
+            thread.start();
+            Thread.sleep(1000);
+            thread.interrupt();
+            p.destroy();
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Check the default implementation for
+        // Process.waitFor(long, TimeUnit)
+        //----------------------------------------------------------------
+        try {
+            List<String> childArgs = new ArrayList<String>(javaChildArgs);
+            childArgs.add("sleep");
+            final Process proc = new ProcessBuilder(childArgs).start();
+            DelegatingProcess p = new DelegatingProcess(proc);
+            long start = System.nanoTime();
+
+            p.waitFor(1000, TimeUnit.MILLISECONDS);
+
+            long end = System.nanoTime();
+            if ((end - start) < 500000000)
+                fail("Test failed: waitFor didn't take long enough");
+
+            p.destroy();
+
+            start = System.nanoTime();
+            p.waitFor(1000, TimeUnit.MILLISECONDS);
+            end = System.nanoTime();
+            // allow for the less accurate default implementation
+            if ((end - start) > 200000000)
+                fail("Test failed: waitFor took too long on a dead process.");
+        } catch (Throwable t) { unexpected(t); }
     }
 
     static void closeStreams(Process p) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/ProcessBuilder/DestroyTest.java	Tue Jul 03 20:58:02 2012 -0700
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2012, 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 4244896
+ * @summary Test for the various platform specific implementations of
+ *          destroyForcibly.
+ */
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+
+abstract class ProcessTest implements Runnable {
+    ProcessBuilder bldr;
+    Process p;
+
+    public Process killProc(boolean force) throws Exception {
+        if (force) {
+            p.destroyForcibly();
+        } else {
+            p.destroy();
+        }
+        return p;
+    }
+
+    public boolean isAlive() {
+        return p.isAlive();
+    }
+
+    public void run() {
+        try {
+            String line;
+            BufferedReader is =
+                new BufferedReader(new InputStreamReader(p.getInputStream()));
+            while ((line = is.readLine()) != null)
+                System.err.println("ProcessTrap: " + line);
+        } catch(IOException e) {
+            if (!e.getMessage().matches("[Ss]tream [Cc]losed")) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    public abstract void runTest() throws Exception;
+}
+
+class UnixTest extends ProcessTest {
+    public UnixTest(File script) throws IOException {
+        script.deleteOnExit();
+        createScript(script);
+        bldr = new ProcessBuilder(script.getCanonicalPath());
+        bldr.redirectErrorStream(true);
+        bldr.directory(new File("."));
+        p = bldr.start();
+    }
+
+    void createScript(File processTrapScript) throws IOException {
+        processTrapScript.deleteOnExit();
+        FileWriter fstream = new FileWriter(processTrapScript);
+        try (BufferedWriter out = new BufferedWriter(fstream)) {
+            out.write("#!/bin/bash\n" +
+                "echo \\\"ProcessTrap.sh started: trapping SIGTERM/SIGINT\\\"\n" +
+                "trap bashtrap SIGTERM SIGINT\n" +
+                "bashtrap()\n" +
+                "{\n" +
+                "    echo \\\"SIGTERM/SIGINT detected!\\\"\n" +
+                "}\n" +
+                "\n" +
+                "while :\n" +
+                "do\n" +
+                "    sleep 1;\n" +
+                "done\n");
+        }
+        processTrapScript.setExecutable(true, true);
+    }
+
+    @Override
+    public void runTest() throws Exception {
+        killProc(false);
+        Thread.sleep(1000);
+        if (!p.isAlive())
+            throw new RuntimeException("Process terminated prematurely.");
+        killProc(true).waitFor();
+        if (p.isAlive())
+            throw new RuntimeException("Problem terminating the process.");
+    }
+}
+
+class MacTest extends UnixTest {
+    public MacTest(File script) throws IOException {
+        super(script);
+    }
+
+    @Override
+    public void runTest() throws Exception {
+        // On Mac, it appears that when we close the processes streams
+        // after a destroy() call, the process terminates with a
+        // SIGPIPE even if it was trapping the SIGTERM, so as with
+        // windows, we skip the trap test and go straight to destroyForcibly().
+        killProc(true).waitFor();
+        if (p.isAlive())
+            throw new RuntimeException("Problem terminating the process.");
+    }
+}
+
+class WindowsTest extends ProcessTest {
+    public WindowsTest() throws IOException {
+        bldr = new ProcessBuilder("ftp");
+        bldr.redirectErrorStream(true);
+        bldr.directory(new File("."));
+        p = bldr.start();
+    }
+
+    @Override
+    public void runTest() throws Exception {
+        killProc(true).waitFor();
+    }
+}
+
+public class DestroyTest {
+
+    public static ProcessTest getTest() throws Exception {
+        String osName = System.getProperty("os.name");
+        if (osName.startsWith("Windows")) {
+            return new WindowsTest();
+        } else if (osName.startsWith("Linux") == true) {
+            return new UnixTest(
+                File.createTempFile("ProcessTrap-", ".sh",null));
+        } else if (osName.startsWith("Mac OS")) {
+            return new MacTest(
+                File.createTempFile("ProcessTrap-", ".sh",null));
+        } else if (osName.equals("SunOS")) {
+            return new UnixTest(
+                File.createTempFile("ProcessTrap-", ".sh",null));
+        }
+        return null;
+    }
+
+    public static void main(String args[]) throws Exception {
+        ProcessTest test = getTest();
+        if (test == null) {
+            throw new RuntimeException("Unrecognised OS");
+        } else {
+            new Thread(test).start();
+            Thread.sleep(1000);
+            test.runTest();
+        }
+    }
+}
+
--- a/test/java/util/concurrent/BlockingQueue/LastElement.java	Tue Jul 03 20:56:24 2012 -0700
+++ b/test/java/util/concurrent/BlockingQueue/LastElement.java	Tue Jul 03 20:58:02 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 6215625
+ * @bug 6215625 7161229
  * @summary Check correct behavior when last element is removed.
  * @author Martin Buchholz
  */
@@ -38,9 +38,7 @@
         testQueue(new ArrayBlockingQueue<Integer>(10, true));
         testQueue(new ArrayBlockingQueue<Integer>(10, false));
         testQueue(new LinkedTransferQueue<Integer>());
-
-        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
-        if (failed > 0) throw new Exception("Some tests failed");
+        testQueue(new PriorityBlockingQueue<Integer>());
     }
 
     void testQueue(BlockingQueue<Integer> q) throws Throwable {
@@ -59,6 +57,7 @@
         try {check(q.take() == three);}
         catch (Throwable t) {unexpected(t);}
         check(q.isEmpty() && q.size() == 0);
+        check(noRetention(q));
 
         // iterator().remove()
         q.clear();
@@ -77,6 +76,26 @@
         check(q.isEmpty() && q.size() == 0);
     }
 
+    boolean noRetention(BlockingQueue<?> q) {
+        if (q instanceof PriorityBlockingQueue) {
+            PriorityBlockingQueue<?> pbq = (PriorityBlockingQueue) q;
+            try {
+                java.lang.reflect.Field queue =
+                    PriorityBlockingQueue.class.getDeclaredField("queue");
+                queue.setAccessible(true);
+                Object[] a = (Object[]) queue.get(pbq);
+                return a[0] == null;
+            }
+            catch (NoSuchFieldException e) {
+                unexpected(e);
+            }
+            catch (IllegalAccessException e) {
+                // ignore - security manager must be installed
+            }
+        }
+        return true;
+    }
+
     //--------------------- Infrastructure ---------------------------
     volatile int passed = 0, failed = 0;
     void pass() {passed++;}
--- a/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java	Tue Jul 03 20:56:24 2012 -0700
+++ b/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java	Tue Jul 03 20:58:02 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, 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
@@ -287,18 +287,27 @@
                     if (serverClose) {
                         serverEngine.closeOutbound();
                     }
+                }
+
+                if (closed && isEngineClosed(serverEngine)) {
                     serverIn.flip();
 
                     /*
                      * A sanity check to ensure we got what was sent.
                      */
                     if (serverIn.remaining() != clientMsg.length) {
-                        throw new Exception("Client:  Data length error");
+                        throw new Exception("Client: Data length error -" +
+                            " IF THIS FAILS, PLEASE REPORT THIS TO THE" +
+                            " SECURITY TEAM.  WE HAVE BEEN UNABLE TO" +
+                            " RELIABLY DUPLICATE.");
                     }
 
                     for (int i = 0; i < clientMsg.length; i++) {
                         if (clientMsg[i] != serverIn.get()) {
-                            throw new Exception("Client:  Data content error");
+                            throw new Exception("Client: Data content error -" +
+                            " IF THIS FAILS, PLEASE REPORT THIS TO THE" +
+                            " SECURITY TEAM.  WE HAVE BEEN UNABLE TO" +
+                            " RELIABLY DUPLICATE.");
                         }
                     }
                     serverIn.compact();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/tools/native2ascii/Permission.java	Tue Jul 03 20:58:02 2012 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2012, 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 7177216
+ * @summary resulting file of native2ascii should have normal permission
+ */
+
+import java.io.*;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import sun.tools.native2ascii.Main;
+
+public class Permission {
+
+    private static void cleanup(String... fnames) throws Throwable {
+        for (String fname : fnames) {
+            Files.deleteIfExists(Paths.get(fname));
+        }
+    }
+
+    public static void realMain(String[] args) throws Throwable {
+        if (!System.getProperty("os.name").startsWith("Windows")) {
+            String src = "native2ascii_permtest_src";
+            String dst = "native2ascii_permtest_dst";
+
+            cleanup(src, dst);
+            try {
+                try (FileOutputStream fos = new FileOutputStream(src)) {
+                    fos.write('a'); fos.write('b'); fos.write('c');
+                }
+                String[] n2aArgs = new String[] {"-encoding", "utf8", src, dst};
+                if (!new Main().convert(n2aArgs)) {
+                    fail("n2a failed.");
+                }
+                equal(Files.getPosixFilePermissions(Paths.get(src)),
+                      Files.getPosixFilePermissions(Paths.get(dst)));
+                String[] a2nArgs = new String[] {"-reverse", "-encoding", "utf8", dst, src};
+                if (!new Main().convert(a2nArgs)) {
+                    fail("a2n failed.");
+                }
+                equal(Files.getPosixFilePermissions(Paths.get(src)),
+                      Files.getPosixFilePermissions(Paths.get(dst)));
+            } finally {
+                cleanup(src, dst);
+            }
+        }
+    }
+
+    //--------------------- Infrastructure ---------------------------
+    static volatile int passed = 0, failed = 0;
+    static void pass() {passed++;}
+    static void fail() {failed++; Thread.dumpStack();}
+    static void fail(String msg) {System.out.println(msg); fail();}
+    static void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    static void check(boolean cond) {if (cond) pass(); else fail();}
+    static void equal(Object x, Object y) {
+        if (x == null ? y == null : x.equals(y)) pass();
+        else fail(x + " not equal to " + y);}
+    public static void main(String[] args) throws Throwable {
+        try {realMain(args);} catch (Throwable t) {unexpected(t);}
+        System.out.println("\nPassed = " + passed + " failed = " + failed);
+        if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/jar/UpdateJar.java	Tue Jul 03 20:58:02 2012 -0700
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2012, 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 7175845
+ * @summary jar -uf should not change file permission
+ */
+
+import java.io.*;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.util.Set;
+import sun.tools.jar.Main;
+
+public class UpdateJar {
+
+    private static void cleanup(String... fnames) throws Throwable {
+        for (String fname : fnames) {
+            Files.deleteIfExists(Paths.get(fname));
+        }
+    }
+
+    public static void realMain(String[] args) throws Throwable {
+        if (!System.getProperty("os.name").startsWith("Windows")) {
+            String jar = "testUpdateJar.jar";
+            String e0  = "testUpdateJar_entry0.txt";
+            String e1  = "testUpdateJar_entry1.txt";
+            cleanup(jar, e0, e1);
+            try {
+                try (FileOutputStream fos0 = new FileOutputStream(e0);
+                     FileOutputStream fos1 = new FileOutputStream(e1)) {
+                    fos0.write(0);
+                    fos1.write(0);
+                }
+                String[] jarArgs = new String[] {"cfM0", jar, e0};
+                if (!new Main(System.out, System.err, "jar").run(jarArgs)) {
+                    fail("Could not create jar file.");
+                }
+                Set<PosixFilePermission> pm = Files.getPosixFilePermissions(Paths.get(jar));
+                jarArgs = new String[] {"uf", jar, e1};
+                if (!new Main(System.out, System.err, "jar").run(jarArgs)) {
+                    fail("Could not create jar file.");
+                }
+                equal(pm, Files.getPosixFilePermissions(Paths.get(jar)));
+            } finally {
+                cleanup(jar, e0, e1);
+            }
+        }
+    }
+
+    //--------------------- Infrastructure ---------------------------
+    static volatile int passed = 0, failed = 0;
+    static void pass() {passed++;}
+    static void fail() {failed++; Thread.dumpStack();}
+    static void fail(String msg) {System.out.println(msg); fail();}
+    static void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    static void check(boolean cond) {if (cond) pass(); else fail();}
+    static void equal(Object x, Object y) {
+        if (x == null ? y == null : x.equals(y)) pass();
+        else fail(x + " not equal to " + y);}
+    public static void main(String[] args) throws Throwable {
+        try {realMain(args);} catch (Throwable t) {unexpected(t);}
+        System.out.println("\nPassed = " + passed + " failed = " + failed);
+        if (failed > 0) throw new AssertionError("Some tests failed");}
+}