Merge jdk7-b118
authorduke
Wed, 05 Jul 2017 17:26:57 +0200
changeset 7085 2e876e59938a
parent 7084 ea14efe08312 (diff)
parent 6954 68d3a9bc7a08 (current diff)
child 7086 dad682f1a84a
child 7087 8d472c364129
child 7093 67ef650c64e0
child 7095 dc71e7fdd835
child 7099 85b133463786
child 7130 7f370da0805b
child 7132 d45d466d6759
child 7134 1db26590e632
child 7136 80bacb622b68
child 7138 2322464ada6f
child 7466 07f818b7f200
child 7468 6cab86212adb
child 7574 50a48a04ea49
child 7610 bca07afa2afe
Merge
--- a/.hgtags-top-repo	Wed Jul 05 17:26:05 2017 +0200
+++ b/.hgtags-top-repo	Wed Jul 05 17:26:57 2017 +0200
@@ -91,3 +91,4 @@
 27985a5c6e5268014d25d55886e0ecb96af4763d jdk7-b114
 e8ebdf41b9c01a26642848f4134f5504e8fb3233 jdk7-b115
 94e9a1bfba8b8d1fe0bfd43b88629b1f27b02a76 jdk7-b116
+7220e60b097fa027e922f1aeecdd330f3e37409f jdk7-b117
--- a/corba/.hgtags	Wed Jul 05 17:26:05 2017 +0200
+++ b/corba/.hgtags	Wed Jul 05 17:26:57 2017 +0200
@@ -91,3 +91,4 @@
 88fddb73c5c4a4b50c319cbae9380caf5172ab45 jdk7-b114
 da7561d479e0ddaa4650d8023ac0fc7294e014e3 jdk7-b115
 98c028de4301106f2285ac0e128a1bb9b4c24f5c jdk7-b116
+fa502e4834dac2176499cc1f44794d5dc32a11b9 jdk7-b117
--- a/corba/make/com/sun/corba/minclude/com_sun_corba_se_impl_io.jmk	Wed Jul 05 17:26:05 2017 +0200
+++ b/corba/make/com/sun/corba/minclude/com_sun_corba_se_impl_io.jmk	Wed Jul 05 17:26:57 2017 +0200
@@ -34,7 +34,7 @@
 	com/sun/corba/se/impl/io/ObjectStreamField.java \
 	com/sun/corba/se/impl/io/OptionalDataException.java \
 	com/sun/corba/se/impl/io/ValueHandlerImpl.java \
-	com/sun/corba/se/impl/io/IIOPInputStream.java \
+        com/sun/corba/se/impl/io/IIOPInputStream.java \
 	com/sun/corba/se/impl/io/IIOPOutputStream.java \
 	com/sun/corba/se/impl/io/TypeMismatchException.java \
 	com/sun/corba/se/impl/io/InputStreamHook.java \
--- a/corba/src/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/corba/src/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java	Wed Jul 05 17:26:57 2017 +0200
@@ -2553,8 +2553,8 @@
             bridge.putObject( o, key, v ) ;
         } catch (Exception e) {
             throw utilWrapper.errorSetObjectField( e, fieldName,
-                ObjectUtility.compactObjectToString( o ),
-                ObjectUtility.compactObjectToString( v )) ;
+                o.toString(),
+                v.toString() ) ;
         }
     }
 
@@ -2566,7 +2566,7 @@
             bridge.putBoolean( o, key, v ) ;
         } catch (Exception e) {
             throw utilWrapper.errorSetBooleanField( e, fieldName,
-                ObjectUtility.compactObjectToString( o ),
+                o.toString(),
                 new Boolean(v) ) ;
         }
     }
@@ -2579,7 +2579,7 @@
             bridge.putByte( o, key, v ) ;
         } catch (Exception e) {
             throw utilWrapper.errorSetByteField( e, fieldName,
-                ObjectUtility.compactObjectToString( o ),
+                o.toString(),
                 new Byte(v) ) ;
         }
     }
@@ -2592,7 +2592,7 @@
             bridge.putChar( o, key, v ) ;
         } catch (Exception e) {
             throw utilWrapper.errorSetCharField( e, fieldName,
-                ObjectUtility.compactObjectToString( o ),
+                o.toString(),
                 new Character(v) ) ;
         }
     }
@@ -2605,7 +2605,7 @@
             bridge.putShort( o, key, v ) ;
         } catch (Exception e) {
             throw utilWrapper.errorSetShortField( e, fieldName,
-                ObjectUtility.compactObjectToString( o ),
+                o.toString(),
                 new Short(v) ) ;
         }
     }
@@ -2618,7 +2618,7 @@
             bridge.putInt( o, key, v ) ;
         } catch (Exception e) {
             throw utilWrapper.errorSetIntField( e, fieldName,
-                ObjectUtility.compactObjectToString( o ),
+                o.toString(),
                 new Integer(v) ) ;
         }
     }
@@ -2631,7 +2631,7 @@
             bridge.putLong( o, key, v ) ;
         } catch (Exception e) {
             throw utilWrapper.errorSetLongField( e, fieldName,
-                ObjectUtility.compactObjectToString( o ),
+                o.toString(),
                 new Long(v) ) ;
         }
     }
@@ -2644,7 +2644,7 @@
             bridge.putFloat( o, key, v ) ;
         } catch (Exception e) {
             throw utilWrapper.errorSetFloatField( e, fieldName,
-                ObjectUtility.compactObjectToString( o ),
+                o.toString(),
                 new Float(v) ) ;
         }
     }
@@ -2657,7 +2657,7 @@
             bridge.putDouble( o, key, v ) ;
         } catch (Exception e) {
             throw utilWrapper.errorSetDoubleField( e, fieldName,
-                ObjectUtility.compactObjectToString( o ),
+                o.toString(),
                 new Double(v) ) ;
         }
     }
--- a/corba/src/share/classes/com/sun/corba/se/impl/io/ValueHandlerImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/corba/src/share/classes/com/sun/corba/se/impl/io/ValueHandlerImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,32 +32,22 @@
 package com.sun.corba.se.impl.io;
 
 import javax.rmi.CORBA.Util;
-import javax.rmi.PortableRemoteObject;
 
 import java.util.Hashtable;
-import java.util.Stack;
 import java.io.IOException;
-import java.util.EmptyStackException;
 
-import com.sun.corba.se.impl.util.Utility;
-import com.sun.corba.se.impl.io.IIOPInputStream;
-import com.sun.corba.se.impl.io.IIOPOutputStream;
 import com.sun.corba.se.impl.util.RepositoryId;
 import com.sun.corba.se.impl.util.Utility;
 
 import org.omg.CORBA.TCKind;
 
-import org.omg.CORBA.MARSHAL;
-import org.omg.CORBA.BAD_PARAM;
-import org.omg.CORBA.CompletionStatus;
 import org.omg.CORBA.portable.IndirectionException;
 import com.sun.org.omg.SendingContext.CodeBase;
 import com.sun.org.omg.SendingContext.CodeBaseHelper;
 
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-
-import com.sun.corba.se.impl.io.IIOPInputStream.ActiveRecursionManager;
+import java.security.PrivilegedExceptionAction;
 
 import com.sun.corba.se.spi.logging.CORBALogDomains;
 import com.sun.corba.se.impl.logging.OMGSystemException;
@@ -809,65 +799,163 @@
         return "com.sun.corba.se.impl.io.IIOPOutputStream";
     }
 
-    private com.sun.corba.se.impl.io.IIOPOutputStream createOutputStream() {
-        return (com.sun.corba.se.impl.io.IIOPOutputStream)AccessController.doPrivileged(
-            new StreamFactory(getOutputStreamClassName()));
+   private IIOPOutputStream createOutputStream() {
+        final String name = getOutputStreamClassName();
+        try {
+             IIOPOutputStream stream = createOutputStreamBuiltIn(name);
+             if (stream != null) {
+                 return stream;
+             }
+             return createCustom(IIOPOutputStream.class, name);
+        } catch (Throwable t) {
+            // Throw exception under the carpet.
+            InternalError ie = new InternalError(
+                "Error loading " + name
+            );
+                ie.initCause(t);
+                throw ie;
+        }
+    }
+
+    /**
+     * Construct a built in implementation with priveleges.
+     * Returning null indicates a non-built is specified.
+     */
+    private IIOPOutputStream createOutputStreamBuiltIn(
+        final String name
+    ) throws Throwable {
+        try {
+            return AccessController.doPrivileged(
+                new PrivilegedExceptionAction<IIOPOutputStream>() {
+                    public IIOPOutputStream run() throws IOException {
+                        return createOutputStreamBuiltInNoPriv(name);
+                    }
+                }
+            );
+        } catch (java.security.PrivilegedActionException exc) {
+            throw exc.getCause();
+        }
+    }
+
+    /**
+     * Returning null indicates a non-built is specified.
+     */
+    private IIOPOutputStream createOutputStreamBuiltInNoPriv(
+        final String name
+    ) throws IOException {
+        return
+            name.equals(
+                IIOPOutputStream
+                    .class.getName()
+            ) ?
+            new IIOPOutputStream() :
+
+            name.equals(
+                com.sun.corba.se.impl.orbutil.IIOPOutputStream_1_3
+                    .class.getName()
+            ) ?
+            new com.sun.corba.se.impl.orbutil.IIOPOutputStream_1_3() :
+
+            name.equals(
+                com.sun.corba.se.impl.orbutil.IIOPOutputStream_1_3_1
+                    .class.getName()
+            ) ?
+            new com.sun.corba.se.impl.orbutil.IIOPOutputStream_1_3_1() :
+
+            null;
     }
 
     protected String getInputStreamClassName() {
         return "com.sun.corba.se.impl.io.IIOPInputStream";
     }
 
-    private com.sun.corba.se.impl.io.IIOPInputStream createInputStream() {
-        return (com.sun.corba.se.impl.io.IIOPInputStream)AccessController.doPrivileged(
-            new StreamFactory(getInputStreamClassName()));
+    private IIOPInputStream createInputStream() {
+        final String name = getInputStreamClassName();
+        try {
+             IIOPInputStream stream = createInputStreamBuiltIn(name);
+             if (stream != null) {
+                 return stream;
+             }
+             return createCustom(IIOPInputStream.class, name);
+        } catch (Throwable t) {
+            // Throw exception under the carpet.
+            InternalError ie = new InternalError(
+                "Error loading " + name
+            );
+                ie.initCause(t);
+                throw ie;
+        }
     }
 
     /**
-     * Instantiates a class of the given name using the system ClassLoader
-     * as part of a PrivilegedAction.
-     *
-     * It's private final so hopefully people can't grab it outside of
-     * this class.
-     *
-     * If you're worried that someone could subclass ValueHandlerImpl,
-     * install his own streams, and snoop what's on the wire:
-     * Someone can do that only if he's allowed to use the feature
-     * of installing his own javax.rmi.CORBA.Util delegate (via a
-     * JVM property or orb.properties file, read the first time the
-     * Util class is used).  If he can do that, he can snoop
-     * anything on the wire, anyway, without abusing the
-     * StreamFactory class.
+     * Construct a built in implementation with priveleges.
+     * Returning null indicates a non-built is specified.
      */
-    private static final class StreamFactory implements PrivilegedAction {
-        private String className;
-
-        public StreamFactory (String _className) {
-            className = _className;
-        }
+     private IIOPInputStream createInputStreamBuiltIn(
+         final String name
+     ) throws Throwable {
+         try {
+             return AccessController.doPrivileged(
+                 new PrivilegedExceptionAction<IIOPInputStream>() {
+                     public IIOPInputStream run() throws IOException {
+                         return createInputStreamBuiltInNoPriv(name);
+                     }
+                 }
+             );
+         } catch (java.security.PrivilegedActionException exc) {
+             throw exc.getCause();
+         }
+     }
 
-        public Object run() {
-            try {
-                // Note: We must use the system ClassLoader here
-                // since we want to load classes outside of the
-                // core JDK when running J2EE Pure ORB and
-                // talking to Kestrel.
+     /**
+      * Returning null indicates a non-built is specified.
+      */
+     private IIOPInputStream createInputStreamBuiltInNoPriv(
+         final String name
+     ) throws IOException {
+         return
+             name.equals(
+                 IIOPInputStream
+                     .class.getName()
+             ) ?
+             new IIOPInputStream() :
+
+             name.equals(
+                 com.sun.corba.se.impl.orbutil.IIOPInputStream_1_3
+                     .class.getName()
+             ) ?
+             new com.sun.corba.se.impl.orbutil.IIOPInputStream_1_3() :
+
+             name.equals(
+                 com.sun.corba.se.impl.orbutil.IIOPInputStream_1_3_1
+                     .class.getName()
+             ) ?
+             new com.sun.corba.se.impl.orbutil.IIOPInputStream_1_3_1() :
+
+             null;
+     }
+
+     /**
+      * Create a custom implementation without privileges.
+      */
+     private <T> T createCustom(
+         final Class<T> type, final String className
+     ) throws Throwable {
+           // Note: We use the thread context or system ClassLoader here
+           // since we want to load classes outside of the
+           // core JDK when running J2EE Pure ORB and
+           // talking to Kestrel.
                 ClassLoader cl = Thread.currentThread().getContextClassLoader();
                 if (cl == null)
                     cl = ClassLoader.getSystemClassLoader();
 
-                Class streamClass = cl.loadClass(className);
+                Class<?> clazz = cl.loadClass(className);
+                Class<? extends T> streamClass = clazz.asSubclass(type);
 
                 // Since the ClassLoader should cache the class, this isn't
                 // as expensive as it looks.
                 return streamClass.newInstance();
 
-            } catch(Throwable t) {
-                InternalError ie = new InternalError( "Error loading " + className ) ;
-                ie.initCause( t ) ;
-                throw ie ;
-            }
-        }
     }
 
     /**
--- a/corba/src/share/classes/com/sun/corba/se/impl/orb/PrefixParserAction.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/corba/src/share/classes/com/sun/corba/se/impl/orb/PrefixParserAction.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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
@@ -110,7 +110,7 @@
                     throw wrapper.couldNotSetArray( thr,
                         getPropertyName(), new Integer(ctr),
                         componentType, new Integer(size),
-                        ObjectUtility.compactObjectToString( obj )) ;
+                        obj.toString() ) ;
                 }
                 ctr++ ;
             }
--- a/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectUtility.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectUtility.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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
@@ -50,103 +50,8 @@
 import java.math.BigDecimal ;
 
 public final class ObjectUtility {
-    private boolean useToString ;
-    private boolean isIndenting ;
-    private int initialLevel ;
-    private int increment ;
-    private ClassMap classToPrinter = new ClassMap() ;
-
-    private static ObjectUtility standard = new ObjectUtility( false, true,
-        0, 4 ) ;
-    private static ObjectUtility compact = new ObjectUtility( true, false,
-        0, 4 ) ;
-
-    private ObjectUtility( boolean useToString, boolean isIndenting,
-        int initialLevel, int increment )
-    {
-        this.useToString = useToString ;
-        this.isIndenting = isIndenting ;
-        this.initialLevel = initialLevel ;
-        this.increment = increment ;
-        classToPrinter.put( Properties.class, propertiesPrinter ) ;
-        classToPrinter.put( Collection.class, collectionPrinter ) ;
-        classToPrinter.put( Map.class, mapPrinter ) ;
-    }
-
-    /** Construct an Utility instance with the desired objectToString
-    * behavior.
-    */
-    public static ObjectUtility make( boolean useToString, boolean isIndenting,
-        int initialLevel, int increment )
-    {
-        return new ObjectUtility( useToString, isIndenting, initialLevel,
-            increment ) ;
-    }
-
-    /** Construct an Utility instance with the desired objectToString
-    * behavior.
-    */
-    public static ObjectUtility make( boolean useToString, boolean isIndenting )
-    {
-        return new ObjectUtility( useToString, isIndenting, 0, 4 ) ;
-    }
-
-    /** Get the standard Utility object that supports objectToString with
-    * indented display and no use of toString() methods.
-    */
-    public static ObjectUtility make()
-    {
-        return standard ;
-    }
+    private ObjectUtility() {}
 
-    /** A convenience method that gives the default behavior: use indenting
-    * to display the object's structure and do not use built-in toString
-    * methods.
-    */
-    public static String defaultObjectToString( java.lang.Object object )
-    {
-        return standard.objectToString( object ) ;
-    }
-
-    public static String compactObjectToString( java.lang.Object object )
-    {
-        return compact.objectToString( object ) ;
-    }
-
-    /** objectToString handles display of arbitrary objects.  It correctly
-    * handles objects whose elements form an arbitrary graph.  It uses
-    * reflection to display the contents of any kind of object.
-    * An object's toString() method may optionally be used, but the default
-    * is to ignore all toString() methods except for those defined for
-    * primitive types, primitive type wrappers, and strings.
-    */
-    public String objectToString(java.lang.Object obj)
-    {
-        IdentityHashMap printed = new IdentityHashMap() ;
-        ObjectWriter result = ObjectWriter.make( isIndenting, initialLevel,
-            increment ) ;
-        objectToStringHelper( printed, result, obj ) ;
-        return result.toString() ;
-    }
-
-    // Perform a deep structural equality comparison of the two objects.
-    // This handles all arrays, maps, and sets specially, otherwise
-    // it just calls the object's equals() method.
-    public static boolean equals( java.lang.Object obj1, java.lang.Object obj2 )
-    {
-        // Set of pairs of objects that have been (or are being) considered for
-        // equality.  Such pairs are presumed to be equals.  If they are not,
-        // this will be detected eventually and the equals method will return
-        // false.
-        Set considered = new HashSet() ;
-
-        // Map that gives the corresponding component of obj2 for a component
-        // of obj1.  This is used to check for the same aliasing and use of
-        // equal objects in both objects.
-        Map counterpart = new IdentityHashMap() ;
-
-        return equalsHelper( counterpart, considered, obj1, obj2 ) ;
-    }
 
     /** If arr1 and arr2 are both arrays of the same component type,
      * return an array of that component type that consists of the
@@ -179,544 +84,4 @@
         return result ;
     }
 
-//===========================================================================
-//  Implementation
-//===========================================================================
-
-    private void objectToStringHelper( IdentityHashMap printed,
-        ObjectWriter result, java.lang.Object obj)
-    {
-        if (obj==null) {
-            result.append( "null" ) ;
-            result.endElement() ;
-        } else {
-            Class cls = obj.getClass() ;
-            result.startObject( obj ) ;
-
-            if (printed.keySet().contains( obj )) {
-                result.endObject( "*VISITED*" ) ;
-            } else {
-                printed.put( obj, null ) ;
-
-                if (mustUseToString(cls)) {
-                    result.endObject( obj.toString() ) ;
-                } else {
-                    // First, handle any classes that have special printer
-                    // methods defined.  This is useful when the class
-                    // overrides toString with something that
-                    // is not sufficiently detailed.
-                    ObjectPrinter printer = (ObjectPrinter)(classToPrinter.get(
-                        cls )) ;
-                    if (printer != null) {
-                        printer.print( printed, result, obj ) ;
-                        result.endObject() ;
-                    } else {
-                        Class compClass = cls.getComponentType() ;
-
-                        if (compClass == null)
-                            // handleObject always calls endObject
-                            handleObject( printed, result, obj ) ;
-                        else {
-                            handleArray( printed, result, obj ) ;
-                            result.endObject() ;
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    private static interface ObjectPrinter {
-        void print( IdentityHashMap printed, ObjectWriter buff,
-            java.lang.Object obj ) ;
-    }
-
-    private ObjectPrinter propertiesPrinter = new ObjectPrinter() {
-        public void print( IdentityHashMap printed, ObjectWriter buff,
-            java.lang.Object obj )
-        {
-            if (!(obj instanceof Properties))
-                throw new Error() ;
-
-            Properties props = (Properties)obj ;
-            Enumeration keys = props.propertyNames() ;
-            while (keys.hasMoreElements()) {
-                String key = (String)(keys.nextElement()) ;
-                String value = props.getProperty( key ) ;
-                buff.startElement() ;
-                buff.append( key ) ;
-                buff.append( "=" ) ;
-                buff.append( value ) ;
-                buff.endElement() ;
-            }
-        }
-    } ;
-
-    private ObjectPrinter collectionPrinter = new ObjectPrinter() {
-        public void print( IdentityHashMap printed, ObjectWriter buff,
-            java.lang.Object obj )
-        {
-            if (!(obj instanceof Collection))
-                throw new Error() ;
-
-            Collection coll = (Collection)obj ;
-            Iterator iter = coll.iterator() ;
-            while (iter.hasNext()) {
-                java.lang.Object element = iter.next() ;
-                buff.startElement() ;
-                objectToStringHelper( printed, buff, element ) ;
-                buff.endElement() ;
-            }
-        }
-    } ;
-
-    private ObjectPrinter mapPrinter = new ObjectPrinter() {
-        public void print( IdentityHashMap printed, ObjectWriter buff,
-            java.lang.Object obj )
-        {
-            if (!(obj instanceof Map))
-                throw new Error() ;
-
-            Map map = (Map)obj ;
-            Iterator iter = map.entrySet().iterator() ;
-            while (iter.hasNext()) {
-                Entry entry = (Entry)(iter.next()) ;
-                buff.startElement() ;
-                objectToStringHelper( printed, buff, entry.getKey() ) ;
-                buff.append( "=>" ) ;
-                objectToStringHelper( printed, buff, entry.getValue() ) ;
-                buff.endElement() ;
-            }
-        }
-    } ;
-
-    private static class ClassMap {
-        ArrayList data ;
-
-        public ClassMap()
-        {
-            data = new ArrayList() ;
-        }
-
-        /** Return the first element of the ClassMap that is assignable to cls.
-        * The order is determined by the order in which the put method was
-        * called.  Returns null if there is no match.
-        */
-        public java.lang.Object get( Class cls )
-        {
-            Iterator iter = data.iterator() ;
-            while (iter.hasNext()) {
-                java.lang.Object[] arr = (java.lang.Object[])(iter.next()) ;
-                Class key = (Class)(arr[0]) ;
-                if (key.isAssignableFrom( cls ))
-                    return arr[1] ;
-            }
-
-            return null ;
-        }
-
-        /** Add obj to the map with key cls.  Note that order matters,
-         * as the first match is returned.
-         */
-        public void put( Class cls, java.lang.Object obj )
-        {
-            java.lang.Object[] pair = { cls, obj } ;
-            data.add( pair ) ;
-        }
-    }
-
-    private boolean mustUseToString( Class cls )
-    {
-        // These probably never occur
-        if (cls.isPrimitive())
-            return true ;
-
-        // We must use toString for all primitive wrappers, since
-        // otherwise the code recurses endlessly (access value field
-        // inside Integer, returns another Integer through reflection).
-        if ((cls == Integer.class) ||
-            (cls == BigInteger.class) ||
-            (cls == BigDecimal.class) ||
-            (cls == String.class) ||
-            (cls == StringBuffer.class) ||
-            (cls == Long.class) ||
-            (cls == Short.class) ||
-            (cls == Byte.class) ||
-            (cls == Character.class) ||
-            (cls == Float.class) ||
-            (cls == Double.class) ||
-            (cls == Boolean.class))
-            return true ;
-
-        if (useToString) {
-            try {
-                cls.getDeclaredMethod( "toString", (Class[])null ) ;
-                return true ;
-            } catch (Exception exc) {
-                return false ;
-            }
-        }
-
-        return false ;
-    }
-
-    private void handleObject( IdentityHashMap printed, ObjectWriter result,
-        java.lang.Object obj )
-    {
-        Class cls = obj.getClass() ;
-
-        try {
-            Field[] fields;
-            SecurityManager security = System.getSecurityManager();
-            if (security != null && !Modifier.isPublic(cls.getModifiers())) {
-                fields = new Field[0];
-            } else {
-                fields = cls.getDeclaredFields();
-            }
-
-            for (int ctr=0; ctr<fields.length; ctr++ ) {
-                final Field fld = fields[ctr] ;
-                int modifiers = fld.getModifiers() ;
-
-                // Do not display field if it is static, since these fields
-                // are always the same for every instances.  This could
-                // be made configurable, but I don't think it is
-                // useful to do so.
-                if (!Modifier.isStatic( modifiers )) {
-                    if (security != null) {
-                        if (!Modifier.isPublic(modifiers))
-                            continue;
-                    }
-                    result.startElement() ;
-                    result.append( fld.getName() ) ;
-                    result.append( ":" ) ;
-
-                    try {
-                        // Make sure that we can read the field if it is
-                        // not public
-                        AccessController.doPrivileged( new PrivilegedAction() {
-                            public Object run() {
-                                fld.setAccessible( true ) ;
-                                return null ;
-                            }
-                        } ) ;
-
-                        java.lang.Object value = fld.get( obj ) ;
-                        objectToStringHelper( printed, result, value ) ;
-                    } catch (Exception exc2) {
-                        result.append( "???" ) ;
-                    }
-
-                    result.endElement() ;
-                }
-            }
-
-            result.endObject() ;
-        } catch (Exception exc2) {
-            result.endObject( obj.toString() ) ;
-        }
-    }
-
-    private void handleArray( IdentityHashMap printed, ObjectWriter result,
-        java.lang.Object obj )
-    {
-        Class compClass = obj.getClass().getComponentType() ;
-        if (compClass == boolean.class) {
-            boolean[] arr = (boolean[])obj ;
-            for (int ctr=0; ctr<arr.length; ctr++) {
-                result.startElement() ;
-                result.append( arr[ctr] ) ;
-                result.endElement() ;
-            }
-        } else if (compClass == byte.class) {
-            byte[] arr = (byte[])obj ;
-            for (int ctr=0; ctr<arr.length; ctr++) {
-                result.startElement() ;
-                result.append( arr[ctr] ) ;
-                result.endElement() ;
-            }
-        } else if (compClass == short.class) {
-            short[] arr = (short[])obj ;
-            for (int ctr=0; ctr<arr.length; ctr++) {
-                result.startElement() ;
-                result.append( arr[ctr] ) ;
-                result.endElement() ;
-            }
-        } else if (compClass == int.class) {
-            int[] arr = (int[])obj ;
-            for (int ctr=0; ctr<arr.length; ctr++) {
-                result.startElement() ;
-                result.append( arr[ctr] ) ;
-                result.endElement() ;
-            }
-        } else if (compClass == long.class) {
-            long[] arr = (long[])obj ;
-            for (int ctr=0; ctr<arr.length; ctr++) {
-                result.startElement() ;
-                result.append( arr[ctr] ) ;
-                result.endElement() ;
-            }
-        } else if (compClass == char.class) {
-            char[] arr = (char[])obj ;
-            for (int ctr=0; ctr<arr.length; ctr++) {
-                result.startElement() ;
-                result.append( arr[ctr] ) ;
-                result.endElement() ;
-            }
-        } else if (compClass == float.class) {
-            float[] arr = (float[])obj ;
-            for (int ctr=0; ctr<arr.length; ctr++) {
-                result.startElement() ;
-                result.append( arr[ctr] ) ;
-                result.endElement() ;
-            }
-        } else if (compClass == double.class) {
-            double[] arr = (double[])obj ;
-            for (int ctr=0; ctr<arr.length; ctr++) {
-                result.startElement() ;
-                result.append( arr[ctr] ) ;
-                result.endElement() ;
-            }
-        } else { // array of object
-            java.lang.Object[] arr = (java.lang.Object[])obj ;
-            for (int ctr=0; ctr<arr.length; ctr++) {
-                result.startElement() ;
-                objectToStringHelper( printed, result, arr[ctr] ) ;
-                result.endElement() ;
-            }
-        }
-    }
-
-    private static class Pair
-    {
-        private java.lang.Object obj1 ;
-        private java.lang.Object obj2 ;
-
-        Pair( java.lang.Object obj1, java.lang.Object obj2 )
-        {
-            this.obj1 = obj1 ;
-            this.obj2 = obj2 ;
-        }
-
-        public boolean equals( java.lang.Object obj )
-        {
-            if (!(obj instanceof Pair))
-                return false ;
-
-            Pair other = (Pair)obj ;
-            return other.obj1 == obj1 && other.obj2 == obj2 ;
-        }
-
-        public int hashCode()
-        {
-            return System.identityHashCode( obj1 ) ^
-                System.identityHashCode( obj2 ) ;
-        }
-    }
-
-    private static boolean equalsHelper( Map counterpart, Set considered,
-        java.lang.Object obj1, java.lang.Object obj2 )
-    {
-        if ((obj1 == null) || (obj2 == null))
-            return obj1 == obj2 ;
-
-        java.lang.Object other2 = counterpart.get( obj1 ) ;
-        if (other2 == null) {
-            other2 = obj2 ;
-            counterpart.put( obj1, other2 ) ;
-        }
-
-        if (obj1 == other2)
-            return true ;
-
-        if (obj2 != other2)
-            return false ;
-
-        Pair pair = new Pair( obj1, obj2 ) ;
-        if (considered.contains( pair ))
-            return true ;
-        else
-            considered.add( pair ) ;
-
-        if (obj1 instanceof java.lang.Object[] &&
-            obj2 instanceof java.lang.Object[])
-            return equalArrays( counterpart, considered,
-                (java.lang.Object[])obj1, (java.lang.Object[])obj2 ) ;
-        else if (obj1 instanceof Map && obj2 instanceof Map)
-            return equalMaps( counterpart, considered,
-                (Map)obj1, (Map)obj2 ) ;
-        else if (obj1 instanceof Set && obj2 instanceof Set)
-            return equalSets( counterpart, considered,
-                (Set)obj1, (Set)obj2 ) ;
-        else if (obj1 instanceof List && obj2 instanceof List)
-            return equalLists( counterpart, considered,
-                (List)obj1, (List)obj2 ) ;
-        else if (obj1 instanceof boolean[] && obj2 instanceof boolean[])
-            return Arrays.equals( (boolean[])obj1, (boolean[])obj2 ) ;
-        else if (obj1 instanceof byte[] && obj2 instanceof byte[])
-            return Arrays.equals( (byte[])obj1, (byte[])obj2 ) ;
-        else if (obj1 instanceof char[] && obj2 instanceof char[])
-            return Arrays.equals( (char[])obj1, (char[])obj2 ) ;
-        else if (obj1 instanceof double[] && obj2 instanceof double[])
-            return Arrays.equals( (double[])obj1, (double[])obj2 ) ;
-        else if (obj1 instanceof float[] && obj2 instanceof float[])
-            return Arrays.equals( (float[])obj1, (float[])obj2 ) ;
-        else if (obj1 instanceof int[] && obj2 instanceof int[])
-            return Arrays.equals( (int[])obj1, (int[])obj2 ) ;
-        else if (obj1 instanceof long[] && obj2 instanceof long[])
-            return Arrays.equals( (long[])obj1, (long[])obj2 ) ;
-        else {
-            Class cls = obj1.getClass() ;
-            if (cls != obj2.getClass())
-                return obj1.equals( obj2 ) ;
-            else
-                return equalsObject( counterpart, considered, cls, obj1, obj2 ) ;
-        }
-    }
-
-    private static boolean equalsObject( Map counterpart, Set considered,
-        Class cls, java.lang.Object obj1, java.lang.Object obj2 )
-    {
-        Class objectClass = java.lang.Object.class ;
-        if (cls == objectClass)
-            return true ;
-
-        Class[] equalsTypes = { objectClass } ;
-        try {
-            Method equalsMethod = cls.getDeclaredMethod( "equals",
-                equalsTypes ) ;
-            return obj1.equals( obj2 ) ;
-        } catch (Exception exc) {
-            if (equalsObjectFields( counterpart, considered,
-                    cls, obj1, obj2 ))
-                return equalsObject( counterpart, considered,
-                    cls.getSuperclass(), obj1, obj2 ) ;
-            else
-                return false ;
-        }
-    }
-
-    private static boolean equalsObjectFields( Map counterpart, Set considered,
-        Class cls, java.lang.Object obj1, java.lang.Object obj2 )
-    {
-        Field[] fields = cls.getDeclaredFields() ;
-        for (int ctr=0; ctr<fields.length; ctr++) {
-            try {
-                final Field field = fields[ctr] ;
-                // Ignore static fields
-                if (!Modifier.isStatic( field.getModifiers())) {
-                    AccessController.doPrivileged(new PrivilegedAction() {
-                        public Object run() {
-                            field.setAccessible( true ) ;
-                            return null ;
-                        }
-                    } ) ;
-
-                    java.lang.Object value1 = field.get( obj1 ) ;
-                    java.lang.Object value2 = field.get( obj2 ) ;
-                    if (!equalsHelper( counterpart, considered, value1,
-                        value2 ))
-                        return false ;
-                }
-            } catch (IllegalAccessException exc) {
-                return false ;
-            }
-        }
-
-        return true ;
-    }
-
-    private static boolean equalArrays( Map counterpart, Set considered,
-        java.lang.Object[] arr1, java.lang.Object[] arr2 )
-    {
-        int len = arr1.length ;
-        if (len != arr2.length)
-            return false ;
-
-        for (int ctr = 0; ctr<len; ctr++ )
-            if (!equalsHelper( counterpart, considered, arr1[ctr], arr2[ctr] ))
-                return false ;
-
-        return true ;
-    }
-
-    private static boolean equalMaps( Map counterpart, Set considered,
-        Map map1, Map map2 )
-    {
-        if (map2.size() != map1.size())
-            return false;
-
-        try {
-            Iterator i = map1.entrySet().iterator();
-            while (i.hasNext()) {
-                Entry e = (Entry) i.next();
-                java.lang.Object key = e.getKey();
-                java.lang.Object value = e.getValue();
-                if (value == null) {
-                    if (!(map2.get(key)==null && map2.containsKey(key)))
-                        return false;
-                } else {
-                    if (!equalsHelper( counterpart, considered,
-                        value, map2.get(key)))
-                        return false;
-                }
-            }
-        } catch(ClassCastException unused)   {
-            return false;
-        } catch(NullPointerException unused) {
-            return false;
-        }
-
-        return true;
-    }
-
-    // Obviously this is an inefficient quadratic algorithm.
-    // This is taken pretty directly from AbstractSet and AbstractCollection
-    // in the JDK.
-    // For HashSet, an O(n) (with a good hash function) algorithm
-    // is possible, and likewise TreeSet, since it is
-    // ordered, is O(n).  But this is not worth the effort here.
-    // Note that the inner loop uses equals, not equalsHelper.
-    // This is needed because of the searching behavior of this test.
-    // However, note that this will NOT correctly handle sets that
-    // contain themselves as members, or that have members that reference
-    // themselves.  These cases will cause infinite regress!
-    private static boolean equalSets( Map counterpart, Set considered,
-        Set set1, Set set2 )
-    {
-        if (set1.size() != set2.size())
-            return false ;
-
-        Iterator e1 = set1.iterator() ;
-        while (e1.hasNext()) {
-            java.lang.Object obj1 = e1.next() ;
-
-            boolean found = false ;
-            Iterator e2 = set2.iterator() ;
-            while (e2.hasNext() && !found) {
-                java.lang.Object obj2 = e2.next() ;
-                found = equals( obj1, obj2 ) ;
-            }
-
-            if (!found)
-                return false ;
-        }
-
-        return true ;
-    }
-
-    private static boolean equalLists( Map counterpart, Set considered,
-        List list1, List list2 )
-    {
-        ListIterator e1 = list1.listIterator();
-        ListIterator e2 = list2.listIterator();
-        while(e1.hasNext() && e2.hasNext()) {
-            java.lang.Object o1 = e1.next();
-            java.lang.Object o2 = e2.next();
-            if (!(o1==null ? o2==null : equalsHelper(
-                counterpart, considered, o1, o2)))
-                return false;
-        }
-        return !(e1.hasNext() || e2.hasNext());
-    }
 }
--- a/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelAcceptorImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelAcceptorImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, 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
@@ -33,14 +33,7 @@
 import java.nio.channels.SelectionKey;
 import java.nio.channels.ServerSocketChannel;
 import java.nio.channels.SocketChannel;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.Collection;
 import java.util.Iterator;
-import java.util.LinkedList;
-
-import org.omg.CORBA.CompletionStatus;
-import org.omg.CORBA.INTERNAL;
 
 import com.sun.corba.se.pept.broker.Broker;
 import com.sun.corba.se.pept.encoding.InputObject;
@@ -61,18 +54,12 @@
 import com.sun.corba.se.spi.ior.iiop.IIOPProfileTemplate ;
 import com.sun.corba.se.spi.ior.iiop.GIOPVersion ;
 import com.sun.corba.se.spi.ior.iiop.AlternateIIOPAddressComponent;
-import com.sun.corba.se.spi.legacy.connection.LegacyServerSocketEndPointInfo;
 import com.sun.corba.se.spi.logging.CORBALogDomains;
-import com.sun.corba.se.spi.monitoring.LongMonitoredAttributeBase;
-import com.sun.corba.se.spi.monitoring.MonitoringConstants;
-import com.sun.corba.se.spi.monitoring.MonitoringFactories;
-import com.sun.corba.se.spi.monitoring.MonitoredObject;
 import com.sun.corba.se.spi.orb.ORB;
 import com.sun.corba.se.spi.orbutil.threadpool.Work;
 import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
 import com.sun.corba.se.spi.transport.CorbaAcceptor;
 import com.sun.corba.se.spi.transport.CorbaConnection;
-import com.sun.corba.se.spi.transport.CorbaContactInfo;
 import com.sun.corba.se.spi.transport.SocketInfo;
 import com.sun.corba.se.spi.transport.SocketOrChannelAcceptor;
 
@@ -82,7 +69,6 @@
 import com.sun.corba.se.impl.oa.poa.Policies; // REVISIT impl/poa specific
 import com.sun.corba.se.impl.orbutil.ORBConstants;
 import com.sun.corba.se.impl.orbutil.ORBUtility;
-import com.sun.corba.se.impl.ior.iiop.JavaSerializationComponent;
 
 // BEGIN Legacy support.
 import com.sun.corba.se.spi.legacy.connection.LegacyServerSocketEndPointInfo;
@@ -442,12 +428,7 @@
                 dprint(".doWork->: " + this);
             }
             if (selectionKey.isAcceptable()) {
-                AccessController.doPrivileged(new PrivilegedAction() {
-                    public java.lang.Object run() {
                         accept();
-                        return null;
-                    }
-                });
             } else {
                 if (orb.transportDebugFlag) {
                     dprint(".doWork: ! selectionKey.isAcceptable: " + this);
--- a/corba/src/share/classes/com/sun/corba/se/spi/orb/OperationFactory.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/corba/src/share/classes/com/sun/corba/se/spi/orb/OperationFactory.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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,6 +25,7 @@
 package com.sun.corba.se.spi.orb ;
 
 import java.util.StringTokenizer ;
+import java.util.Arrays ;
 
 import java.lang.reflect.Array ;
 
@@ -446,7 +447,7 @@
         public String toString() {
             return "sequenceAction(separator=\"" + sep +
                 "\",actions=" +
-                ObjectUtility.compactObjectToString(actions) + ")" ;
+                Arrays.toString(actions) + ")" ;
         }
     }
 
@@ -533,7 +534,7 @@
 
         public String toString() {
             return "mapSequenceAction(" +
-                ObjectUtility.compactObjectToString(op) + ")" ;
+                Arrays.toString(op) + ")" ;
         }
     }
 
--- a/corba/src/share/classes/com/sun/corba/se/spi/orb/ParserImplBase.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/corba/src/share/classes/com/sun/corba/se/spi/orb/ParserImplBase.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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
@@ -125,7 +125,7 @@
                 // Since exc wraps the actual exception, use exc.getCause()
                 // instead of exc.
                 throw wrapper.errorSettingField( exc.getCause(), name,
-                    ObjectUtility.compactObjectToString(value) ) ;
+                    value.toString() ) ;
             }
         }
 
--- a/hotspot/.hgtags	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/.hgtags	Wed Jul 05 17:26:57 2017 +0200
@@ -127,3 +127,5 @@
 5511edd5d719f3fc9fdd04879482026a3d2c8652 hs20-b01
 bdbc48857210a509b3c50a3291ecb9dd6a72e016 jdk7-b115
 96b3f2a7add0b445b8aa421f6823cff5a2e2fe03 jdk7-b116
+52f19c724d9634af79044a2e0defbe4a5f1adbda hs20-b02
+806d0c037e6bbb88dac0699673f4ba55ee8c02da jdk7-b117
--- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -664,7 +664,7 @@
   // Use temps to avoid kills
   LIR_Opr t1 = FrameMap::G1_opr;
   LIR_Opr t2 = FrameMap::G3_opr;
-  LIR_Opr addr = (type == objectType) ? new_register(T_OBJECT) : new_pointer_register();
+  LIR_Opr addr = new_pointer_register();
 
   // get address of field
   obj.load_item();
--- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -62,3 +62,5 @@
 
 define_pd_global(bool, RewriteBytecodes,     true);
 define_pd_global(bool, RewriteFrequentPairs, true);
+
+define_pd_global(bool, UseMembar,            false);
--- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -499,7 +499,7 @@
   Register new_val_reg = new_val()->as_register();
   __ cmpptr(new_val_reg, (int32_t) NULL_WORD);
   __ jcc(Assembler::equal, _continuation);
-  ce->store_parameter(addr()->as_register(), 0);
+  ce->store_parameter(addr()->as_pointer_register(), 0);
   __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::g1_post_barrier_slow_id)));
   __ jmp(_continuation);
 }
--- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -765,7 +765,7 @@
     ShouldNotReachHere();
   }
 
-  LIR_Opr addr = (type == objectType) ? new_register(T_OBJECT) : new_pointer_register();
+  LIR_Opr addr = new_pointer_register();
   LIR_Address* a;
   if(offset.result()->is_constant()) {
     a = new LIR_Address(obj.result(),
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -63,3 +63,5 @@
 
 define_pd_global(bool, RewriteBytecodes,     true);
 define_pd_global(bool, RewriteFrequentPairs, true);
+
+define_pd_global(bool, UseMembar,            false);
--- a/hotspot/src/cpu/zero/vm/globals_zero.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -45,3 +45,5 @@
 
 define_pd_global(bool,  RewriteBytecodes,     true);
 define_pd_global(bool,  RewriteFrequentPairs, true);
+
+define_pd_global(bool,  UseMembar,            false);
--- a/hotspot/src/os/linux/vm/attachListener_linux.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/os/linux/vm/attachListener_linux.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -176,10 +176,10 @@
 
   int n = snprintf(path, UNIX_PATH_MAX, "%s/.java_pid%d",
                    os::get_temp_directory(), os::current_process_id());
-  if (n <= (int)UNIX_PATH_MAX) {
+  if (n < (int)UNIX_PATH_MAX) {
     n = snprintf(initial_path, UNIX_PATH_MAX, "%s.tmp", path);
   }
-  if (n > (int)UNIX_PATH_MAX) {
+  if (n >= (int)UNIX_PATH_MAX) {
     return -1;
   }
 
--- a/hotspot/src/os/linux/vm/objectMonitor_linux.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-
-/*
- * Copyright (c) 1999, 2005, 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.
- *
- */
--- a/hotspot/src/os/linux/vm/objectMonitor_linux.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 1999, 2005, 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.
- *
- */
-
- private:
--- a/hotspot/src/os/linux/vm/objectMonitor_linux.inline.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 1999, 2005, 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.
- *
- */
--- a/hotspot/src/os/linux/vm/os_linux.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/os/linux/vm/os_linux.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, 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
@@ -827,8 +827,10 @@
 
       switch (thr_type) {
       case os::java_thread:
-        // Java threads use ThreadStackSize which default value can be changed with the flag -Xss
-        if (JavaThread::stack_size_at_create() > 0) stack_size = JavaThread::stack_size_at_create();
+        // Java threads use ThreadStackSize which default value can be
+        // changed with the flag -Xss
+        assert (JavaThread::stack_size_at_create() > 0, "this should be set");
+        stack_size = JavaThread::stack_size_at_create();
         break;
       case os::compiler_thread:
         if (CompilerThreadStackSize > 0) {
@@ -3922,12 +3924,21 @@
   Linux::signal_sets_init();
   Linux::install_signal_handlers();
 
+  // Check minimum allowable stack size for thread creation and to initialize
+  // the java system classes, including StackOverflowError - depends on page
+  // size.  Add a page for compiler2 recursion in main thread.
+  // Add in 2*BytesPerWord times page size to account for VM stack during
+  // class initialization depending on 32 or 64 bit VM.
+  os::Linux::min_stack_allowed = MAX2(os::Linux::min_stack_allowed,
+            (size_t)(StackYellowPages+StackRedPages+StackShadowPages+
+                    2*BytesPerWord COMPILER2_PRESENT(+1)) * Linux::page_size());
+
   size_t threadStackSizeInBytes = ThreadStackSize * K;
   if (threadStackSizeInBytes != 0 &&
-      threadStackSizeInBytes < Linux::min_stack_allowed) {
+      threadStackSizeInBytes < os::Linux::min_stack_allowed) {
         tty->print_cr("\nThe stack size specified is too small, "
                       "Specify at least %dk",
-                      Linux::min_stack_allowed / K);
+                      os::Linux::min_stack_allowed/ K);
         return JNI_ERR;
   }
 
@@ -4839,7 +4850,7 @@
 
   // Next, demultiplex/decode time arguments
   timespec absTime;
-  if (time < 0) { // don't wait at all
+  if (time < 0 || (isAbsolute && time == 0) ) { // don't wait at all
     return;
   }
   if (time > 0) {
--- a/hotspot/src/os/solaris/vm/objectMonitor_solaris.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 1998, 2005, 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.
- *
- */
--- a/hotspot/src/os/solaris/vm/objectMonitor_solaris.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 1998, 2005, 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.
- *
- */
-
- private:
--- a/hotspot/src/os/solaris/vm/objectMonitor_solaris.inline.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 1998, 2005, 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.
- *
- */
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -4878,18 +4878,17 @@
   // Check minimum allowable stack size for thread creation and to initialize
   // the java system classes, including StackOverflowError - depends on page
   // size.  Add a page for compiler2 recursion in main thread.
-  // Add in BytesPerWord times page size to account for VM stack during
+  // Add in 2*BytesPerWord times page size to account for VM stack during
   // class initialization depending on 32 or 64 bit VM.
-  guarantee((Solaris::min_stack_allowed >=
-    (StackYellowPages+StackRedPages+StackShadowPages+BytesPerWord
-     COMPILER2_PRESENT(+1)) * page_size),
-    "need to increase Solaris::min_stack_allowed on this platform");
+  os::Solaris::min_stack_allowed = MAX2(os::Solaris::min_stack_allowed,
+            (size_t)(StackYellowPages+StackRedPages+StackShadowPages+
+                    2*BytesPerWord COMPILER2_PRESENT(+1)) * page_size);
 
   size_t threadStackSizeInBytes = ThreadStackSize * K;
   if (threadStackSizeInBytes != 0 &&
-    threadStackSizeInBytes < Solaris::min_stack_allowed) {
+    threadStackSizeInBytes < os::Solaris::min_stack_allowed) {
     tty->print_cr("\nThe stack size specified is too small, Specify at least %dk",
-                  Solaris::min_stack_allowed/K);
+                  os::Solaris::min_stack_allowed/K);
     return JNI_ERR;
   }
 
@@ -5837,7 +5836,7 @@
 
   // First, demultiplex/decode time arguments
   timespec absTime;
-  if (time < 0) { // don't wait at all
+  if (time < 0 || (isAbsolute && time == 0) ) { // don't wait at all
     return;
   }
   if (time > 0) {
--- a/hotspot/src/os/windows/vm/objectMonitor_windows.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 1998, 2005, 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.
- *
- */
-
-#include "incls/_precompiled.incl"
--- a/hotspot/src/os/windows/vm/objectMonitor_windows.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 1998, 2005, 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.
- *
- */
-
- private:
--- a/hotspot/src/os/windows/vm/objectMonitor_windows.inline.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 1998, 2005, 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.
- *
- */
--- a/hotspot/src/os/windows/vm/os_windows.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/os/windows/vm/os_windows.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -3311,7 +3311,6 @@
   }
 }
 
-
 // this is called _after_ the global arguments have been parsed
 jint os::init_2(void) {
   // Allocate a single page and mark it as readable for safepoint polling
@@ -3390,6 +3389,21 @@
     actual_reserve_size = default_reserve_size;
   }
 
+  // Check minimum allowable stack size for thread creation and to initialize
+  // the java system classes, including StackOverflowError - depends on page
+  // size.  Add a page for compiler2 recursion in main thread.
+  // Add in 2*BytesPerWord times page size to account for VM stack during
+  // class initialization depending on 32 or 64 bit VM.
+  size_t min_stack_allowed =
+            (size_t)(StackYellowPages+StackRedPages+StackShadowPages+
+            2*BytesPerWord COMPILER2_PRESENT(+1)) * os::vm_page_size();
+  if (actual_reserve_size < min_stack_allowed) {
+    tty->print_cr("\nThe stack size specified is too small, "
+                  "Specify at least %dk",
+                  min_stack_allowed / K);
+    return JNI_ERR;
+  }
+
   JavaThread::set_stack_size_at_create(stack_commit_size);
 
   // Calculate theoretical max. size of Threads to guard gainst artifical
@@ -3992,7 +4006,7 @@
   if (time < 0) { // don't wait
     return;
   }
-  else if (time == 0) {
+  else if (time == 0 && !isAbsolute) {
     time = INFINITE;
   }
   else if  (isAbsolute) {
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -1350,7 +1350,6 @@
     addr = ptr;
   }
   assert(addr->is_register(), "must be a register at this point");
-  assert(addr->type() == T_OBJECT, "addr should point to an object");
 
   LIR_Opr xor_res = new_pointer_register();
   LIR_Opr xor_shift_res = new_pointer_register();
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -4309,20 +4309,21 @@
 }
 
 
-// Unqualified names may not contain the characters '.', ';', or '/'.
-// Method names also may not contain the characters '<' or '>', unless <init> or <clinit>.
-// Note that method names may not be <init> or <clinit> in this method.
-// Because these names have been checked as special cases before calling this method
-// in verify_legal_method_name.
-bool ClassFileParser::verify_unqualified_name(char* name, unsigned int length, int type) {
+// Unqualified names may not contain the characters '.', ';', '[', or '/'.
+// Method names also may not contain the characters '<' or '>', unless <init>
+// or <clinit>.  Note that method names may not be <init> or <clinit> in this
+// method.  Because these names have been checked as special cases before
+// calling this method in verify_legal_method_name.
+bool ClassFileParser::verify_unqualified_name(
+    char* name, unsigned int length, int type) {
   jchar ch;
 
   for (char* p = name; p != name + length; ) {
     ch = *p;
     if (ch < 128) {
       p++;
-      if (ch == '.' || ch == ';') {
-        return false;   // do not permit '.' or ';'
+      if (ch == '.' || ch == ';' || ch == '[' ) {
+        return false;   // do not permit '.', ';', or '['
       }
       if (type != LegalClass && ch == '/') {
         return false;   // do not permit '/' unless it's class name
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/classfile/stackMapTableFormat.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,916 @@
+/*
+ * Copyright (c) 2010, 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.
+ *
+ */
+
+// These classes represent the stack-map substructures described in the JVMS
+// (hence the non-conforming naming scheme).
+
+// These classes work with the types in their compressed form in-place (as they
+// would appear in the classfile).  No virtual methods or fields allowed.
+
+class verification_type_info {
+ private:
+  // u1 tag
+  // u2 cpool_index || u2 bci (for ITEM_Object & ITEM_Uninitailized only)
+
+  address tag_addr() const { return (address)this; }
+  address cpool_index_addr() const { return tag_addr() + sizeof(u1); }
+  address bci_addr() const { return cpool_index_addr(); }
+
+ protected:
+  // No constructors  - should be 'private', but GCC issues a warning if it is
+  verification_type_info() {}
+  verification_type_info(const verification_type_info&) {}
+
+ public:
+
+  static verification_type_info* at(address addr) {
+    return (verification_type_info*)addr;
+  }
+
+  static verification_type_info* create_at(address addr, u1 tag) {
+    verification_type_info* vti = (verification_type_info*)addr;
+    vti->set_tag(tag);
+    return vti;
+  }
+
+  static verification_type_info* create_object_at(address addr, u2 cp_idx) {
+    verification_type_info* vti = (verification_type_info*)addr;
+    vti->set_tag(ITEM_Object);
+    vti->set_cpool_index(cp_idx);
+    return vti;
+  }
+
+  static verification_type_info* create_uninit_at(address addr, u2 bci) {
+    verification_type_info* vti = (verification_type_info*)addr;
+    vti->set_tag(ITEM_Uninitialized);
+    vti->set_bci(bci);
+    return vti;
+  }
+
+  static size_t calculate_size(u1 tag) {
+    if (tag == ITEM_Object || tag == ITEM_Uninitialized) {
+      return sizeof(u1) + sizeof(u2);
+    } else {
+      return sizeof(u1);
+    }
+  }
+
+  static size_t max_size() { return sizeof(u1) + sizeof(u2); }
+
+  u1 tag() const { return *(u1*)tag_addr(); }
+  void set_tag(u1 tag) { *((u1*)tag_addr()) = tag; }
+
+  bool is_object() const { return tag() == ITEM_Object; }
+  bool is_uninitialized() const { return tag() == ITEM_Uninitialized; }
+
+  u2 cpool_index() const {
+    assert(is_object(), "This type has no cp_index");
+    return Bytes::get_Java_u2(cpool_index_addr());
+  }
+  void set_cpool_index(u2 idx) {
+    assert(is_object(), "This type has no cp_index");
+    Bytes::put_Java_u2(cpool_index_addr(), idx);
+  }
+
+  u2 bci() const {
+    assert(is_uninitialized(), "This type has no bci");
+    return Bytes::get_Java_u2(bci_addr());
+  }
+
+  void set_bci(u2 bci) {
+    assert(is_uninitialized(), "This type has no bci");
+    Bytes::put_Java_u2(bci_addr(), bci);
+  }
+
+  void copy_from(verification_type_info* from) {
+    set_tag(from->tag());
+    if (from->is_object()) {
+      set_cpool_index(from->cpool_index());
+    } else if (from->is_uninitialized()) {
+      set_bci(from->bci());
+    }
+  }
+
+  size_t size() const {
+    return calculate_size(tag());
+  }
+
+  verification_type_info* next() {
+    return (verification_type_info*)((address)this + size());
+  }
+
+  // This method is used when reading unverified data in order to ensure
+  // that we don't read past a particular memory limit.  It returns false
+  // if any part of the data structure is outside the specified memory bounds.
+  bool verify(address start, address end) {
+    return ((address)this >= start &&
+            (address)this < end &&
+            (bci_addr() + sizeof(u2) <= end ||
+                !is_object() && !is_uninitialized()));
+  }
+
+#ifdef ASSERT
+  void print_on(outputStream* st) {
+    switch (tag()) {
+      case ITEM_Top: st->print("Top"); break;
+      case ITEM_Integer: st->print("Integer"); break;
+      case ITEM_Float: st->print("Float"); break;
+      case ITEM_Double: st->print("Double"); break;
+      case ITEM_Long: st->print("Long"); break;
+      case ITEM_Null: st->print("Null"); break;
+      case ITEM_UninitializedThis:
+        st->print("UninitializedThis"); break;
+      case ITEM_Uninitialized:
+        st->print("Uninitialized[#%d]", bci()); break;
+      case ITEM_Object:
+        st->print("Object[#%d]", cpool_index()); break;
+      default:
+        assert(false, "Bad verification_type_info");
+    }
+  }
+#endif
+};
+
+#define FOR_EACH_STACKMAP_FRAME_TYPE(macro, arg1, arg2) \
+  macro(same_frame, arg1, arg2) \
+  macro(same_frame_extended, arg1, arg2) \
+  macro(same_frame_1_stack_item_frame, arg1, arg2) \
+  macro(same_frame_1_stack_item_extended, arg1, arg2) \
+  macro(chop_frame, arg1, arg2) \
+  macro(append_frame, arg1, arg2) \
+  macro(full_frame, arg1, arg2)
+
+#define SM_FORWARD_DECL(type, arg1, arg2) class type;
+FOR_EACH_STACKMAP_FRAME_TYPE(SM_FORWARD_DECL, x, x)
+#undef SM_FORWARD_DECL
+
+class stack_map_frame {
+ protected:
+  address frame_type_addr() const { return (address)this; }
+
+  // No constructors  - should be 'private', but GCC issues a warning if it is
+  stack_map_frame() {}
+  stack_map_frame(const stack_map_frame&) {}
+
+ public:
+
+  static stack_map_frame* at(address addr) {
+    return (stack_map_frame*)addr;
+  }
+
+  stack_map_frame* next() const {
+    return at((address)this + size());
+  }
+
+  u1 frame_type() const { return *(u1*)frame_type_addr(); }
+  void set_frame_type(u1 type) { *((u1*)frame_type_addr()) = type; }
+
+  // pseudo-virtual methods
+  inline size_t size() const;
+  inline int offset_delta() const;
+  inline void set_offset_delta(int offset_delta);
+  inline int number_of_types() const; // number of types contained in the frame
+  inline verification_type_info* types() const; // pointer to first type
+  inline bool is_valid_offset(int offset_delta) const;
+
+  // This method must be used when reading unverified data in order to ensure
+  // that we don't read past a particular memory limit.  It returns false
+  // if any part of the data structure is outside the specified memory bounds.
+  inline bool verify(address start, address end) const;
+#ifdef ASSERT
+  inline void print_on(outputStream* st) const;
+#endif
+
+  // Create as_xxx and is_xxx methods for the subtypes
+#define FRAME_TYPE_DECL(stackmap_frame_type, arg1, arg2) \
+  inline stackmap_frame_type* as_##stackmap_frame_type() const; \
+  bool is_##stackmap_frame_type() { \
+    return as_##stackmap_frame_type() != NULL; \
+  }
+
+  FOR_EACH_STACKMAP_FRAME_TYPE(FRAME_TYPE_DECL, x, x)
+#undef FRAME_TYPE_DECL
+};
+
+class same_frame : public stack_map_frame {
+ private:
+  static int frame_type_to_offset_delta(u1 frame_type) {
+      return frame_type + 1; }
+  static u1 offset_delta_to_frame_type(int offset_delta) {
+      return (u1)(offset_delta - 1); }
+
+ public:
+
+  static bool is_frame_type(u1 tag) {
+    return tag < 64;
+  }
+
+  static same_frame* at(address addr) {
+    assert(is_frame_type(*addr), "Wrong frame id");
+    return (same_frame*)addr;
+  }
+
+  static same_frame* create_at(address addr, int offset_delta) {
+    same_frame* sm = (same_frame*)addr;
+    sm->set_offset_delta(offset_delta);
+    return sm;
+  }
+
+  static size_t calculate_size() { return sizeof(u1); }
+
+  size_t size() const { return calculate_size(); }
+  int offset_delta() const { return frame_type_to_offset_delta(frame_type()); }
+
+  void set_offset_delta(int offset_delta) {
+    assert(offset_delta <= 64, "Offset too large for same_frame");
+    set_frame_type(offset_delta_to_frame_type(offset_delta));
+  }
+
+  int number_of_types() const { return 0; }
+  verification_type_info* types() const { return NULL; }
+
+  bool is_valid_offset(int offset_delta) const {
+    return is_frame_type(offset_delta_to_frame_type(offset_delta));
+  }
+
+  bool verify_subtype(address start, address end) const {
+    return true;
+  }
+
+#ifdef ASSERT
+  void print_on(outputStream* st) const {
+    st->print("same_frame(%d)", offset_delta());
+  }
+#endif
+};
+
+class same_frame_extended : public stack_map_frame {
+ private:
+  enum { _frame_id = 251 };
+  address offset_delta_addr() const { return frame_type_addr() + sizeof(u1); }
+
+ public:
+  static bool is_frame_type(u1 tag) {
+    return tag == _frame_id;
+  }
+
+  static same_frame_extended* at(address addr) {
+    assert(is_frame_type(*addr), "Wrong frame type");
+    return (same_frame_extended*)addr;
+  }
+
+  static same_frame_extended* create_at(address addr, u2 offset_delta) {
+    same_frame_extended* sm = (same_frame_extended*)addr;
+    sm->set_frame_type(_frame_id);
+    sm->set_offset_delta(offset_delta);
+    return sm;
+  }
+
+  static size_t calculate_size() { return sizeof(u1) + sizeof(u2); }
+
+  size_t size() const { return calculate_size(); }
+  int offset_delta() const {
+    return Bytes::get_Java_u2(offset_delta_addr()) + 1;
+  }
+
+  void set_offset_delta(int offset_delta) {
+    Bytes::put_Java_u2(offset_delta_addr(), offset_delta - 1);
+  }
+
+  int number_of_types() const { return 0; }
+  verification_type_info* types() const { return NULL; }
+  bool is_valid_offset(int offset) const { return true; }
+
+  bool verify_subtype(address start, address end) const {
+    return frame_type_addr() + size() <= end;
+  }
+
+#ifdef ASSERT
+  void print_on(outputStream* st) const {
+    st->print("same_frame_extended(%d)", offset_delta());
+  }
+#endif
+};
+
+class same_frame_1_stack_item_frame : public stack_map_frame {
+ private:
+  address type_addr() const { return frame_type_addr() + sizeof(u1); }
+
+  static int frame_type_to_offset_delta(u1 frame_type) {
+      return frame_type - 63; }
+  static u1 offset_delta_to_frame_type(int offset_delta) {
+      return (u1)(offset_delta + 63); }
+
+ public:
+  static bool is_frame_type(u1 tag) {
+    return tag >= 64 && tag < 128;
+  }
+
+  static same_frame_1_stack_item_frame* at(address addr) {
+    assert(is_frame_type(*addr), "Wrong frame id");
+    return (same_frame_1_stack_item_frame*)addr;
+  }
+
+  static same_frame_1_stack_item_frame* create_at(
+      address addr, int offset_delta, verification_type_info* vti) {
+    same_frame_1_stack_item_frame* sm = (same_frame_1_stack_item_frame*)addr;
+    sm->set_offset_delta(offset_delta);
+    if (vti != NULL) {
+      sm->set_type(vti);
+    }
+    return sm;
+  }
+
+  static size_t calculate_size(verification_type_info* vti) {
+    return sizeof(u1) + vti->size();
+  }
+
+  static size_t max_size() {
+    return sizeof(u1) + verification_type_info::max_size();
+  }
+
+  size_t size() const { return calculate_size(types()); }
+  int offset_delta() const { return frame_type_to_offset_delta(frame_type()); }
+
+  void set_offset_delta(int offset_delta) {
+    assert(offset_delta > 0 && offset_delta <= 64,
+           "Offset too large for this frame type");
+    set_frame_type(offset_delta_to_frame_type(offset_delta));
+  }
+
+  void set_type(verification_type_info* vti) {
+    verification_type_info* cur = types();
+    cur->copy_from(vti);
+  }
+
+  int number_of_types() const { return 1; }
+  verification_type_info* types() const {
+    return verification_type_info::at(type_addr());
+  }
+
+  bool is_valid_offset(int offset_delta) const {
+    return is_frame_type(offset_delta_to_frame_type(offset_delta));
+  }
+
+  bool verify_subtype(address start, address end) const {
+    return types()->verify(start, end);
+  }
+
+#ifdef ASSERT
+  void print_on(outputStream* st) const {
+    st->print("same_frame_1_stack_item_frame(%d,", offset_delta());
+    types()->print_on(st);
+    st->print(")");
+  }
+#endif
+};
+
+class same_frame_1_stack_item_extended : public stack_map_frame {
+ private:
+  address offset_delta_addr() const { return frame_type_addr() + sizeof(u1); }
+  address type_addr() const { return offset_delta_addr() + sizeof(u2); }
+
+  enum { _frame_id = 247 };
+
+ public:
+  static bool is_frame_type(u1 tag) {
+    return tag == _frame_id;
+  }
+
+  static same_frame_1_stack_item_extended* at(address addr) {
+    assert(is_frame_type(*addr), "Wrong frame id");
+    return (same_frame_1_stack_item_extended*)addr;
+  }
+
+  static same_frame_1_stack_item_extended* create_at(
+      address addr, int offset_delta, verification_type_info* vti) {
+    same_frame_1_stack_item_extended* sm =
+       (same_frame_1_stack_item_extended*)addr;
+    sm->set_frame_type(_frame_id);
+    sm->set_offset_delta(offset_delta);
+    if (vti != NULL) {
+      sm->set_type(vti);
+    }
+    return sm;
+  }
+
+  static size_t calculate_size(verification_type_info* vti) {
+    return sizeof(u1) + sizeof(u2) + vti->size();
+  }
+
+  size_t size() const { return calculate_size(types()); }
+  int offset_delta() const {
+    return Bytes::get_Java_u2(offset_delta_addr()) + 1;
+  }
+
+  void set_offset_delta(int offset_delta) {
+    Bytes::put_Java_u2(offset_delta_addr(), offset_delta - 1);
+  }
+
+  void set_type(verification_type_info* vti) {
+    verification_type_info* cur = types();
+    cur->copy_from(vti);
+  }
+
+  int number_of_types() const { return 1; }
+  verification_type_info* types() const {
+    return verification_type_info::at(type_addr());
+  }
+  bool is_valid_offset(int offset) { return true; }
+
+  bool verify_subtype(address start, address end) const {
+    return type_addr() < end && types()->verify(start, end);
+  }
+
+#ifdef ASSERT
+  void print_on(outputStream* st) const {
+    st->print("same_frame_1_stack_item_extended(%d,", offset_delta());
+    types()->print_on(st);
+    st->print(")");
+  }
+#endif
+};
+
+class chop_frame : public stack_map_frame {
+ private:
+  address offset_delta_addr() const { return frame_type_addr() + sizeof(u1); }
+
+  static int frame_type_to_chops(u1 frame_type) {
+    int chop = 251 - frame_type;
+    return chop;
+  }
+
+  static u1 chops_to_frame_type(int chop) {
+    return 251 - chop;
+  }
+
+ public:
+  static bool is_frame_type(u1 tag) {
+    return frame_type_to_chops(tag) > 0 && frame_type_to_chops(tag) < 4;
+  }
+
+  static chop_frame* at(address addr) {
+    assert(is_frame_type(*addr), "Wrong frame id");
+    return (chop_frame*)addr;
+  }
+
+  static chop_frame* create_at(address addr, int offset_delta, int chops) {
+    chop_frame* sm = (chop_frame*)addr;
+    sm->set_chops(chops);
+    sm->set_offset_delta(offset_delta);
+    return sm;
+  }
+
+  static size_t calculate_size() {
+    return sizeof(u1) + sizeof(u2);
+  }
+
+  size_t size() const { return calculate_size(); }
+  int offset_delta() const {
+    return Bytes::get_Java_u2(offset_delta_addr()) + 1;
+  }
+  void set_offset_delta(int offset_delta) {
+    Bytes::put_Java_u2(offset_delta_addr(), offset_delta - 1);
+  }
+
+  int chops() const {
+    int chops = frame_type_to_chops(frame_type());
+    assert(chops > 0 && chops < 4, "Invalid number of chops in frame");
+    return chops;
+  }
+  void set_chops(int chops) {
+    assert(chops > 0 && chops <= 3, "Bad number of chops");
+    set_frame_type(chops_to_frame_type(chops));
+  }
+
+  int number_of_types() const { return 0; }
+  verification_type_info* types() const { return NULL; }
+  bool is_valid_offset(int offset) { return true; }
+
+  bool verify_subtype(address start, address end) const {
+    return frame_type_addr() + size() <= end;
+  }
+
+#ifdef ASSERT
+  void print_on(outputStream* st) const {
+    st->print("chop_frame(%d,%d)", offset_delta(), chops());
+  }
+#endif
+};
+
+class append_frame : public stack_map_frame {
+ private:
+  address offset_delta_addr() const { return frame_type_addr() + sizeof(u1); }
+  address types_addr() const { return offset_delta_addr() + sizeof(u2); }
+
+  static int frame_type_to_appends(u1 frame_type) {
+    int append = frame_type - 251;
+    return append;
+  }
+
+  static u1 appends_to_frame_type(int appends) {
+    assert(appends > 0 && appends < 4, "Invalid append amount");
+    return 251 + appends;
+  }
+
+ public:
+  static bool is_frame_type(u1 tag) {
+    return frame_type_to_appends(tag) > 0 && frame_type_to_appends(tag) < 4;
+  }
+
+  static append_frame* at(address addr) {
+    assert(is_frame_type(*addr), "Wrong frame id");
+    return (append_frame*)addr;
+  }
+
+  static append_frame* create_at(
+      address addr, int offset_delta, int appends,
+      verification_type_info* types) {
+    append_frame* sm = (append_frame*)addr;
+    sm->set_appends(appends);
+    sm->set_offset_delta(offset_delta);
+    if (types != NULL) {
+      verification_type_info* cur = sm->types();
+      for (int i = 0; i < appends; ++i) {
+        cur->copy_from(types);
+        cur = cur->next();
+        types = types->next();
+      }
+    }
+    return sm;
+  }
+
+  static size_t calculate_size(int appends, verification_type_info* types) {
+    size_t sz = sizeof(u1) + sizeof(u2);
+    for (int i = 0; i < appends; ++i) {
+      sz += types->size();
+      types = types->next();
+    }
+    return sz;
+  }
+
+  static size_t max_size() {
+    return sizeof(u1) + sizeof(u2) + 3 * verification_type_info::max_size();
+  }
+
+  size_t size() const { return calculate_size(number_of_types(), types()); }
+  int offset_delta() const {
+    return Bytes::get_Java_u2(offset_delta_addr()) + 1;
+  }
+
+  void set_offset_delta(int offset_delta) {
+    Bytes::put_Java_u2(offset_delta_addr(), offset_delta - 1);
+  }
+
+  void set_appends(int appends) {
+    assert(appends > 0 && appends < 4, "Bad number of appends");
+    set_frame_type(appends_to_frame_type(appends));
+  }
+
+  int number_of_types() const {
+    int appends = frame_type_to_appends(frame_type());
+    assert(appends > 0 && appends < 4, "Invalid number of appends in frame");
+    return appends;
+  }
+  verification_type_info* types() const {
+    return verification_type_info::at(types_addr());
+  }
+  bool is_valid_offset(int offset) const { return true; }
+
+  bool verify_subtype(address start, address end) const {
+    verification_type_info* vti = types();
+    if ((address)vti < end && vti->verify(start, end)) {
+      int nof = number_of_types();
+      vti = vti->next();
+      if (nof < 2 || vti->verify(start, end)) {
+        vti = vti->next();
+        if (nof < 3 || vti->verify(start, end)) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+#ifdef ASSERT
+  void print_on(outputStream* st) const {
+    st->print("append_frame(%d,", offset_delta());
+    verification_type_info* vti = types();
+    for (int i = 0; i < number_of_types(); ++i) {
+      vti->print_on(st);
+      if (i != number_of_types() - 1) {
+        st->print(",");
+      }
+      vti = vti->next();
+    }
+    st->print(")");
+  }
+#endif
+};
+
+class full_frame : public stack_map_frame {
+ private:
+  address offset_delta_addr() const { return frame_type_addr() + sizeof(u1); }
+  address num_locals_addr() const { return offset_delta_addr() + sizeof(u2); }
+  address locals_addr() const { return num_locals_addr() + sizeof(u2); }
+  address stack_slots_addr(address end_of_locals) const {
+      return end_of_locals; }
+  address stack_addr(address end_of_locals) const {
+      return stack_slots_addr(end_of_locals) + sizeof(u2); }
+
+  enum { _frame_id = 255 };
+
+ public:
+  static bool is_frame_type(u1 tag) {
+    return tag == _frame_id;
+  }
+
+  static full_frame* at(address addr) {
+    assert(is_frame_type(*addr), "Wrong frame id");
+    return (full_frame*)addr;
+  }
+
+  static full_frame* create_at(
+      address addr, int offset_delta, int num_locals,
+      verification_type_info* locals,
+      int stack_slots, verification_type_info* stack) {
+    full_frame* sm = (full_frame*)addr;
+    sm->set_frame_type(_frame_id);
+    sm->set_offset_delta(offset_delta);
+    sm->set_num_locals(num_locals);
+    if (locals != NULL) {
+      verification_type_info* cur = sm->locals();
+      for (int i = 0; i < num_locals; ++i) {
+        cur->copy_from(locals);
+        cur = cur->next();
+        locals = locals->next();
+      }
+      address end_of_locals = (address)cur;
+      sm->set_stack_slots(end_of_locals, stack_slots);
+      cur = sm->stack(end_of_locals);
+      for (int i = 0; i < stack_slots; ++i) {
+        cur->copy_from(stack);
+        cur = cur->next();
+        stack = stack->next();
+      }
+    }
+    return sm;
+  }
+
+  static size_t calculate_size(
+      int num_locals, verification_type_info* locals,
+      int stack_slots, verification_type_info* stack) {
+    size_t sz = sizeof(u1) + sizeof(u2) + sizeof(u2) + sizeof(u2);
+    verification_type_info* vti = locals;
+    for (int i = 0; i < num_locals; ++i) {
+      sz += vti->size();
+      vti = vti->next();
+    }
+    vti = stack;
+    for (int i = 0; i < stack_slots; ++i) {
+      sz += vti->size();
+      vti = vti->next();
+    }
+    return sz;
+  }
+
+  static size_t max_size(int locals, int stack) {
+    return sizeof(u1) + 3 * sizeof(u2) +
+        (locals + stack) * verification_type_info::max_size();
+  }
+
+  size_t size() const {
+    address eol = end_of_locals();
+    return calculate_size(num_locals(), locals(), stack_slots(eol), stack(eol));
+  }
+
+  int offset_delta() const {
+    return Bytes::get_Java_u2(offset_delta_addr()) + 1;
+  }
+  int num_locals() const { return Bytes::get_Java_u2(num_locals_addr()); }
+  verification_type_info* locals() const {
+    return verification_type_info::at(locals_addr());
+  }
+  address end_of_locals() const {
+    verification_type_info* vti = locals();
+    for (int i = 0; i < num_locals(); ++i) {
+      vti = vti->next();
+    }
+    return (address)vti;
+  }
+  int stack_slots(address end_of_locals) const {
+    return Bytes::get_Java_u2(stack_slots_addr(end_of_locals));
+  }
+  verification_type_info* stack(address end_of_locals) const {
+    return verification_type_info::at(stack_addr(end_of_locals));
+  }
+
+  void set_offset_delta(int offset_delta) {
+    Bytes::put_Java_u2(offset_delta_addr(), offset_delta - 1);
+  }
+  void set_num_locals(int num_locals) {
+    Bytes::put_Java_u2(num_locals_addr(), num_locals);
+  }
+  void set_stack_slots(address end_of_locals, int stack_slots) {
+    Bytes::put_Java_u2(stack_slots_addr(end_of_locals), stack_slots);
+  }
+
+  // These return only the locals.  Extra processing is required for stack
+  // types of full frames.
+  int number_of_types() const { return num_locals(); }
+  verification_type_info* types() const { return locals(); }
+  bool is_valid_offset(int offset) { return true; }
+
+  bool verify_subtype(address start, address end) const {
+    verification_type_info* vti = types();
+    if ((address)vti >= end) {
+      return false;
+    }
+    int count = number_of_types();
+    for (int i = 0; i < count; ++i) {
+      if (!vti->verify(start, end)) {
+        return false;
+      }
+      vti = vti->next();
+    }
+    address eol = (address)vti;
+    if (eol + sizeof(u2) > end) {
+      return false;
+    }
+    count = stack_slots(eol);
+    vti = stack(eol);
+    for (int i = 0; i < stack_slots(eol); ++i) {
+      if (!vti->verify(start, end)) {
+        return false;
+      }
+      vti = vti->next();
+    }
+    return true;
+  }
+
+#ifdef ASSERT
+  void print_on(outputStream* st) const {
+    st->print("full_frame(%d,{", offset_delta());
+    verification_type_info* vti = locals();
+    for (int i = 0; i < num_locals(); ++i) {
+      vti->print_on(st);
+      if (i != num_locals() - 1) {
+        st->print(",");
+      }
+      vti = vti->next();
+    }
+    st->print("},{");
+    address end_of_locals = (address)vti;
+    vti = stack(end_of_locals);
+    int ss = stack_slots(end_of_locals);
+    for (int i = 0; i < ss; ++i) {
+      vti->print_on(st);
+      if (i != ss - 1) {
+        st->print(",");
+      }
+      vti = vti->next();
+    }
+    st->print("})");
+  }
+#endif
+};
+
+#define VIRTUAL_DISPATCH(stack_frame_type, func_name, args) \
+  stack_frame_type* item_##stack_frame_type = as_##stack_frame_type(); \
+  if (item_##stack_frame_type != NULL) { \
+    return item_##stack_frame_type->func_name args;  \
+  }
+
+#define VOID_VIRTUAL_DISPATCH(stack_frame_type, func_name, args) \
+  stack_frame_type* item_##stack_frame_type = as_##stack_frame_type(); \
+  if (item_##stack_frame_type != NULL) { \
+    item_##stack_frame_type->func_name args;  \
+    return; \
+  }
+
+size_t stack_map_frame::size() const {
+  FOR_EACH_STACKMAP_FRAME_TYPE(VIRTUAL_DISPATCH, size, ());
+  return 0;
+}
+
+int stack_map_frame::offset_delta() const {
+  FOR_EACH_STACKMAP_FRAME_TYPE(VIRTUAL_DISPATCH, offset_delta, ());
+  return 0;
+}
+
+void stack_map_frame::set_offset_delta(int offset_delta) {
+  FOR_EACH_STACKMAP_FRAME_TYPE(
+      VOID_VIRTUAL_DISPATCH, set_offset_delta, (offset_delta));
+}
+
+int stack_map_frame::number_of_types() const {
+  FOR_EACH_STACKMAP_FRAME_TYPE(VIRTUAL_DISPATCH, number_of_types, ());
+  return 0;
+}
+
+verification_type_info* stack_map_frame::types() const {
+  FOR_EACH_STACKMAP_FRAME_TYPE(VIRTUAL_DISPATCH, types, ());
+  return NULL;
+}
+
+bool stack_map_frame::is_valid_offset(int offset) const {
+  FOR_EACH_STACKMAP_FRAME_TYPE(VIRTUAL_DISPATCH, is_valid_offset, (offset));
+  return true;
+}
+
+bool stack_map_frame::verify(address start, address end) const {
+  if (frame_type_addr() >= start && frame_type_addr() < end) {
+    FOR_EACH_STACKMAP_FRAME_TYPE(
+       VIRTUAL_DISPATCH, verify_subtype, (start, end));
+  }
+  return false;
+}
+
+#ifdef ASSERT
+void stack_map_frame::print_on(outputStream* st) const {
+  FOR_EACH_STACKMAP_FRAME_TYPE(VOID_VIRTUAL_DISPATCH, print_on, (st));
+}
+#endif
+
+#undef VIRTUAL_DISPATCH
+#undef VOID_VIRTUAL_DISPATCH
+
+#define AS_SUBTYPE_DEF(stack_frame_type, arg1, arg2) \
+stack_frame_type* stack_map_frame::as_##stack_frame_type() const { \
+  if (stack_frame_type::is_frame_type(frame_type())) { \
+    return (stack_frame_type*)this; \
+  } else { \
+    return NULL; \
+  } \
+}
+
+FOR_EACH_STACKMAP_FRAME_TYPE(AS_SUBTYPE_DEF, x, x)
+#undef AS_SUBTYPE_DEF
+
+class stack_map_table_attribute {
+ private:
+  address name_index_addr() const {
+      return (address)this; }
+  address attribute_length_addr() const {
+      return name_index_addr() + sizeof(u2); }
+  address number_of_entries_addr() const {
+      return attribute_length_addr() + sizeof(u4); }
+  address entries_addr() const {
+      return number_of_entries_addr() + sizeof(u2); }
+
+ protected:
+  // No constructors  - should be 'private', but GCC issues a warning if it is
+  stack_map_table_attribute() {}
+  stack_map_table_attribute(const stack_map_table_attribute&) {}
+
+ public:
+
+  static stack_map_table_attribute* at(address addr) {
+    return (stack_map_table_attribute*)addr;
+  }
+
+  u2 name_index() const {
+       return Bytes::get_Java_u2(name_index_addr()); }
+  u4 attribute_length() const {
+      return Bytes::get_Java_u4(attribute_length_addr()); }
+  u2 number_of_entries() const {
+      return Bytes::get_Java_u2(number_of_entries_addr()); }
+  stack_map_frame* entries() const {
+    return stack_map_frame::at(entries_addr());
+  }
+
+  static size_t header_size() {
+      return sizeof(u2) + sizeof(u4);
+  }
+
+  void set_name_index(u2 idx) {
+    Bytes::put_Java_u2(name_index_addr(), idx);
+  }
+  void set_attribute_length(u4 len) {
+    Bytes::put_Java_u4(attribute_length_addr(), len);
+  }
+  void set_number_of_entries(u2 num) {
+    Bytes::put_Java_u2(number_of_entries_addr(), num);
+  }
+};
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -354,12 +354,8 @@
 double CMSStats::time_until_cms_gen_full() const {
   size_t cms_free = _cms_gen->cmsSpace()->free();
   GenCollectedHeap* gch = GenCollectedHeap::heap();
-  size_t expected_promotion = gch->get_gen(0)->capacity();
-  if (HandlePromotionFailure) {
-    expected_promotion = MIN2(
-        (size_t) _cms_gen->gc_stats()->avg_promoted()->padded_average(),
-        expected_promotion);
-  }
+  size_t expected_promotion = MIN2(gch->get_gen(0)->capacity(),
+                                   (size_t) _cms_gen->gc_stats()->avg_promoted()->padded_average());
   if (cms_free > expected_promotion) {
     // Start a cms collection if there isn't enough space to promote
     // for the next minor collection.  Use the padded average as
@@ -865,57 +861,18 @@
   return free() + _virtual_space.uncommitted_size();
 }
 
-bool ConcurrentMarkSweepGeneration::promotion_attempt_is_safe(
-    size_t max_promotion_in_bytes,
-    bool younger_handles_promotion_failure) const {
-
-  // This is the most conservative test.  Full promotion is
-  // guaranteed if this is used. The multiplicative factor is to
-  // account for the worst case "dilatation".
-  double adjusted_max_promo_bytes = _dilatation_factor * max_promotion_in_bytes;
-  if (adjusted_max_promo_bytes > (double)max_uintx) { // larger than size_t
-    adjusted_max_promo_bytes = (double)max_uintx;
-  }
-  bool result = (max_contiguous_available() >= (size_t)adjusted_max_promo_bytes);
-
-  if (younger_handles_promotion_failure && !result) {
-    // Full promotion is not guaranteed because fragmentation
-    // of the cms generation can prevent the full promotion.
-    result = (max_available() >= (size_t)adjusted_max_promo_bytes);
-
-    if (!result) {
-      // With promotion failure handling the test for the ability
-      // to support the promotion does not have to be guaranteed.
-      // Use an average of the amount promoted.
-      result = max_available() >= (size_t)
-        gc_stats()->avg_promoted()->padded_average();
-      if (PrintGC && Verbose && result) {
-        gclog_or_tty->print_cr(
-          "\nConcurrentMarkSweepGeneration::promotion_attempt_is_safe"
-          " max_available: " SIZE_FORMAT
-          " avg_promoted: " SIZE_FORMAT,
-          max_available(), (size_t)
-          gc_stats()->avg_promoted()->padded_average());
-      }
-    } else {
-      if (PrintGC && Verbose) {
-        gclog_or_tty->print_cr(
-          "\nConcurrentMarkSweepGeneration::promotion_attempt_is_safe"
-          " max_available: " SIZE_FORMAT
-          " adj_max_promo_bytes: " SIZE_FORMAT,
-          max_available(), (size_t)adjusted_max_promo_bytes);
-      }
-    }
-  } else {
-    if (PrintGC && Verbose) {
-      gclog_or_tty->print_cr(
-        "\nConcurrentMarkSweepGeneration::promotion_attempt_is_safe"
-        " contiguous_available: " SIZE_FORMAT
-        " adj_max_promo_bytes: " SIZE_FORMAT,
-        max_contiguous_available(), (size_t)adjusted_max_promo_bytes);
-    }
-  }
-  return result;
+bool ConcurrentMarkSweepGeneration::promotion_attempt_is_safe(size_t max_promotion_in_bytes) const {
+  size_t available = max_available();
+  size_t av_promo  = (size_t)gc_stats()->avg_promoted()->padded_average();
+  bool   res = (available >= av_promo) || (available >= max_promotion_in_bytes);
+  if (PrintGC && Verbose) {
+    gclog_or_tty->print_cr(
+      "CMS: promo attempt is%s safe: available("SIZE_FORMAT") %s av_promo("SIZE_FORMAT"),"
+      "max_promo("SIZE_FORMAT")",
+      res? "":" not", available, res? ">=":"<",
+      av_promo, max_promotion_in_bytes);
+  }
+  return res;
 }
 
 // At a promotion failure dump information on block layout in heap
@@ -6091,23 +6048,14 @@
   assert(_collectorState == Resizing, "Change of collector state to"
     " Resizing must be done under the freelistLocks (plural)");
 
-  // Now that sweeping has been completed, if the GCH's
-  // incremental_collection_will_fail flag is set, clear it,
+  // Now that sweeping has been completed, we clear
+  // the incremental_collection_failed flag,
   // thus inviting a younger gen collection to promote into
   // this generation. If such a promotion may still fail,
   // the flag will be set again when a young collection is
   // attempted.
-  // I think the incremental_collection_will_fail flag's use
-  // is specific to a 2 generation collection policy, so i'll
-  // assert that that's the configuration we are operating within.
-  // The use of the flag can and should be generalized appropriately
-  // in the future to deal with a general n-generation system.
-
   GenCollectedHeap* gch = GenCollectedHeap::heap();
-  assert(gch->collector_policy()->is_two_generation_policy(),
-         "Resetting of incremental_collection_will_fail flag"
-         " may be incorrect otherwise");
-  gch->clear_incremental_collection_will_fail();
+  gch->clear_incremental_collection_failed();  // Worth retrying as fresh space may have been freed up
   gch->update_full_collections_completed(_collection_count_start);
 }
 
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -1185,8 +1185,7 @@
   virtual void par_promote_alloc_done(int thread_num);
   virtual void par_oop_since_save_marks_iterate_done(int thread_num);
 
-  virtual bool promotion_attempt_is_safe(size_t promotion_in_bytes,
-    bool younger_handles_promotion_failure) const;
+  virtual bool promotion_attempt_is_safe(size_t promotion_in_bytes) const;
 
   // Inform this (non-young) generation that a promotion failure was
   // encountered during a collection of a younger generation that
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, 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
@@ -272,12 +272,16 @@
   }
 }
 
-// Wait until the next synchronous GC or a timeout, whichever is earlier.
-void ConcurrentMarkSweepThread::wait_on_cms_lock(long t) {
+// Wait until the next synchronous GC, a concurrent full gc request,
+// or a timeout, whichever is earlier.
+void ConcurrentMarkSweepThread::wait_on_cms_lock(long t_millis) {
   MutexLockerEx x(CGC_lock,
                   Mutex::_no_safepoint_check_flag);
+  if (_should_terminate || _collector->_full_gc_requested) {
+    return;
+  }
   set_CMS_flag(CMS_cms_wants_token);   // to provoke notifies
-  CGC_lock->wait(Mutex::_no_safepoint_check_flag, t);
+  CGC_lock->wait(Mutex::_no_safepoint_check_flag, t_millis);
   clear_CMS_flag(CMS_cms_wants_token);
   assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token),
          "Should not be set");
@@ -289,7 +293,8 @@
       icms_wait();
       return;
     } else {
-      // Wait until the next synchronous GC or a timeout, whichever is earlier
+      // Wait until the next synchronous GC, a concurrent full gc
+      // request or a timeout, whichever is earlier.
       wait_on_cms_lock(CMSWaitDuration);
     }
     // Check if we should start a CMS collection cycle
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -120,8 +120,10 @@
   }
 
   // Wait on CMS lock until the next synchronous GC
-  // or given timeout, whichever is earlier.
-  void    wait_on_cms_lock(long t); // milliseconds
+  // or given timeout, whichever is earlier. A timeout value
+  // of 0 indicates that there is no upper bound on the wait time.
+  // A concurrent full gc request terminates the wait.
+  void wait_on_cms_lock(long t_millis);
 
   // The CMS thread will yield during the work portion of its cycle
   // only when requested to.  Both synchronous and asychronous requests
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -2418,6 +2418,8 @@
   for (int i = 0; i < (int)_max_task_num; ++i) {
     OopTaskQueue* queue = _task_queues->queue(i);
     queue->set_empty();
+    // Clear any partial regions from the CMTasks
+    _tasks[i]->clear_aborted_region();
   }
 }
 
@@ -2706,7 +2708,6 @@
   clear_marking_state();
   for (int i = 0; i < (int)_max_task_num; ++i) {
     _tasks[i]->clear_region_fields();
-    _tasks[i]->clear_aborted_region();
   }
   _has_aborted = true;
 
@@ -2985,7 +2986,7 @@
 
   _nextMarkBitMap                = nextMarkBitMap;
   clear_region_fields();
-  clear_aborted_region();
+  assert(_aborted_region.is_empty(), "should have been cleared");
 
   _calls                         = 0;
   _elapsed_time_ms               = 0.0;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -175,7 +175,7 @@
   }
   assert(start_card > _array->index_for(_bottom), "Cannot be first card");
   assert(_array->offset_array(start_card-1) <= N_words,
-    "Offset card has an unexpected value");
+         "Offset card has an unexpected value");
   size_t start_card_for_region = start_card;
   u_char offset = max_jubyte;
   for (int i = 0; i < BlockOffsetArray::N_powers; i++) {
@@ -577,6 +577,16 @@
 #endif
 }
 
+void
+G1BlockOffsetArray::set_for_starts_humongous(HeapWord* new_end) {
+  assert(_end ==  new_end, "_end should have already been updated");
+
+  // The first BOT entry should have offset 0.
+  _array->set_offset_array(_array->index_for(_bottom), 0);
+  // The rest should point to the first one.
+  set_remainder_to_point_to_start(_bottom + N_words, new_end);
+}
+
 //////////////////////////////////////////////////////////////////////
 // G1BlockOffsetArrayContigSpace
 //////////////////////////////////////////////////////////////////////
@@ -626,3 +636,12 @@
          "Precondition of call");
   _array->set_offset_array(bottom_index, 0);
 }
+
+void
+G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_end) {
+  G1BlockOffsetArray::set_for_starts_humongous(new_end);
+
+  // Make sure _next_offset_threshold and _next_offset_index point to new_end.
+  _next_offset_threshold = new_end;
+  _next_offset_index     = _array->index_for(new_end);
+}
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -436,6 +436,8 @@
   }
 
   void check_all_cards(size_t left_card, size_t right_card) const;
+
+  virtual void set_for_starts_humongous(HeapWord* new_end);
 };
 
 // A subtype of BlockOffsetArray that takes advantage of the fact
@@ -484,4 +486,6 @@
 
   HeapWord* block_start_unsafe(const void* addr);
   HeapWord* block_start_unsafe_const(const void* addr) const;
+
+  virtual void set_for_starts_humongous(HeapWord* new_end);
 };
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -791,7 +791,7 @@
   int                _worker_i;
 public:
   RebuildRSOutOfRegionClosure(G1CollectedHeap* g1, int worker_i = 0) :
-    _cl(g1->g1_rem_set()->as_HRInto_G1RemSet(), worker_i),
+    _cl(g1->g1_rem_set(), worker_i),
     _worker_i(worker_i),
     _g1h(g1)
   { }
@@ -890,7 +890,7 @@
     abandon_cur_alloc_region();
     abandon_gc_alloc_regions();
     assert(_cur_alloc_region == NULL, "Invariant.");
-    g1_rem_set()->as_HRInto_G1RemSet()->cleanupHRRS();
+    g1_rem_set()->cleanupHRRS();
     tear_down_region_lists();
     set_used_regions_to_need_zero_fill();
 
@@ -1506,15 +1506,11 @@
   }
 
   // Also create a G1 rem set.
-  if (G1UseHRIntoRS) {
-    if (mr_bs()->is_a(BarrierSet::CardTableModRef)) {
-      _g1_rem_set = new HRInto_G1RemSet(this, (CardTableModRefBS*)mr_bs());
-    } else {
-      vm_exit_during_initialization("G1 requires a cardtable mod ref bs.");
-      return JNI_ENOMEM;
-    }
+  if (mr_bs()->is_a(BarrierSet::CardTableModRef)) {
+    _g1_rem_set = new G1RemSet(this, (CardTableModRefBS*)mr_bs());
   } else {
-    _g1_rem_set = new StupidG1RemSet(this);
+    vm_exit_during_initialization("G1 requires a cardtable mod ref bs.");
+    return JNI_ENOMEM;
   }
 
   // Carve out the G1 part of the heap.
@@ -2706,8 +2702,7 @@
 }
 
 size_t G1CollectedHeap::cards_scanned() {
-  HRInto_G1RemSet* g1_rset = (HRInto_G1RemSet*) g1_rem_set();
-  return g1_rset->cardsScanned();
+  return g1_rem_set()->cardsScanned();
 }
 
 void
@@ -3850,6 +3845,54 @@
                undo_waste() * HeapWordSize / K);
 }
 
+#ifdef ASSERT
+bool G1ParScanThreadState::verify_ref(narrowOop* ref) const {
+  assert(ref != NULL, "invariant");
+  assert(UseCompressedOops, "sanity");
+  assert(!has_partial_array_mask(ref), err_msg("ref=" PTR_FORMAT, ref));
+  oop p = oopDesc::load_decode_heap_oop(ref);
+  assert(_g1h->is_in_g1_reserved(p),
+         err_msg("ref=" PTR_FORMAT " p=" PTR_FORMAT, ref, intptr_t(p)));
+  return true;
+}
+
+bool G1ParScanThreadState::verify_ref(oop* ref) const {
+  assert(ref != NULL, "invariant");
+  if (has_partial_array_mask(ref)) {
+    // Must be in the collection set--it's already been copied.
+    oop p = clear_partial_array_mask(ref);
+    assert(_g1h->obj_in_cs(p),
+           err_msg("ref=" PTR_FORMAT " p=" PTR_FORMAT, ref, intptr_t(p)));
+  } else {
+    oop p = oopDesc::load_decode_heap_oop(ref);
+    assert(_g1h->is_in_g1_reserved(p),
+           err_msg("ref=" PTR_FORMAT " p=" PTR_FORMAT, ref, intptr_t(p)));
+  }
+  return true;
+}
+
+bool G1ParScanThreadState::verify_task(StarTask ref) const {
+  if (ref.is_narrow()) {
+    return verify_ref((narrowOop*) ref);
+  } else {
+    return verify_ref((oop*) ref);
+  }
+}
+#endif // ASSERT
+
+void G1ParScanThreadState::trim_queue() {
+  StarTask ref;
+  do {
+    // Drain the overflow stack first, so other threads can steal.
+    while (refs()->pop_overflow(ref)) {
+      deal_with_reference(ref);
+    }
+    while (refs()->pop_local(ref)) {
+      deal_with_reference(ref);
+    }
+  } while (!refs()->is_empty());
+}
+
 G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
   _g1(g1), _g1_rem(_g1->g1_rem_set()), _cm(_g1->concurrent_mark()),
   _par_scan_state(par_scan_state) { }
@@ -4052,38 +4095,43 @@
     : _g1h(g1h), _par_scan_state(par_scan_state),
       _queues(queues), _terminator(terminator) {}
 
-  void do_void() {
-    G1ParScanThreadState* pss = par_scan_state();
-    while (true) {
+  void do_void();
+
+private:
+  inline bool offer_termination();
+};
+
+bool G1ParEvacuateFollowersClosure::offer_termination() {
+  G1ParScanThreadState* const pss = par_scan_state();
+  pss->start_term_time();
+  const bool res = terminator()->offer_termination();
+  pss->end_term_time();
+  return res;
+}
+
+void G1ParEvacuateFollowersClosure::do_void() {
+  StarTask stolen_task;
+  G1ParScanThreadState* const pss = par_scan_state();
+  pss->trim_queue();
+
+  do {
+    while (queues()->steal(pss->queue_num(), pss->hash_seed(), stolen_task)) {
+      assert(pss->verify_task(stolen_task), "sanity");
+      if (stolen_task.is_narrow()) {
+        pss->deal_with_reference((narrowOop*) stolen_task);
+      } else {
+        pss->deal_with_reference((oop*) stolen_task);
+      }
+
+      // We've just processed a reference and we might have made
+      // available new entries on the queues. So we have to make sure
+      // we drain the queues as necessary.
       pss->trim_queue();
-
-      StarTask stolen_task;
-      if (queues()->steal(pss->queue_num(), pss->hash_seed(), stolen_task)) {
-        // slightly paranoid tests; I'm trying to catch potential
-        // problems before we go into push_on_queue to know where the
-        // problem is coming from
-        assert((oop*)stolen_task != NULL, "Error");
-        if (stolen_task.is_narrow()) {
-          assert(UseCompressedOops, "Error");
-          narrowOop* p = (narrowOop*) stolen_task;
-          assert(has_partial_array_mask(p) ||
-                 _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "Error");
-          pss->push_on_queue(p);
-        } else {
-          oop* p = (oop*) stolen_task;
-          assert(has_partial_array_mask(p) || _g1h->is_in_g1_reserved(*p), "Error");
-          pss->push_on_queue(p);
-        }
-        continue;
-      }
-      pss->start_term_time();
-      if (terminator()->offer_termination()) break;
-      pss->end_term_time();
     }
-    pss->end_term_time();
-    pss->retire_alloc_buffers();
-  }
-};
+  } while (!offer_termination());
+
+  pss->retire_alloc_buffers();
+}
 
 class G1ParTask : public AbstractGangTask {
 protected:
@@ -4182,8 +4230,7 @@
       pss.print_termination_stats(i);
     }
 
-    assert(pss.refs_to_scan() == 0, "Task queue should be empty");
-    assert(pss.overflowed_refs_to_scan() == 0, "Overflow queue should be empty");
+    assert(pss.refs()->is_empty(), "should be empty");
     double end_time_ms = os::elapsedTime() * 1000.0;
     _g1h->g1_policy()->record_gc_worker_end_time(i, end_time_ms);
   }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -1651,49 +1651,17 @@
   size_t alloc_buffer_waste() const              { return _alloc_buffer_waste; }
   size_t undo_waste() const                      { return _undo_waste; }
 
+#ifdef ASSERT
+  bool verify_ref(narrowOop* ref) const;
+  bool verify_ref(oop* ref) const;
+  bool verify_task(StarTask ref) const;
+#endif // ASSERT
+
   template <class T> void push_on_queue(T* ref) {
-    assert(ref != NULL, "invariant");
-    assert(has_partial_array_mask(ref) ||
-           _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(ref)), "invariant");
-#ifdef ASSERT
-    if (has_partial_array_mask(ref)) {
-      oop p = clear_partial_array_mask(ref);
-      // Verify that we point into the CS
-      assert(_g1h->obj_in_cs(p), "Should be in CS");
-    }
-#endif
+    assert(verify_ref(ref), "sanity");
     refs()->push(ref);
   }
 
-  void pop_from_queue(StarTask& ref) {
-    if (refs()->pop_local(ref)) {
-      assert((oop*)ref != NULL, "pop_local() returned true");
-      assert(UseCompressedOops || !ref.is_narrow(), "Error");
-      assert(has_partial_array_mask((oop*)ref) ||
-             _g1h->is_in_g1_reserved(ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)ref)
-                                                     : oopDesc::load_decode_heap_oop((oop*)ref)),
-              "invariant");
-    } else {
-      StarTask null_task;
-      ref = null_task;
-    }
-  }
-
-  void pop_from_overflow_queue(StarTask& ref) {
-    StarTask new_ref;
-    refs()->pop_overflow(new_ref);
-    assert((oop*)new_ref != NULL, "pop() from a local non-empty stack");
-    assert(UseCompressedOops || !new_ref.is_narrow(), "Error");
-    assert(has_partial_array_mask((oop*)new_ref) ||
-           _g1h->is_in_g1_reserved(new_ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)new_ref)
-                                                       : oopDesc::load_decode_heap_oop((oop*)new_ref)),
-           "invariant");
-    ref = new_ref;
-  }
-
-  int refs_to_scan()            { return (int)refs()->size(); }
-  int overflowed_refs_to_scan() { return (int)refs()->overflow_stack()->size(); }
-
   template <class T> void update_rs(HeapRegion* from, T* p, int tid) {
     if (G1DeferredRSUpdate) {
       deferred_rs_update(from, p, tid);
@@ -1804,7 +1772,6 @@
     }
   }
 
-private:
   template <class T> void deal_with_reference(T* ref_to_scan) {
     if (has_partial_array_mask(ref_to_scan)) {
       _partial_scan_cl->do_oop_nv(ref_to_scan);
@@ -1818,59 +1785,15 @@
     }
   }
 
-public:
-  void trim_queue() {
-    // I've replicated the loop twice, first to drain the overflow
-    // queue, second to drain the task queue. This is better than
-    // having a single loop, which checks both conditions and, inside
-    // it, either pops the overflow queue or the task queue, as each
-    // loop is tighter. Also, the decision to drain the overflow queue
-    // first is not arbitrary, as the overflow queue is not visible
-    // to the other workers, whereas the task queue is. So, we want to
-    // drain the "invisible" entries first, while allowing the other
-    // workers to potentially steal the "visible" entries.
-
-    while (refs_to_scan() > 0 || overflowed_refs_to_scan() > 0) {
-      while (overflowed_refs_to_scan() > 0) {
-        StarTask ref_to_scan;
-        assert((oop*)ref_to_scan == NULL, "Constructed above");
-        pop_from_overflow_queue(ref_to_scan);
-        // We shouldn't have pushed it on the queue if it was not
-        // pointing into the CSet.
-        assert((oop*)ref_to_scan != NULL, "Follows from inner loop invariant");
-        if (ref_to_scan.is_narrow()) {
-          assert(UseCompressedOops, "Error");
-          narrowOop* p = (narrowOop*)ref_to_scan;
-          assert(!has_partial_array_mask(p) &&
-                 _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "sanity");
-          deal_with_reference(p);
-        } else {
-          oop* p = (oop*)ref_to_scan;
-          assert((has_partial_array_mask(p) && _g1h->is_in_g1_reserved(clear_partial_array_mask(p))) ||
-                 _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "sanity");
-          deal_with_reference(p);
-        }
-      }
-
-      while (refs_to_scan() > 0) {
-        StarTask ref_to_scan;
-        assert((oop*)ref_to_scan == NULL, "Constructed above");
-        pop_from_queue(ref_to_scan);
-        if ((oop*)ref_to_scan != NULL) {
-          if (ref_to_scan.is_narrow()) {
-            assert(UseCompressedOops, "Error");
-            narrowOop* p = (narrowOop*)ref_to_scan;
-            assert(!has_partial_array_mask(p) &&
-                    _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "sanity");
-            deal_with_reference(p);
-          } else {
-            oop* p = (oop*)ref_to_scan;
-            assert((has_partial_array_mask(p) && _g1h->obj_in_cs(clear_partial_array_mask(p))) ||
-                   _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "sanity");
-            deal_with_reference(p);
-          }
-        }
-      }
+  void deal_with_reference(StarTask ref) {
+    assert(verify_task(ref), "sanity");
+    if (ref.is_narrow()) {
+      deal_with_reference((narrowOop*)ref);
+    } else {
+      deal_with_reference((oop*)ref);
     }
   }
+
+public:
+  void trim_queue();
 };
--- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -25,8 +25,6 @@
 class HeapRegion;
 class G1CollectedHeap;
 class G1RemSet;
-class HRInto_G1RemSet;
-class G1RemSet;
 class ConcurrentMark;
 class DirtyCardToOopClosure;
 class CMBitMap;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -97,13 +97,6 @@
   }
 };
 
-void
-StupidG1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
-                                            int worker_i) {
-  IntoCSRegionClosure rc(_g1, oc);
-  _g1->heap_region_iterate(&rc);
-}
-
 class VerifyRSCleanCardOopClosure: public OopClosure {
   G1CollectedHeap* _g1;
 public:
@@ -119,8 +112,9 @@
   }
 };
 
-HRInto_G1RemSet::HRInto_G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs)
-  : G1RemSet(g1), _ct_bs(ct_bs), _g1p(_g1->g1_policy()),
+G1RemSet::G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs)
+  : _g1(g1), _conc_refine_cards(0),
+    _ct_bs(ct_bs), _g1p(_g1->g1_policy()),
     _cg1r(g1->concurrent_g1_refine()),
     _traversal_in_progress(false),
     _cset_rs_update_cl(NULL),
@@ -134,7 +128,7 @@
   }
 }
 
-HRInto_G1RemSet::~HRInto_G1RemSet() {
+G1RemSet::~G1RemSet() {
   delete _seq_task;
   for (uint i = 0; i < n_workers(); i++) {
     assert(_cset_rs_update_cl[i] == NULL, "it should be");
@@ -277,7 +271,7 @@
 //          p threads
 // Then thread t will start at region t * floor (n/p)
 
-HeapRegion* HRInto_G1RemSet::calculateStartRegion(int worker_i) {
+HeapRegion* G1RemSet::calculateStartRegion(int worker_i) {
   HeapRegion* result = _g1p->collection_set();
   if (ParallelGCThreads > 0) {
     size_t cs_size = _g1p->collection_set_size();
@@ -290,7 +284,7 @@
   return result;
 }
 
-void HRInto_G1RemSet::scanRS(OopsInHeapRegionClosure* oc, int worker_i) {
+void G1RemSet::scanRS(OopsInHeapRegionClosure* oc, int worker_i) {
   double rs_time_start = os::elapsedTime();
   HeapRegion *startRegion = calculateStartRegion(worker_i);
 
@@ -340,7 +334,7 @@
   }
 };
 
-void HRInto_G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, int worker_i) {
+void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, int worker_i) {
   double start = os::elapsedTime();
   // Apply the given closure to all remaining log entries.
   RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq);
@@ -439,12 +433,11 @@
   }
 };
 
-void HRInto_G1RemSet::cleanupHRRS() {
+void G1RemSet::cleanupHRRS() {
   HeapRegionRemSet::cleanup();
 }
 
-void
-HRInto_G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
+void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
                                              int worker_i) {
 #if CARD_REPEAT_HISTO
   ct_freq_update_histo_and_reset();
@@ -508,8 +501,7 @@
   _cset_rs_update_cl[worker_i] = NULL;
 }
 
-void HRInto_G1RemSet::
-prepare_for_oops_into_collection_set_do() {
+void G1RemSet::prepare_for_oops_into_collection_set_do() {
 #if G1_REM_SET_LOGGING
   PrintRSClosure cl;
   _g1->collection_set_iterate(&cl);
@@ -581,7 +573,7 @@
     //   RSet updating,
     // * the post-write barrier shouldn't be logging updates to young
     //   regions (but there is a situation where this can happen - see
-    //   the comment in HRInto_G1RemSet::concurrentRefineOneCard below -
+    //   the comment in G1RemSet::concurrentRefineOneCard below -
     //   that should not be applicable here), and
     // * during actual RSet updating, the filtering of cards in young
     //   regions in HeapRegion::oops_on_card_seq_iterate_careful is
@@ -601,7 +593,7 @@
   }
 };
 
-void HRInto_G1RemSet::cleanup_after_oops_into_collection_set_do() {
+void G1RemSet::cleanup_after_oops_into_collection_set_do() {
   guarantee( _cards_scanned != NULL, "invariant" );
   _total_cards_scanned = 0;
   for (uint i = 0; i < n_workers(); ++i)
@@ -692,12 +684,12 @@
   }
 };
 
-void HRInto_G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm) {
+void G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm) {
   ScrubRSClosure scrub_cl(region_bm, card_bm);
   _g1->heap_region_iterate(&scrub_cl);
 }
 
-void HRInto_G1RemSet::scrub_par(BitMap* region_bm, BitMap* card_bm,
+void G1RemSet::scrub_par(BitMap* region_bm, BitMap* card_bm,
                                 int worker_num, int claim_val) {
   ScrubRSClosure scrub_cl(region_bm, card_bm);
   _g1->heap_region_par_iterate_chunked(&scrub_cl, worker_num, claim_val);
@@ -741,7 +733,7 @@
   virtual void do_oop(narrowOop* p)  { do_oop_nv(p); }
 };
 
-bool HRInto_G1RemSet::concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i,
+bool G1RemSet::concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i,
                                                    bool check_for_refs_into_cset) {
   // Construct the region representing the card.
   HeapWord* start = _ct_bs->addr_for(card_ptr);
@@ -820,7 +812,7 @@
   return trigger_cl.value();
 }
 
-bool HRInto_G1RemSet::concurrentRefineOneCard(jbyte* card_ptr, int worker_i,
+bool G1RemSet::concurrentRefineOneCard(jbyte* card_ptr, int worker_i,
                                               bool check_for_refs_into_cset) {
   // If the card is no longer dirty, nothing to do.
   if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
@@ -995,7 +987,7 @@
   }
 };
 
-void HRInto_G1RemSet::print_summary_info() {
+void G1RemSet::print_summary_info() {
   G1CollectedHeap* g1 = G1CollectedHeap::heap();
 
 #if CARD_REPEAT_HISTO
@@ -1029,30 +1021,26 @@
   g1->concurrent_g1_refine()->threads_do(&p);
   gclog_or_tty->print_cr("");
 
-  if (G1UseHRIntoRS) {
-    HRRSStatsIter blk;
-    g1->heap_region_iterate(&blk);
-    gclog_or_tty->print_cr("  Total heap region rem set sizes = " SIZE_FORMAT "K."
-                           "  Max = " SIZE_FORMAT "K.",
-                           blk.total_mem_sz()/K, blk.max_mem_sz()/K);
-    gclog_or_tty->print_cr("  Static structures = " SIZE_FORMAT "K,"
-                           " free_lists = " SIZE_FORMAT "K.",
-                           HeapRegionRemSet::static_mem_size()/K,
-                           HeapRegionRemSet::fl_mem_size()/K);
-    gclog_or_tty->print_cr("    %d occupied cards represented.",
-                           blk.occupied());
-    gclog_or_tty->print_cr("    Max sz region = [" PTR_FORMAT ", " PTR_FORMAT " )"
-                           ", cap = " SIZE_FORMAT "K, occ = " SIZE_FORMAT "K.",
-                           blk.max_mem_sz_region()->bottom(), blk.max_mem_sz_region()->end(),
-                           (blk.max_mem_sz_region()->rem_set()->mem_size() + K - 1)/K,
-                           (blk.max_mem_sz_region()->rem_set()->occupied() + K - 1)/K);
-    gclog_or_tty->print_cr("    Did %d coarsenings.",
-                  HeapRegionRemSet::n_coarsenings());
-
-  }
+  HRRSStatsIter blk;
+  g1->heap_region_iterate(&blk);
+  gclog_or_tty->print_cr("  Total heap region rem set sizes = " SIZE_FORMAT "K."
+                         "  Max = " SIZE_FORMAT "K.",
+                         blk.total_mem_sz()/K, blk.max_mem_sz()/K);
+  gclog_or_tty->print_cr("  Static structures = " SIZE_FORMAT "K,"
+                         " free_lists = " SIZE_FORMAT "K.",
+                         HeapRegionRemSet::static_mem_size()/K,
+                         HeapRegionRemSet::fl_mem_size()/K);
+  gclog_or_tty->print_cr("    %d occupied cards represented.",
+                         blk.occupied());
+  gclog_or_tty->print_cr("    Max sz region = [" PTR_FORMAT ", " PTR_FORMAT " )"
+                         ", cap = " SIZE_FORMAT "K, occ = " SIZE_FORMAT "K.",
+                         blk.max_mem_sz_region()->bottom(), blk.max_mem_sz_region()->end(),
+                         (blk.max_mem_sz_region()->rem_set()->mem_size() + K - 1)/K,
+                         (blk.max_mem_sz_region()->rem_set()->occupied() + K - 1)/K);
+  gclog_or_tty->print_cr("    Did %d coarsenings.", HeapRegionRemSet::n_coarsenings());
 }
 
-void HRInto_G1RemSet::prepare_for_verify() {
+void G1RemSet::prepare_for_verify() {
   if (G1HRRSFlushLogBuffersOnVerify &&
       (VerifyBeforeGC || VerifyAfterGC)
       &&  !_g1->full_collection()) {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -27,107 +27,18 @@
 
 class G1CollectedHeap;
 class CardTableModRefBarrierSet;
-class HRInto_G1RemSet;
 class ConcurrentG1Refine;
 
+// A G1RemSet in which each heap region has a rem set that records the
+// external heap references into it.  Uses a mod ref bs to track updates,
+// so that they can be used to update the individual region remsets.
+
 class G1RemSet: public CHeapObj {
 protected:
   G1CollectedHeap* _g1;
   unsigned _conc_refine_cards;
   size_t n_workers();
 
-public:
-  G1RemSet(G1CollectedHeap* g1) :
-    _g1(g1), _conc_refine_cards(0)
-  {}
-
-  // Invoke "blk->do_oop" on all pointers into the CS in object in regions
-  // outside the CS (having invoked "blk->set_region" to set the "from"
-  // region correctly beforehand.) The "worker_i" param is for the
-  // parallel case where the number of the worker thread calling this
-  // function can be helpful in partitioning the work to be done. It
-  // should be the same as the "i" passed to the calling thread's
-  // work(i) function. In the sequential case this param will be ingored.
-  virtual void oops_into_collection_set_do(OopsInHeapRegionClosure* blk,
-                                           int worker_i) = 0;
-
-  // Prepare for and cleanup after an oops_into_collection_set_do
-  // call.  Must call each of these once before and after (in sequential
-  // code) any threads call oops into collection set do.  (This offers an
-  // opportunity to sequential setup and teardown of structures needed by a
-  // parallel iteration over the CS's RS.)
-  virtual void prepare_for_oops_into_collection_set_do() = 0;
-  virtual void cleanup_after_oops_into_collection_set_do() = 0;
-
-  // If "this" is of the given subtype, return "this", else "NULL".
-  virtual HRInto_G1RemSet* as_HRInto_G1RemSet() { return NULL; }
-
-  // Record, if necessary, the fact that *p (where "p" is in region "from",
-  // and is, a fortiori, required to be non-NULL) has changed to its new value.
-  virtual void write_ref(HeapRegion* from, oop* p) = 0;
-  virtual void write_ref(HeapRegion* from, narrowOop* p) = 0;
-  virtual void par_write_ref(HeapRegion* from, oop* p, int tid) = 0;
-  virtual void par_write_ref(HeapRegion* from, narrowOop* p, int tid) = 0;
-
-  // Requires "region_bm" and "card_bm" to be bitmaps with 1 bit per region
-  // or card, respectively, such that a region or card with a corresponding
-  // 0 bit contains no part of any live object.  Eliminates any remembered
-  // set entries that correspond to dead heap ranges.
-  virtual void scrub(BitMap* region_bm, BitMap* card_bm) = 0;
-  // Like the above, but assumes is called in parallel: "worker_num" is the
-  // parallel thread id of the current thread, and "claim_val" is the
-  // value that should be used to claim heap regions.
-  virtual void scrub_par(BitMap* region_bm, BitMap* card_bm,
-                         int worker_num, int claim_val) = 0;
-
-  // Refine the card corresponding to "card_ptr".  If "sts" is non-NULL,
-  // join and leave around parts that must be atomic wrt GC.  (NULL means
-  // being done at a safepoint.)
-  // With some implementations of this routine, when check_for_refs_into_cset
-  // is true, a true result may be returned if the given card contains oops
-  // that have references into the current collection set.
-  virtual bool concurrentRefineOneCard(jbyte* card_ptr, int worker_i,
-                                       bool check_for_refs_into_cset) {
-    return false;
-  }
-
-  // Print any relevant summary info.
-  virtual void print_summary_info() {}
-
-  // Prepare remebered set for verification.
-  virtual void prepare_for_verify() {};
-};
-
-
-// The simplest possible G1RemSet: iterates over all objects in non-CS
-// regions, searching for pointers into the CS.
-class StupidG1RemSet: public G1RemSet {
-public:
-  StupidG1RemSet(G1CollectedHeap* g1) : G1RemSet(g1) {}
-
-  void oops_into_collection_set_do(OopsInHeapRegionClosure* blk,
-                                   int worker_i);
-
-  void prepare_for_oops_into_collection_set_do() {}
-  void cleanup_after_oops_into_collection_set_do() {}
-
-  // Nothing is necessary in the version below.
-  void write_ref(HeapRegion* from, oop* p) {}
-  void write_ref(HeapRegion* from, narrowOop* p) {}
-  void par_write_ref(HeapRegion* from, oop* p, int tid) {}
-  void par_write_ref(HeapRegion* from, narrowOop* p, int tid) {}
-
-  void scrub(BitMap* region_bm, BitMap* card_bm) {}
-  void scrub_par(BitMap* region_bm, BitMap* card_bm,
-                 int worker_num, int claim_val) {}
-
-};
-
-// A G1RemSet in which each heap region has a rem set that records the
-// external heap references into it.  Uses a mod ref bs to track updates,
-// so that they can be used to update the individual region remsets.
-
-class HRInto_G1RemSet: public G1RemSet {
 protected:
   enum SomePrivateConstants {
     UpdateRStoMergeSync  = 0,
@@ -175,28 +86,32 @@
   // scanned.
   void cleanupHRRS();
 
-  HRInto_G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs);
-  ~HRInto_G1RemSet();
+  G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs);
+  ~G1RemSet();
 
+  // Invoke "blk->do_oop" on all pointers into the CS in objects in regions
+  // outside the CS (having invoked "blk->set_region" to set the "from"
+  // region correctly beforehand.) The "worker_i" param is for the
+  // parallel case where the number of the worker thread calling this
+  // function can be helpful in partitioning the work to be done. It
+  // should be the same as the "i" passed to the calling thread's
+  // work(i) function. In the sequential case this param will be ingored.
   void oops_into_collection_set_do(OopsInHeapRegionClosure* blk,
                                    int worker_i);
 
+  // Prepare for and cleanup after an oops_into_collection_set_do
+  // call.  Must call each of these once before and after (in sequential
+  // code) any threads call oops_into_collection_set_do.  (This offers an
+  // opportunity to sequential setup and teardown of structures needed by a
+  // parallel iteration over the CS's RS.)
   void prepare_for_oops_into_collection_set_do();
   void cleanup_after_oops_into_collection_set_do();
+
   void scanRS(OopsInHeapRegionClosure* oc, int worker_i);
-  template <class T> void scanNewRefsRS_work(OopsInHeapRegionClosure* oc, int worker_i);
-  void scanNewRefsRS(OopsInHeapRegionClosure* oc, int worker_i) {
-    if (UseCompressedOops) {
-      scanNewRefsRS_work<narrowOop>(oc, worker_i);
-    } else {
-      scanNewRefsRS_work<oop>(oc, worker_i);
-    }
-  }
   void updateRS(DirtyCardQueue* into_cset_dcq, int worker_i);
+
   HeapRegion* calculateStartRegion(int i);
 
-  HRInto_G1RemSet* as_HRInto_G1RemSet() { return this; }
-
   CardTableModRefBS* ct_bs() { return _ct_bs; }
   size_t cardsScanned() { return _total_cards_scanned; }
 
@@ -219,17 +134,31 @@
 
   bool self_forwarded(oop obj);
 
+  // Requires "region_bm" and "card_bm" to be bitmaps with 1 bit per region
+  // or card, respectively, such that a region or card with a corresponding
+  // 0 bit contains no part of any live object.  Eliminates any remembered
+  // set entries that correspond to dead heap ranges.
   void scrub(BitMap* region_bm, BitMap* card_bm);
+
+  // Like the above, but assumes is called in parallel: "worker_num" is the
+  // parallel thread id of the current thread, and "claim_val" is the
+  // value that should be used to claim heap regions.
   void scrub_par(BitMap* region_bm, BitMap* card_bm,
                  int worker_num, int claim_val);
 
-  // If check_for_refs_into_cset is true then a true result is returned
-  // if the card contains oops that have references into the current
-  // collection set.
+  // Refine the card corresponding to "card_ptr".  If "sts" is non-NULL,
+  // join and leave around parts that must be atomic wrt GC.  (NULL means
+  // being done at a safepoint.)
+  // If check_for_refs_into_cset is true, a true result is returned
+  // if the given card contains oops that have references into the
+  // current collection set.
   virtual bool concurrentRefineOneCard(jbyte* card_ptr, int worker_i,
                                        bool check_for_refs_into_cset);
 
+  // Print any relevant summary info.
   virtual void print_summary_info();
+
+  // Prepare remembered set for verification.
   virtual void prepare_for_verify();
 };
 
@@ -250,13 +179,13 @@
 
 class UpdateRSOopClosure: public OopClosure {
   HeapRegion* _from;
-  HRInto_G1RemSet* _rs;
+  G1RemSet* _rs;
   int _worker_i;
 
   template <class T> void do_oop_work(T* p);
 
 public:
-  UpdateRSOopClosure(HRInto_G1RemSet* rs, int worker_i = 0) :
+  UpdateRSOopClosure(G1RemSet* rs, int worker_i = 0) :
     _from(NULL), _rs(rs), _worker_i(worker_i) {
     guarantee(_rs != NULL, "Requires an HRIntoG1RemSet");
   }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -30,16 +30,18 @@
   }
 }
 
-template <class T> inline void HRInto_G1RemSet::write_ref_nv(HeapRegion* from, T* p) {
+template <class T>
+inline void G1RemSet::write_ref_nv(HeapRegion* from, T* p) {
   par_write_ref_nv(from, p, 0);
 }
 
-inline bool HRInto_G1RemSet::self_forwarded(oop obj) {
+inline bool G1RemSet::self_forwarded(oop obj) {
   bool result =  (obj->is_forwarded() && (obj->forwardee()== obj));
   return result;
 }
 
-template <class T> inline void HRInto_G1RemSet::par_write_ref_nv(HeapRegion* from, T* p, int tid) {
+template <class T>
+inline void G1RemSet::par_write_ref_nv(HeapRegion* from, T* p, int tid) {
   oop obj = oopDesc::load_decode_heap_oop(p);
 #ifdef ASSERT
   // can't do because of races
@@ -77,7 +79,7 @@
       // Deferred updates to the CSet are either discarded (in the normal case),
       // or processed (if an evacuation failure occurs) at the end
       // of the collection.
-      // See HRInto_G1RemSet::cleanup_after_oops_into_collection_set_do().
+      // See G1RemSet::cleanup_after_oops_into_collection_set_do().
     } else {
 #if G1_REM_SET_LOGGING
       gclog_or_tty->print_cr("Adding " PTR_FORMAT " (" PTR_FORMAT ") to RS"
@@ -91,12 +93,14 @@
   }
 }
 
-template <class T> inline void UpdateRSOopClosure::do_oop_work(T* p) {
+template <class T>
+inline void UpdateRSOopClosure::do_oop_work(T* p) {
   assert(_from != NULL, "from region must be non-NULL");
   _rs->par_write_ref(_from, p, _worker_i);
 }
 
-template <class T> inline void UpdateRSetImmediate::do_oop_work(T* p) {
+template <class T>
+inline void UpdateRSetImmediate::do_oop_work(T* p) {
   assert(_from->is_in_reserved(p), "paranoia");
   T heap_oop = oopDesc::load_heap_oop(p);
   if (!oopDesc::is_null(heap_oop) && !_from->is_survivor()) {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -40,9 +40,6 @@
   develop(intx, G1PolicyVerbose, 0,                                         \
           "The verbosity level on G1 policy decisions")                     \
                                                                             \
-  develop(bool, G1UseHRIntoRS, true,                                        \
-          "Determines whether the 'advanced' HR Into rem set is used.")     \
-                                                                            \
   develop(intx, G1MarkingVerboseLevel, 0,                                   \
           "Level (0-4) of verboseness of the marking code")                 \
                                                                             \
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -377,10 +377,26 @@
 }
 // </PREDICTION>
 
-void HeapRegion::set_startsHumongous() {
+void HeapRegion::set_startsHumongous(HeapWord* new_end) {
+  assert(end() == _orig_end,
+         "Should be normal before the humongous object allocation");
+  assert(top() == bottom(), "should be empty");
+
   _humongous_type = StartsHumongous;
   _humongous_start_region = this;
-  assert(end() == _orig_end, "Should be normal before alloc.");
+
+  set_end(new_end);
+  _offsets.set_for_starts_humongous(new_end);
+}
+
+void HeapRegion::set_continuesHumongous(HeapRegion* start) {
+  assert(end() == _orig_end,
+         "Should be normal before the humongous object allocation");
+  assert(top() == bottom(), "should be empty");
+  assert(start->startsHumongous(), "pre-condition");
+
+  _humongous_type = ContinuesHumongous;
+  _humongous_start_region = start;
 }
 
 bool HeapRegion::claimHeapRegion(jint claimValue) {
@@ -500,23 +516,6 @@
   return blk.result();
 }
 
-void HeapRegion::set_continuesHumongous(HeapRegion* start) {
-  // The order is important here.
-  start->add_continuingHumongousRegion(this);
-  _humongous_type = ContinuesHumongous;
-  _humongous_start_region = start;
-}
-
-void HeapRegion::add_continuingHumongousRegion(HeapRegion* cont) {
-  // Must join the blocks of the current H region seq with the block of the
-  // added region.
-  offsets()->join_blocks(bottom(), cont->bottom());
-  arrayOop obj = (arrayOop)(bottom());
-  obj->set_length((int) (obj->length() + cont->capacity()/jintSize));
-  set_end(cont->end());
-  set_top(cont->end());
-}
-
 void HeapRegion::save_marks() {
   set_saved_mark();
 }
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -395,14 +395,12 @@
 
   // Causes the current region to represent a humongous object spanning "n"
   // regions.
-  virtual void set_startsHumongous();
+  void set_startsHumongous(HeapWord* new_end);
 
   // The regions that continue a humongous sequence should be added using
   // this method, in increasing address order.
   void set_continuesHumongous(HeapRegion* start);
 
-  void add_continuingHumongousRegion(HeapRegion* cont);
-
   // If the region has a remembered set, return a pointer to it.
   HeapRegionRemSet* rem_set() const {
     return _rem_set;
@@ -733,13 +731,6 @@
                                    FilterOutOfRegionClosure* cl,
                                    bool filter_young);
 
-  // The region "mr" is entirely in "this", and starts and ends at block
-  // boundaries. The caller declares that all the contained blocks are
-  // coalesced into one.
-  void declare_filled_region_to_BOT(MemRegion mr) {
-    _offsets.single_block(mr.start(), mr.end());
-  }
-
   // A version of block start that is guaranteed to find *some* block
   // boundary at or before "p", but does not object iteration, and may
   // therefore be used safely when the heap is unparseable.
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -1159,9 +1159,7 @@
   _hrrs(NULL),
   _g1h(G1CollectedHeap::heap()),
   _bosa(NULL),
-  _sparse_iter(size_t(G1CollectedHeap::heap()->reserved_region().start())
-               >> CardTableModRefBS::card_shift)
-{}
+  _sparse_iter() { }
 
 void HeapRegionRemSetIterator::initialize(const HeapRegionRemSet* hrrs) {
   _hrrs = hrrs;
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -91,34 +91,118 @@
   }
   if (sumSizes >= word_size) {
     _alloc_search_start = cur;
-    // Mark the allocated regions as allocated.
+
+    // We need to initialize the region(s) we just discovered. This is
+    // a bit tricky given that it can happen concurrently with
+    // refinement threads refining cards on these regions and
+    // potentially wanting to refine the BOT as they are scanning
+    // those cards (this can happen shortly after a cleanup; see CR
+    // 6991377). So we have to set up the region(s) carefully and in
+    // a specific order.
+
+    // Currently, allocs_are_zero_filled() returns false. The zero
+    // filling infrastructure will be going away soon (see CR 6977804).
+    // So no need to do anything else here.
     bool zf = G1CollectedHeap::heap()->allocs_are_zero_filled();
+    assert(!zf, "not supported");
+
+    // This will be the "starts humongous" region.
     HeapRegion* first_hr = _regions.at(first);
-    for (int i = first; i < cur; i++) {
-      HeapRegion* hr = _regions.at(i);
-      if (zf)
-        hr->ensure_zero_filled();
+    {
+      MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
+      first_hr->set_zero_fill_allocated();
+    }
+    // The header of the new object will be placed at the bottom of
+    // the first region.
+    HeapWord* new_obj = first_hr->bottom();
+    // This will be the new end of the first region in the series that
+    // should also match the end of the last region in the seriers.
+    // (Note: sumSizes = "region size" x "number of regions we found").
+    HeapWord* new_end = new_obj + sumSizes;
+    // This will be the new top of the first region that will reflect
+    // this allocation.
+    HeapWord* new_top = new_obj + word_size;
+
+    // First, we need to zero the header of the space that we will be
+    // allocating. When we update top further down, some refinement
+    // threads might try to scan the region. By zeroing the header we
+    // ensure that any thread that will try to scan the region will
+    // come across the zero klass word and bail out.
+    //
+    // NOTE: It would not have been correct to have used
+    // CollectedHeap::fill_with_object() and make the space look like
+    // an int array. The thread that is doing the allocation will
+    // later update the object header to a potentially different array
+    // type and, for a very short period of time, the klass and length
+    // fields will be inconsistent. This could cause a refinement
+    // thread to calculate the object size incorrectly.
+    Copy::fill_to_words(new_obj, oopDesc::header_size(), 0);
+
+    // We will set up the first region as "starts humongous". This
+    // will also update the BOT covering all the regions to reflect
+    // that there is a single object that starts at the bottom of the
+    // first region.
+    first_hr->set_startsHumongous(new_end);
+
+    // Then, if there are any, we will set up the "continues
+    // humongous" regions.
+    HeapRegion* hr = NULL;
+    for (int i = first + 1; i < cur; ++i) {
+      hr = _regions.at(i);
       {
         MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
         hr->set_zero_fill_allocated();
       }
-      size_t sz = hr->capacity() / HeapWordSize;
-      HeapWord* tmp = hr->allocate(sz);
-      assert(tmp != NULL, "Humongous allocation failure");
-      MemRegion mr = MemRegion(tmp, sz);
-      CollectedHeap::fill_with_object(mr);
-      hr->declare_filled_region_to_BOT(mr);
-      if (i == first) {
-        first_hr->set_startsHumongous();
+      hr->set_continuesHumongous(first_hr);
+    }
+    // If we have "continues humongous" regions (hr != NULL), then the
+    // end of the last one should match new_end.
+    assert(hr == NULL || hr->end() == new_end, "sanity");
+
+    // Up to this point no concurrent thread would have been able to
+    // do any scanning on any region in this series. All the top
+    // fields still point to bottom, so the intersection between
+    // [bottom,top] and [card_start,card_end] will be empty. Before we
+    // update the top fields, we'll do a storestore to make sure that
+    // no thread sees the update to top before the zeroing of the
+    // object header and the BOT initialization.
+    OrderAccess::storestore();
+
+    // Now that the BOT and the object header have been initialized,
+    // we can update top of the "starts humongous" region.
+    assert(first_hr->bottom() < new_top && new_top <= first_hr->end(),
+           "new_top should be in this region");
+    first_hr->set_top(new_top);
+
+    // Now, we will update the top fields of the "continues humongous"
+    // regions. The reason we need to do this is that, otherwise,
+    // these regions would look empty and this will confuse parts of
+    // G1. For example, the code that looks for a consecutive number
+    // of empty regions will consider them empty and try to
+    // re-allocate them. We can extend is_empty() to also include
+    // !continuesHumongous(), but it is easier to just update the top
+    // fields here.
+    hr = NULL;
+    for (int i = first + 1; i < cur; ++i) {
+      hr = _regions.at(i);
+      if ((i + 1) == cur) {
+        // last continues humongous region
+        assert(hr->bottom() < new_top && new_top <= hr->end(),
+               "new_top should fall on this region");
+        hr->set_top(new_top);
       } else {
-        assert(i > first, "sanity");
-        hr->set_continuesHumongous(first_hr);
+        // not last one
+        assert(new_top > hr->end(), "new_top should be above this region");
+        hr->set_top(hr->end());
       }
     }
-    HeapWord* first_hr_bot = first_hr->bottom();
-    HeapWord* obj_end = first_hr_bot + word_size;
-    first_hr->set_top(obj_end);
-    return first_hr_bot;
+    // If we have continues humongous regions (hr != NULL), then the
+    // end of the last one should match new_end and its top should
+    // match new_top.
+    assert(hr == NULL ||
+           (hr->end() == new_end && hr->top() == new_top), "sanity");
+
+    return new_obj;
   } else {
     // If we started from the beginning, we want to know why we can't alloc.
     return NULL;
--- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -308,7 +308,7 @@
   assert(e2->num_valid_cards() > 0, "Postcondition.");
 }
 
-CardIdx_t /* RSHashTable:: */ RSHashTableIter::find_first_card_in_list() {
+CardIdx_t RSHashTableIter::find_first_card_in_list() {
   CardIdx_t res;
   while (_bl_ind != RSHashTable::NullEntry) {
     res = _rsht->entry(_bl_ind)->card(0);
@@ -322,14 +322,11 @@
   return SparsePRTEntry::NullEntry;
 }
 
-size_t /* RSHashTable:: */ RSHashTableIter::compute_card_ind(CardIdx_t ci) {
-  return
-    _heap_bot_card_ind
-    + (_rsht->entry(_bl_ind)->r_ind() * HeapRegion::CardsPerRegion)
-    + ci;
+size_t RSHashTableIter::compute_card_ind(CardIdx_t ci) {
+  return (_rsht->entry(_bl_ind)->r_ind() * HeapRegion::CardsPerRegion) + ci;
 }
 
-bool /* RSHashTable:: */ RSHashTableIter::has_next(size_t& card_index) {
+bool RSHashTableIter::has_next(size_t& card_index) {
   _card_ind++;
   CardIdx_t ci;
   if (_card_ind < SparsePRTEntry::cards_num() &&
--- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -169,7 +169,6 @@
   int _bl_ind;          // [-1, 0.._rsht->_capacity)
   short _card_ind;      // [0..SparsePRTEntry::cards_num())
   RSHashTable* _rsht;
-  size_t _heap_bot_card_ind;
 
   // If the bucket list pointed to by _bl_ind contains a card, sets
   // _bl_ind to the index of that entry, and returns the card.
@@ -183,13 +182,11 @@
   size_t compute_card_ind(CardIdx_t ci);
 
 public:
-  RSHashTableIter(size_t heap_bot_card_ind) :
+  RSHashTableIter() :
     _tbl_ind(RSHashTable::NullEntry),
     _bl_ind(RSHashTable::NullEntry),
     _card_ind((SparsePRTEntry::cards_num() - 1)),
-    _rsht(NULL),
-    _heap_bot_card_ind(heap_bot_card_ind)
-  {}
+    _rsht(NULL) {}
 
   void init(RSHashTable* rsht) {
     _rsht = rsht;
@@ -280,20 +277,11 @@
   bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const {
     return _next->contains_card(region_id, card_index);
   }
-
-#if 0
-  void verify_is_cleared();
-  void print();
-#endif
 };
 
 
-class SparsePRTIter: public /* RSHashTable:: */RSHashTableIter {
+class SparsePRTIter: public RSHashTableIter {
 public:
-  SparsePRTIter(size_t heap_bot_card_ind) :
-    /* RSHashTable:: */RSHashTableIter(heap_bot_card_ind)
-  {}
-
   void init(const SparsePRT* sprt) {
     RSHashTableIter::init(sprt->cur());
   }
--- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1	Wed Jul 05 17:26:57 2017 +0200
@@ -310,10 +310,16 @@
 
 heapRegionSeq.inline.hpp                heapRegionSeq.hpp
 
+instanceKlass.cpp                       g1RemSet.inline.hpp
+
+instanceRefKlass.cpp                    g1RemSet.inline.hpp
+
 klass.hpp				g1OopClosures.hpp
 
 memoryService.cpp                       g1MemoryPool.hpp
 
+objArrayKlass.cpp                       g1RemSet.inline.hpp
+
 ptrQueue.cpp                            allocation.hpp
 ptrQueue.cpp                            allocation.inline.hpp
 ptrQueue.cpp                            mutex.hpp
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -846,7 +846,7 @@
   // from this generation, pass on collection; let the next generation
   // do it.
   if (!collection_attempt_is_safe()) {
-    gch->set_incremental_collection_will_fail();
+    gch->set_incremental_collection_failed();  // slight lie, in that we did not even attempt one
     return;
   }
   assert(to()->is_empty(), "Else not collection_attempt_is_safe");
@@ -935,8 +935,6 @@
 
     assert(to()->is_empty(), "to space should be empty now");
   } else {
-    assert(HandlePromotionFailure,
-      "Should only be here if promotion failure handling is on");
     assert(_promo_failure_scan_stack.is_empty(), "post condition");
     _promo_failure_scan_stack.clear(true); // Clear cached segments.
 
@@ -947,7 +945,7 @@
     // All the spaces are in play for mark-sweep.
     swap_spaces();  // Make life simpler for CMS || rescan; see 6483690.
     from()->set_next_compaction_space(to());
-    gch->set_incremental_collection_will_fail();
+    gch->set_incremental_collection_failed();
     // Inform the next generation that a promotion failure occurred.
     _next_gen->promotion_failure_occurred();
 
@@ -1092,11 +1090,6 @@
                                        old, m, sz);
 
     if (new_obj == NULL) {
-      if (!HandlePromotionFailure) {
-        // A failed promotion likely means the MaxLiveObjectEvacuationRatio flag
-        // is incorrectly set. In any case, its seriously wrong to be here!
-        vm_exit_out_of_memory(sz*wordSize, "promotion");
-      }
       // promotion failed, forward to self
       _promotion_failed = true;
       new_obj = old;
@@ -1206,12 +1199,6 @@
                                        old, m, sz);
 
     if (new_obj == NULL) {
-      if (!HandlePromotionFailure) {
-        // A failed promotion likely means the MaxLiveObjectEvacuationRatio
-        // flag is incorrectly set. In any case, its seriously wrong to be
-        // here!
-        vm_exit_out_of_memory(sz*wordSize, "promotion");
-      }
       // promotion failed, forward to self
       forward_ptr = old->forward_to_atomic(old);
       new_obj = old;
--- a/hotspot/src/share/vm/includeDB_compiler1	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/includeDB_compiler1	Wed Jul 05 17:26:57 2017 +0200
@@ -301,6 +301,7 @@
 c1_MacroAssembler.hpp                   assembler_<arch>.inline.hpp
 
 c1_MacroAssembler_<arch>.cpp            arrayOop.hpp
+c1_MacroAssembler_<arch>.cpp            basicLock.hpp
 c1_MacroAssembler_<arch>.cpp            biasedLocking.hpp
 c1_MacroAssembler_<arch>.cpp            c1_MacroAssembler.hpp
 c1_MacroAssembler_<arch>.cpp            c1_Runtime1.hpp
@@ -309,7 +310,6 @@
 c1_MacroAssembler_<arch>.cpp            markOop.hpp
 c1_MacroAssembler_<arch>.cpp            os.hpp
 c1_MacroAssembler_<arch>.cpp            stubRoutines.hpp
-c1_MacroAssembler_<arch>.cpp            synchronizer.hpp
 c1_MacroAssembler_<arch>.cpp            systemDictionary.hpp
 
 c1_MacroAssembler_<arch>.hpp            generate_platform_dependent_include
--- a/hotspot/src/share/vm/includeDB_core	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/includeDB_core	Wed Jul 05 17:26:57 2017 +0200
@@ -300,10 +300,17 @@
 barrierSet.inline.hpp                   barrierSet.hpp
 barrierSet.inline.hpp                   cardTableModRefBS.hpp
 
+basicLock.cpp                           basicLock.hpp
+basicLock.cpp                           synchronizer.hpp
+
+basicLock.hpp                           handles.hpp
+basicLock.hpp                           markOop.hpp
+basicLock.hpp                           top.hpp
+
+biasedLocking.cpp                       basicLock.hpp
 biasedLocking.cpp                       biasedLocking.hpp
 biasedLocking.cpp                       klass.inline.hpp
 biasedLocking.cpp                       markOop.hpp
-biasedLocking.cpp                       synchronizer.hpp
 biasedLocking.cpp                       task.hpp
 biasedLocking.cpp                       vframe.hpp
 biasedLocking.cpp                       vmThread.hpp
@@ -404,13 +411,13 @@
 bytecodeInterpreterWithChecks.cpp       bytecodeInterpreter.cpp
 
 bytecodeInterpreter.hpp                 allocation.hpp
+bytecodeInterpreter.hpp                 basicLock.hpp
 bytecodeInterpreter.hpp                 bytes_<arch>.hpp
 bytecodeInterpreter.hpp                 frame.hpp
 bytecodeInterpreter.hpp                 globalDefinitions.hpp
 bytecodeInterpreter.hpp                 globals.hpp
 bytecodeInterpreter.hpp                 methodDataOop.hpp
 bytecodeInterpreter.hpp                 methodOop.hpp
-bytecodeInterpreter.hpp                 synchronizer.hpp
 
 bytecodeInterpreter.inline.hpp          bytecodeInterpreter.hpp
 bytecodeInterpreter.inline.hpp          stubRoutines.hpp
@@ -1667,10 +1674,10 @@
 frame.cpp                               universe.inline.hpp
 
 frame.hpp                               assembler.hpp
+frame.hpp                               basicLock.hpp
 frame.hpp                               methodOop.hpp
 frame.hpp                               monitorChunk.hpp
 frame.hpp                               registerMap.hpp
-frame.hpp                               synchronizer.hpp
 frame.hpp                               top.hpp
 
 frame.inline.hpp                        bytecodeInterpreter.hpp
@@ -2120,6 +2127,7 @@
 interfaceSupport_<os_family>.hpp        generate_platform_dependent_include
 
 interp_masm_<arch_model>.cpp            arrayOop.hpp
+interp_masm_<arch_model>.cpp            basicLock.hpp
 interp_masm_<arch_model>.cpp            biasedLocking.hpp
 interp_masm_<arch_model>.cpp            interp_masm_<arch_model>.hpp
 interp_masm_<arch_model>.cpp            interpreterRuntime.hpp
@@ -2131,7 +2139,6 @@
 interp_masm_<arch_model>.cpp            methodDataOop.hpp
 interp_masm_<arch_model>.cpp            methodOop.hpp
 interp_masm_<arch_model>.cpp            sharedRuntime.hpp
-interp_masm_<arch_model>.cpp            synchronizer.hpp
 interp_masm_<arch_model>.cpp            thread_<os_family>.inline.hpp
 
 interp_masm_<arch_model>.hpp            assembler_<arch>.inline.hpp
@@ -3094,25 +3101,26 @@
 
 objArrayOop.hpp                         arrayOop.hpp
 
+objectMonitor.cpp                       dtrace.hpp
+objectMonitor.cpp                       handles.inline.hpp
+objectMonitor.cpp                       interfaceSupport.hpp
+objectMonitor.cpp                       markOop.hpp
+objectMonitor.cpp                       mutexLocker.hpp
+objectMonitor.cpp                       objectMonitor.hpp
+objectMonitor.cpp                       objectMonitor.inline.hpp
+objectMonitor.cpp                       oop.inline.hpp
+objectMonitor.cpp                       osThread.hpp
+objectMonitor.cpp                       os_<os_family>.inline.hpp
+objectMonitor.cpp                       preserveException.hpp
+objectMonitor.cpp                       resourceArea.hpp
+objectMonitor.cpp                       stubRoutines.hpp
+objectMonitor.cpp                       thread.hpp
+objectMonitor.cpp                       thread_<os_family>.inline.hpp
+objectMonitor.cpp                       threadService.hpp
+objectMonitor.cpp                       vmSymbols.hpp
+
 objectMonitor.hpp                       os.hpp
-
-objectMonitor_<os_family>.cpp           dtrace.hpp
-objectMonitor_<os_family>.cpp           interfaceSupport.hpp
-objectMonitor_<os_family>.cpp           objectMonitor.hpp
-objectMonitor_<os_family>.cpp           objectMonitor.inline.hpp
-objectMonitor_<os_family>.cpp           oop.inline.hpp
-objectMonitor_<os_family>.cpp           osThread.hpp
-objectMonitor_<os_family>.cpp           os_<os_family>.inline.hpp
-objectMonitor_<os_family>.cpp           threadService.hpp
-objectMonitor_<os_family>.cpp           thread_<os_family>.inline.hpp
-objectMonitor_<os_family>.cpp           vmSymbols.hpp
-
-objectMonitor_<os_family>.hpp           generate_platform_dependent_include
-objectMonitor_<os_family>.hpp           os_<os_family>.inline.hpp
-objectMonitor_<os_family>.hpp           thread_<os_family>.inline.hpp
-objectMonitor_<os_family>.hpp           top.hpp
-
-objectMonitor_<os_family>.inline.hpp    generate_platform_dependent_include
+objectMonitor.hpp                       perfData.hpp
 
 oop.cpp                                 copy.hpp
 oop.cpp                                 handles.inline.hpp
@@ -3231,6 +3239,7 @@
 orderAccess.hpp                         os.hpp
 
 orderAccess_<os_arch>.inline.hpp        orderAccess.hpp
+orderAccess_<os_arch>.inline.hpp        vm_version_<arch>.hpp
 
 os.cpp                                  allocation.inline.hpp
 os.cpp                                  arguments.hpp
@@ -3328,7 +3337,6 @@
 os_<os_family>.cpp                      nativeInst_<arch>.hpp
 os_<os_family>.cpp                      no_precompiled_headers
 os_<os_family>.cpp                      objectMonitor.hpp
-os_<os_family>.cpp                      objectMonitor.inline.hpp
 os_<os_family>.cpp                      oop.inline.hpp
 os_<os_family>.cpp                      osThread.hpp
 os_<os_family>.cpp                      os_share_<os_family>.hpp
@@ -3388,6 +3396,12 @@
 ostream.hpp                             allocation.hpp
 ostream.hpp                             timer.hpp
 
+// include thread.hpp to prevent cyclic includes
+park.cpp                                thread.hpp
+
+park.hpp                                debug.hpp
+park.hpp                                globalDefinitions.hpp
+
 pcDesc.cpp                              debugInfoRec.hpp
 pcDesc.cpp                              nmethod.hpp
 pcDesc.cpp                              pcDesc.hpp
@@ -3600,7 +3614,9 @@
 relocator.cpp                           bytecodes.hpp
 relocator.cpp                           handles.inline.hpp
 relocator.cpp                           oop.inline.hpp
+relocator.cpp                           oopFactory.hpp
 relocator.cpp                           relocator.hpp
+relocator.cpp                           stackMapTableFormat.hpp
 relocator.cpp                           universe.inline.hpp
 
 relocator.hpp                           bytecodes.hpp
@@ -3907,6 +3923,8 @@
 stackMapTable.hpp                       methodOop.hpp
 stackMapTable.hpp                       stackMapFrame.hpp
 
+stackMapTableFormat.hpp                 verificationType.hpp
+
 stackValue.cpp                          debugInfo.hpp
 stackValue.cpp                          frame.inline.hpp
 stackValue.cpp                          handles.inline.hpp
@@ -4062,10 +4080,10 @@
 synchronizer.cpp                        resourceArea.hpp
 synchronizer.cpp                        stubRoutines.hpp
 synchronizer.cpp                        synchronizer.hpp
-synchronizer.cpp                        threadService.hpp
 synchronizer.cpp                        thread_<os_family>.inline.hpp
 synchronizer.cpp                        vmSymbols.hpp
 
+synchronizer.hpp                        basicLock.hpp
 synchronizer.hpp                        handles.hpp
 synchronizer.hpp                        markOop.hpp
 synchronizer.hpp                        perfData.hpp
@@ -4237,7 +4255,6 @@
 thread.cpp                              mutexLocker.hpp
 thread.cpp                              objArrayOop.hpp
 thread.cpp                              objectMonitor.hpp
-thread.cpp                              objectMonitor.inline.hpp
 thread.cpp                              oop.inline.hpp
 thread.cpp                              oopFactory.hpp
 thread.cpp                              osThread.hpp
@@ -4275,6 +4292,7 @@
 thread.hpp                              oop.hpp
 thread.hpp                              os.hpp
 thread.hpp                              osThread.hpp
+thread.hpp                              park.hpp
 thread.hpp                              safepoint.hpp
 thread.hpp                              stubRoutines.hpp
 thread.hpp                              threadLocalAllocBuffer.hpp
@@ -4586,6 +4604,7 @@
 vframeArray.hpp                         growableArray.hpp
 vframeArray.hpp                         monitorChunk.hpp
 
+vframe_hp.cpp                           basicLock.hpp
 vframe_hp.cpp                           codeCache.hpp
 vframe_hp.cpp                           debugInfoRec.hpp
 vframe_hp.cpp                           handles.inline.hpp
@@ -4599,7 +4618,6 @@
 vframe_hp.cpp                           scopeDesc.hpp
 vframe_hp.cpp                           signature.hpp
 vframe_hp.cpp                           stubRoutines.hpp
-vframe_hp.cpp                           synchronizer.hpp
 vframe_hp.cpp                           vframeArray.hpp
 vframe_hp.cpp                           vframe_hp.hpp
 
@@ -4751,6 +4769,7 @@
 workgroup.cpp                           workgroup.hpp
 
 workgroup.hpp                           taskqueue.hpp
+
 workgroup.hpp                           thread_<os_family>.inline.hpp
 
 xmlstream.cpp                           allocation.hpp
--- a/hotspot/src/share/vm/includeDB_features	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/includeDB_features	Wed Jul 05 17:26:57 2017 +0200
@@ -184,6 +184,13 @@
 jvmtiImpl.hpp                           systemDictionary.hpp
 jvmtiImpl.hpp                           vm_operations.hpp
 
+jvmtiRawMonitor.cpp                     interfaceSupport.hpp
+jvmtiRawMonitor.cpp                     jvmtiRawMonitor.hpp
+jvmtiRawMonitor.cpp                     thread.hpp
+
+jvmtiRawMonitor.hpp                     growableArray.hpp
+jvmtiRawMonitor.hpp                     objectMonitor.hpp
+
 jvmtiTagMap.cpp                         biasedLocking.hpp
 jvmtiTagMap.cpp                         javaCalls.hpp
 jvmtiTagMap.cpp                         jniHandles.hpp
--- a/hotspot/src/share/vm/includeDB_jvmti	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/includeDB_jvmti	Wed Jul 05 17:26:57 2017 +0200
@@ -35,6 +35,7 @@
 // jvmtiCodeBlobEvents is jck optional, please put deps in includeDB_features
 
 jvmtiEnter.cpp                          jvmtiEnter.hpp
+jvmtiEnter.cpp                          jvmtiRawMonitor.hpp
 jvmtiEnter.cpp                          jvmtiUtil.hpp
 
 jvmtiEnter.hpp                          interfaceSupport.hpp
@@ -44,6 +45,7 @@
 jvmtiEnter.hpp                          systemDictionary.hpp
 
 jvmtiEnterTrace.cpp                     jvmtiEnter.hpp
+jvmtiEnterTrace.cpp                     jvmtiRawMonitor.hpp
 jvmtiEnterTrace.cpp                     jvmtiUtil.hpp
 
 jvmtiEnv.cpp                            arguments.hpp
@@ -66,11 +68,11 @@
 jvmtiEnv.cpp                            jvmtiGetLoadedClasses.hpp
 jvmtiEnv.cpp                            jvmtiImpl.hpp
 jvmtiEnv.cpp                            jvmtiManageCapabilities.hpp
+jvmtiEnv.cpp                            jvmtiRawMonitor.hpp
 jvmtiEnv.cpp                            jvmtiRedefineClasses.hpp
 jvmtiEnv.cpp                            jvmtiTagMap.hpp
 jvmtiEnv.cpp                            jvmtiThreadState.inline.hpp
 jvmtiEnv.cpp                            jvmtiUtil.hpp
-jvmtiEnv.cpp                            objectMonitor.inline.hpp
 jvmtiEnv.cpp                            osThread.hpp
 jvmtiEnv.cpp                            preserveException.hpp
 jvmtiEnv.cpp                            reflectionUtils.hpp
@@ -178,11 +180,13 @@
 jvmtiExport.cpp                         jvmtiExport.hpp
 jvmtiExport.cpp                         jvmtiImpl.hpp
 jvmtiExport.cpp                         jvmtiManageCapabilities.hpp
+jvmtiExport.cpp                         jvmtiRawMonitor.hpp
 jvmtiExport.cpp                         jvmtiTagMap.hpp
 jvmtiExport.cpp                         jvmtiThreadState.inline.hpp
 jvmtiExport.cpp                         nmethod.hpp
 jvmtiExport.cpp                         objArrayKlass.hpp
 jvmtiExport.cpp                         objArrayOop.hpp
+jvmtiExport.cpp                         objectMonitor.hpp
 jvmtiExport.cpp                         objectMonitor.inline.hpp
 jvmtiExport.cpp                         pcDesc.hpp
 jvmtiExport.cpp                         resourceArea.hpp
@@ -210,6 +214,8 @@
 jvmtiManageCapabilities.hpp             allocation.hpp
 jvmtiManageCapabilities.hpp             jvmti.h
 
+// jvmtiRawMonitor is jck optional, please put deps in includeDB_features
+
 jvmtiRedefineClasses.cpp                bitMap.inline.hpp
 jvmtiRedefineClasses.cpp                codeCache.hpp
 jvmtiRedefineClasses.cpp                deoptimization.hpp
--- a/hotspot/src/share/vm/memory/collectorPolicy.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -659,9 +659,6 @@
     }
     return result;   // could be null if we are out of space
   } else if (!gch->incremental_collection_will_fail()) {
-    // The gc_prologues have not executed yet.  The value
-    // for incremental_collection_will_fail() is the remanent
-    // of the last collection.
     // Do an incremental collection.
     gch->do_collection(false            /* full */,
                        false            /* clear_all_soft_refs */,
@@ -739,9 +736,8 @@
   GenCollectedHeap* gch = GenCollectedHeap::heap();
   size_t gen0_capacity = gch->get_gen(0)->capacity_before_gc();
   return    (word_size > heap_word_size(gen0_capacity))
-         || (GC_locker::is_active_and_needs_gc())
-         || (   gch->last_incremental_collection_failed()
-             && gch->incremental_collection_will_fail());
+         || GC_locker::is_active_and_needs_gc()
+         || gch->incremental_collection_failed();
 }
 
 
--- a/hotspot/src/share/vm/memory/defNewGeneration.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -510,7 +510,7 @@
   // from this generation, pass on collection; let the next generation
   // do it.
   if (!collection_attempt_is_safe()) {
-    gch->set_incremental_collection_will_fail();
+    gch->set_incremental_collection_failed(); // Slight lie: we did not even attempt one
     return;
   }
   assert(to()->is_empty(), "Else not collection_attempt_is_safe");
@@ -596,9 +596,8 @@
     if (PrintGC && !PrintGCDetails) {
       gch->print_heap_change(gch_prev_used);
     }
+    assert(!gch->incremental_collection_failed(), "Should be clear");
   } else {
-    assert(HandlePromotionFailure,
-      "Should not be here unless promotion failure handling is on");
     assert(_promo_failure_scan_stack.is_empty(), "post condition");
     _promo_failure_scan_stack.clear(true); // Clear cached segments.
 
@@ -613,7 +612,7 @@
     // and from-space.
     swap_spaces();   // For uniformity wrt ParNewGeneration.
     from()->set_next_compaction_space(to());
-    gch->set_incremental_collection_will_fail();
+    gch->set_incremental_collection_failed();
 
     // Inform the next generation that a promotion failure occurred.
     _next_gen->promotion_failure_occurred();
@@ -700,12 +699,6 @@
   if (obj == NULL) {
     obj = _next_gen->promote(old, s);
     if (obj == NULL) {
-      if (!HandlePromotionFailure) {
-        // A failed promotion likely means the MaxLiveObjectEvacuationRatio flag
-        // is incorrectly set. In any case, its seriously wrong to be here!
-        vm_exit_out_of_memory(s*wordSize, "promotion");
-      }
-
       handle_promotion_failure(old);
       return old;
     }
@@ -812,47 +805,43 @@
     assert(_next_gen != NULL,
            "This must be the youngest gen, and not the only gen");
   }
-
-  // Decide if there's enough room for a full promotion
-  // When using extremely large edens, we effectively lose a
-  // large amount of old space.  Use the "MaxLiveObjectEvacuationRatio"
-  // flag to reduce the minimum evacuation space requirements. If
-  // there is not enough space to evacuate eden during a scavenge,
-  // the VM will immediately exit with an out of memory error.
-  // This flag has not been tested
-  // with collectors other than simple mark & sweep.
-  //
-  // Note that with the addition of promotion failure handling, the
-  // VM will not immediately exit but will undo the young generation
-  // collection.  The parameter is left here for compatibility.
-  const double evacuation_ratio = MaxLiveObjectEvacuationRatio / 100.0;
-
-  // worst_case_evacuation is based on "used()".  For the case where this
-  // method is called after a collection, this is still appropriate because
-  // the case that needs to be detected is one in which a full collection
-  // has been done and has overflowed into the young generation.  In that
-  // case a minor collection will fail (the overflow of the full collection
-  // means there is no space in the old generation for any promotion).
-  size_t worst_case_evacuation = (size_t)(used() * evacuation_ratio);
-
-  return _next_gen->promotion_attempt_is_safe(worst_case_evacuation,
-                                              HandlePromotionFailure);
+  return _next_gen->promotion_attempt_is_safe(used());
 }
 
 void DefNewGeneration::gc_epilogue(bool full) {
+  DEBUG_ONLY(static bool seen_incremental_collection_failed = false;)
+
+  assert(!GC_locker::is_active(), "We should not be executing here");
   // Check if the heap is approaching full after a collection has
   // been done.  Generally the young generation is empty at
   // a minimum at the end of a collection.  If it is not, then
   // the heap is approaching full.
   GenCollectedHeap* gch = GenCollectedHeap::heap();
-  clear_should_allocate_from_space();
-  if (collection_attempt_is_safe()) {
-    gch->clear_incremental_collection_will_fail();
+  if (full) {
+    DEBUG_ONLY(seen_incremental_collection_failed = false;)
+    if (!collection_attempt_is_safe()) {
+      gch->set_incremental_collection_failed(); // Slight lie: a full gc left us in that state
+      set_should_allocate_from_space(); // we seem to be running out of space
+    } else {
+      gch->clear_incremental_collection_failed(); // We just did a full collection
+      clear_should_allocate_from_space(); // if set
+    }
   } else {
-    gch->set_incremental_collection_will_fail();
-    if (full) { // we seem to be running out of space
-      set_should_allocate_from_space();
+#ifdef ASSERT
+    // It is possible that incremental_collection_failed() == true
+    // here, because an attempted scavenge did not succeed. The policy
+    // is normally expected to cause a full collection which should
+    // clear that condition, so we should not be here twice in a row
+    // with incremental_collection_failed() == true without having done
+    // a full collection in between.
+    if (!seen_incremental_collection_failed &&
+        gch->incremental_collection_failed()) {
+      seen_incremental_collection_failed = true;
+    } else if (seen_incremental_collection_failed) {
+      assert(!gch->incremental_collection_failed(), "Twice in a row");
+      seen_incremental_collection_failed = false;
     }
+#endif // ASSERT
   }
 
   if (ZapUnusedHeapArea) {
--- a/hotspot/src/share/vm/memory/defNewGeneration.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/memory/defNewGeneration.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -82,12 +82,6 @@
   Stack<oop>     _objs_with_preserved_marks;
   Stack<markOop> _preserved_marks_of_objs;
 
-  // Returns true if the collection can be safely attempted.
-  // If this method returns false, a collection is not
-  // guaranteed to fail but the system may not be able
-  // to recover from the failure.
-  bool collection_attempt_is_safe();
-
   // Promotion failure handling
   OopClosure *_promo_failure_scan_stack_closure;
   void set_promo_failure_scan_stack_closure(OopClosure *scan_stack_closure) {
@@ -304,6 +298,14 @@
 
   // GC support
   virtual void compute_new_size();
+
+  // Returns true if the collection is likely to be safely
+  // completed. Even if this method returns true, a collection
+  // may not be guaranteed to succeed, and the system should be
+  // able to safely unwind and recover from that failure, albeit
+  // at some additional cost. Override superclass's implementation.
+  virtual bool collection_attempt_is_safe();
+
   virtual void collect(bool   full,
                        bool   clear_all_soft_refs,
                        size_t size,
--- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -142,8 +142,7 @@
   }
   _perm_gen = perm_gen_spec->init(heap_rs, PermSize, rem_set());
 
-  clear_incremental_collection_will_fail();
-  clear_last_incremental_collection_failed();
+  clear_incremental_collection_failed();
 
 #ifndef SERIALGC
   // If we are running CMS, create the collector responsible
@@ -1347,17 +1346,6 @@
 };
 
 void GenCollectedHeap::gc_epilogue(bool full) {
-  // Remember if a partial collection of the heap failed, and
-  // we did a complete collection.
-  if (full && incremental_collection_will_fail()) {
-    set_last_incremental_collection_failed();
-  } else {
-    clear_last_incremental_collection_failed();
-  }
-  // Clear the flag, if set; the generation gc_epilogues will set the
-  // flag again if the condition persists despite the collection.
-  clear_incremental_collection_will_fail();
-
 #ifdef COMPILER2
   assert(DerivedPointerTable::is_empty(), "derived pointer present");
   size_t actual_gap = pointer_delta((HeapWord*) (max_uintx-3), *(end_addr()));
--- a/hotspot/src/share/vm/memory/genCollectedHeap.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -62,11 +62,10 @@
   // The generational collector policy.
   GenCollectorPolicy* _gen_policy;
 
-  // If a generation would bail out of an incremental collection,
-  // it sets this flag.  If the flag is set, satisfy_failed_allocation
-  // will attempt allocating in all generations before doing a full GC.
-  bool _incremental_collection_will_fail;
-  bool _last_incremental_collection_failed;
+  // Indicates that the most recent previous incremental collection failed.
+  // The flag is cleared when an action is taken that might clear the
+  // condition that caused that incremental collection to fail.
+  bool _incremental_collection_failed;
 
   // In support of ExplicitGCInvokesConcurrent functionality
   unsigned int _full_collections_completed;
@@ -469,26 +468,26 @@
   // call to "save_marks".
   bool no_allocs_since_save_marks(int level);
 
+  // Returns true if an incremental collection is likely to fail.
+  bool incremental_collection_will_fail() {
+    // Assumes a 2-generation system; the first disjunct remembers if an
+    // incremental collection failed, even when we thought (second disjunct)
+    // that it would not.
+    assert(heap()->collector_policy()->is_two_generation_policy(),
+           "the following definition may not be suitable for an n(>2)-generation system");
+    return incremental_collection_failed() || !get_gen(0)->collection_attempt_is_safe();
+  }
+
   // If a generation bails out of an incremental collection,
   // it sets this flag.
-  bool incremental_collection_will_fail() {
-    return _incremental_collection_will_fail;
-  }
-  void set_incremental_collection_will_fail() {
-    _incremental_collection_will_fail = true;
-  }
-  void clear_incremental_collection_will_fail() {
-    _incremental_collection_will_fail = false;
+  bool incremental_collection_failed() const {
+    return _incremental_collection_failed;
   }
-
-  bool last_incremental_collection_failed() const {
-    return _last_incremental_collection_failed;
+  void set_incremental_collection_failed() {
+    _incremental_collection_failed = true;
   }
-  void set_last_incremental_collection_failed() {
-    _last_incremental_collection_failed = true;
-  }
-  void clear_last_incremental_collection_failed() {
-    _last_incremental_collection_failed = false;
+  void clear_incremental_collection_failed() {
+    _incremental_collection_failed = false;
   }
 
   // Promotion of obj into gen failed.  Try to promote obj to higher non-perm
--- a/hotspot/src/share/vm/memory/generation.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/memory/generation.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -165,15 +165,16 @@
   return max;
 }
 
-bool Generation::promotion_attempt_is_safe(size_t promotion_in_bytes,
-                                           bool not_used) const {
+bool Generation::promotion_attempt_is_safe(size_t max_promotion_in_bytes) const {
+  size_t available = max_contiguous_available();
+  bool   res = (available >= max_promotion_in_bytes);
   if (PrintGC && Verbose) {
-    gclog_or_tty->print_cr("Generation::promotion_attempt_is_safe"
-                " contiguous_available: " SIZE_FORMAT
-                " promotion_in_bytes: " SIZE_FORMAT,
-                max_contiguous_available(), promotion_in_bytes);
+    gclog_or_tty->print_cr(
+      "Generation: promo attempt is%s safe: available("SIZE_FORMAT") %s max_promo("SIZE_FORMAT")",
+      res? "":" not", available, res? ">=":"<",
+      max_promotion_in_bytes);
   }
-  return max_contiguous_available() >= promotion_in_bytes;
+  return res;
 }
 
 // Ignores "ref" and calls allocate().
--- a/hotspot/src/share/vm/memory/generation.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/memory/generation.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -173,15 +173,11 @@
   // The largest number of contiguous free bytes in this or any higher generation.
   virtual size_t max_contiguous_available() const;
 
-  // Returns true if promotions of the specified amount can
-  // be attempted safely (without a vm failure).
+  // Returns true if promotions of the specified amount are
+  // likely to succeed without a promotion failure.
   // Promotion of the full amount is not guaranteed but
-  // can be attempted.
-  //   younger_handles_promotion_failure
-  // is true if the younger generation handles a promotion
-  // failure.
-  virtual bool promotion_attempt_is_safe(size_t promotion_in_bytes,
-    bool younger_handles_promotion_failure) const;
+  // might be attempted in the worst case.
+  virtual bool promotion_attempt_is_safe(size_t max_promotion_in_bytes) const;
 
   // For a non-young generation, this interface can be used to inform a
   // generation that a promotion attempt into that generation failed.
@@ -358,6 +354,16 @@
     return (full || should_allocate(word_size, is_tlab));
   }
 
+  // Returns true if the collection is likely to be safely
+  // completed. Even if this method returns true, a collection
+  // may not be guaranteed to succeed, and the system should be
+  // able to safely unwind and recover from that failure, albeit
+  // at some additional cost.
+  virtual bool collection_attempt_is_safe() {
+    guarantee(false, "Are you sure you want to call this method?");
+    return true;
+  }
+
   // Perform a garbage collection.
   // If full is true attempt a full garbage collection of this generation.
   // Otherwise, attempting to (at least) free enough space to support an
--- a/hotspot/src/share/vm/memory/tenuredGeneration.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/memory/tenuredGeneration.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -419,29 +419,16 @@
 void TenuredGeneration::verify_alloc_buffers_clean() {}
 #endif // SERIALGC
 
-bool TenuredGeneration::promotion_attempt_is_safe(
-    size_t max_promotion_in_bytes,
-    bool younger_handles_promotion_failure) const {
-
-  bool result = max_contiguous_available() >= max_promotion_in_bytes;
-
-  if (younger_handles_promotion_failure && !result) {
-    result = max_contiguous_available() >=
-      (size_t) gc_stats()->avg_promoted()->padded_average();
-    if (PrintGC && Verbose && result) {
-      gclog_or_tty->print_cr("TenuredGeneration::promotion_attempt_is_safe"
-                  " contiguous_available: " SIZE_FORMAT
-                  " avg_promoted: " SIZE_FORMAT,
-                  max_contiguous_available(),
-                  gc_stats()->avg_promoted()->padded_average());
-    }
-  } else {
-    if (PrintGC && Verbose) {
-      gclog_or_tty->print_cr("TenuredGeneration::promotion_attempt_is_safe"
-                  " contiguous_available: " SIZE_FORMAT
-                  " promotion_in_bytes: " SIZE_FORMAT,
-                  max_contiguous_available(), max_promotion_in_bytes);
-    }
+bool TenuredGeneration::promotion_attempt_is_safe(size_t max_promotion_in_bytes) const {
+  size_t available = max_contiguous_available();
+  size_t av_promo  = (size_t)gc_stats()->avg_promoted()->padded_average();
+  bool   res = (available >= av_promo) || (available >= max_promotion_in_bytes);
+  if (PrintGC && Verbose) {
+    gclog_or_tty->print_cr(
+      "Tenured: promo attempt is%s safe: available("SIZE_FORMAT") %s av_promo("SIZE_FORMAT"),"
+      "max_promo("SIZE_FORMAT")",
+      res? "":" not", available, res? ">=":"<",
+      av_promo, max_promotion_in_bytes);
   }
-  return result;
+  return res;
 }
--- a/hotspot/src/share/vm/memory/tenuredGeneration.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/memory/tenuredGeneration.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -101,8 +101,7 @@
 
   virtual void update_gc_stats(int level, bool full);
 
-  virtual bool promotion_attempt_is_safe(size_t max_promoted_in_bytes,
-    bool younger_handles_promotion_failure) const;
+  virtual bool promotion_attempt_is_safe(size_t max_promoted_in_bytes) const;
 
   void verify_alloc_buffers_clean();
 };
--- a/hotspot/src/share/vm/oops/methodOop.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/oops/methodOop.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -247,6 +247,10 @@
     return constMethod()->stackmap_data();
   }
 
+  void set_stackmap_data(typeArrayOop sd) {
+    constMethod()->set_stackmap_data(sd);
+  }
+
   // exception handler table
   typeArrayOop exception_table() const
                                    { return constMethod()->exception_table(); }
--- a/hotspot/src/share/vm/prims/jvmtiImpl.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiImpl.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -25,26 +25,6 @@
 # include "incls/_precompiled.incl"
 # include "incls/_jvmtiImpl.cpp.incl"
 
-GrowableArray<JvmtiRawMonitor*> *JvmtiPendingMonitors::_monitors = new (ResourceObj::C_HEAP) GrowableArray<JvmtiRawMonitor*>(1,true);
-
-void JvmtiPendingMonitors::transition_raw_monitors() {
-  assert((Threads::number_of_threads()==1),
-         "Java thread has not created yet or more than one java thread \
-is running. Raw monitor transition will not work");
-  JavaThread *current_java_thread = JavaThread::current();
-  assert(current_java_thread->thread_state() == _thread_in_vm, "Must be in vm");
-  {
-    ThreadBlockInVM __tbivm(current_java_thread);
-    for(int i=0; i< count(); i++) {
-      JvmtiRawMonitor *rmonitor = monitors()->at(i);
-      int r = rmonitor->raw_enter(current_java_thread);
-      assert(r == ObjectMonitor::OM_OK, "raw_enter should have worked");
-    }
-  }
-  // pending monitors are converted to real monitor so delete them all.
-  dispose();
-}
-
 //
 // class JvmtiAgentThread
 //
@@ -216,57 +196,6 @@
   }
 }
 
-
-//
-// class JvmtiRawMonitor
-//
-
-JvmtiRawMonitor::JvmtiRawMonitor(const char *name) {
-#ifdef ASSERT
-  _name = strcpy(NEW_C_HEAP_ARRAY(char, strlen(name) + 1), name);
-#else
-  _name = NULL;
-#endif
-  _magic = JVMTI_RM_MAGIC;
-}
-
-JvmtiRawMonitor::~JvmtiRawMonitor() {
-#ifdef ASSERT
-  FreeHeap(_name);
-#endif
-  _magic = 0;
-}
-
-
-bool
-JvmtiRawMonitor::is_valid() {
-  int value = 0;
-
-  // This object might not be a JvmtiRawMonitor so we can't assume
-  // the _magic field is properly aligned. Get the value in a safe
-  // way and then check against JVMTI_RM_MAGIC.
-
-  switch (sizeof(_magic)) {
-  case 2:
-    value = Bytes::get_native_u2((address)&_magic);
-    break;
-
-  case 4:
-    value = Bytes::get_native_u4((address)&_magic);
-    break;
-
-  case 8:
-    value = Bytes::get_native_u8((address)&_magic);
-    break;
-
-  default:
-    guarantee(false, "_magic field is an unexpected size");
-  }
-
-  return value == JVMTI_RM_MAGIC;
-}
-
-
 //
 // class JvmtiBreakpoint
 //
--- a/hotspot/src/share/vm/prims/jvmtiImpl.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiImpl.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -26,7 +26,6 @@
 // Forward Declarations
 //
 
-class JvmtiRawMonitor;
 class JvmtiBreakpoint;
 class JvmtiBreakpoints;
 
@@ -327,76 +326,6 @@
     return false;
 }
 
-
-///////////////////////////////////////////////////////////////
-//
-// class JvmtiRawMonitor
-//
-// Used by JVMTI methods: All RawMonitor methods (CreateRawMonitor, EnterRawMonitor, etc.)
-//
-// Wrapper for ObjectMonitor class that saves the Monitor's name
-//
-
-class JvmtiRawMonitor : public ObjectMonitor  {
-private:
-  int           _magic;
-  char *        _name;
-  // JVMTI_RM_MAGIC is set in contructor and unset in destructor.
-  enum { JVMTI_RM_MAGIC = (int)(('T' << 24) | ('I' << 16) | ('R' << 8) | 'M') };
-
-public:
-  JvmtiRawMonitor(const char *name);
-  ~JvmtiRawMonitor();
-  int            magic()   { return _magic;  }
-  const char *get_name()   { return _name; }
-  bool        is_valid();
-};
-
-// Onload pending raw monitors
-// Class is used to cache onload or onstart monitor enter
-// which will transition into real monitor when
-// VM is fully initialized.
-class JvmtiPendingMonitors : public AllStatic {
-
-private:
-  static GrowableArray<JvmtiRawMonitor*> *_monitors; // Cache raw monitor enter
-
-  inline static GrowableArray<JvmtiRawMonitor*>* monitors() { return _monitors; }
-
-  static void dispose() {
-    delete monitors();
-  }
-
-public:
-  static void enter(JvmtiRawMonitor *monitor) {
-    monitors()->append(monitor);
-  }
-
-  static int count() {
-    return monitors()->length();
-  }
-
-  static void destroy(JvmtiRawMonitor *monitor) {
-    while (monitors()->contains(monitor)) {
-      monitors()->remove(monitor);
-    }
-  }
-
-  // Return false if monitor is not found in the list.
-  static bool exit(JvmtiRawMonitor *monitor) {
-    if (monitors()->contains(monitor)) {
-      monitors()->remove(monitor);
-      return true;
-    } else {
-      return false;
-    }
-  }
-
-  static void transition_raw_monitors();
-};
-
-
-
 ///////////////////////////////////////////////////////////////
 // The get/set local operations must only be done by the VM thread
 // because the interpreter version needs to access oop maps, which can
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/prims/jvmtiRawMonitor.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,420 @@
+/*
+ * Copyright (c) 2003, 2007, 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.
+ *
+ */
+
+# include "incls/_precompiled.incl"
+# include "incls/_jvmtiRawMonitor.cpp.incl"
+
+GrowableArray<JvmtiRawMonitor*> *JvmtiPendingMonitors::_monitors = new (ResourceObj::C_HEAP) GrowableArray<JvmtiRawMonitor*>(1,true);
+
+void JvmtiPendingMonitors::transition_raw_monitors() {
+  assert((Threads::number_of_threads()==1),
+         "Java thread has not created yet or more than one java thread \
+is running. Raw monitor transition will not work");
+  JavaThread *current_java_thread = JavaThread::current();
+  assert(current_java_thread->thread_state() == _thread_in_vm, "Must be in vm");
+  {
+    ThreadBlockInVM __tbivm(current_java_thread);
+    for(int i=0; i< count(); i++) {
+      JvmtiRawMonitor *rmonitor = monitors()->at(i);
+      int r = rmonitor->raw_enter(current_java_thread);
+      assert(r == ObjectMonitor::OM_OK, "raw_enter should have worked");
+    }
+  }
+  // pending monitors are converted to real monitor so delete them all.
+  dispose();
+}
+
+//
+// class JvmtiRawMonitor
+//
+
+JvmtiRawMonitor::JvmtiRawMonitor(const char *name) {
+#ifdef ASSERT
+  _name = strcpy(NEW_C_HEAP_ARRAY(char, strlen(name) + 1), name);
+#else
+  _name = NULL;
+#endif
+  _magic = JVMTI_RM_MAGIC;
+}
+
+JvmtiRawMonitor::~JvmtiRawMonitor() {
+#ifdef ASSERT
+  FreeHeap(_name);
+#endif
+  _magic = 0;
+}
+
+
+bool
+JvmtiRawMonitor::is_valid() {
+  int value = 0;
+
+  // This object might not be a JvmtiRawMonitor so we can't assume
+  // the _magic field is properly aligned. Get the value in a safe
+  // way and then check against JVMTI_RM_MAGIC.
+
+  switch (sizeof(_magic)) {
+  case 2:
+    value = Bytes::get_native_u2((address)&_magic);
+    break;
+
+  case 4:
+    value = Bytes::get_native_u4((address)&_magic);
+    break;
+
+  case 8:
+    value = Bytes::get_native_u8((address)&_magic);
+    break;
+
+  default:
+    guarantee(false, "_magic field is an unexpected size");
+  }
+
+  return value == JVMTI_RM_MAGIC;
+}
+
+// -------------------------------------------------------------------------
+// The raw monitor subsystem is entirely distinct from normal
+// java-synchronization or jni-synchronization.  raw monitors are not
+// associated with objects.  They can be implemented in any manner
+// that makes sense.  The original implementors decided to piggy-back
+// the raw-monitor implementation on the existing Java objectMonitor mechanism.
+// This flaw needs to fixed.  We should reimplement raw monitors as sui-generis.
+// Specifically, we should not implement raw monitors via java monitors.
+// Time permitting, we should disentangle and deconvolve the two implementations
+// and move the resulting raw monitor implementation over to the JVMTI directories.
+// Ideally, the raw monitor implementation would be built on top of
+// park-unpark and nothing else.
+//
+// raw monitors are used mainly by JVMTI
+// The raw monitor implementation borrows the ObjectMonitor structure,
+// but the operators are degenerate and extremely simple.
+//
+// Mixed use of a single objectMonitor instance -- as both a raw monitor
+// and a normal java monitor -- is not permissible.
+//
+// Note that we use the single RawMonitor_lock to protect queue operations for
+// _all_ raw monitors.  This is a scalability impediment, but since raw monitor usage
+// is deprecated and rare, this is not of concern.  The RawMonitor_lock can not
+// be held indefinitely.  The critical sections must be short and bounded.
+//
+// -------------------------------------------------------------------------
+
+int JvmtiRawMonitor::SimpleEnter (Thread * Self) {
+  for (;;) {
+    if (Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {
+       return OS_OK ;
+    }
+
+    ObjectWaiter Node (Self) ;
+    Self->_ParkEvent->reset() ;     // strictly optional
+    Node.TState = ObjectWaiter::TS_ENTER ;
+
+    RawMonitor_lock->lock_without_safepoint_check() ;
+    Node._next  = _EntryList ;
+    _EntryList  = &Node ;
+    OrderAccess::fence() ;
+    if (_owner == NULL && Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {
+        _EntryList = Node._next ;
+        RawMonitor_lock->unlock() ;
+        return OS_OK ;
+    }
+    RawMonitor_lock->unlock() ;
+    while (Node.TState == ObjectWaiter::TS_ENTER) {
+       Self->_ParkEvent->park() ;
+    }
+  }
+}
+
+int JvmtiRawMonitor::SimpleExit (Thread * Self) {
+  guarantee (_owner == Self, "invariant") ;
+  OrderAccess::release_store_ptr (&_owner, NULL) ;
+  OrderAccess::fence() ;
+  if (_EntryList == NULL) return OS_OK ;
+  ObjectWaiter * w ;
+
+  RawMonitor_lock->lock_without_safepoint_check() ;
+  w = _EntryList ;
+  if (w != NULL) {
+      _EntryList = w->_next ;
+  }
+  RawMonitor_lock->unlock() ;
+  if (w != NULL) {
+      guarantee (w ->TState == ObjectWaiter::TS_ENTER, "invariant") ;
+      ParkEvent * ev = w->_event ;
+      w->TState = ObjectWaiter::TS_RUN ;
+      OrderAccess::fence() ;
+      ev->unpark() ;
+  }
+  return OS_OK ;
+}
+
+int JvmtiRawMonitor::SimpleWait (Thread * Self, jlong millis) {
+  guarantee (_owner == Self  , "invariant") ;
+  guarantee (_recursions == 0, "invariant") ;
+
+  ObjectWaiter Node (Self) ;
+  Node._notified = 0 ;
+  Node.TState    = ObjectWaiter::TS_WAIT ;
+
+  RawMonitor_lock->lock_without_safepoint_check() ;
+  Node._next     = _WaitSet ;
+  _WaitSet       = &Node ;
+  RawMonitor_lock->unlock() ;
+
+  SimpleExit (Self) ;
+  guarantee (_owner != Self, "invariant") ;
+
+  int ret = OS_OK ;
+  if (millis <= 0) {
+    Self->_ParkEvent->park();
+  } else {
+    ret = Self->_ParkEvent->park(millis);
+  }
+
+  // If thread still resides on the waitset then unlink it.
+  // Double-checked locking -- the usage is safe in this context
+  // as we TState is volatile and the lock-unlock operators are
+  // serializing (barrier-equivalent).
+
+  if (Node.TState == ObjectWaiter::TS_WAIT) {
+    RawMonitor_lock->lock_without_safepoint_check() ;
+    if (Node.TState == ObjectWaiter::TS_WAIT) {
+      // Simple O(n) unlink, but performance isn't critical here.
+      ObjectWaiter * p ;
+      ObjectWaiter * q = NULL ;
+      for (p = _WaitSet ; p != &Node; p = p->_next) {
+         q = p ;
+      }
+      guarantee (p == &Node, "invariant") ;
+      if (q == NULL) {
+        guarantee (p == _WaitSet, "invariant") ;
+        _WaitSet = p->_next ;
+      } else {
+        guarantee (p == q->_next, "invariant") ;
+        q->_next = p->_next ;
+      }
+      Node.TState = ObjectWaiter::TS_RUN ;
+    }
+    RawMonitor_lock->unlock() ;
+  }
+
+  guarantee (Node.TState == ObjectWaiter::TS_RUN, "invariant") ;
+  SimpleEnter (Self) ;
+
+  guarantee (_owner == Self, "invariant") ;
+  guarantee (_recursions == 0, "invariant") ;
+  return ret ;
+}
+
+int JvmtiRawMonitor::SimpleNotify (Thread * Self, bool All) {
+  guarantee (_owner == Self, "invariant") ;
+  if (_WaitSet == NULL) return OS_OK ;
+
+  // We have two options:
+  // A. Transfer the threads from the WaitSet to the EntryList
+  // B. Remove the thread from the WaitSet and unpark() it.
+  //
+  // We use (B), which is crude and results in lots of futile
+  // context switching.  In particular (B) induces lots of contention.
+
+  ParkEvent * ev = NULL ;       // consider using a small auto array ...
+  RawMonitor_lock->lock_without_safepoint_check() ;
+  for (;;) {
+      ObjectWaiter * w = _WaitSet ;
+      if (w == NULL) break ;
+      _WaitSet = w->_next ;
+      if (ev != NULL) { ev->unpark(); ev = NULL; }
+      ev = w->_event ;
+      OrderAccess::loadstore() ;
+      w->TState = ObjectWaiter::TS_RUN ;
+      OrderAccess::storeload();
+      if (!All) break ;
+  }
+  RawMonitor_lock->unlock() ;
+  if (ev != NULL) ev->unpark();
+  return OS_OK ;
+}
+
+// Any JavaThread will enter here with state _thread_blocked
+int JvmtiRawMonitor::raw_enter(TRAPS) {
+  TEVENT (raw_enter) ;
+  void * Contended ;
+
+  // don't enter raw monitor if thread is being externally suspended, it will
+  // surprise the suspender if a "suspended" thread can still enter monitor
+  JavaThread * jt = (JavaThread *)THREAD;
+  if (THREAD->is_Java_thread()) {
+    jt->SR_lock()->lock_without_safepoint_check();
+    while (jt->is_external_suspend()) {
+      jt->SR_lock()->unlock();
+      jt->java_suspend_self();
+      jt->SR_lock()->lock_without_safepoint_check();
+    }
+    // guarded by SR_lock to avoid racing with new external suspend requests.
+    Contended = Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) ;
+    jt->SR_lock()->unlock();
+  } else {
+    Contended = Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) ;
+  }
+
+  if (Contended == THREAD) {
+     _recursions ++ ;
+     return OM_OK ;
+  }
+
+  if (Contended == NULL) {
+     guarantee (_owner == THREAD, "invariant") ;
+     guarantee (_recursions == 0, "invariant") ;
+     return OM_OK ;
+  }
+
+  THREAD->set_current_pending_monitor(this);
+
+  if (!THREAD->is_Java_thread()) {
+     // No other non-Java threads besides VM thread would acquire
+     // a raw monitor.
+     assert(THREAD->is_VM_thread(), "must be VM thread");
+     SimpleEnter (THREAD) ;
+   } else {
+     guarantee (jt->thread_state() == _thread_blocked, "invariant") ;
+     for (;;) {
+       jt->set_suspend_equivalent();
+       // cleared by handle_special_suspend_equivalent_condition() or
+       // java_suspend_self()
+       SimpleEnter (THREAD) ;
+
+       // were we externally suspended while we were waiting?
+       if (!jt->handle_special_suspend_equivalent_condition()) break ;
+
+       // This thread was externally suspended
+       //
+       // This logic isn't needed for JVMTI raw monitors,
+       // but doesn't hurt just in case the suspend rules change. This
+           // logic is needed for the JvmtiRawMonitor.wait() reentry phase.
+           // We have reentered the contended monitor, but while we were
+           // waiting another thread suspended us. We don't want to reenter
+           // the monitor while suspended because that would surprise the
+           // thread that suspended us.
+           //
+           // Drop the lock -
+       SimpleExit (THREAD) ;
+
+           jt->java_suspend_self();
+         }
+
+     assert(_owner == THREAD, "Fatal error with monitor owner!");
+     assert(_recursions == 0, "Fatal error with monitor recursions!");
+  }
+
+  THREAD->set_current_pending_monitor(NULL);
+  guarantee (_recursions == 0, "invariant") ;
+  return OM_OK;
+}
+
+// Used mainly for JVMTI raw monitor implementation
+// Also used for JvmtiRawMonitor::wait().
+int JvmtiRawMonitor::raw_exit(TRAPS) {
+  TEVENT (raw_exit) ;
+  if (THREAD != _owner) {
+    return OM_ILLEGAL_MONITOR_STATE;
+  }
+  if (_recursions > 0) {
+    --_recursions ;
+    return OM_OK ;
+  }
+
+  void * List = _EntryList ;
+  SimpleExit (THREAD) ;
+
+  return OM_OK;
+}
+
+// Used for JVMTI raw monitor implementation.
+// All JavaThreads will enter here with state _thread_blocked
+
+int JvmtiRawMonitor::raw_wait(jlong millis, bool interruptible, TRAPS) {
+  TEVENT (raw_wait) ;
+  if (THREAD != _owner) {
+    return OM_ILLEGAL_MONITOR_STATE;
+  }
+
+  // To avoid spurious wakeups we reset the parkevent -- This is strictly optional.
+  // The caller must be able to tolerate spurious returns from raw_wait().
+  THREAD->_ParkEvent->reset() ;
+  OrderAccess::fence() ;
+
+  // check interrupt event
+  if (interruptible && Thread::is_interrupted(THREAD, true)) {
+    return OM_INTERRUPTED;
+  }
+
+  intptr_t save = _recursions ;
+  _recursions = 0 ;
+  _waiters ++ ;
+  if (THREAD->is_Java_thread()) {
+    guarantee (((JavaThread *) THREAD)->thread_state() == _thread_blocked, "invariant") ;
+    ((JavaThread *)THREAD)->set_suspend_equivalent();
+  }
+  int rv = SimpleWait (THREAD, millis) ;
+  _recursions = save ;
+  _waiters -- ;
+
+  guarantee (THREAD == _owner, "invariant") ;
+  if (THREAD->is_Java_thread()) {
+     JavaThread * jSelf = (JavaThread *) THREAD ;
+     for (;;) {
+        if (!jSelf->handle_special_suspend_equivalent_condition()) break ;
+        SimpleExit (THREAD) ;
+        jSelf->java_suspend_self();
+        SimpleEnter (THREAD) ;
+        jSelf->set_suspend_equivalent() ;
+     }
+  }
+  guarantee (THREAD == _owner, "invariant") ;
+
+  if (interruptible && Thread::is_interrupted(THREAD, true)) {
+    return OM_INTERRUPTED;
+  }
+  return OM_OK ;
+}
+
+int JvmtiRawMonitor::raw_notify(TRAPS) {
+  TEVENT (raw_notify) ;
+  if (THREAD != _owner) {
+    return OM_ILLEGAL_MONITOR_STATE;
+  }
+  SimpleNotify (THREAD, false) ;
+  return OM_OK;
+}
+
+int JvmtiRawMonitor::raw_notifyAll(TRAPS) {
+  TEVENT (raw_notifyAll) ;
+  if (THREAD != _owner) {
+    return OM_ILLEGAL_MONITOR_STATE;
+  }
+  SimpleNotify (THREAD, true) ;
+  return OM_OK;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/prims/jvmtiRawMonitor.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 1999, 2007, 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.
+ *
+ */
+
+//
+// class JvmtiRawMonitor
+//
+// Used by JVMTI methods: All RawMonitor methods (CreateRawMonitor, EnterRawMonitor, etc.)
+//
+// Wrapper for ObjectMonitor class that saves the Monitor's name
+//
+
+class JvmtiRawMonitor : public ObjectMonitor  {
+private:
+  int           _magic;
+  char *        _name;
+  // JVMTI_RM_MAGIC is set in contructor and unset in destructor.
+  enum { JVMTI_RM_MAGIC = (int)(('T' << 24) | ('I' << 16) | ('R' << 8) | 'M') };
+
+  int       SimpleEnter (Thread * Self) ;
+  int       SimpleExit  (Thread * Self) ;
+  int       SimpleWait  (Thread * Self, jlong millis) ;
+  int       SimpleNotify (Thread * Self, bool All) ;
+
+public:
+  JvmtiRawMonitor(const char *name);
+  ~JvmtiRawMonitor();
+  int       raw_enter(TRAPS);
+  int       raw_exit(TRAPS);
+  int       raw_wait(jlong millis, bool interruptable, TRAPS);
+  int       raw_notify(TRAPS);
+  int       raw_notifyAll(TRAPS);
+  int            magic()   { return _magic;  }
+  const char *get_name()   { return _name; }
+  bool        is_valid();
+};
+
+// Onload pending raw monitors
+// Class is used to cache onload or onstart monitor enter
+// which will transition into real monitor when
+// VM is fully initialized.
+class JvmtiPendingMonitors : public AllStatic {
+
+private:
+  static GrowableArray<JvmtiRawMonitor*> *_monitors; // Cache raw monitor enter
+
+  inline static GrowableArray<JvmtiRawMonitor*>* monitors() { return _monitors; }
+
+  static void dispose() {
+    delete monitors();
+  }
+
+public:
+  static void enter(JvmtiRawMonitor *monitor) {
+    monitors()->append(monitor);
+  }
+
+  static int count() {
+    return monitors()->length();
+  }
+
+  static void destroy(JvmtiRawMonitor *monitor) {
+    while (monitors()->contains(monitor)) {
+      monitors()->remove(monitor);
+    }
+  }
+
+  // Return false if monitor is not found in the list.
+  static bool exit(JvmtiRawMonitor *monitor) {
+    if (monitors()->contains(monitor)) {
+      monitors()->remove(monitor);
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  static void transition_raw_monitors();
+};
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -119,11 +119,8 @@
   PropertyList_add(&_system_properties, new SystemProperty("java.vm.specification.version", "1.0", false));
   PropertyList_add(&_system_properties, new SystemProperty("java.vm.specification.name",
                                                                  "Java Virtual Machine Specification",  false));
-  PropertyList_add(&_system_properties, new SystemProperty("java.vm.specification.vendor",
-        JDK_Version::is_gte_jdk17x_version() ? "Oracle Corporation" : "Sun Microsystems Inc.", false));
   PropertyList_add(&_system_properties, new SystemProperty("java.vm.version", VM_Version::vm_release(),  false));
   PropertyList_add(&_system_properties, new SystemProperty("java.vm.name", VM_Version::vm_name(),  false));
-  PropertyList_add(&_system_properties, new SystemProperty("java.vm.vendor", VM_Version::vm_vendor(),  false));
   PropertyList_add(&_system_properties, new SystemProperty("java.vm.info", VM_Version::vm_info_string(),  true));
 
   // following are JVMTI agent writeable properties.
@@ -151,6 +148,14 @@
   os::init_system_properties_values();
 }
 
+
+  // Update/Initialize System properties after JDK version number is known
+void Arguments::init_version_specific_system_properties() {
+  PropertyList_add(&_system_properties, new SystemProperty("java.vm.specification.vendor",
+        JDK_Version::is_gte_jdk17x_version() ? "Oracle Corporation" : "Sun Microsystems Inc.", false));
+  PropertyList_add(&_system_properties, new SystemProperty("java.vm.vendor", VM_Version::vm_vendor(),  false));
+}
+
 /**
  * Provide a slightly more user-friendly way of eliminating -XX flags.
  * When a flag is eliminated, it can be added to this list in order to
@@ -185,6 +190,10 @@
                            JDK_Version::jdk_update(6,18), JDK_Version::jdk(7) },
   { "UseDepthFirstScavengeOrder",
                            JDK_Version::jdk_update(6,22), JDK_Version::jdk(7) },
+  { "HandlePromotionFailure",
+                           JDK_Version::jdk_update(6,24), JDK_Version::jdk(8) },
+  { "MaxLiveObjectEvacuationRatio",
+                           JDK_Version::jdk_update(6,24), JDK_Version::jdk(8) },
   { NULL, JDK_Version(0), JDK_Version(0) }
 };
 
@@ -948,26 +957,65 @@
   }
 }
 
+void Arguments::check_compressed_oops_compat() {
+#ifdef _LP64
+  assert(UseCompressedOops, "Precondition");
+#  if defined(COMPILER1) && !defined(TIERED)
+  // Until c1 supports compressed oops turn them off.
+  FLAG_SET_DEFAULT(UseCompressedOops, false);
+#  else
+  // Is it on by default or set on ergonomically
+  bool is_on_by_default = FLAG_IS_DEFAULT(UseCompressedOops) || FLAG_IS_ERGO(UseCompressedOops);
+
+  // Tiered currently doesn't work with compressed oops
+  if (TieredCompilation) {
+    if (is_on_by_default) {
+      FLAG_SET_DEFAULT(UseCompressedOops, false);
+      return;
+    } else {
+      vm_exit_during_initialization(
+        "Tiered compilation is not supported with compressed oops yet", NULL);
+    }
+  }
+
+  // XXX JSR 292 currently does not support compressed oops
+  if (EnableMethodHandles) {
+    if (is_on_by_default) {
+      FLAG_SET_DEFAULT(UseCompressedOops, false);
+      return;
+    } else {
+      vm_exit_during_initialization(
+        "JSR292 is not supported with compressed oops yet", NULL);
+    }
+  }
+
+  // If dumping an archive or forcing its use, disable compressed oops if possible
+  if (DumpSharedSpaces || RequireSharedSpaces) {
+    if (is_on_by_default) {
+      FLAG_SET_DEFAULT(UseCompressedOops, false);
+      return;
+    } else {
+      vm_exit_during_initialization(
+        "Class Data Sharing is not supported with compressed oops yet", NULL);
+    }
+  } else if (UseSharedSpaces) {
+    // UseSharedSpaces is on by default. With compressed oops, we turn it off.
+    FLAG_SET_DEFAULT(UseSharedSpaces, false);
+  }
+
+#  endif // defined(COMPILER1) && !defined(TIERED)
+#endif // _LP64
+}
+
 void Arguments::set_tiered_flags() {
   if (FLAG_IS_DEFAULT(CompilationPolicyChoice)) {
     FLAG_SET_DEFAULT(CompilationPolicyChoice, 2);
   }
-
   if (CompilationPolicyChoice < 2) {
     vm_exit_during_initialization(
       "Incompatible compilation policy selected", NULL);
   }
-
-#ifdef _LP64
-  if (FLAG_IS_DEFAULT(UseCompressedOops) || FLAG_IS_ERGO(UseCompressedOops)) {
-    UseCompressedOops = false;
-  }
-  if (UseCompressedOops) {
-    vm_exit_during_initialization(
-      "Tiered compilation is not supported with compressed oops yet", NULL);
-  }
-#endif
- // Increase the code cache size - tiered compiles a lot more.
+  // Increase the code cache size - tiered compiles a lot more.
   if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) {
     FLAG_SET_DEFAULT(ReservedCodeCacheSize, ReservedCodeCacheSize * 2);
   }
@@ -1676,7 +1724,8 @@
   bool status = true;
   status = status && verify_min_value(StackYellowPages, 1, "StackYellowPages");
   status = status && verify_min_value(StackRedPages, 1, "StackRedPages");
-  status = status && verify_min_value(StackShadowPages, 1, "StackShadowPages");
+  // greater stack shadow pages can't generate instruction to bang stack
+  status = status && verify_interval(StackShadowPages, 1, 50, "StackShadowPages");
   return status;
 }
 
@@ -1722,8 +1771,6 @@
     status = false;
   }
 
-  status = status && verify_percentage(MaxLiveObjectEvacuationRatio,
-                              "MaxLiveObjectEvacuationRatio");
   status = status && verify_percentage(AdaptiveSizePolicyWeight,
                               "AdaptiveSizePolicyWeight");
   status = status && verify_percentage(AdaptivePermSizeWeight, "AdaptivePermSizeWeight");
@@ -2827,6 +2874,7 @@
   return JNI_OK;
 }
 
+
 // Parse entry point called from JNI_CreateJavaVM
 
 jint Arguments::parse(const JavaVMInitArgs* args) {
@@ -2969,10 +3017,6 @@
     PrintGC = true;
   }
 
-#if defined(_LP64) && defined(COMPILER1) && !defined(TIERED)
-  UseCompressedOops = false;
-#endif
-
   // Set object alignment values.
   set_object_alignment();
 
@@ -2987,13 +3031,10 @@
   set_ergonomics_flags();
 
 #ifdef _LP64
-  // XXX JSR 292 currently does not support compressed oops.
-  if (EnableMethodHandles && UseCompressedOops) {
-    if (FLAG_IS_DEFAULT(UseCompressedOops) || FLAG_IS_ERGO(UseCompressedOops)) {
-      UseCompressedOops = false;
-    }
+  if (UseCompressedOops) {
+    check_compressed_oops_compat();
   }
-#endif // _LP64
+#endif
 
   // Check the GC selections again.
   if (!check_gc_consistency()) {
--- a/hotspot/src/share/vm/runtime/arguments.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -291,6 +291,8 @@
 
   // Tiered
   static void set_tiered_flags();
+  // Check compressed oops compatibility with other flags
+  static void check_compressed_oops_compat();
   // CMS/ParNew garbage collectors
   static void set_parnew_gc_flags();
   static void set_cms_and_parnew_gc_flags();
@@ -484,6 +486,9 @@
   // System properties
   static void init_system_properties();
 
+  // Update/Initialize System properties after JDK version number is known
+  static void init_version_specific_system_properties();
+
   // Property List manipulation
   static void PropertyList_add(SystemProperty** plist, SystemProperty *element);
   static void PropertyList_add(SystemProperty** plist, const char* k, char* v);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/runtime/basicLock.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1997, 2010, 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.
+ *
+ */
+
+# include "incls/_precompiled.incl"
+# include "incls/_basicLock.cpp.incl"
+
+void BasicLock::print_on(outputStream* st) const {
+  st->print("monitor");
+}
+
+void BasicLock::move_to(oop obj, BasicLock* dest) {
+  // Check to see if we need to inflate the lock. This is only needed
+  // if an object is locked using "this" lightweight monitor. In that
+  // case, the displaced_header() is unlocked, because the
+  // displaced_header() contains the header for the originally unlocked
+  // object. However the object could have already been inflated. But it
+  // does not matter, the inflation will just a no-op. For other cases,
+  // the displaced header will be either 0x0 or 0x3, which are location
+  // independent, therefore the BasicLock is free to move.
+  //
+  // During OSR we may need to relocate a BasicLock (which contains a
+  // displaced word) from a location in an interpreter frame to a
+  // new location in a compiled frame.  "this" refers to the source
+  // basiclock in the interpreter frame.  "dest" refers to the destination
+  // basiclock in the new compiled frame.  We *always* inflate in move_to().
+  // The always-Inflate policy works properly, but in 1.5.0 it can sometimes
+  // cause performance problems in code that makes heavy use of a small # of
+  // uncontended locks.   (We'd inflate during OSR, and then sync performance
+  // would subsequently plummet because the thread would be forced thru the slow-path).
+  // This problem has been made largely moot on IA32 by inlining the inflated fast-path
+  // operations in Fast_Lock and Fast_Unlock in i486.ad.
+  //
+  // Note that there is a way to safely swing the object's markword from
+  // one stack location to another.  This avoids inflation.  Obviously,
+  // we need to ensure that both locations refer to the current thread's stack.
+  // There are some subtle concurrency issues, however, and since the benefit is
+  // is small (given the support for inflated fast-path locking in the fast_lock, etc)
+  // we'll leave that optimization for another time.
+
+  if (displaced_header()->is_neutral()) {
+    ObjectSynchronizer::inflate_helper(obj);
+    // WARNING: We can not put check here, because the inflation
+    // will not update the displaced header. Once BasicLock is inflated,
+    // no one should ever look at its content.
+  } else {
+    // Typically the displaced header will be 0 (recursive stack lock) or
+    // unused_mark.  Naively we'd like to assert that the displaced mark
+    // value is either 0, neutral, or 3.  But with the advent of the
+    // store-before-CAS avoidance in fast_lock/compiler_lock_object
+    // we can find any flavor mark in the displaced mark.
+  }
+// [RGV] The next line appears to do nothing!
+  intptr_t dh = (intptr_t) displaced_header();
+  dest->set_displaced_header(displaced_header());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/runtime/basicLock.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 1998, 2007, 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.
+ *
+ */
+
+class BasicLock VALUE_OBJ_CLASS_SPEC {
+  friend class VMStructs;
+ private:
+  volatile markOop _displaced_header;
+ public:
+  markOop      displaced_header() const               { return _displaced_header; }
+  void         set_displaced_header(markOop header)   { _displaced_header = header; }
+
+  void print_on(outputStream* st) const;
+
+  // move a basic lock (used during deoptimization
+  void move_to(oop obj, BasicLock* dest);
+
+  static int displaced_header_offset_in_bytes()       { return offset_of(BasicLock, _displaced_header); }
+};
+
+// A BasicObjectLock associates a specific Java object with a BasicLock.
+// It is currently embedded in an interpreter frame.
+
+// Because some machines have alignment restrictions on the control stack,
+// the actual space allocated by the interpreter may include padding words
+// after the end of the BasicObjectLock.  Also, in order to guarantee
+// alignment of the embedded BasicLock objects on such machines, we
+// put the embedded BasicLock at the beginning of the struct.
+
+class BasicObjectLock VALUE_OBJ_CLASS_SPEC {
+  friend class VMStructs;
+ private:
+  BasicLock _lock;                                    // the lock, must be double word aligned
+  oop       _obj;                                     // object holds the lock;
+
+ public:
+  // Manipulation
+  oop      obj() const                                { return _obj;  }
+  void set_obj(oop obj)                               { _obj = obj; }
+  BasicLock* lock()                                   { return &_lock; }
+
+  // Note: Use frame::interpreter_frame_monitor_size() for the size of BasicObjectLocks
+  //       in interpreter activation frames since it includes machine-specific padding.
+  static int size()                                   { return sizeof(BasicObjectLock)/wordSize; }
+
+  // GC support
+  void oops_do(OopClosure* f) { f->do_oop(&_obj); }
+
+  static int obj_offset_in_bytes()                    { return offset_of(BasicObjectLock, _obj);  }
+  static int lock_offset_in_bytes()                   { return offset_of(BasicObjectLock, _lock); }
+};
+
--- a/hotspot/src/share/vm/runtime/globals.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -327,10 +327,10 @@
   /* UseMembar is theoretically a temp flag used for memory barrier         \
    * removal testing.  It was supposed to be removed before FCS but has     \
    * been re-added (see 6401008) */                                         \
-  product(bool, UseMembar, false,                                           \
+  product_pd(bool, UseMembar,                                               \
           "(Unstable) Issues membars on thread state transitions")          \
                                                                             \
-  /* Temporary: See 6948537 */                                             \
+  /* Temporary: See 6948537 */                                              \
   experimental(bool, UseMemSetInBOT, true,                                  \
           "(Unstable) uses memset in BOT updates in GC code")               \
                                                                             \
@@ -822,6 +822,9 @@
   develop(bool, PrintJVMWarnings, false,                                    \
           "Prints warnings for unimplemented JVM functions")                \
                                                                             \
+  product(bool, PrintWarnings, true,                                        \
+          "Prints JVM warnings to output stream")                           \
+                                                                            \
   notproduct(uintx, WarnOnStalledSpinLock, 0,                               \
           "Prints warnings for stalled SpinLocks")                          \
                                                                             \
@@ -1585,7 +1588,7 @@
           "(Temporary, subject to experimentation)"                         \
           "Nominal minimum work per abortable preclean iteration")          \
                                                                             \
-  product(intx, CMSAbortablePrecleanWaitMillis, 100,                        \
+  manageable(intx, CMSAbortablePrecleanWaitMillis, 100,                     \
           "(Temporary, subject to experimentation)"                         \
           " Time that we sleep between iterations when not given"           \
           " enough work per iteration")                                     \
@@ -1677,7 +1680,7 @@
   product(uintx, CMSWorkQueueDrainThreshold, 10,                            \
           "Don't drain below this size per parallel worker/thief")          \
                                                                             \
-  product(intx, CMSWaitDuration, 2000,                                      \
+  manageable(intx, CMSWaitDuration, 2000,                                   \
           "Time in milliseconds that CMS thread waits for young GC")        \
                                                                             \
   product(bool, CMSYield, true,                                             \
@@ -1786,10 +1789,6 @@
   notproduct(bool, GCALotAtAllSafepoints, false,                            \
           "Enforce ScavengeALot/GCALot at all potential safepoints")        \
                                                                             \
-  product(bool, HandlePromotionFailure, true,                               \
-          "The youngest generation collection does not require "            \
-          "a guarantee of full promotion of all live objects.")             \
-                                                                            \
   product(bool, PrintPromotionFailure, false,                               \
           "Print additional diagnostic information following "              \
           " promotion failure")                                             \
@@ -3003,9 +3002,6 @@
   product(intx, NewRatio, 2,                                                \
           "Ratio of new/old generation sizes")                              \
                                                                             \
-  product(uintx, MaxLiveObjectEvacuationRatio, 100,                         \
-          "Max percent of eden objects that will be live at scavenge")      \
-                                                                            \
   product_pd(uintx, NewSizeThreadIncrease,                                  \
           "Additional size added to desired new generation size per "       \
           "non-daemon thread (in bytes)")                                   \
@@ -3542,7 +3538,7 @@
   product(uintx, SharedDummyBlockSize, 512*M,                               \
           "Size of dummy block used to shift heap addresses (in bytes)")    \
                                                                             \
-  product(uintx, SharedReadWriteSize,  12*M,                                \
+  product(uintx, SharedReadWriteSize,  NOT_LP64(12*M) LP64_ONLY(13*M),      \
           "Size of read-write space in permanent generation (in bytes)")    \
                                                                             \
   product(uintx, SharedReadOnlySize,   10*M,                                \
--- a/hotspot/src/share/vm/runtime/mutex.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/runtime/mutex.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -265,48 +265,3 @@
    }
 };
 
-/*
- * Per-thread blocking support for JSR166. See the Java-level
- * Documentation for rationale. Basically, park acts like wait, unpark
- * like notify.
- *
- * 6271289 --
- * To avoid errors where an os thread expires but the JavaThread still
- * exists, Parkers are immortal (type-stable) and are recycled across
- * new threads.  This parallels the ParkEvent implementation.
- * Because park-unpark allow spurious wakeups it is harmless if an
- * unpark call unparks a new thread using the old Parker reference.
- *
- * In the future we'll want to think about eliminating Parker and using
- * ParkEvent instead.  There's considerable duplication between the two
- * services.
- *
- */
-
-class Parker : public os::PlatformParker {
-private:
-  volatile int _counter ;
-  Parker * FreeNext ;
-  JavaThread * AssociatedWith ; // Current association
-
-public:
-  Parker() : PlatformParker() {
-    _counter       = 0 ;
-    FreeNext       = NULL ;
-    AssociatedWith = NULL ;
-  }
-protected:
-  ~Parker() { ShouldNotReachHere(); }
-public:
-  // For simplicity of interface with Java, all forms of park (indefinite,
-  // relative, and absolute) are multiplexed into one call.
-  void park(bool isAbsolute, jlong time);
-  void unpark();
-
-  // Lifecycle operators
-  static Parker * Allocate (JavaThread * t) ;
-  static void Release (Parker * e) ;
-private:
-  static Parker * volatile FreeList ;
-  static volatile int ListLock ;
-};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/runtime/objectMonitor.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,2421 @@
+/*
+ * Copyright (c) 1998, 2009, 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.
+ *
+ */
+
+# include "incls/_precompiled.incl"
+# include "incls/_objectMonitor.cpp.incl"
+
+#if defined(__GNUC__) && !defined(IA64)
+  // Need to inhibit inlining for older versions of GCC to avoid build-time failures
+  #define ATTR __attribute__((noinline))
+#else
+  #define ATTR
+#endif
+
+
+#ifdef DTRACE_ENABLED
+
+// Only bother with this argument setup if dtrace is available
+// TODO-FIXME: probes should not fire when caller is _blocked.  assert() accordingly.
+
+HS_DTRACE_PROBE_DECL4(hotspot, monitor__notify,
+  jlong, uintptr_t, char*, int);
+HS_DTRACE_PROBE_DECL4(hotspot, monitor__notifyAll,
+  jlong, uintptr_t, char*, int);
+HS_DTRACE_PROBE_DECL4(hotspot, monitor__contended__enter,
+  jlong, uintptr_t, char*, int);
+HS_DTRACE_PROBE_DECL4(hotspot, monitor__contended__entered,
+  jlong, uintptr_t, char*, int);
+HS_DTRACE_PROBE_DECL4(hotspot, monitor__contended__exit,
+  jlong, uintptr_t, char*, int);
+
+#define DTRACE_MONITOR_PROBE_COMMON(klassOop, thread)                      \
+  char* bytes = NULL;                                                      \
+  int len = 0;                                                             \
+  jlong jtid = SharedRuntime::get_java_tid(thread);                        \
+  symbolOop klassname = ((oop)(klassOop))->klass()->klass_part()->name();  \
+  if (klassname != NULL) {                                                 \
+    bytes = (char*)klassname->bytes();                                     \
+    len = klassname->utf8_length();                                        \
+  }
+
+#define DTRACE_MONITOR_WAIT_PROBE(monitor, klassOop, thread, millis)       \
+  {                                                                        \
+    if (DTraceMonitorProbes) {                                            \
+      DTRACE_MONITOR_PROBE_COMMON(klassOop, thread);                       \
+      HS_DTRACE_PROBE5(hotspot, monitor__wait, jtid,                       \
+                       (monitor), bytes, len, (millis));                   \
+    }                                                                      \
+  }
+
+#define DTRACE_MONITOR_PROBE(probe, monitor, klassOop, thread)             \
+  {                                                                        \
+    if (DTraceMonitorProbes) {                                            \
+      DTRACE_MONITOR_PROBE_COMMON(klassOop, thread);                       \
+      HS_DTRACE_PROBE4(hotspot, monitor__##probe, jtid,                    \
+                       (uintptr_t)(monitor), bytes, len);                  \
+    }                                                                      \
+  }
+
+#else //  ndef DTRACE_ENABLED
+
+#define DTRACE_MONITOR_WAIT_PROBE(klassOop, thread, millis, mon)    {;}
+#define DTRACE_MONITOR_PROBE(probe, klassOop, thread, mon)          {;}
+
+#endif // ndef DTRACE_ENABLED
+
+// Tunables ...
+// The knob* variables are effectively final.  Once set they should
+// never be modified hence.  Consider using __read_mostly with GCC.
+
+int ObjectMonitor::Knob_Verbose    = 0 ;
+int ObjectMonitor::Knob_SpinLimit  = 5000 ;    // derived by an external tool -
+static int Knob_LogSpins           = 0 ;       // enable jvmstat tally for spins
+static int Knob_HandOff            = 0 ;
+static int Knob_ReportSettings     = 0 ;
+
+static int Knob_SpinBase           = 0 ;       // Floor AKA SpinMin
+static int Knob_SpinBackOff        = 0 ;       // spin-loop backoff
+static int Knob_CASPenalty         = -1 ;      // Penalty for failed CAS
+static int Knob_OXPenalty          = -1 ;      // Penalty for observed _owner change
+static int Knob_SpinSetSucc        = 1 ;       // spinners set the _succ field
+static int Knob_SpinEarly          = 1 ;
+static int Knob_SuccEnabled        = 1 ;       // futile wake throttling
+static int Knob_SuccRestrict       = 0 ;       // Limit successors + spinners to at-most-one
+static int Knob_MaxSpinners        = -1 ;      // Should be a function of # CPUs
+static int Knob_Bonus              = 100 ;     // spin success bonus
+static int Knob_BonusB             = 100 ;     // spin success bonus
+static int Knob_Penalty            = 200 ;     // spin failure penalty
+static int Knob_Poverty            = 1000 ;
+static int Knob_SpinAfterFutile    = 1 ;       // Spin after returning from park()
+static int Knob_FixedSpin          = 0 ;
+static int Knob_OState             = 3 ;       // Spinner checks thread state of _owner
+static int Knob_UsePause           = 1 ;
+static int Knob_ExitPolicy         = 0 ;
+static int Knob_PreSpin            = 10 ;      // 20-100 likely better
+static int Knob_ResetEvent         = 0 ;
+static int BackOffMask             = 0 ;
+
+static int Knob_FastHSSEC          = 0 ;
+static int Knob_MoveNotifyee       = 2 ;       // notify() - disposition of notifyee
+static int Knob_QMode              = 0 ;       // EntryList-cxq policy - queue discipline
+static volatile int InitDone       = 0 ;
+
+#define TrySpin TrySpin_VaryDuration
+
+// -----------------------------------------------------------------------------
+// Theory of operations -- Monitors lists, thread residency, etc:
+//
+// * A thread acquires ownership of a monitor by successfully
+//   CAS()ing the _owner field from null to non-null.
+//
+// * Invariant: A thread appears on at most one monitor list --
+//   cxq, EntryList or WaitSet -- at any one time.
+//
+// * Contending threads "push" themselves onto the cxq with CAS
+//   and then spin/park.
+//
+// * After a contending thread eventually acquires the lock it must
+//   dequeue itself from either the EntryList or the cxq.
+//
+// * The exiting thread identifies and unparks an "heir presumptive"
+//   tentative successor thread on the EntryList.  Critically, the
+//   exiting thread doesn't unlink the successor thread from the EntryList.
+//   After having been unparked, the wakee will recontend for ownership of
+//   the monitor.   The successor (wakee) will either acquire the lock or
+//   re-park itself.
+//
+//   Succession is provided for by a policy of competitive handoff.
+//   The exiting thread does _not_ grant or pass ownership to the
+//   successor thread.  (This is also referred to as "handoff" succession").
+//   Instead the exiting thread releases ownership and possibly wakes
+//   a successor, so the successor can (re)compete for ownership of the lock.
+//   If the EntryList is empty but the cxq is populated the exiting
+//   thread will drain the cxq into the EntryList.  It does so by
+//   by detaching the cxq (installing null with CAS) and folding
+//   the threads from the cxq into the EntryList.  The EntryList is
+//   doubly linked, while the cxq is singly linked because of the
+//   CAS-based "push" used to enqueue recently arrived threads (RATs).
+//
+// * Concurrency invariants:
+//
+//   -- only the monitor owner may access or mutate the EntryList.
+//      The mutex property of the monitor itself protects the EntryList
+//      from concurrent interference.
+//   -- Only the monitor owner may detach the cxq.
+//
+// * The monitor entry list operations avoid locks, but strictly speaking
+//   they're not lock-free.  Enter is lock-free, exit is not.
+//   See http://j2se.east/~dice/PERSIST/040825-LockFreeQueues.html
+//
+// * The cxq can have multiple concurrent "pushers" but only one concurrent
+//   detaching thread.  This mechanism is immune from the ABA corruption.
+//   More precisely, the CAS-based "push" onto cxq is ABA-oblivious.
+//
+// * Taken together, the cxq and the EntryList constitute or form a
+//   single logical queue of threads stalled trying to acquire the lock.
+//   We use two distinct lists to improve the odds of a constant-time
+//   dequeue operation after acquisition (in the ::enter() epilog) and
+//   to reduce heat on the list ends.  (c.f. Michael Scott's "2Q" algorithm).
+//   A key desideratum is to minimize queue & monitor metadata manipulation
+//   that occurs while holding the monitor lock -- that is, we want to
+//   minimize monitor lock holds times.  Note that even a small amount of
+//   fixed spinning will greatly reduce the # of enqueue-dequeue operations
+//   on EntryList|cxq.  That is, spinning relieves contention on the "inner"
+//   locks and monitor metadata.
+//
+//   Cxq points to the the set of Recently Arrived Threads attempting entry.
+//   Because we push threads onto _cxq with CAS, the RATs must take the form of
+//   a singly-linked LIFO.  We drain _cxq into EntryList  at unlock-time when
+//   the unlocking thread notices that EntryList is null but _cxq is != null.
+//
+//   The EntryList is ordered by the prevailing queue discipline and
+//   can be organized in any convenient fashion, such as a doubly-linked list or
+//   a circular doubly-linked list.  Critically, we want insert and delete operations
+//   to operate in constant-time.  If we need a priority queue then something akin
+//   to Solaris' sleepq would work nicely.  Viz.,
+//   http://agg.eng/ws/on10_nightly/source/usr/src/uts/common/os/sleepq.c.
+//   Queue discipline is enforced at ::exit() time, when the unlocking thread
+//   drains the cxq into the EntryList, and orders or reorders the threads on the
+//   EntryList accordingly.
+//
+//   Barring "lock barging", this mechanism provides fair cyclic ordering,
+//   somewhat similar to an elevator-scan.
+//
+// * The monitor synchronization subsystem avoids the use of native
+//   synchronization primitives except for the narrow platform-specific
+//   park-unpark abstraction.  See the comments in os_solaris.cpp regarding
+//   the semantics of park-unpark.  Put another way, this monitor implementation
+//   depends only on atomic operations and park-unpark.  The monitor subsystem
+//   manages all RUNNING->BLOCKED and BLOCKED->READY transitions while the
+//   underlying OS manages the READY<->RUN transitions.
+//
+// * Waiting threads reside on the WaitSet list -- wait() puts
+//   the caller onto the WaitSet.
+//
+// * notify() or notifyAll() simply transfers threads from the WaitSet to
+//   either the EntryList or cxq.  Subsequent exit() operations will
+//   unpark the notifyee.  Unparking a notifee in notify() is inefficient -
+//   it's likely the notifyee would simply impale itself on the lock held
+//   by the notifier.
+//
+// * An interesting alternative is to encode cxq as (List,LockByte) where
+//   the LockByte is 0 iff the monitor is owned.  _owner is simply an auxiliary
+//   variable, like _recursions, in the scheme.  The threads or Events that form
+//   the list would have to be aligned in 256-byte addresses.  A thread would
+//   try to acquire the lock or enqueue itself with CAS, but exiting threads
+//   could use a 1-0 protocol and simply STB to set the LockByte to 0.
+//   Note that is is *not* word-tearing, but it does presume that full-word
+//   CAS operations are coherent with intermix with STB operations.  That's true
+//   on most common processors.
+//
+// * See also http://blogs.sun.com/dave
+
+
+// -----------------------------------------------------------------------------
+// Enter support
+
+bool ObjectMonitor::try_enter(Thread* THREAD) {
+  if (THREAD != _owner) {
+    if (THREAD->is_lock_owned ((address)_owner)) {
+       assert(_recursions == 0, "internal state error");
+       _owner = THREAD ;
+       _recursions = 1 ;
+       OwnerIsThread = 1 ;
+       return true;
+    }
+    if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
+      return false;
+    }
+    return true;
+  } else {
+    _recursions++;
+    return true;
+  }
+}
+
+void ATTR ObjectMonitor::enter(TRAPS) {
+  // The following code is ordered to check the most common cases first
+  // and to reduce RTS->RTO cache line upgrades on SPARC and IA32 processors.
+  Thread * const Self = THREAD ;
+  void * cur ;
+
+  cur = Atomic::cmpxchg_ptr (Self, &_owner, NULL) ;
+  if (cur == NULL) {
+     // Either ASSERT _recursions == 0 or explicitly set _recursions = 0.
+     assert (_recursions == 0   , "invariant") ;
+     assert (_owner      == Self, "invariant") ;
+     // CONSIDER: set or assert OwnerIsThread == 1
+     return ;
+  }
+
+  if (cur == Self) {
+     // TODO-FIXME: check for integer overflow!  BUGID 6557169.
+     _recursions ++ ;
+     return ;
+  }
+
+  if (Self->is_lock_owned ((address)cur)) {
+    assert (_recursions == 0, "internal state error");
+    _recursions = 1 ;
+    // Commute owner from a thread-specific on-stack BasicLockObject address to
+    // a full-fledged "Thread *".
+    _owner = Self ;
+    OwnerIsThread = 1 ;
+    return ;
+  }
+
+  // We've encountered genuine contention.
+  assert (Self->_Stalled == 0, "invariant") ;
+  Self->_Stalled = intptr_t(this) ;
+
+  // Try one round of spinning *before* enqueueing Self
+  // and before going through the awkward and expensive state
+  // transitions.  The following spin is strictly optional ...
+  // Note that if we acquire the monitor from an initial spin
+  // we forgo posting JVMTI events and firing DTRACE probes.
+  if (Knob_SpinEarly && TrySpin (Self) > 0) {
+     assert (_owner == Self      , "invariant") ;
+     assert (_recursions == 0    , "invariant") ;
+     assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
+     Self->_Stalled = 0 ;
+     return ;
+  }
+
+  assert (_owner != Self          , "invariant") ;
+  assert (_succ  != Self          , "invariant") ;
+  assert (Self->is_Java_thread()  , "invariant") ;
+  JavaThread * jt = (JavaThread *) Self ;
+  assert (!SafepointSynchronize::is_at_safepoint(), "invariant") ;
+  assert (jt->thread_state() != _thread_blocked   , "invariant") ;
+  assert (this->object() != NULL  , "invariant") ;
+  assert (_count >= 0, "invariant") ;
+
+  // Prevent deflation at STW-time.  See deflate_idle_monitors() and is_busy().
+  // Ensure the object-monitor relationship remains stable while there's contention.
+  Atomic::inc_ptr(&_count);
+
+  { // Change java thread status to indicate blocked on monitor enter.
+    JavaThreadBlockedOnMonitorEnterState jtbmes(jt, this);
+
+    DTRACE_MONITOR_PROBE(contended__enter, this, object(), jt);
+    if (JvmtiExport::should_post_monitor_contended_enter()) {
+      JvmtiExport::post_monitor_contended_enter(jt, this);
+    }
+
+    OSThreadContendState osts(Self->osthread());
+    ThreadBlockInVM tbivm(jt);
+
+    Self->set_current_pending_monitor(this);
+
+    // TODO-FIXME: change the following for(;;) loop to straight-line code.
+    for (;;) {
+      jt->set_suspend_equivalent();
+      // cleared by handle_special_suspend_equivalent_condition()
+      // or java_suspend_self()
+
+      EnterI (THREAD) ;
+
+      if (!ExitSuspendEquivalent(jt)) break ;
+
+      //
+      // We have acquired the contended monitor, but while we were
+      // waiting another thread suspended us. We don't want to enter
+      // the monitor while suspended because that would surprise the
+      // thread that suspended us.
+      //
+          _recursions = 0 ;
+      _succ = NULL ;
+      exit (Self) ;
+
+      jt->java_suspend_self();
+    }
+    Self->set_current_pending_monitor(NULL);
+  }
+
+  Atomic::dec_ptr(&_count);
+  assert (_count >= 0, "invariant") ;
+  Self->_Stalled = 0 ;
+
+  // Must either set _recursions = 0 or ASSERT _recursions == 0.
+  assert (_recursions == 0     , "invariant") ;
+  assert (_owner == Self       , "invariant") ;
+  assert (_succ  != Self       , "invariant") ;
+  assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
+
+  // The thread -- now the owner -- is back in vm mode.
+  // Report the glorious news via TI,DTrace and jvmstat.
+  // The probe effect is non-trivial.  All the reportage occurs
+  // while we hold the monitor, increasing the length of the critical
+  // section.  Amdahl's parallel speedup law comes vividly into play.
+  //
+  // Another option might be to aggregate the events (thread local or
+  // per-monitor aggregation) and defer reporting until a more opportune
+  // time -- such as next time some thread encounters contention but has
+  // yet to acquire the lock.  While spinning that thread could
+  // spinning we could increment JVMStat counters, etc.
+
+  DTRACE_MONITOR_PROBE(contended__entered, this, object(), jt);
+  if (JvmtiExport::should_post_monitor_contended_entered()) {
+    JvmtiExport::post_monitor_contended_entered(jt, this);
+  }
+  if (ObjectMonitor::_sync_ContendedLockAttempts != NULL) {
+     ObjectMonitor::_sync_ContendedLockAttempts->inc() ;
+  }
+}
+
+
+// Caveat: TryLock() is not necessarily serializing if it returns failure.
+// Callers must compensate as needed.
+
+int ObjectMonitor::TryLock (Thread * Self) {
+   for (;;) {
+      void * own = _owner ;
+      if (own != NULL) return 0 ;
+      if (Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {
+         // Either guarantee _recursions == 0 or set _recursions = 0.
+         assert (_recursions == 0, "invariant") ;
+         assert (_owner == Self, "invariant") ;
+         // CONSIDER: set or assert that OwnerIsThread == 1
+         return 1 ;
+      }
+      // The lock had been free momentarily, but we lost the race to the lock.
+      // Interference -- the CAS failed.
+      // We can either return -1 or retry.
+      // Retry doesn't make as much sense because the lock was just acquired.
+      if (true) return -1 ;
+   }
+}
+
+void ATTR ObjectMonitor::EnterI (TRAPS) {
+    Thread * Self = THREAD ;
+    assert (Self->is_Java_thread(), "invariant") ;
+    assert (((JavaThread *) Self)->thread_state() == _thread_blocked   , "invariant") ;
+
+    // Try the lock - TATAS
+    if (TryLock (Self) > 0) {
+        assert (_succ != Self              , "invariant") ;
+        assert (_owner == Self             , "invariant") ;
+        assert (_Responsible != Self       , "invariant") ;
+        return ;
+    }
+
+    DeferredInitialize () ;
+
+    // We try one round of spinning *before* enqueueing Self.
+    //
+    // If the _owner is ready but OFFPROC we could use a YieldTo()
+    // operation to donate the remainder of this thread's quantum
+    // to the owner.  This has subtle but beneficial affinity
+    // effects.
+
+    if (TrySpin (Self) > 0) {
+        assert (_owner == Self        , "invariant") ;
+        assert (_succ != Self         , "invariant") ;
+        assert (_Responsible != Self  , "invariant") ;
+        return ;
+    }
+
+    // The Spin failed -- Enqueue and park the thread ...
+    assert (_succ  != Self            , "invariant") ;
+    assert (_owner != Self            , "invariant") ;
+    assert (_Responsible != Self      , "invariant") ;
+
+    // Enqueue "Self" on ObjectMonitor's _cxq.
+    //
+    // Node acts as a proxy for Self.
+    // As an aside, if were to ever rewrite the synchronization code mostly
+    // in Java, WaitNodes, ObjectMonitors, and Events would become 1st-class
+    // Java objects.  This would avoid awkward lifecycle and liveness issues,
+    // as well as eliminate a subset of ABA issues.
+    // TODO: eliminate ObjectWaiter and enqueue either Threads or Events.
+    //
+
+    ObjectWaiter node(Self) ;
+    Self->_ParkEvent->reset() ;
+    node._prev   = (ObjectWaiter *) 0xBAD ;
+    node.TState  = ObjectWaiter::TS_CXQ ;
+
+    // Push "Self" onto the front of the _cxq.
+    // Once on cxq/EntryList, Self stays on-queue until it acquires the lock.
+    // Note that spinning tends to reduce the rate at which threads
+    // enqueue and dequeue on EntryList|cxq.
+    ObjectWaiter * nxt ;
+    for (;;) {
+        node._next = nxt = _cxq ;
+        if (Atomic::cmpxchg_ptr (&node, &_cxq, nxt) == nxt) break ;
+
+        // Interference - the CAS failed because _cxq changed.  Just retry.
+        // As an optional optimization we retry the lock.
+        if (TryLock (Self) > 0) {
+            assert (_succ != Self         , "invariant") ;
+            assert (_owner == Self        , "invariant") ;
+            assert (_Responsible != Self  , "invariant") ;
+            return ;
+        }
+    }
+
+    // Check for cxq|EntryList edge transition to non-null.  This indicates
+    // the onset of contention.  While contention persists exiting threads
+    // will use a ST:MEMBAR:LD 1-1 exit protocol.  When contention abates exit
+    // operations revert to the faster 1-0 mode.  This enter operation may interleave
+    // (race) a concurrent 1-0 exit operation, resulting in stranding, so we
+    // arrange for one of the contending thread to use a timed park() operations
+    // to detect and recover from the race.  (Stranding is form of progress failure
+    // where the monitor is unlocked but all the contending threads remain parked).
+    // That is, at least one of the contended threads will periodically poll _owner.
+    // One of the contending threads will become the designated "Responsible" thread.
+    // The Responsible thread uses a timed park instead of a normal indefinite park
+    // operation -- it periodically wakes and checks for and recovers from potential
+    // strandings admitted by 1-0 exit operations.   We need at most one Responsible
+    // thread per-monitor at any given moment.  Only threads on cxq|EntryList may
+    // be responsible for a monitor.
+    //
+    // Currently, one of the contended threads takes on the added role of "Responsible".
+    // A viable alternative would be to use a dedicated "stranding checker" thread
+    // that periodically iterated over all the threads (or active monitors) and unparked
+    // successors where there was risk of stranding.  This would help eliminate the
+    // timer scalability issues we see on some platforms as we'd only have one thread
+    // -- the checker -- parked on a timer.
+
+    if ((SyncFlags & 16) == 0 && nxt == NULL && _EntryList == NULL) {
+        // Try to assume the role of responsible thread for the monitor.
+        // CONSIDER:  ST vs CAS vs { if (Responsible==null) Responsible=Self }
+        Atomic::cmpxchg_ptr (Self, &_Responsible, NULL) ;
+    }
+
+    // The lock have been released while this thread was occupied queueing
+    // itself onto _cxq.  To close the race and avoid "stranding" and
+    // progress-liveness failure we must resample-retry _owner before parking.
+    // Note the Dekker/Lamport duality: ST cxq; MEMBAR; LD Owner.
+    // In this case the ST-MEMBAR is accomplished with CAS().
+    //
+    // TODO: Defer all thread state transitions until park-time.
+    // Since state transitions are heavy and inefficient we'd like
+    // to defer the state transitions until absolutely necessary,
+    // and in doing so avoid some transitions ...
+
+    TEVENT (Inflated enter - Contention) ;
+    int nWakeups = 0 ;
+    int RecheckInterval = 1 ;
+
+    for (;;) {
+
+        if (TryLock (Self) > 0) break ;
+        assert (_owner != Self, "invariant") ;
+
+        if ((SyncFlags & 2) && _Responsible == NULL) {
+           Atomic::cmpxchg_ptr (Self, &_Responsible, NULL) ;
+        }
+
+        // park self
+        if (_Responsible == Self || (SyncFlags & 1)) {
+            TEVENT (Inflated enter - park TIMED) ;
+            Self->_ParkEvent->park ((jlong) RecheckInterval) ;
+            // Increase the RecheckInterval, but clamp the value.
+            RecheckInterval *= 8 ;
+            if (RecheckInterval > 1000) RecheckInterval = 1000 ;
+        } else {
+            TEVENT (Inflated enter - park UNTIMED) ;
+            Self->_ParkEvent->park() ;
+        }
+
+        if (TryLock(Self) > 0) break ;
+
+        // The lock is still contested.
+        // Keep a tally of the # of futile wakeups.
+        // Note that the counter is not protected by a lock or updated by atomics.
+        // That is by design - we trade "lossy" counters which are exposed to
+        // races during updates for a lower probe effect.
+        TEVENT (Inflated enter - Futile wakeup) ;
+        if (ObjectMonitor::_sync_FutileWakeups != NULL) {
+           ObjectMonitor::_sync_FutileWakeups->inc() ;
+        }
+        ++ nWakeups ;
+
+        // Assuming this is not a spurious wakeup we'll normally find _succ == Self.
+        // We can defer clearing _succ until after the spin completes
+        // TrySpin() must tolerate being called with _succ == Self.
+        // Try yet another round of adaptive spinning.
+        if ((Knob_SpinAfterFutile & 1) && TrySpin (Self) > 0) break ;
+
+        // We can find that we were unpark()ed and redesignated _succ while
+        // we were spinning.  That's harmless.  If we iterate and call park(),
+        // park() will consume the event and return immediately and we'll
+        // just spin again.  This pattern can repeat, leaving _succ to simply
+        // spin on a CPU.  Enable Knob_ResetEvent to clear pending unparks().
+        // Alternately, we can sample fired() here, and if set, forgo spinning
+        // in the next iteration.
+
+        if ((Knob_ResetEvent & 1) && Self->_ParkEvent->fired()) {
+           Self->_ParkEvent->reset() ;
+           OrderAccess::fence() ;
+        }
+        if (_succ == Self) _succ = NULL ;
+
+        // Invariant: after clearing _succ a thread *must* retry _owner before parking.
+        OrderAccess::fence() ;
+    }
+
+    // Egress :
+    // Self has acquired the lock -- Unlink Self from the cxq or EntryList.
+    // Normally we'll find Self on the EntryList .
+    // From the perspective of the lock owner (this thread), the
+    // EntryList is stable and cxq is prepend-only.
+    // The head of cxq is volatile but the interior is stable.
+    // In addition, Self.TState is stable.
+
+    assert (_owner == Self      , "invariant") ;
+    assert (object() != NULL    , "invariant") ;
+    // I'd like to write:
+    //   guarantee (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
+    // but as we're at a safepoint that's not safe.
+
+    UnlinkAfterAcquire (Self, &node) ;
+    if (_succ == Self) _succ = NULL ;
+
+    assert (_succ != Self, "invariant") ;
+    if (_Responsible == Self) {
+        _Responsible = NULL ;
+        // Dekker pivot-point.
+        // Consider OrderAccess::storeload() here
+
+        // We may leave threads on cxq|EntryList without a designated
+        // "Responsible" thread.  This is benign.  When this thread subsequently
+        // exits the monitor it can "see" such preexisting "old" threads --
+        // threads that arrived on the cxq|EntryList before the fence, above --
+        // by LDing cxq|EntryList.  Newly arrived threads -- that is, threads
+        // that arrive on cxq after the ST:MEMBAR, above -- will set Responsible
+        // non-null and elect a new "Responsible" timer thread.
+        //
+        // This thread executes:
+        //    ST Responsible=null; MEMBAR    (in enter epilog - here)
+        //    LD cxq|EntryList               (in subsequent exit)
+        //
+        // Entering threads in the slow/contended path execute:
+        //    ST cxq=nonnull; MEMBAR; LD Responsible (in enter prolog)
+        //    The (ST cxq; MEMBAR) is accomplished with CAS().
+        //
+        // The MEMBAR, above, prevents the LD of cxq|EntryList in the subsequent
+        // exit operation from floating above the ST Responsible=null.
+        //
+        // In *practice* however, EnterI() is always followed by some atomic
+        // operation such as the decrement of _count in ::enter().  Those atomics
+        // obviate the need for the explicit MEMBAR, above.
+    }
+
+    // We've acquired ownership with CAS().
+    // CAS is serializing -- it has MEMBAR/FENCE-equivalent semantics.
+    // But since the CAS() this thread may have also stored into _succ,
+    // EntryList, cxq or Responsible.  These meta-data updates must be
+    // visible __before this thread subsequently drops the lock.
+    // Consider what could occur if we didn't enforce this constraint --
+    // STs to monitor meta-data and user-data could reorder with (become
+    // visible after) the ST in exit that drops ownership of the lock.
+    // Some other thread could then acquire the lock, but observe inconsistent
+    // or old monitor meta-data and heap data.  That violates the JMM.
+    // To that end, the 1-0 exit() operation must have at least STST|LDST
+    // "release" barrier semantics.  Specifically, there must be at least a
+    // STST|LDST barrier in exit() before the ST of null into _owner that drops
+    // the lock.   The barrier ensures that changes to monitor meta-data and data
+    // protected by the lock will be visible before we release the lock, and
+    // therefore before some other thread (CPU) has a chance to acquire the lock.
+    // See also: http://gee.cs.oswego.edu/dl/jmm/cookbook.html.
+    //
+    // Critically, any prior STs to _succ or EntryList must be visible before
+    // the ST of null into _owner in the *subsequent* (following) corresponding
+    // monitorexit.  Recall too, that in 1-0 mode monitorexit does not necessarily
+    // execute a serializing instruction.
+
+    if (SyncFlags & 8) {
+       OrderAccess::fence() ;
+    }
+    return ;
+}
+
+// ReenterI() is a specialized inline form of the latter half of the
+// contended slow-path from EnterI().  We use ReenterI() only for
+// monitor reentry in wait().
+//
+// In the future we should reconcile EnterI() and ReenterI(), adding
+// Knob_Reset and Knob_SpinAfterFutile support and restructuring the
+// loop accordingly.
+
+void ATTR ObjectMonitor::ReenterI (Thread * Self, ObjectWaiter * SelfNode) {
+    assert (Self != NULL                , "invariant") ;
+    assert (SelfNode != NULL            , "invariant") ;
+    assert (SelfNode->_thread == Self   , "invariant") ;
+    assert (_waiters > 0                , "invariant") ;
+    assert (((oop)(object()))->mark() == markOopDesc::encode(this) , "invariant") ;
+    assert (((JavaThread *)Self)->thread_state() != _thread_blocked, "invariant") ;
+    JavaThread * jt = (JavaThread *) Self ;
+
+    int nWakeups = 0 ;
+    for (;;) {
+        ObjectWaiter::TStates v = SelfNode->TState ;
+        guarantee (v == ObjectWaiter::TS_ENTER || v == ObjectWaiter::TS_CXQ, "invariant") ;
+        assert    (_owner != Self, "invariant") ;
+
+        if (TryLock (Self) > 0) break ;
+        if (TrySpin (Self) > 0) break ;
+
+        TEVENT (Wait Reentry - parking) ;
+
+        // State transition wrappers around park() ...
+        // ReenterI() wisely defers state transitions until
+        // it's clear we must park the thread.
+        {
+           OSThreadContendState osts(Self->osthread());
+           ThreadBlockInVM tbivm(jt);
+
+           // cleared by handle_special_suspend_equivalent_condition()
+           // or java_suspend_self()
+           jt->set_suspend_equivalent();
+           if (SyncFlags & 1) {
+              Self->_ParkEvent->park ((jlong)1000) ;
+           } else {
+              Self->_ParkEvent->park () ;
+           }
+
+           // were we externally suspended while we were waiting?
+           for (;;) {
+              if (!ExitSuspendEquivalent (jt)) break ;
+              if (_succ == Self) { _succ = NULL; OrderAccess::fence(); }
+              jt->java_suspend_self();
+              jt->set_suspend_equivalent();
+           }
+        }
+
+        // Try again, but just so we distinguish between futile wakeups and
+        // successful wakeups.  The following test isn't algorithmically
+        // necessary, but it helps us maintain sensible statistics.
+        if (TryLock(Self) > 0) break ;
+
+        // The lock is still contested.
+        // Keep a tally of the # of futile wakeups.
+        // Note that the counter is not protected by a lock or updated by atomics.
+        // That is by design - we trade "lossy" counters which are exposed to
+        // races during updates for a lower probe effect.
+        TEVENT (Wait Reentry - futile wakeup) ;
+        ++ nWakeups ;
+
+        // Assuming this is not a spurious wakeup we'll normally
+        // find that _succ == Self.
+        if (_succ == Self) _succ = NULL ;
+
+        // Invariant: after clearing _succ a contending thread
+        // *must* retry  _owner before parking.
+        OrderAccess::fence() ;
+
+        if (ObjectMonitor::_sync_FutileWakeups != NULL) {
+          ObjectMonitor::_sync_FutileWakeups->inc() ;
+        }
+    }
+
+    // Self has acquired the lock -- Unlink Self from the cxq or EntryList .
+    // Normally we'll find Self on the EntryList.
+    // Unlinking from the EntryList is constant-time and atomic-free.
+    // From the perspective of the lock owner (this thread), the
+    // EntryList is stable and cxq is prepend-only.
+    // The head of cxq is volatile but the interior is stable.
+    // In addition, Self.TState is stable.
+
+    assert (_owner == Self, "invariant") ;
+    assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
+    UnlinkAfterAcquire (Self, SelfNode) ;
+    if (_succ == Self) _succ = NULL ;
+    assert (_succ != Self, "invariant") ;
+    SelfNode->TState = ObjectWaiter::TS_RUN ;
+    OrderAccess::fence() ;      // see comments at the end of EnterI()
+}
+
+// after the thread acquires the lock in ::enter().  Equally, we could defer
+// unlinking the thread until ::exit()-time.
+
+void ObjectMonitor::UnlinkAfterAcquire (Thread * Self, ObjectWaiter * SelfNode)
+{
+    assert (_owner == Self, "invariant") ;
+    assert (SelfNode->_thread == Self, "invariant") ;
+
+    if (SelfNode->TState == ObjectWaiter::TS_ENTER) {
+        // Normal case: remove Self from the DLL EntryList .
+        // This is a constant-time operation.
+        ObjectWaiter * nxt = SelfNode->_next ;
+        ObjectWaiter * prv = SelfNode->_prev ;
+        if (nxt != NULL) nxt->_prev = prv ;
+        if (prv != NULL) prv->_next = nxt ;
+        if (SelfNode == _EntryList ) _EntryList = nxt ;
+        assert (nxt == NULL || nxt->TState == ObjectWaiter::TS_ENTER, "invariant") ;
+        assert (prv == NULL || prv->TState == ObjectWaiter::TS_ENTER, "invariant") ;
+        TEVENT (Unlink from EntryList) ;
+    } else {
+        guarantee (SelfNode->TState == ObjectWaiter::TS_CXQ, "invariant") ;
+        // Inopportune interleaving -- Self is still on the cxq.
+        // This usually means the enqueue of self raced an exiting thread.
+        // Normally we'll find Self near the front of the cxq, so
+        // dequeueing is typically fast.  If needbe we can accelerate
+        // this with some MCS/CHL-like bidirectional list hints and advisory
+        // back-links so dequeueing from the interior will normally operate
+        // in constant-time.
+        // Dequeue Self from either the head (with CAS) or from the interior
+        // with a linear-time scan and normal non-atomic memory operations.
+        // CONSIDER: if Self is on the cxq then simply drain cxq into EntryList
+        // and then unlink Self from EntryList.  We have to drain eventually,
+        // so it might as well be now.
+
+        ObjectWaiter * v = _cxq ;
+        assert (v != NULL, "invariant") ;
+        if (v != SelfNode || Atomic::cmpxchg_ptr (SelfNode->_next, &_cxq, v) != v) {
+            // The CAS above can fail from interference IFF a "RAT" arrived.
+            // In that case Self must be in the interior and can no longer be
+            // at the head of cxq.
+            if (v == SelfNode) {
+                assert (_cxq != v, "invariant") ;
+                v = _cxq ;          // CAS above failed - start scan at head of list
+            }
+            ObjectWaiter * p ;
+            ObjectWaiter * q = NULL ;
+            for (p = v ; p != NULL && p != SelfNode; p = p->_next) {
+                q = p ;
+                assert (p->TState == ObjectWaiter::TS_CXQ, "invariant") ;
+            }
+            assert (v != SelfNode,  "invariant") ;
+            assert (p == SelfNode,  "Node not found on cxq") ;
+            assert (p != _cxq,      "invariant") ;
+            assert (q != NULL,      "invariant") ;
+            assert (q->_next == p,  "invariant") ;
+            q->_next = p->_next ;
+        }
+        TEVENT (Unlink from cxq) ;
+    }
+
+    // Diagnostic hygiene ...
+    SelfNode->_prev  = (ObjectWaiter *) 0xBAD ;
+    SelfNode->_next  = (ObjectWaiter *) 0xBAD ;
+    SelfNode->TState = ObjectWaiter::TS_RUN ;
+}
+
+// -----------------------------------------------------------------------------
+// Exit support
+//
+// exit()
+// ~~~~~~
+// Note that the collector can't reclaim the objectMonitor or deflate
+// the object out from underneath the thread calling ::exit() as the
+// thread calling ::exit() never transitions to a stable state.
+// This inhibits GC, which in turn inhibits asynchronous (and
+// inopportune) reclamation of "this".
+//
+// We'd like to assert that: (THREAD->thread_state() != _thread_blocked) ;
+// There's one exception to the claim above, however.  EnterI() can call
+// exit() to drop a lock if the acquirer has been externally suspended.
+// In that case exit() is called with _thread_state as _thread_blocked,
+// but the monitor's _count field is > 0, which inhibits reclamation.
+//
+// 1-0 exit
+// ~~~~~~~~
+// ::exit() uses a canonical 1-1 idiom with a MEMBAR although some of
+// the fast-path operators have been optimized so the common ::exit()
+// operation is 1-0.  See i486.ad fast_unlock(), for instance.
+// The code emitted by fast_unlock() elides the usual MEMBAR.  This
+// greatly improves latency -- MEMBAR and CAS having considerable local
+// latency on modern processors -- but at the cost of "stranding".  Absent the
+// MEMBAR, a thread in fast_unlock() can race a thread in the slow
+// ::enter() path, resulting in the entering thread being stranding
+// and a progress-liveness failure.   Stranding is extremely rare.
+// We use timers (timed park operations) & periodic polling to detect
+// and recover from stranding.  Potentially stranded threads periodically
+// wake up and poll the lock.  See the usage of the _Responsible variable.
+//
+// The CAS() in enter provides for safety and exclusion, while the CAS or
+// MEMBAR in exit provides for progress and avoids stranding.  1-0 locking
+// eliminates the CAS/MEMBAR from the exist path, but it admits stranding.
+// We detect and recover from stranding with timers.
+//
+// If a thread transiently strands it'll park until (a) another
+// thread acquires the lock and then drops the lock, at which time the
+// exiting thread will notice and unpark the stranded thread, or, (b)
+// the timer expires.  If the lock is high traffic then the stranding latency
+// will be low due to (a).  If the lock is low traffic then the odds of
+// stranding are lower, although the worst-case stranding latency
+// is longer.  Critically, we don't want to put excessive load in the
+// platform's timer subsystem.  We want to minimize both the timer injection
+// rate (timers created/sec) as well as the number of timers active at
+// any one time.  (more precisely, we want to minimize timer-seconds, which is
+// the integral of the # of active timers at any instant over time).
+// Both impinge on OS scalability.  Given that, at most one thread parked on
+// a monitor will use a timer.
+
+void ATTR ObjectMonitor::exit(TRAPS) {
+   Thread * Self = THREAD ;
+   if (THREAD != _owner) {
+     if (THREAD->is_lock_owned((address) _owner)) {
+       // Transmute _owner from a BasicLock pointer to a Thread address.
+       // We don't need to hold _mutex for this transition.
+       // Non-null to Non-null is safe as long as all readers can
+       // tolerate either flavor.
+       assert (_recursions == 0, "invariant") ;
+       _owner = THREAD ;
+       _recursions = 0 ;
+       OwnerIsThread = 1 ;
+     } else {
+       // NOTE: we need to handle unbalanced monitor enter/exit
+       // in native code by throwing an exception.
+       // TODO: Throw an IllegalMonitorStateException ?
+       TEVENT (Exit - Throw IMSX) ;
+       assert(false, "Non-balanced monitor enter/exit!");
+       if (false) {
+          THROW(vmSymbols::java_lang_IllegalMonitorStateException());
+       }
+       return;
+     }
+   }
+
+   if (_recursions != 0) {
+     _recursions--;        // this is simple recursive enter
+     TEVENT (Inflated exit - recursive) ;
+     return ;
+   }
+
+   // Invariant: after setting Responsible=null an thread must execute
+   // a MEMBAR or other serializing instruction before fetching EntryList|cxq.
+   if ((SyncFlags & 4) == 0) {
+      _Responsible = NULL ;
+   }
+
+   for (;;) {
+      assert (THREAD == _owner, "invariant") ;
+
+
+      if (Knob_ExitPolicy == 0) {
+         // release semantics: prior loads and stores from within the critical section
+         // must not float (reorder) past the following store that drops the lock.
+         // On SPARC that requires MEMBAR #loadstore|#storestore.
+         // But of course in TSO #loadstore|#storestore is not required.
+         // I'd like to write one of the following:
+         // A.  OrderAccess::release() ; _owner = NULL
+         // B.  OrderAccess::loadstore(); OrderAccess::storestore(); _owner = NULL;
+         // Unfortunately OrderAccess::release() and OrderAccess::loadstore() both
+         // store into a _dummy variable.  That store is not needed, but can result
+         // in massive wasteful coherency traffic on classic SMP systems.
+         // Instead, I use release_store(), which is implemented as just a simple
+         // ST on x64, x86 and SPARC.
+         OrderAccess::release_store_ptr (&_owner, NULL) ;   // drop the lock
+         OrderAccess::storeload() ;                         // See if we need to wake a successor
+         if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {
+            TEVENT (Inflated exit - simple egress) ;
+            return ;
+         }
+         TEVENT (Inflated exit - complex egress) ;
+
+         // Normally the exiting thread is responsible for ensuring succession,
+         // but if other successors are ready or other entering threads are spinning
+         // then this thread can simply store NULL into _owner and exit without
+         // waking a successor.  The existence of spinners or ready successors
+         // guarantees proper succession (liveness).  Responsibility passes to the
+         // ready or running successors.  The exiting thread delegates the duty.
+         // More precisely, if a successor already exists this thread is absolved
+         // of the responsibility of waking (unparking) one.
+         //
+         // The _succ variable is critical to reducing futile wakeup frequency.
+         // _succ identifies the "heir presumptive" thread that has been made
+         // ready (unparked) but that has not yet run.  We need only one such
+         // successor thread to guarantee progress.
+         // See http://www.usenix.org/events/jvm01/full_papers/dice/dice.pdf
+         // section 3.3 "Futile Wakeup Throttling" for details.
+         //
+         // Note that spinners in Enter() also set _succ non-null.
+         // In the current implementation spinners opportunistically set
+         // _succ so that exiting threads might avoid waking a successor.
+         // Another less appealing alternative would be for the exiting thread
+         // to drop the lock and then spin briefly to see if a spinner managed
+         // to acquire the lock.  If so, the exiting thread could exit
+         // immediately without waking a successor, otherwise the exiting
+         // thread would need to dequeue and wake a successor.
+         // (Note that we'd need to make the post-drop spin short, but no
+         // shorter than the worst-case round-trip cache-line migration time.
+         // The dropped lock needs to become visible to the spinner, and then
+         // the acquisition of the lock by the spinner must become visible to
+         // the exiting thread).
+         //
+
+         // It appears that an heir-presumptive (successor) must be made ready.
+         // Only the current lock owner can manipulate the EntryList or
+         // drain _cxq, so we need to reacquire the lock.  If we fail
+         // to reacquire the lock the responsibility for ensuring succession
+         // falls to the new owner.
+         //
+         if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
+            return ;
+         }
+         TEVENT (Exit - Reacquired) ;
+      } else {
+         if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {
+            OrderAccess::release_store_ptr (&_owner, NULL) ;   // drop the lock
+            OrderAccess::storeload() ;
+            // Ratify the previously observed values.
+            if (_cxq == NULL || _succ != NULL) {
+                TEVENT (Inflated exit - simple egress) ;
+                return ;
+            }
+
+            // inopportune interleaving -- the exiting thread (this thread)
+            // in the fast-exit path raced an entering thread in the slow-enter
+            // path.
+            // We have two choices:
+            // A.  Try to reacquire the lock.
+            //     If the CAS() fails return immediately, otherwise
+            //     we either restart/rerun the exit operation, or simply
+            //     fall-through into the code below which wakes a successor.
+            // B.  If the elements forming the EntryList|cxq are TSM
+            //     we could simply unpark() the lead thread and return
+            //     without having set _succ.
+            if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
+               TEVENT (Inflated exit - reacquired succeeded) ;
+               return ;
+            }
+            TEVENT (Inflated exit - reacquired failed) ;
+         } else {
+            TEVENT (Inflated exit - complex egress) ;
+         }
+      }
+
+      guarantee (_owner == THREAD, "invariant") ;
+
+      ObjectWaiter * w = NULL ;
+      int QMode = Knob_QMode ;
+
+      if (QMode == 2 && _cxq != NULL) {
+          // QMode == 2 : cxq has precedence over EntryList.
+          // Try to directly wake a successor from the cxq.
+          // If successful, the successor will need to unlink itself from cxq.
+          w = _cxq ;
+          assert (w != NULL, "invariant") ;
+          assert (w->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
+          ExitEpilog (Self, w) ;
+          return ;
+      }
+
+      if (QMode == 3 && _cxq != NULL) {
+          // Aggressively drain cxq into EntryList at the first opportunity.
+          // This policy ensure that recently-run threads live at the head of EntryList.
+          // Drain _cxq into EntryList - bulk transfer.
+          // First, detach _cxq.
+          // The following loop is tantamount to: w = swap (&cxq, NULL)
+          w = _cxq ;
+          for (;;) {
+             assert (w != NULL, "Invariant") ;
+             ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;
+             if (u == w) break ;
+             w = u ;
+          }
+          assert (w != NULL              , "invariant") ;
+
+          ObjectWaiter * q = NULL ;
+          ObjectWaiter * p ;
+          for (p = w ; p != NULL ; p = p->_next) {
+              guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
+              p->TState = ObjectWaiter::TS_ENTER ;
+              p->_prev = q ;
+              q = p ;
+          }
+
+          // Append the RATs to the EntryList
+          // TODO: organize EntryList as a CDLL so we can locate the tail in constant-time.
+          ObjectWaiter * Tail ;
+          for (Tail = _EntryList ; Tail != NULL && Tail->_next != NULL ; Tail = Tail->_next) ;
+          if (Tail == NULL) {
+              _EntryList = w ;
+          } else {
+              Tail->_next = w ;
+              w->_prev = Tail ;
+          }
+
+          // Fall thru into code that tries to wake a successor from EntryList
+      }
+
+      if (QMode == 4 && _cxq != NULL) {
+          // Aggressively drain cxq into EntryList at the first opportunity.
+          // This policy ensure that recently-run threads live at the head of EntryList.
+
+          // Drain _cxq into EntryList - bulk transfer.
+          // First, detach _cxq.
+          // The following loop is tantamount to: w = swap (&cxq, NULL)
+          w = _cxq ;
+          for (;;) {
+             assert (w != NULL, "Invariant") ;
+             ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;
+             if (u == w) break ;
+             w = u ;
+          }
+          assert (w != NULL              , "invariant") ;
+
+          ObjectWaiter * q = NULL ;
+          ObjectWaiter * p ;
+          for (p = w ; p != NULL ; p = p->_next) {
+              guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
+              p->TState = ObjectWaiter::TS_ENTER ;
+              p->_prev = q ;
+              q = p ;
+          }
+
+          // Prepend the RATs to the EntryList
+          if (_EntryList != NULL) {
+              q->_next = _EntryList ;
+              _EntryList->_prev = q ;
+          }
+          _EntryList = w ;
+
+          // Fall thru into code that tries to wake a successor from EntryList
+      }
+
+      w = _EntryList  ;
+      if (w != NULL) {
+          // I'd like to write: guarantee (w->_thread != Self).
+          // But in practice an exiting thread may find itself on the EntryList.
+          // Lets say thread T1 calls O.wait().  Wait() enqueues T1 on O's waitset and
+          // then calls exit().  Exit release the lock by setting O._owner to NULL.
+          // Lets say T1 then stalls.  T2 acquires O and calls O.notify().  The
+          // notify() operation moves T1 from O's waitset to O's EntryList. T2 then
+          // release the lock "O".  T2 resumes immediately after the ST of null into
+          // _owner, above.  T2 notices that the EntryList is populated, so it
+          // reacquires the lock and then finds itself on the EntryList.
+          // Given all that, we have to tolerate the circumstance where "w" is
+          // associated with Self.
+          assert (w->TState == ObjectWaiter::TS_ENTER, "invariant") ;
+          ExitEpilog (Self, w) ;
+          return ;
+      }
+
+      // If we find that both _cxq and EntryList are null then just
+      // re-run the exit protocol from the top.
+      w = _cxq ;
+      if (w == NULL) continue ;
+
+      // Drain _cxq into EntryList - bulk transfer.
+      // First, detach _cxq.
+      // The following loop is tantamount to: w = swap (&cxq, NULL)
+      for (;;) {
+          assert (w != NULL, "Invariant") ;
+          ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;
+          if (u == w) break ;
+          w = u ;
+      }
+      TEVENT (Inflated exit - drain cxq into EntryList) ;
+
+      assert (w != NULL              , "invariant") ;
+      assert (_EntryList  == NULL    , "invariant") ;
+
+      // Convert the LIFO SLL anchored by _cxq into a DLL.
+      // The list reorganization step operates in O(LENGTH(w)) time.
+      // It's critical that this step operate quickly as
+      // "Self" still holds the outer-lock, restricting parallelism
+      // and effectively lengthening the critical section.
+      // Invariant: s chases t chases u.
+      // TODO-FIXME: consider changing EntryList from a DLL to a CDLL so
+      // we have faster access to the tail.
+
+      if (QMode == 1) {
+         // QMode == 1 : drain cxq to EntryList, reversing order
+         // We also reverse the order of the list.
+         ObjectWaiter * s = NULL ;
+         ObjectWaiter * t = w ;
+         ObjectWaiter * u = NULL ;
+         while (t != NULL) {
+             guarantee (t->TState == ObjectWaiter::TS_CXQ, "invariant") ;
+             t->TState = ObjectWaiter::TS_ENTER ;
+             u = t->_next ;
+             t->_prev = u ;
+             t->_next = s ;
+             s = t;
+             t = u ;
+         }
+         _EntryList  = s ;
+         assert (s != NULL, "invariant") ;
+      } else {
+         // QMode == 0 or QMode == 2
+         _EntryList = w ;
+         ObjectWaiter * q = NULL ;
+         ObjectWaiter * p ;
+         for (p = w ; p != NULL ; p = p->_next) {
+             guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
+             p->TState = ObjectWaiter::TS_ENTER ;
+             p->_prev = q ;
+             q = p ;
+         }
+      }
+
+      // In 1-0 mode we need: ST EntryList; MEMBAR #storestore; ST _owner = NULL
+      // The MEMBAR is satisfied by the release_store() operation in ExitEpilog().
+
+      // See if we can abdicate to a spinner instead of waking a thread.
+      // A primary goal of the implementation is to reduce the
+      // context-switch rate.
+      if (_succ != NULL) continue;
+
+      w = _EntryList  ;
+      if (w != NULL) {
+          guarantee (w->TState == ObjectWaiter::TS_ENTER, "invariant") ;
+          ExitEpilog (Self, w) ;
+          return ;
+      }
+   }
+}
+
+// ExitSuspendEquivalent:
+// A faster alternate to handle_special_suspend_equivalent_condition()
+//
+// handle_special_suspend_equivalent_condition() unconditionally
+// acquires the SR_lock.  On some platforms uncontended MutexLocker()
+// operations have high latency.  Note that in ::enter() we call HSSEC
+// while holding the monitor, so we effectively lengthen the critical sections.
+//
+// There are a number of possible solutions:
+//
+// A.  To ameliorate the problem we might also defer state transitions
+//     to as late as possible -- just prior to parking.
+//     Given that, we'd call HSSEC after having returned from park(),
+//     but before attempting to acquire the monitor.  This is only a
+//     partial solution.  It avoids calling HSSEC while holding the
+//     monitor (good), but it still increases successor reacquisition latency --
+//     the interval between unparking a successor and the time the successor
+//     resumes and retries the lock.  See ReenterI(), which defers state transitions.
+//     If we use this technique we can also avoid EnterI()-exit() loop
+//     in ::enter() where we iteratively drop the lock and then attempt
+//     to reacquire it after suspending.
+//
+// B.  In the future we might fold all the suspend bits into a
+//     composite per-thread suspend flag and then update it with CAS().
+//     Alternately, a Dekker-like mechanism with multiple variables
+//     would suffice:
+//       ST Self->_suspend_equivalent = false
+//       MEMBAR
+//       LD Self_>_suspend_flags
+//
+
+
+bool ObjectMonitor::ExitSuspendEquivalent (JavaThread * jSelf) {
+   int Mode = Knob_FastHSSEC ;
+   if (Mode && !jSelf->is_external_suspend()) {
+      assert (jSelf->is_suspend_equivalent(), "invariant") ;
+      jSelf->clear_suspend_equivalent() ;
+      if (2 == Mode) OrderAccess::storeload() ;
+      if (!jSelf->is_external_suspend()) return false ;
+      // We raced a suspension -- fall thru into the slow path
+      TEVENT (ExitSuspendEquivalent - raced) ;
+      jSelf->set_suspend_equivalent() ;
+   }
+   return jSelf->handle_special_suspend_equivalent_condition() ;
+}
+
+
+void ObjectMonitor::ExitEpilog (Thread * Self, ObjectWaiter * Wakee) {
+   assert (_owner == Self, "invariant") ;
+
+   // Exit protocol:
+   // 1. ST _succ = wakee
+   // 2. membar #loadstore|#storestore;
+   // 2. ST _owner = NULL
+   // 3. unpark(wakee)
+
+   _succ = Knob_SuccEnabled ? Wakee->_thread : NULL ;
+   ParkEvent * Trigger = Wakee->_event ;
+
+   // Hygiene -- once we've set _owner = NULL we can't safely dereference Wakee again.
+   // The thread associated with Wakee may have grabbed the lock and "Wakee" may be
+   // out-of-scope (non-extant).
+   Wakee  = NULL ;
+
+   // Drop the lock
+   OrderAccess::release_store_ptr (&_owner, NULL) ;
+   OrderAccess::fence() ;                               // ST _owner vs LD in unpark()
+
+   if (SafepointSynchronize::do_call_back()) {
+      TEVENT (unpark before SAFEPOINT) ;
+   }
+
+   DTRACE_MONITOR_PROBE(contended__exit, this, object(), Self);
+   Trigger->unpark() ;
+
+   // Maintain stats and report events to JVMTI
+   if (ObjectMonitor::_sync_Parks != NULL) {
+      ObjectMonitor::_sync_Parks->inc() ;
+   }
+}
+
+
+// -----------------------------------------------------------------------------
+// Class Loader deadlock handling.
+//
+// complete_exit exits a lock returning recursion count
+// complete_exit/reenter operate as a wait without waiting
+// complete_exit requires an inflated monitor
+// The _owner field is not always the Thread addr even with an
+// inflated monitor, e.g. the monitor can be inflated by a non-owning
+// thread due to contention.
+intptr_t ObjectMonitor::complete_exit(TRAPS) {
+   Thread * const Self = THREAD;
+   assert(Self->is_Java_thread(), "Must be Java thread!");
+   JavaThread *jt = (JavaThread *)THREAD;
+
+   DeferredInitialize();
+
+   if (THREAD != _owner) {
+    if (THREAD->is_lock_owned ((address)_owner)) {
+       assert(_recursions == 0, "internal state error");
+       _owner = THREAD ;   /* Convert from basiclock addr to Thread addr */
+       _recursions = 0 ;
+       OwnerIsThread = 1 ;
+    }
+   }
+
+   guarantee(Self == _owner, "complete_exit not owner");
+   intptr_t save = _recursions; // record the old recursion count
+   _recursions = 0;        // set the recursion level to be 0
+   exit (Self) ;           // exit the monitor
+   guarantee (_owner != Self, "invariant");
+   return save;
+}
+
+// reenter() enters a lock and sets recursion count
+// complete_exit/reenter operate as a wait without waiting
+void ObjectMonitor::reenter(intptr_t recursions, TRAPS) {
+   Thread * const Self = THREAD;
+   assert(Self->is_Java_thread(), "Must be Java thread!");
+   JavaThread *jt = (JavaThread *)THREAD;
+
+   guarantee(_owner != Self, "reenter already owner");
+   enter (THREAD);       // enter the monitor
+   guarantee (_recursions == 0, "reenter recursion");
+   _recursions = recursions;
+   return;
+}
+
+
+// -----------------------------------------------------------------------------
+// A macro is used below because there may already be a pending
+// exception which should not abort the execution of the routines
+// which use this (which is why we don't put this into check_slow and
+// call it with a CHECK argument).
+
+#define CHECK_OWNER()                                                             \
+  do {                                                                            \
+    if (THREAD != _owner) {                                                       \
+      if (THREAD->is_lock_owned((address) _owner)) {                              \
+        _owner = THREAD ;  /* Convert from basiclock addr to Thread addr */       \
+        _recursions = 0;                                                          \
+        OwnerIsThread = 1 ;                                                       \
+      } else {                                                                    \
+        TEVENT (Throw IMSX) ;                                                     \
+        THROW(vmSymbols::java_lang_IllegalMonitorStateException());               \
+      }                                                                           \
+    }                                                                             \
+  } while (false)
+
+// check_slow() is a misnomer.  It's called to simply to throw an IMSX exception.
+// TODO-FIXME: remove check_slow() -- it's likely dead.
+
+void ObjectMonitor::check_slow(TRAPS) {
+  TEVENT (check_slow - throw IMSX) ;
+  assert(THREAD != _owner && !THREAD->is_lock_owned((address) _owner), "must not be owner");
+  THROW_MSG(vmSymbols::java_lang_IllegalMonitorStateException(), "current thread not owner");
+}
+
+static int Adjust (volatile int * adr, int dx) {
+  int v ;
+  for (v = *adr ; Atomic::cmpxchg (v + dx, adr, v) != v; v = *adr) ;
+  return v ;
+}
+// -----------------------------------------------------------------------------
+// Wait/Notify/NotifyAll
+//
+// Note: a subset of changes to ObjectMonitor::wait()
+// will need to be replicated in complete_exit above
+void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
+   Thread * const Self = THREAD ;
+   assert(Self->is_Java_thread(), "Must be Java thread!");
+   JavaThread *jt = (JavaThread *)THREAD;
+
+   DeferredInitialize () ;
+
+   // Throw IMSX or IEX.
+   CHECK_OWNER();
+
+   // check for a pending interrupt
+   if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {
+     // post monitor waited event.  Note that this is past-tense, we are done waiting.
+     if (JvmtiExport::should_post_monitor_waited()) {
+        // Note: 'false' parameter is passed here because the
+        // wait was not timed out due to thread interrupt.
+        JvmtiExport::post_monitor_waited(jt, this, false);
+     }
+     TEVENT (Wait - Throw IEX) ;
+     THROW(vmSymbols::java_lang_InterruptedException());
+     return ;
+   }
+   TEVENT (Wait) ;
+
+   assert (Self->_Stalled == 0, "invariant") ;
+   Self->_Stalled = intptr_t(this) ;
+   jt->set_current_waiting_monitor(this);
+
+   // create a node to be put into the queue
+   // Critically, after we reset() the event but prior to park(), we must check
+   // for a pending interrupt.
+   ObjectWaiter node(Self);
+   node.TState = ObjectWaiter::TS_WAIT ;
+   Self->_ParkEvent->reset() ;
+   OrderAccess::fence();          // ST into Event; membar ; LD interrupted-flag
+
+   // Enter the waiting queue, which is a circular doubly linked list in this case
+   // but it could be a priority queue or any data structure.
+   // _WaitSetLock protects the wait queue.  Normally the wait queue is accessed only
+   // by the the owner of the monitor *except* in the case where park()
+   // returns because of a timeout of interrupt.  Contention is exceptionally rare
+   // so we use a simple spin-lock instead of a heavier-weight blocking lock.
+
+   Thread::SpinAcquire (&_WaitSetLock, "WaitSet - add") ;
+   AddWaiter (&node) ;
+   Thread::SpinRelease (&_WaitSetLock) ;
+
+   if ((SyncFlags & 4) == 0) {
+      _Responsible = NULL ;
+   }
+   intptr_t save = _recursions; // record the old recursion count
+   _waiters++;                  // increment the number of waiters
+   _recursions = 0;             // set the recursion level to be 1
+   exit (Self) ;                    // exit the monitor
+   guarantee (_owner != Self, "invariant") ;
+
+   // As soon as the ObjectMonitor's ownership is dropped in the exit()
+   // call above, another thread can enter() the ObjectMonitor, do the
+   // notify(), and exit() the ObjectMonitor. If the other thread's
+   // exit() call chooses this thread as the successor and the unpark()
+   // call happens to occur while this thread is posting a
+   // MONITOR_CONTENDED_EXIT event, then we run the risk of the event
+   // handler using RawMonitors and consuming the unpark().
+   //
+   // To avoid the problem, we re-post the event. This does no harm
+   // even if the original unpark() was not consumed because we are the
+   // chosen successor for this monitor.
+   if (node._notified != 0 && _succ == Self) {
+      node._event->unpark();
+   }
+
+   // The thread is on the WaitSet list - now park() it.
+   // On MP systems it's conceivable that a brief spin before we park
+   // could be profitable.
+   //
+   // TODO-FIXME: change the following logic to a loop of the form
+   //   while (!timeout && !interrupted && _notified == 0) park()
+
+   int ret = OS_OK ;
+   int WasNotified = 0 ;
+   { // State transition wrappers
+     OSThread* osthread = Self->osthread();
+     OSThreadWaitState osts(osthread, true);
+     {
+       ThreadBlockInVM tbivm(jt);
+       // Thread is in thread_blocked state and oop access is unsafe.
+       jt->set_suspend_equivalent();
+
+       if (interruptible && (Thread::is_interrupted(THREAD, false) || HAS_PENDING_EXCEPTION)) {
+           // Intentionally empty
+       } else
+       if (node._notified == 0) {
+         if (millis <= 0) {
+            Self->_ParkEvent->park () ;
+         } else {
+            ret = Self->_ParkEvent->park (millis) ;
+         }
+       }
+
+       // were we externally suspended while we were waiting?
+       if (ExitSuspendEquivalent (jt)) {
+          // TODO-FIXME: add -- if succ == Self then succ = null.
+          jt->java_suspend_self();
+       }
+
+     } // Exit thread safepoint: transition _thread_blocked -> _thread_in_vm
+
+
+     // Node may be on the WaitSet, the EntryList (or cxq), or in transition
+     // from the WaitSet to the EntryList.
+     // See if we need to remove Node from the WaitSet.
+     // We use double-checked locking to avoid grabbing _WaitSetLock
+     // if the thread is not on the wait queue.
+     //
+     // Note that we don't need a fence before the fetch of TState.
+     // In the worst case we'll fetch a old-stale value of TS_WAIT previously
+     // written by the is thread. (perhaps the fetch might even be satisfied
+     // by a look-aside into the processor's own store buffer, although given
+     // the length of the code path between the prior ST and this load that's
+     // highly unlikely).  If the following LD fetches a stale TS_WAIT value
+     // then we'll acquire the lock and then re-fetch a fresh TState value.
+     // That is, we fail toward safety.
+
+     if (node.TState == ObjectWaiter::TS_WAIT) {
+         Thread::SpinAcquire (&_WaitSetLock, "WaitSet - unlink") ;
+         if (node.TState == ObjectWaiter::TS_WAIT) {
+            DequeueSpecificWaiter (&node) ;       // unlink from WaitSet
+            assert(node._notified == 0, "invariant");
+            node.TState = ObjectWaiter::TS_RUN ;
+         }
+         Thread::SpinRelease (&_WaitSetLock) ;
+     }
+
+     // The thread is now either on off-list (TS_RUN),
+     // on the EntryList (TS_ENTER), or on the cxq (TS_CXQ).
+     // The Node's TState variable is stable from the perspective of this thread.
+     // No other threads will asynchronously modify TState.
+     guarantee (node.TState != ObjectWaiter::TS_WAIT, "invariant") ;
+     OrderAccess::loadload() ;
+     if (_succ == Self) _succ = NULL ;
+     WasNotified = node._notified ;
+
+     // Reentry phase -- reacquire the monitor.
+     // re-enter contended monitor after object.wait().
+     // retain OBJECT_WAIT state until re-enter successfully completes
+     // Thread state is thread_in_vm and oop access is again safe,
+     // although the raw address of the object may have changed.
+     // (Don't cache naked oops over safepoints, of course).
+
+     // post monitor waited event. Note that this is past-tense, we are done waiting.
+     if (JvmtiExport::should_post_monitor_waited()) {
+       JvmtiExport::post_monitor_waited(jt, this, ret == OS_TIMEOUT);
+     }
+     OrderAccess::fence() ;
+
+     assert (Self->_Stalled != 0, "invariant") ;
+     Self->_Stalled = 0 ;
+
+     assert (_owner != Self, "invariant") ;
+     ObjectWaiter::TStates v = node.TState ;
+     if (v == ObjectWaiter::TS_RUN) {
+         enter (Self) ;
+     } else {
+         guarantee (v == ObjectWaiter::TS_ENTER || v == ObjectWaiter::TS_CXQ, "invariant") ;
+         ReenterI (Self, &node) ;
+         node.wait_reenter_end(this);
+     }
+
+     // Self has reacquired the lock.
+     // Lifecycle - the node representing Self must not appear on any queues.
+     // Node is about to go out-of-scope, but even if it were immortal we wouldn't
+     // want residual elements associated with this thread left on any lists.
+     guarantee (node.TState == ObjectWaiter::TS_RUN, "invariant") ;
+     assert    (_owner == Self, "invariant") ;
+     assert    (_succ != Self , "invariant") ;
+   } // OSThreadWaitState()
+
+   jt->set_current_waiting_monitor(NULL);
+
+   guarantee (_recursions == 0, "invariant") ;
+   _recursions = save;     // restore the old recursion count
+   _waiters--;             // decrement the number of waiters
+
+   // Verify a few postconditions
+   assert (_owner == Self       , "invariant") ;
+   assert (_succ  != Self       , "invariant") ;
+   assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
+
+   if (SyncFlags & 32) {
+      OrderAccess::fence() ;
+   }
+
+   // check if the notification happened
+   if (!WasNotified) {
+     // no, it could be timeout or Thread.interrupt() or both
+     // check for interrupt event, otherwise it is timeout
+     if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {
+       TEVENT (Wait - throw IEX from epilog) ;
+       THROW(vmSymbols::java_lang_InterruptedException());
+     }
+   }
+
+   // NOTE: Spurious wake up will be consider as timeout.
+   // Monitor notify has precedence over thread interrupt.
+}
+
+
+// Consider:
+// If the lock is cool (cxq == null && succ == null) and we're on an MP system
+// then instead of transferring a thread from the WaitSet to the EntryList
+// we might just dequeue a thread from the WaitSet and directly unpark() it.
+
+void ObjectMonitor::notify(TRAPS) {
+  CHECK_OWNER();
+  if (_WaitSet == NULL) {
+     TEVENT (Empty-Notify) ;
+     return ;
+  }
+  DTRACE_MONITOR_PROBE(notify, this, object(), THREAD);
+
+  int Policy = Knob_MoveNotifyee ;
+
+  Thread::SpinAcquire (&_WaitSetLock, "WaitSet - notify") ;
+  ObjectWaiter * iterator = DequeueWaiter() ;
+  if (iterator != NULL) {
+     TEVENT (Notify1 - Transfer) ;
+     guarantee (iterator->TState == ObjectWaiter::TS_WAIT, "invariant") ;
+     guarantee (iterator->_notified == 0, "invariant") ;
+     if (Policy != 4) {
+        iterator->TState = ObjectWaiter::TS_ENTER ;
+     }
+     iterator->_notified = 1 ;
+
+     ObjectWaiter * List = _EntryList ;
+     if (List != NULL) {
+        assert (List->_prev == NULL, "invariant") ;
+        assert (List->TState == ObjectWaiter::TS_ENTER, "invariant") ;
+        assert (List != iterator, "invariant") ;
+     }
+
+     if (Policy == 0) {       // prepend to EntryList
+         if (List == NULL) {
+             iterator->_next = iterator->_prev = NULL ;
+             _EntryList = iterator ;
+         } else {
+             List->_prev = iterator ;
+             iterator->_next = List ;
+             iterator->_prev = NULL ;
+             _EntryList = iterator ;
+        }
+     } else
+     if (Policy == 1) {      // append to EntryList
+         if (List == NULL) {
+             iterator->_next = iterator->_prev = NULL ;
+             _EntryList = iterator ;
+         } else {
+            // CONSIDER:  finding the tail currently requires a linear-time walk of
+            // the EntryList.  We can make tail access constant-time by converting to
+            // a CDLL instead of using our current DLL.
+            ObjectWaiter * Tail ;
+            for (Tail = List ; Tail->_next != NULL ; Tail = Tail->_next) ;
+            assert (Tail != NULL && Tail->_next == NULL, "invariant") ;
+            Tail->_next = iterator ;
+            iterator->_prev = Tail ;
+            iterator->_next = NULL ;
+        }
+     } else
+     if (Policy == 2) {      // prepend to cxq
+         // prepend to cxq
+         if (List == NULL) {
+             iterator->_next = iterator->_prev = NULL ;
+             _EntryList = iterator ;
+         } else {
+            iterator->TState = ObjectWaiter::TS_CXQ ;
+            for (;;) {
+                ObjectWaiter * Front = _cxq ;
+                iterator->_next = Front ;
+                if (Atomic::cmpxchg_ptr (iterator, &_cxq, Front) == Front) {
+                    break ;
+                }
+            }
+         }
+     } else
+     if (Policy == 3) {      // append to cxq
+        iterator->TState = ObjectWaiter::TS_CXQ ;
+        for (;;) {
+            ObjectWaiter * Tail ;
+            Tail = _cxq ;
+            if (Tail == NULL) {
+                iterator->_next = NULL ;
+                if (Atomic::cmpxchg_ptr (iterator, &_cxq, NULL) == NULL) {
+                   break ;
+                }
+            } else {
+                while (Tail->_next != NULL) Tail = Tail->_next ;
+                Tail->_next = iterator ;
+                iterator->_prev = Tail ;
+                iterator->_next = NULL ;
+                break ;
+            }
+        }
+     } else {
+        ParkEvent * ev = iterator->_event ;
+        iterator->TState = ObjectWaiter::TS_RUN ;
+        OrderAccess::fence() ;
+        ev->unpark() ;
+     }
+
+     if (Policy < 4) {
+       iterator->wait_reenter_begin(this);
+     }
+
+     // _WaitSetLock protects the wait queue, not the EntryList.  We could
+     // move the add-to-EntryList operation, above, outside the critical section
+     // protected by _WaitSetLock.  In practice that's not useful.  With the
+     // exception of  wait() timeouts and interrupts the monitor owner
+     // is the only thread that grabs _WaitSetLock.  There's almost no contention
+     // on _WaitSetLock so it's not profitable to reduce the length of the
+     // critical section.
+  }
+
+  Thread::SpinRelease (&_WaitSetLock) ;
+
+  if (iterator != NULL && ObjectMonitor::_sync_Notifications != NULL) {
+     ObjectMonitor::_sync_Notifications->inc() ;
+  }
+}
+
+
+void ObjectMonitor::notifyAll(TRAPS) {
+  CHECK_OWNER();
+  ObjectWaiter* iterator;
+  if (_WaitSet == NULL) {
+      TEVENT (Empty-NotifyAll) ;
+      return ;
+  }
+  DTRACE_MONITOR_PROBE(notifyAll, this, object(), THREAD);
+
+  int Policy = Knob_MoveNotifyee ;
+  int Tally = 0 ;
+  Thread::SpinAcquire (&_WaitSetLock, "WaitSet - notifyall") ;
+
+  for (;;) {
+     iterator = DequeueWaiter () ;
+     if (iterator == NULL) break ;
+     TEVENT (NotifyAll - Transfer1) ;
+     ++Tally ;
+
+     // Disposition - what might we do with iterator ?
+     // a.  add it directly to the EntryList - either tail or head.
+     // b.  push it onto the front of the _cxq.
+     // For now we use (a).
+
+     guarantee (iterator->TState == ObjectWaiter::TS_WAIT, "invariant") ;
+     guarantee (iterator->_notified == 0, "invariant") ;
+     iterator->_notified = 1 ;
+     if (Policy != 4) {
+        iterator->TState = ObjectWaiter::TS_ENTER ;
+     }
+
+     ObjectWaiter * List = _EntryList ;
+     if (List != NULL) {
+        assert (List->_prev == NULL, "invariant") ;
+        assert (List->TState == ObjectWaiter::TS_ENTER, "invariant") ;
+        assert (List != iterator, "invariant") ;
+     }
+
+     if (Policy == 0) {       // prepend to EntryList
+         if (List == NULL) {
+             iterator->_next = iterator->_prev = NULL ;
+             _EntryList = iterator ;
+         } else {
+             List->_prev = iterator ;
+             iterator->_next = List ;
+             iterator->_prev = NULL ;
+             _EntryList = iterator ;
+        }
+     } else
+     if (Policy == 1) {      // append to EntryList
+         if (List == NULL) {
+             iterator->_next = iterator->_prev = NULL ;
+             _EntryList = iterator ;
+         } else {
+            // CONSIDER:  finding the tail currently requires a linear-time walk of
+            // the EntryList.  We can make tail access constant-time by converting to
+            // a CDLL instead of using our current DLL.
+            ObjectWaiter * Tail ;
+            for (Tail = List ; Tail->_next != NULL ; Tail = Tail->_next) ;
+            assert (Tail != NULL && Tail->_next == NULL, "invariant") ;
+            Tail->_next = iterator ;
+            iterator->_prev = Tail ;
+            iterator->_next = NULL ;
+        }
+     } else
+     if (Policy == 2) {      // prepend to cxq
+         // prepend to cxq
+         iterator->TState = ObjectWaiter::TS_CXQ ;
+         for (;;) {
+             ObjectWaiter * Front = _cxq ;
+             iterator->_next = Front ;
+             if (Atomic::cmpxchg_ptr (iterator, &_cxq, Front) == Front) {
+                 break ;
+             }
+         }
+     } else
+     if (Policy == 3) {      // append to cxq
+        iterator->TState = ObjectWaiter::TS_CXQ ;
+        for (;;) {
+            ObjectWaiter * Tail ;
+            Tail = _cxq ;
+            if (Tail == NULL) {
+                iterator->_next = NULL ;
+                if (Atomic::cmpxchg_ptr (iterator, &_cxq, NULL) == NULL) {
+                   break ;
+                }
+            } else {
+                while (Tail->_next != NULL) Tail = Tail->_next ;
+                Tail->_next = iterator ;
+                iterator->_prev = Tail ;
+                iterator->_next = NULL ;
+                break ;
+            }
+        }
+     } else {
+        ParkEvent * ev = iterator->_event ;
+        iterator->TState = ObjectWaiter::TS_RUN ;
+        OrderAccess::fence() ;
+        ev->unpark() ;
+     }
+
+     if (Policy < 4) {
+       iterator->wait_reenter_begin(this);
+     }
+
+     // _WaitSetLock protects the wait queue, not the EntryList.  We could
+     // move the add-to-EntryList operation, above, outside the critical section
+     // protected by _WaitSetLock.  In practice that's not useful.  With the
+     // exception of  wait() timeouts and interrupts the monitor owner
+     // is the only thread that grabs _WaitSetLock.  There's almost no contention
+     // on _WaitSetLock so it's not profitable to reduce the length of the
+     // critical section.
+  }
+
+  Thread::SpinRelease (&_WaitSetLock) ;
+
+  if (Tally != 0 && ObjectMonitor::_sync_Notifications != NULL) {
+     ObjectMonitor::_sync_Notifications->inc(Tally) ;
+  }
+}
+
+// -----------------------------------------------------------------------------
+// Adaptive Spinning Support
+//
+// Adaptive spin-then-block - rational spinning
+//
+// Note that we spin "globally" on _owner with a classic SMP-polite TATAS
+// algorithm.  On high order SMP systems it would be better to start with
+// a brief global spin and then revert to spinning locally.  In the spirit of MCS/CLH,
+// a contending thread could enqueue itself on the cxq and then spin locally
+// on a thread-specific variable such as its ParkEvent._Event flag.
+// That's left as an exercise for the reader.  Note that global spinning is
+// not problematic on Niagara, as the L2$ serves the interconnect and has both
+// low latency and massive bandwidth.
+//
+// Broadly, we can fix the spin frequency -- that is, the % of contended lock
+// acquisition attempts where we opt to spin --  at 100% and vary the spin count
+// (duration) or we can fix the count at approximately the duration of
+// a context switch and vary the frequency.   Of course we could also
+// vary both satisfying K == Frequency * Duration, where K is adaptive by monitor.
+// See http://j2se.east/~dice/PERSIST/040824-AdaptiveSpinning.html.
+//
+// This implementation varies the duration "D", where D varies with
+// the success rate of recent spin attempts. (D is capped at approximately
+// length of a round-trip context switch).  The success rate for recent
+// spin attempts is a good predictor of the success rate of future spin
+// attempts.  The mechanism adapts automatically to varying critical
+// section length (lock modality), system load and degree of parallelism.
+// D is maintained per-monitor in _SpinDuration and is initialized
+// optimistically.  Spin frequency is fixed at 100%.
+//
+// Note that _SpinDuration is volatile, but we update it without locks
+// or atomics.  The code is designed so that _SpinDuration stays within
+// a reasonable range even in the presence of races.  The arithmetic
+// operations on _SpinDuration are closed over the domain of legal values,
+// so at worst a race will install and older but still legal value.
+// At the very worst this introduces some apparent non-determinism.
+// We might spin when we shouldn't or vice-versa, but since the spin
+// count are relatively short, even in the worst case, the effect is harmless.
+//
+// Care must be taken that a low "D" value does not become an
+// an absorbing state.  Transient spinning failures -- when spinning
+// is overall profitable -- should not cause the system to converge
+// on low "D" values.  We want spinning to be stable and predictable
+// and fairly responsive to change and at the same time we don't want
+// it to oscillate, become metastable, be "too" non-deterministic,
+// or converge on or enter undesirable stable absorbing states.
+//
+// We implement a feedback-based control system -- using past behavior
+// to predict future behavior.  We face two issues: (a) if the
+// input signal is random then the spin predictor won't provide optimal
+// results, and (b) if the signal frequency is too high then the control
+// system, which has some natural response lag, will "chase" the signal.
+// (b) can arise from multimodal lock hold times.  Transient preemption
+// can also result in apparent bimodal lock hold times.
+// Although sub-optimal, neither condition is particularly harmful, as
+// in the worst-case we'll spin when we shouldn't or vice-versa.
+// The maximum spin duration is rather short so the failure modes aren't bad.
+// To be conservative, I've tuned the gain in system to bias toward
+// _not spinning.  Relatedly, the system can sometimes enter a mode where it
+// "rings" or oscillates between spinning and not spinning.  This happens
+// when spinning is just on the cusp of profitability, however, so the
+// situation is not dire.  The state is benign -- there's no need to add
+// hysteresis control to damp the transition rate between spinning and
+// not spinning.
+//
+
+intptr_t ObjectMonitor::SpinCallbackArgument = 0 ;
+int (*ObjectMonitor::SpinCallbackFunction)(intptr_t, int) = NULL ;
+
+// Spinning: Fixed frequency (100%), vary duration
+
+
+int ObjectMonitor::TrySpin_VaryDuration (Thread * Self) {
+
+    // Dumb, brutal spin.  Good for comparative measurements against adaptive spinning.
+    int ctr = Knob_FixedSpin ;
+    if (ctr != 0) {
+        while (--ctr >= 0) {
+            if (TryLock (Self) > 0) return 1 ;
+            SpinPause () ;
+        }
+        return 0 ;
+    }
+
+    for (ctr = Knob_PreSpin + 1; --ctr >= 0 ; ) {
+      if (TryLock(Self) > 0) {
+        // Increase _SpinDuration ...
+        // Note that we don't clamp SpinDuration precisely at SpinLimit.
+        // Raising _SpurDuration to the poverty line is key.
+        int x = _SpinDuration ;
+        if (x < Knob_SpinLimit) {
+           if (x < Knob_Poverty) x = Knob_Poverty ;
+           _SpinDuration = x + Knob_BonusB ;
+        }
+        return 1 ;
+      }
+      SpinPause () ;
+    }
+
+    // Admission control - verify preconditions for spinning
+    //
+    // We always spin a little bit, just to prevent _SpinDuration == 0 from
+    // becoming an absorbing state.  Put another way, we spin briefly to
+    // sample, just in case the system load, parallelism, contention, or lock
+    // modality changed.
+    //
+    // Consider the following alternative:
+    // Periodically set _SpinDuration = _SpinLimit and try a long/full
+    // spin attempt.  "Periodically" might mean after a tally of
+    // the # of failed spin attempts (or iterations) reaches some threshold.
+    // This takes us into the realm of 1-out-of-N spinning, where we
+    // hold the duration constant but vary the frequency.
+
+    ctr = _SpinDuration  ;
+    if (ctr < Knob_SpinBase) ctr = Knob_SpinBase ;
+    if (ctr <= 0) return 0 ;
+
+    if (Knob_SuccRestrict && _succ != NULL) return 0 ;
+    if (Knob_OState && NotRunnable (Self, (Thread *) _owner)) {
+       TEVENT (Spin abort - notrunnable [TOP]);
+       return 0 ;
+    }
+
+    int MaxSpin = Knob_MaxSpinners ;
+    if (MaxSpin >= 0) {
+       if (_Spinner > MaxSpin) {
+          TEVENT (Spin abort -- too many spinners) ;
+          return 0 ;
+       }
+       // Slighty racy, but benign ...
+       Adjust (&_Spinner, 1) ;
+    }
+
+    // We're good to spin ... spin ingress.
+    // CONSIDER: use Prefetch::write() to avoid RTS->RTO upgrades
+    // when preparing to LD...CAS _owner, etc and the CAS is likely
+    // to succeed.
+    int hits    = 0 ;
+    int msk     = 0 ;
+    int caspty  = Knob_CASPenalty ;
+    int oxpty   = Knob_OXPenalty ;
+    int sss     = Knob_SpinSetSucc ;
+    if (sss && _succ == NULL ) _succ = Self ;
+    Thread * prv = NULL ;
+
+    // There are three ways to exit the following loop:
+    // 1.  A successful spin where this thread has acquired the lock.
+    // 2.  Spin failure with prejudice
+    // 3.  Spin failure without prejudice
+
+    while (--ctr >= 0) {
+
+      // Periodic polling -- Check for pending GC
+      // Threads may spin while they're unsafe.
+      // We don't want spinning threads to delay the JVM from reaching
+      // a stop-the-world safepoint or to steal cycles from GC.
+      // If we detect a pending safepoint we abort in order that
+      // (a) this thread, if unsafe, doesn't delay the safepoint, and (b)
+      // this thread, if safe, doesn't steal cycles from GC.
+      // This is in keeping with the "no loitering in runtime" rule.
+      // We periodically check to see if there's a safepoint pending.
+      if ((ctr & 0xFF) == 0) {
+         if (SafepointSynchronize::do_call_back()) {
+            TEVENT (Spin: safepoint) ;
+            goto Abort ;           // abrupt spin egress
+         }
+         if (Knob_UsePause & 1) SpinPause () ;
+
+         int (*scb)(intptr_t,int) = SpinCallbackFunction ;
+         if (hits > 50 && scb != NULL) {
+            int abend = (*scb)(SpinCallbackArgument, 0) ;
+         }
+      }
+
+      if (Knob_UsePause & 2) SpinPause() ;
+
+      // Exponential back-off ...  Stay off the bus to reduce coherency traffic.
+      // This is useful on classic SMP systems, but is of less utility on
+      // N1-style CMT platforms.
+      //
+      // Trade-off: lock acquisition latency vs coherency bandwidth.
+      // Lock hold times are typically short.  A histogram
+      // of successful spin attempts shows that we usually acquire
+      // the lock early in the spin.  That suggests we want to
+      // sample _owner frequently in the early phase of the spin,
+      // but then back-off and sample less frequently as the spin
+      // progresses.  The back-off makes a good citizen on SMP big
+      // SMP systems.  Oversampling _owner can consume excessive
+      // coherency bandwidth.  Relatedly, if we _oversample _owner we
+      // can inadvertently interfere with the the ST m->owner=null.
+      // executed by the lock owner.
+      if (ctr & msk) continue ;
+      ++hits ;
+      if ((hits & 0xF) == 0) {
+        // The 0xF, above, corresponds to the exponent.
+        // Consider: (msk+1)|msk
+        msk = ((msk << 2)|3) & BackOffMask ;
+      }
+
+      // Probe _owner with TATAS
+      // If this thread observes the monitor transition or flicker
+      // from locked to unlocked to locked, then the odds that this
+      // thread will acquire the lock in this spin attempt go down
+      // considerably.  The same argument applies if the CAS fails
+      // or if we observe _owner change from one non-null value to
+      // another non-null value.   In such cases we might abort
+      // the spin without prejudice or apply a "penalty" to the
+      // spin count-down variable "ctr", reducing it by 100, say.
+
+      Thread * ox = (Thread *) _owner ;
+      if (ox == NULL) {
+         ox = (Thread *) Atomic::cmpxchg_ptr (Self, &_owner, NULL) ;
+         if (ox == NULL) {
+            // The CAS succeeded -- this thread acquired ownership
+            // Take care of some bookkeeping to exit spin state.
+            if (sss && _succ == Self) {
+               _succ = NULL ;
+            }
+            if (MaxSpin > 0) Adjust (&_Spinner, -1) ;
+
+            // Increase _SpinDuration :
+            // The spin was successful (profitable) so we tend toward
+            // longer spin attempts in the future.
+            // CONSIDER: factor "ctr" into the _SpinDuration adjustment.
+            // If we acquired the lock early in the spin cycle it
+            // makes sense to increase _SpinDuration proportionally.
+            // Note that we don't clamp SpinDuration precisely at SpinLimit.
+            int x = _SpinDuration ;
+            if (x < Knob_SpinLimit) {
+                if (x < Knob_Poverty) x = Knob_Poverty ;
+                _SpinDuration = x + Knob_Bonus ;
+            }
+            return 1 ;
+         }
+
+         // The CAS failed ... we can take any of the following actions:
+         // * penalize: ctr -= Knob_CASPenalty
+         // * exit spin with prejudice -- goto Abort;
+         // * exit spin without prejudice.
+         // * Since CAS is high-latency, retry again immediately.
+         prv = ox ;
+         TEVENT (Spin: cas failed) ;
+         if (caspty == -2) break ;
+         if (caspty == -1) goto Abort ;
+         ctr -= caspty ;
+         continue ;
+      }
+
+      // Did lock ownership change hands ?
+      if (ox != prv && prv != NULL ) {
+          TEVENT (spin: Owner changed)
+          if (oxpty == -2) break ;
+          if (oxpty == -1) goto Abort ;
+          ctr -= oxpty ;
+      }
+      prv = ox ;
+
+      // Abort the spin if the owner is not executing.
+      // The owner must be executing in order to drop the lock.
+      // Spinning while the owner is OFFPROC is idiocy.
+      // Consider: ctr -= RunnablePenalty ;
+      if (Knob_OState && NotRunnable (Self, ox)) {
+         TEVENT (Spin abort - notrunnable);
+         goto Abort ;
+      }
+      if (sss && _succ == NULL ) _succ = Self ;
+   }
+
+   // Spin failed with prejudice -- reduce _SpinDuration.
+   // TODO: Use an AIMD-like policy to adjust _SpinDuration.
+   // AIMD is globally stable.
+   TEVENT (Spin failure) ;
+   {
+     int x = _SpinDuration ;
+     if (x > 0) {
+        // Consider an AIMD scheme like: x -= (x >> 3) + 100
+        // This is globally sample and tends to damp the response.
+        x -= Knob_Penalty ;
+        if (x < 0) x = 0 ;
+        _SpinDuration = x ;
+     }
+   }
+
+ Abort:
+   if (MaxSpin >= 0) Adjust (&_Spinner, -1) ;
+   if (sss && _succ == Self) {
+      _succ = NULL ;
+      // Invariant: after setting succ=null a contending thread
+      // must recheck-retry _owner before parking.  This usually happens
+      // in the normal usage of TrySpin(), but it's safest
+      // to make TrySpin() as foolproof as possible.
+      OrderAccess::fence() ;
+      if (TryLock(Self) > 0) return 1 ;
+   }
+   return 0 ;
+}
+
+// NotRunnable() -- informed spinning
+//
+// Don't bother spinning if the owner is not eligible to drop the lock.
+// Peek at the owner's schedctl.sc_state and Thread._thread_values and
+// spin only if the owner thread is _thread_in_Java or _thread_in_vm.
+// The thread must be runnable in order to drop the lock in timely fashion.
+// If the _owner is not runnable then spinning will not likely be
+// successful (profitable).
+//
+// Beware -- the thread referenced by _owner could have died
+// so a simply fetch from _owner->_thread_state might trap.
+// Instead, we use SafeFetchXX() to safely LD _owner->_thread_state.
+// Because of the lifecycle issues the schedctl and _thread_state values
+// observed by NotRunnable() might be garbage.  NotRunnable must
+// tolerate this and consider the observed _thread_state value
+// as advisory.
+//
+// Beware too, that _owner is sometimes a BasicLock address and sometimes
+// a thread pointer.  We differentiate the two cases with OwnerIsThread.
+// Alternately, we might tag the type (thread pointer vs basiclock pointer)
+// with the LSB of _owner.  Another option would be to probablistically probe
+// the putative _owner->TypeTag value.
+//
+// Checking _thread_state isn't perfect.  Even if the thread is
+// in_java it might be blocked on a page-fault or have been preempted
+// and sitting on a ready/dispatch queue.  _thread state in conjunction
+// with schedctl.sc_state gives us a good picture of what the
+// thread is doing, however.
+//
+// TODO: check schedctl.sc_state.
+// We'll need to use SafeFetch32() to read from the schedctl block.
+// See RFE #5004247 and http://sac.sfbay.sun.com/Archives/CaseLog/arc/PSARC/2005/351/
+//
+// The return value from NotRunnable() is *advisory* -- the
+// result is based on sampling and is not necessarily coherent.
+// The caller must tolerate false-negative and false-positive errors.
+// Spinning, in general, is probabilistic anyway.
+
+
+int ObjectMonitor::NotRunnable (Thread * Self, Thread * ox) {
+    // Check either OwnerIsThread or ox->TypeTag == 2BAD.
+    if (!OwnerIsThread) return 0 ;
+
+    if (ox == NULL) return 0 ;
+
+    // Avoid transitive spinning ...
+    // Say T1 spins or blocks trying to acquire L.  T1._Stalled is set to L.
+    // Immediately after T1 acquires L it's possible that T2, also
+    // spinning on L, will see L.Owner=T1 and T1._Stalled=L.
+    // This occurs transiently after T1 acquired L but before
+    // T1 managed to clear T1.Stalled.  T2 does not need to abort
+    // its spin in this circumstance.
+    intptr_t BlockedOn = SafeFetchN ((intptr_t *) &ox->_Stalled, intptr_t(1)) ;
+
+    if (BlockedOn == 1) return 1 ;
+    if (BlockedOn != 0) {
+      return BlockedOn != intptr_t(this) && _owner == ox ;
+    }
+
+    assert (sizeof(((JavaThread *)ox)->_thread_state == sizeof(int)), "invariant") ;
+    int jst = SafeFetch32 ((int *) &((JavaThread *) ox)->_thread_state, -1) ; ;
+    // consider also: jst != _thread_in_Java -- but that's overspecific.
+    return jst == _thread_blocked || jst == _thread_in_native ;
+}
+
+
+// -----------------------------------------------------------------------------
+// WaitSet management ...
+
+ObjectWaiter::ObjectWaiter(Thread* thread) {
+  _next     = NULL;
+  _prev     = NULL;
+  _notified = 0;
+  TState    = TS_RUN ;
+  _thread   = thread;
+  _event    = thread->_ParkEvent ;
+  _active   = false;
+  assert (_event != NULL, "invariant") ;
+}
+
+void ObjectWaiter::wait_reenter_begin(ObjectMonitor *mon) {
+  JavaThread *jt = (JavaThread *)this->_thread;
+  _active = JavaThreadBlockedOnMonitorEnterState::wait_reenter_begin(jt, mon);
+}
+
+void ObjectWaiter::wait_reenter_end(ObjectMonitor *mon) {
+  JavaThread *jt = (JavaThread *)this->_thread;
+  JavaThreadBlockedOnMonitorEnterState::wait_reenter_end(jt, _active);
+}
+
+inline void ObjectMonitor::AddWaiter(ObjectWaiter* node) {
+  assert(node != NULL, "should not dequeue NULL node");
+  assert(node->_prev == NULL, "node already in list");
+  assert(node->_next == NULL, "node already in list");
+  // put node at end of queue (circular doubly linked list)
+  if (_WaitSet == NULL) {
+    _WaitSet = node;
+    node->_prev = node;
+    node->_next = node;
+  } else {
+    ObjectWaiter* head = _WaitSet ;
+    ObjectWaiter* tail = head->_prev;
+    assert(tail->_next == head, "invariant check");
+    tail->_next = node;
+    head->_prev = node;
+    node->_next = head;
+    node->_prev = tail;
+  }
+}
+
+inline ObjectWaiter* ObjectMonitor::DequeueWaiter() {
+  // dequeue the very first waiter
+  ObjectWaiter* waiter = _WaitSet;
+  if (waiter) {
+    DequeueSpecificWaiter(waiter);
+  }
+  return waiter;
+}
+
+inline void ObjectMonitor::DequeueSpecificWaiter(ObjectWaiter* node) {
+  assert(node != NULL, "should not dequeue NULL node");
+  assert(node->_prev != NULL, "node already removed from list");
+  assert(node->_next != NULL, "node already removed from list");
+  // when the waiter has woken up because of interrupt,
+  // timeout or other spurious wake-up, dequeue the
+  // waiter from waiting list
+  ObjectWaiter* next = node->_next;
+  if (next == node) {
+    assert(node->_prev == node, "invariant check");
+    _WaitSet = NULL;
+  } else {
+    ObjectWaiter* prev = node->_prev;
+    assert(prev->_next == node, "invariant check");
+    assert(next->_prev == node, "invariant check");
+    next->_prev = prev;
+    prev->_next = next;
+    if (_WaitSet == node) {
+      _WaitSet = next;
+    }
+  }
+  node->_next = NULL;
+  node->_prev = NULL;
+}
+
+// -----------------------------------------------------------------------------
+// PerfData support
+PerfCounter * ObjectMonitor::_sync_ContendedLockAttempts       = NULL ;
+PerfCounter * ObjectMonitor::_sync_FutileWakeups               = NULL ;
+PerfCounter * ObjectMonitor::_sync_Parks                       = NULL ;
+PerfCounter * ObjectMonitor::_sync_EmptyNotifications          = NULL ;
+PerfCounter * ObjectMonitor::_sync_Notifications               = NULL ;
+PerfCounter * ObjectMonitor::_sync_PrivateA                    = NULL ;
+PerfCounter * ObjectMonitor::_sync_PrivateB                    = NULL ;
+PerfCounter * ObjectMonitor::_sync_SlowExit                    = NULL ;
+PerfCounter * ObjectMonitor::_sync_SlowEnter                   = NULL ;
+PerfCounter * ObjectMonitor::_sync_SlowNotify                  = NULL ;
+PerfCounter * ObjectMonitor::_sync_SlowNotifyAll               = NULL ;
+PerfCounter * ObjectMonitor::_sync_FailedSpins                 = NULL ;
+PerfCounter * ObjectMonitor::_sync_SuccessfulSpins             = NULL ;
+PerfCounter * ObjectMonitor::_sync_MonInCirculation            = NULL ;
+PerfCounter * ObjectMonitor::_sync_MonScavenged                = NULL ;
+PerfCounter * ObjectMonitor::_sync_Inflations                  = NULL ;
+PerfCounter * ObjectMonitor::_sync_Deflations                  = NULL ;
+PerfLongVariable * ObjectMonitor::_sync_MonExtant              = NULL ;
+
+// One-shot global initialization for the sync subsystem.
+// We could also defer initialization and initialize on-demand
+// the first time we call inflate().  Initialization would
+// be protected - like so many things - by the MonitorCache_lock.
+
+void ObjectMonitor::Initialize () {
+  static int InitializationCompleted = 0 ;
+  assert (InitializationCompleted == 0, "invariant") ;
+  InitializationCompleted = 1 ;
+  if (UsePerfData) {
+      EXCEPTION_MARK ;
+      #define NEWPERFCOUNTER(n)   {n = PerfDataManager::create_counter(SUN_RT, #n, PerfData::U_Events,CHECK); }
+      #define NEWPERFVARIABLE(n)  {n = PerfDataManager::create_variable(SUN_RT, #n, PerfData::U_Events,CHECK); }
+      NEWPERFCOUNTER(_sync_Inflations) ;
+      NEWPERFCOUNTER(_sync_Deflations) ;
+      NEWPERFCOUNTER(_sync_ContendedLockAttempts) ;
+      NEWPERFCOUNTER(_sync_FutileWakeups) ;
+      NEWPERFCOUNTER(_sync_Parks) ;
+      NEWPERFCOUNTER(_sync_EmptyNotifications) ;
+      NEWPERFCOUNTER(_sync_Notifications) ;
+      NEWPERFCOUNTER(_sync_SlowEnter) ;
+      NEWPERFCOUNTER(_sync_SlowExit) ;
+      NEWPERFCOUNTER(_sync_SlowNotify) ;
+      NEWPERFCOUNTER(_sync_SlowNotifyAll) ;
+      NEWPERFCOUNTER(_sync_FailedSpins) ;
+      NEWPERFCOUNTER(_sync_SuccessfulSpins) ;
+      NEWPERFCOUNTER(_sync_PrivateA) ;
+      NEWPERFCOUNTER(_sync_PrivateB) ;
+      NEWPERFCOUNTER(_sync_MonInCirculation) ;
+      NEWPERFCOUNTER(_sync_MonScavenged) ;
+      NEWPERFVARIABLE(_sync_MonExtant) ;
+      #undef NEWPERFCOUNTER
+  }
+}
+
+
+// Compile-time asserts
+// When possible, it's better to catch errors deterministically at
+// compile-time than at runtime.  The down-side to using compile-time
+// asserts is that error message -- often something about negative array
+// indices -- is opaque.
+
+#define CTASSERT(x) { int tag[1-(2*!(x))]; printf ("Tag @" INTPTR_FORMAT "\n", (intptr_t)tag); }
+
+void ObjectMonitor::ctAsserts() {
+  CTASSERT(offset_of (ObjectMonitor, _header) == 0);
+}
+
+
+static char * kvGet (char * kvList, const char * Key) {
+    if (kvList == NULL) return NULL ;
+    size_t n = strlen (Key) ;
+    char * Search ;
+    for (Search = kvList ; *Search ; Search += strlen(Search) + 1) {
+        if (strncmp (Search, Key, n) == 0) {
+            if (Search[n] == '=') return Search + n + 1 ;
+            if (Search[n] == 0)   return (char *) "1" ;
+        }
+    }
+    return NULL ;
+}
+
+static int kvGetInt (char * kvList, const char * Key, int Default) {
+    char * v = kvGet (kvList, Key) ;
+    int rslt = v ? ::strtol (v, NULL, 0) : Default ;
+    if (Knob_ReportSettings && v != NULL) {
+        ::printf ("  SyncKnob: %s %d(%d)\n", Key, rslt, Default) ;
+        ::fflush (stdout) ;
+    }
+    return rslt ;
+}
+
+void ObjectMonitor::DeferredInitialize () {
+  if (InitDone > 0) return ;
+  if (Atomic::cmpxchg (-1, &InitDone, 0) != 0) {
+      while (InitDone != 1) ;
+      return ;
+  }
+
+  // One-shot global initialization ...
+  // The initialization is idempotent, so we don't need locks.
+  // In the future consider doing this via os::init_2().
+  // SyncKnobs consist of <Key>=<Value> pairs in the style
+  // of environment variables.  Start by converting ':' to NUL.
+
+  if (SyncKnobs == NULL) SyncKnobs = "" ;
+
+  size_t sz = strlen (SyncKnobs) ;
+  char * knobs = (char *) malloc (sz + 2) ;
+  if (knobs == NULL) {
+     vm_exit_out_of_memory (sz + 2, "Parse SyncKnobs") ;
+     guarantee (0, "invariant") ;
+  }
+  strcpy (knobs, SyncKnobs) ;
+  knobs[sz+1] = 0 ;
+  for (char * p = knobs ; *p ; p++) {
+     if (*p == ':') *p = 0 ;
+  }
+
+  #define SETKNOB(x) { Knob_##x = kvGetInt (knobs, #x, Knob_##x); }
+  SETKNOB(ReportSettings) ;
+  SETKNOB(Verbose) ;
+  SETKNOB(FixedSpin) ;
+  SETKNOB(SpinLimit) ;
+  SETKNOB(SpinBase) ;
+  SETKNOB(SpinBackOff);
+  SETKNOB(CASPenalty) ;
+  SETKNOB(OXPenalty) ;
+  SETKNOB(LogSpins) ;
+  SETKNOB(SpinSetSucc) ;
+  SETKNOB(SuccEnabled) ;
+  SETKNOB(SuccRestrict) ;
+  SETKNOB(Penalty) ;
+  SETKNOB(Bonus) ;
+  SETKNOB(BonusB) ;
+  SETKNOB(Poverty) ;
+  SETKNOB(SpinAfterFutile) ;
+  SETKNOB(UsePause) ;
+  SETKNOB(SpinEarly) ;
+  SETKNOB(OState) ;
+  SETKNOB(MaxSpinners) ;
+  SETKNOB(PreSpin) ;
+  SETKNOB(ExitPolicy) ;
+  SETKNOB(QMode);
+  SETKNOB(ResetEvent) ;
+  SETKNOB(MoveNotifyee) ;
+  SETKNOB(FastHSSEC) ;
+  #undef SETKNOB
+
+  if (os::is_MP()) {
+     BackOffMask = (1 << Knob_SpinBackOff) - 1 ;
+     if (Knob_ReportSettings) ::printf ("BackOffMask=%X\n", BackOffMask) ;
+     // CONSIDER: BackOffMask = ROUNDUP_NEXT_POWER2 (ncpus-1)
+  } else {
+     Knob_SpinLimit = 0 ;
+     Knob_SpinBase  = 0 ;
+     Knob_PreSpin   = 0 ;
+     Knob_FixedSpin = -1 ;
+  }
+
+  if (Knob_LogSpins == 0) {
+     ObjectMonitor::_sync_FailedSpins = NULL ;
+  }
+
+  free (knobs) ;
+  OrderAccess::fence() ;
+  InitDone = 1 ;
+}
+
+#ifndef PRODUCT
+void ObjectMonitor::verify() {
+}
+
+void ObjectMonitor::print() {
+}
+#endif
--- a/hotspot/src/share/vm/runtime/objectMonitor.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/runtime/objectMonitor.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -22,6 +22,32 @@
  *
  */
 
+
+// ObjectWaiter serves as a "proxy" or surrogate thread.
+// TODO-FIXME: Eliminate ObjectWaiter and use the thread-specific
+// ParkEvent instead.  Beware, however, that the JVMTI code
+// knows about ObjectWaiters, so we'll have to reconcile that code.
+// See next_waiter(), first_waiter(), etc.
+
+class ObjectWaiter : public StackObj {
+ public:
+  enum TStates { TS_UNDEF, TS_READY, TS_RUN, TS_WAIT, TS_ENTER, TS_CXQ } ;
+  enum Sorted  { PREPEND, APPEND, SORTED } ;
+  ObjectWaiter * volatile _next;
+  ObjectWaiter * volatile _prev;
+  Thread*       _thread;
+  ParkEvent *   _event;
+  volatile int  _notified ;
+  volatile TStates TState ;
+  Sorted        _Sorted ;           // List placement disposition
+  bool          _active ;           // Contention monitoring is enabled
+ public:
+  ObjectWaiter(Thread* thread);
+
+  void wait_reenter_begin(ObjectMonitor *mon);
+  void wait_reenter_end(ObjectMonitor *mon);
+};
+
 // WARNING:
 //   This is a very sensitive and fragile class. DO NOT make any
 // change unless you are fully aware of the underlying semantics.
@@ -38,8 +64,6 @@
 // It is also used as RawMonitor by the JVMTI
 
 
-class ObjectWaiter;
-
 class ObjectMonitor {
  public:
   enum {
@@ -74,13 +98,16 @@
 
 
  public:
-  ObjectMonitor();
-  ~ObjectMonitor();
-
   markOop   header() const;
   void      set_header(markOop hdr);
 
-  intptr_t  is_busy() const;
+  intptr_t is_busy() const {
+    // TODO-FIXME: merge _count and _waiters.
+    // TODO-FIXME: assert _owner == null implies _recursions = 0
+    // TODO-FIXME: assert _WaitSet != null implies _count > 0
+    return _count|_waiters|intptr_t(_owner)|intptr_t(_cxq)|intptr_t(_EntryList ) ;
+  }
+
   intptr_t  is_entered(Thread* current) const;
 
   void*     owner() const;
@@ -91,13 +118,58 @@
   intptr_t  count() const;
   void      set_count(intptr_t count);
   intptr_t  contentions() const ;
+  intptr_t  recursions() const                                         { return _recursions; }
 
   // JVM/DI GetMonitorInfo() needs this
-  Thread *  thread_of_waiter (ObjectWaiter *) ;
-  ObjectWaiter * first_waiter () ;
-  ObjectWaiter * next_waiter(ObjectWaiter* o);
+  ObjectWaiter* first_waiter()                                         { return _WaitSet; }
+  ObjectWaiter* next_waiter(ObjectWaiter* o)                           { return o->_next; }
+  Thread* thread_of_waiter(ObjectWaiter* o)                            { return o->_thread; }
+
+  // initialize the monitor, exception the semaphore, all other fields
+  // are simple integers or pointers
+  ObjectMonitor() {
+    _header       = NULL;
+    _count        = 0;
+    _waiters      = 0,
+    _recursions   = 0;
+    _object       = NULL;
+    _owner        = NULL;
+    _WaitSet      = NULL;
+    _WaitSetLock  = 0 ;
+    _Responsible  = NULL ;
+    _succ         = NULL ;
+    _cxq          = NULL ;
+    FreeNext      = NULL ;
+    _EntryList    = NULL ;
+    _SpinFreq     = 0 ;
+    _SpinClock    = 0 ;
+    OwnerIsThread = 0 ;
+  }
 
-  intptr_t  recursions() const { return _recursions; }
+  ~ObjectMonitor() {
+   // TODO: Add asserts ...
+   // _cxq == 0 _succ == NULL _owner == NULL _waiters == 0
+   // _count == 0 _EntryList  == NULL etc
+  }
+
+private:
+  void Recycle () {
+    // TODO: add stronger asserts ...
+    // _cxq == 0 _succ == NULL _owner == NULL _waiters == 0
+    // _count == 0 EntryList  == NULL
+    // _recursions == 0 _WaitSet == NULL
+    // TODO: assert (is_busy()|_recursions) == 0
+    _succ          = NULL ;
+    _EntryList     = NULL ;
+    _cxq           = NULL ;
+    _WaitSet       = NULL ;
+    _recursions    = 0 ;
+    _SpinFreq      = 0 ;
+    _SpinClock     = 0 ;
+    OwnerIsThread  = 0 ;
+  }
+
+public:
 
   void*     object() const;
   void*     object_addr();
@@ -122,22 +194,9 @@
   intptr_t  complete_exit(TRAPS);
   void      reenter(intptr_t recursions, TRAPS);
 
-  int       raw_enter(TRAPS);
-  int       raw_exit(TRAPS);
-  int       raw_wait(jlong millis, bool interruptable, TRAPS);
-  int       raw_notify(TRAPS);
-  int       raw_notifyAll(TRAPS);
-
  private:
-  // JVMTI support -- remove ASAP
-  int       SimpleEnter (Thread * Self) ;
-  int       SimpleExit  (Thread * Self) ;
-  int       SimpleWait  (Thread * Self, jlong millis) ;
-  int       SimpleNotify (Thread * Self, bool All) ;
-
- private:
-  void      Recycle () ;
   void      AddWaiter (ObjectWaiter * waiter) ;
+  static    void DeferredInitialize();
 
   ObjectWaiter * DequeueWaiter () ;
   void      DequeueSpecificWaiter (ObjectWaiter * waiter) ;
@@ -172,13 +231,17 @@
   // The VM assumes write ordering wrt these fields, which can be
   // read from other threads.
 
+ protected:                         // protected for jvmtiRawMonitor
   void *  volatile _owner;          // pointer to owning thread OR BasicLock
   volatile intptr_t  _recursions;   // recursion count, 0 for first entry
+ private:
   int OwnerIsThread ;               // _owner is (Thread *) vs SP/BasicLock
   ObjectWaiter * volatile _cxq ;    // LL of recently-arrived threads blocked on entry.
                                     // The list is actually composed of WaitNodes, acting
                                     // as proxies for Threads.
+ protected:
   ObjectWaiter * volatile _EntryList ;     // Threads blocked on entry or reentry.
+ private:
   Thread * volatile _succ ;          // Heir presumptive thread - used for futile wakeup throttling
   Thread * volatile _Responsible ;
   int _PromptDrain ;                // rqst to drain cxq into EntryList ASAP
@@ -196,8 +259,12 @@
   volatile intptr_t  _count;        // reference count to prevent reclaimation/deflation
                                     // at stop-the-world time.  See deflate_idle_monitors().
                                     // _count is approximately |_WaitSet| + |_EntryList|
+ protected:
   volatile intptr_t  _waiters;      // number of waiting threads
+ private:
+ protected:
   ObjectWaiter * volatile _WaitSet; // LL of threads wait()ing on the monitor
+ private:
   volatile int _WaitSetLock;        // protects Wait Queue - simple spinlock
 
  public:
@@ -205,4 +272,37 @@
   ObjectMonitor * FreeNext ;        // Free list linkage
   intptr_t StatA, StatsB ;
 
+ public:
+  static void Initialize () ;
+  static PerfCounter * _sync_ContendedLockAttempts ;
+  static PerfCounter * _sync_FutileWakeups ;
+  static PerfCounter * _sync_Parks ;
+  static PerfCounter * _sync_EmptyNotifications ;
+  static PerfCounter * _sync_Notifications ;
+  static PerfCounter * _sync_SlowEnter ;
+  static PerfCounter * _sync_SlowExit ;
+  static PerfCounter * _sync_SlowNotify ;
+  static PerfCounter * _sync_SlowNotifyAll ;
+  static PerfCounter * _sync_FailedSpins ;
+  static PerfCounter * _sync_SuccessfulSpins ;
+  static PerfCounter * _sync_PrivateA ;
+  static PerfCounter * _sync_PrivateB ;
+  static PerfCounter * _sync_MonInCirculation ;
+  static PerfCounter * _sync_MonScavenged ;
+  static PerfCounter * _sync_Inflations ;
+  static PerfCounter * _sync_Deflations ;
+  static PerfLongVariable * _sync_MonExtant ;
+
+ public:
+  static int Knob_Verbose;
+  static int Knob_SpinLimit;
 };
+
+#undef TEVENT
+#define TEVENT(nom) {if (SyncVerbose) FEVENT(nom); }
+
+#define FEVENT(nom) { static volatile int ctr = 0 ; int v = ++ctr ; if ((v & (v-1)) == 0) { ::printf (#nom " : %d \n", v); ::fflush(stdout); }}
+
+#undef  TEVENT
+#define TEVENT(nom) {;}
+
--- a/hotspot/src/share/vm/runtime/objectMonitor.inline.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/runtime/objectMonitor.inline.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -104,7 +104,3 @@
   _count = 0;
 }
 
-
-// here are the platform-dependent bodies:
-
-# include "incls/_objectMonitor_pd.inline.hpp.incl"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/runtime/park.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 1997, 2010, 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.
+ *
+ */
+
+
+# include "incls/_precompiled.incl"
+# include "incls/_park.cpp.incl"
+
+
+// Lifecycle management for TSM ParkEvents.
+// ParkEvents are type-stable (TSM).
+// In our particular implementation they happen to be immortal.
+//
+// We manage concurrency on the FreeList with a CAS-based
+// detach-modify-reattach idiom that avoids the ABA problems
+// that would otherwise be present in a simple CAS-based
+// push-pop implementation.   (push-one and pop-all)
+//
+// Caveat: Allocate() and Release() may be called from threads
+// other than the thread associated with the Event!
+// If we need to call Allocate() when running as the thread in
+// question then look for the PD calls to initialize native TLS.
+// Native TLS (Win32/Linux/Solaris) can only be initialized or
+// accessed by the associated thread.
+// See also pd_initialize().
+//
+// Note that we could defer associating a ParkEvent with a thread
+// until the 1st time the thread calls park().  unpark() calls to
+// an unprovisioned thread would be ignored.  The first park() call
+// for a thread would allocate and associate a ParkEvent and return
+// immediately.
+
+volatile int ParkEvent::ListLock = 0 ;
+ParkEvent * volatile ParkEvent::FreeList = NULL ;
+
+ParkEvent * ParkEvent::Allocate (Thread * t) {
+  // In rare cases -- JVM_RawMonitor* operations -- we can find t == null.
+  ParkEvent * ev ;
+
+  // Start by trying to recycle an existing but unassociated
+  // ParkEvent from the global free list.
+  for (;;) {
+    ev = FreeList ;
+    if (ev == NULL) break ;
+    // 1: Detach - sequester or privatize the list
+    // Tantamount to ev = Swap (&FreeList, NULL)
+    if (Atomic::cmpxchg_ptr (NULL, &FreeList, ev) != ev) {
+       continue ;
+    }
+
+    // We've detached the list.  The list in-hand is now
+    // local to this thread.   This thread can operate on the
+    // list without risk of interference from other threads.
+    // 2: Extract -- pop the 1st element from the list.
+    ParkEvent * List = ev->FreeNext ;
+    if (List == NULL) break ;
+    for (;;) {
+        // 3: Try to reattach the residual list
+        guarantee (List != NULL, "invariant") ;
+        ParkEvent * Arv =  (ParkEvent *) Atomic::cmpxchg_ptr (List, &FreeList, NULL) ;
+        if (Arv == NULL) break ;
+
+        // New nodes arrived.  Try to detach the recent arrivals.
+        if (Atomic::cmpxchg_ptr (NULL, &FreeList, Arv) != Arv) {
+            continue ;
+        }
+        guarantee (Arv != NULL, "invariant") ;
+        // 4: Merge Arv into List
+        ParkEvent * Tail = List ;
+        while (Tail->FreeNext != NULL) Tail = Tail->FreeNext ;
+        Tail->FreeNext = Arv ;
+    }
+    break ;
+  }
+
+  if (ev != NULL) {
+    guarantee (ev->AssociatedWith == NULL, "invariant") ;
+  } else {
+    // Do this the hard way -- materialize a new ParkEvent.
+    // In rare cases an allocating thread might detach a long list --
+    // installing null into FreeList -- and then stall or be obstructed.
+    // A 2nd thread calling Allocate() would see FreeList == null.
+    // The list held privately by the 1st thread is unavailable to the 2nd thread.
+    // In that case the 2nd thread would have to materialize a new ParkEvent,
+    // even though free ParkEvents existed in the system.  In this case we end up
+    // with more ParkEvents in circulation than we need, but the race is
+    // rare and the outcome is benign.  Ideally, the # of extant ParkEvents
+    // is equal to the maximum # of threads that existed at any one time.
+    // Because of the race mentioned above, segments of the freelist
+    // can be transiently inaccessible.  At worst we may end up with the
+    // # of ParkEvents in circulation slightly above the ideal.
+    // Note that if we didn't have the TSM/immortal constraint, then
+    // when reattaching, above, we could trim the list.
+    ev = new ParkEvent () ;
+    guarantee ((intptr_t(ev) & 0xFF) == 0, "invariant") ;
+  }
+  ev->reset() ;                     // courtesy to caller
+  ev->AssociatedWith = t ;          // Associate ev with t
+  ev->FreeNext       = NULL ;
+  return ev ;
+}
+
+void ParkEvent::Release (ParkEvent * ev) {
+  if (ev == NULL) return ;
+  guarantee (ev->FreeNext == NULL      , "invariant") ;
+  ev->AssociatedWith = NULL ;
+  for (;;) {
+    // Push ev onto FreeList
+    // The mechanism is "half" lock-free.
+    ParkEvent * List = FreeList ;
+    ev->FreeNext = List ;
+    if (Atomic::cmpxchg_ptr (ev, &FreeList, List) == List) break ;
+  }
+}
+
+// Override operator new and delete so we can ensure that the
+// least significant byte of ParkEvent addresses is 0.
+// Beware that excessive address alignment is undesirable
+// as it can result in D$ index usage imbalance as
+// well as bank access imbalance on Niagara-like platforms,
+// although Niagara's hash function should help.
+
+void * ParkEvent::operator new (size_t sz) {
+  return (void *) ((intptr_t (CHeapObj::operator new (sz + 256)) + 256) & -256) ;
+}
+
+void ParkEvent::operator delete (void * a) {
+  // ParkEvents are type-stable and immortal ...
+  ShouldNotReachHere();
+}
+
+
+// 6399321 As a temporary measure we copied & modified the ParkEvent::
+// allocate() and release() code for use by Parkers.  The Parker:: forms
+// will eventually be removed as we consolide and shift over to ParkEvents
+// for both builtin synchronization and JSR166 operations.
+
+volatile int Parker::ListLock = 0 ;
+Parker * volatile Parker::FreeList = NULL ;
+
+Parker * Parker::Allocate (JavaThread * t) {
+  guarantee (t != NULL, "invariant") ;
+  Parker * p ;
+
+  // Start by trying to recycle an existing but unassociated
+  // Parker from the global free list.
+  for (;;) {
+    p = FreeList ;
+    if (p  == NULL) break ;
+    // 1: Detach
+    // Tantamount to p = Swap (&FreeList, NULL)
+    if (Atomic::cmpxchg_ptr (NULL, &FreeList, p) != p) {
+       continue ;
+    }
+
+    // We've detached the list.  The list in-hand is now
+    // local to this thread.   This thread can operate on the
+    // list without risk of interference from other threads.
+    // 2: Extract -- pop the 1st element from the list.
+    Parker * List = p->FreeNext ;
+    if (List == NULL) break ;
+    for (;;) {
+        // 3: Try to reattach the residual list
+        guarantee (List != NULL, "invariant") ;
+        Parker * Arv =  (Parker *) Atomic::cmpxchg_ptr (List, &FreeList, NULL) ;
+        if (Arv == NULL) break ;
+
+        // New nodes arrived.  Try to detach the recent arrivals.
+        if (Atomic::cmpxchg_ptr (NULL, &FreeList, Arv) != Arv) {
+            continue ;
+        }
+        guarantee (Arv != NULL, "invariant") ;
+        // 4: Merge Arv into List
+        Parker * Tail = List ;
+        while (Tail->FreeNext != NULL) Tail = Tail->FreeNext ;
+        Tail->FreeNext = Arv ;
+    }
+    break ;
+  }
+
+  if (p != NULL) {
+    guarantee (p->AssociatedWith == NULL, "invariant") ;
+  } else {
+    // Do this the hard way -- materialize a new Parker..
+    // In rare cases an allocating thread might detach
+    // a long list -- installing null into FreeList --and
+    // then stall.  Another thread calling Allocate() would see
+    // FreeList == null and then invoke the ctor.  In this case we
+    // end up with more Parkers in circulation than we need, but
+    // the race is rare and the outcome is benign.
+    // Ideally, the # of extant Parkers is equal to the
+    // maximum # of threads that existed at any one time.
+    // Because of the race mentioned above, segments of the
+    // freelist can be transiently inaccessible.  At worst
+    // we may end up with the # of Parkers in circulation
+    // slightly above the ideal.
+    p = new Parker() ;
+  }
+  p->AssociatedWith = t ;          // Associate p with t
+  p->FreeNext       = NULL ;
+  return p ;
+}
+
+
+void Parker::Release (Parker * p) {
+  if (p == NULL) return ;
+  guarantee (p->AssociatedWith != NULL, "invariant") ;
+  guarantee (p->FreeNext == NULL      , "invariant") ;
+  p->AssociatedWith = NULL ;
+  for (;;) {
+    // Push p onto FreeList
+    Parker * List = FreeList ;
+    p->FreeNext = List ;
+    if (Atomic::cmpxchg_ptr (p, &FreeList, List) == List) break ;
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/runtime/park.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 1997, 2010, 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.
+ *
+ */
+/*
+ * Per-thread blocking support for JSR166. See the Java-level
+ * Documentation for rationale. Basically, park acts like wait, unpark
+ * like notify.
+ *
+ * 6271289 --
+ * To avoid errors where an os thread expires but the JavaThread still
+ * exists, Parkers are immortal (type-stable) and are recycled across
+ * new threads.  This parallels the ParkEvent implementation.
+ * Because park-unpark allow spurious wakeups it is harmless if an
+ * unpark call unparks a new thread using the old Parker reference.
+ *
+ * In the future we'll want to think about eliminating Parker and using
+ * ParkEvent instead.  There's considerable duplication between the two
+ * services.
+ *
+ */
+
+class Parker : public os::PlatformParker {
+private:
+  volatile int _counter ;
+  Parker * FreeNext ;
+  JavaThread * AssociatedWith ; // Current association
+
+public:
+  Parker() : PlatformParker() {
+    _counter       = 0 ;
+    FreeNext       = NULL ;
+    AssociatedWith = NULL ;
+  }
+protected:
+  ~Parker() { ShouldNotReachHere(); }
+public:
+  // For simplicity of interface with Java, all forms of park (indefinite,
+  // relative, and absolute) are multiplexed into one call.
+  void park(bool isAbsolute, jlong time);
+  void unpark();
+
+  // Lifecycle operators
+  static Parker * Allocate (JavaThread * t) ;
+  static void Release (Parker * e) ;
+private:
+  static Parker * volatile FreeList ;
+  static volatile int ListLock ;
+
+};
+
+/////////////////////////////////////////////////////////////
+//
+// ParkEvents are type-stable and immortal.
+//
+// Lifecycle: Once a ParkEvent is associated with a thread that ParkEvent remains
+// associated with the thread for the thread's entire lifetime - the relationship is
+// stable. A thread will be associated at most one ParkEvent.  When the thread
+// expires, the ParkEvent moves to the EventFreeList.  New threads attempt to allocate from
+// the EventFreeList before creating a new Event.  Type-stability frees us from
+// worrying about stale Event or Thread references in the objectMonitor subsystem.
+// (A reference to ParkEvent is always valid, even though the event may no longer be associated
+// with the desired or expected thread.  A key aspect of this design is that the callers of
+// park, unpark, etc must tolerate stale references and spurious wakeups).
+//
+// Only the "associated" thread can block (park) on the ParkEvent, although
+// any other thread can unpark a reachable parkevent.  Park() is allowed to
+// return spuriously.  In fact park-unpark a really just an optimization to
+// avoid unbounded spinning and surrender the CPU to be a polite system citizen.
+// A degenerate albeit "impolite" park-unpark implementation could simply return.
+// See http://blogs.sun.com/dave for more details.
+//
+// Eventually I'd like to eliminate Events and ObjectWaiters, both of which serve as
+// thread proxies, and simply make the THREAD structure type-stable and persistent.
+// Currently, we unpark events associated with threads, but ideally we'd just
+// unpark threads.
+//
+// The base-class, PlatformEvent, is platform-specific while the ParkEvent is
+// platform-independent.  PlatformEvent provides park(), unpark(), etc., and
+// is abstract -- that is, a PlatformEvent should never be instantiated except
+// as part of a ParkEvent.
+// Equivalently we could have defined a platform-independent base-class that
+// exported Allocate(), Release(), etc.  The platform-specific class would extend
+// that base-class, adding park(), unpark(), etc.
+//
+// A word of caution: The JVM uses 2 very similar constructs:
+// 1. ParkEvent are used for Java-level "monitor" synchronization.
+// 2. Parkers are used by JSR166-JUC park-unpark.
+//
+// We'll want to eventually merge these redundant facilities and use ParkEvent.
+
+
+class ParkEvent : public os::PlatformEvent {
+  private:
+    ParkEvent * FreeNext ;
+
+    // Current association
+    Thread * AssociatedWith ;
+    intptr_t RawThreadIdentity ;        // LWPID etc
+    volatile int Incarnation ;
+
+    // diagnostic : keep track of last thread to wake this thread.
+    // this is useful for construction of dependency graphs.
+    void * LastWaker ;
+
+  public:
+    // MCS-CLH list linkage and Native Mutex/Monitor
+    ParkEvent * volatile ListNext ;
+    ParkEvent * volatile ListPrev ;
+    volatile intptr_t OnList ;
+    volatile int TState ;
+    volatile int Notified ;             // for native monitor construct
+    volatile int IsWaiting ;            // Enqueued on WaitSet
+
+
+  private:
+    static ParkEvent * volatile FreeList ;
+    static volatile int ListLock ;
+
+    // It's prudent to mark the dtor as "private"
+    // ensuring that it's not visible outside the package.
+    // Unfortunately gcc warns about such usage, so
+    // we revert to the less desirable "protected" visibility.
+    // The other compilers accept private dtors.
+
+  protected:        // Ensure dtor is never invoked
+    ~ParkEvent() { guarantee (0, "invariant") ; }
+
+    ParkEvent() : PlatformEvent() {
+       AssociatedWith = NULL ;
+       FreeNext       = NULL ;
+       ListNext       = NULL ;
+       ListPrev       = NULL ;
+       OnList         = 0 ;
+       TState         = 0 ;
+       Notified       = 0 ;
+       IsWaiting      = 0 ;
+    }
+
+    // We use placement-new to force ParkEvent instances to be
+    // aligned on 256-byte address boundaries.  This ensures that the least
+    // significant byte of a ParkEvent address is always 0.
+
+    void * operator new (size_t sz) ;
+    void operator delete (void * a) ;
+
+  public:
+    static ParkEvent * Allocate (Thread * t) ;
+    static void Release (ParkEvent * e) ;
+} ;
--- a/hotspot/src/share/vm/runtime/relocator.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/runtime/relocator.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -435,6 +435,120 @@
   }
 }
 
+// Create a new array, copying the src array but adding a hole at
+// the specified location
+static typeArrayOop insert_hole_at(
+    size_t where, int hole_sz, typeArrayOop src) {
+  Thread* THREAD = Thread::current();
+  Handle src_hnd(THREAD, src);
+  typeArrayOop dst =
+      oopFactory::new_permanent_byteArray(src->length() + hole_sz, CHECK_NULL);
+  src = (typeArrayOop)src_hnd();
+
+  address src_addr = (address)src->byte_at_addr(0);
+  address dst_addr = (address)dst->byte_at_addr(0);
+
+  memcpy(dst_addr, src_addr, where);
+  memcpy(dst_addr + where + hole_sz,
+         src_addr + where, src->length() - where);
+  return dst;
+}
+
+// The width of instruction at "bci" is changing by "delta".  Adjust the stack
+// map frames.
+void Relocator::adjust_stack_map_table(int bci, int delta) {
+  if (method()->has_stackmap_table()) {
+    typeArrayOop data = method()->stackmap_data();
+    // The data in the array is a classfile representation of the stackmap
+    // table attribute, less the initial u2 tag and u4 attribute_length fields.
+    stack_map_table_attribute* attr = stack_map_table_attribute::at(
+        (address)data->byte_at_addr(0) - (sizeof(u2) + sizeof(u4)));
+
+    int count = attr->number_of_entries();
+    stack_map_frame* frame = attr->entries();
+    int bci_iter = -1;
+    bool offset_adjusted = false; // only need to adjust one offset
+
+    for (int i = 0; i < count; ++i) {
+      int offset_delta = frame->offset_delta();
+      bci_iter += offset_delta;
+
+      if (!offset_adjusted && bci_iter > bci) {
+        int new_offset_delta = offset_delta + delta;
+
+        if (frame->is_valid_offset(new_offset_delta)) {
+          frame->set_offset_delta(new_offset_delta);
+        } else {
+          assert(frame->is_same_frame() ||
+                 frame->is_same_frame_1_stack_item_frame(),
+                 "Frame must be one of the compressed forms");
+          // The new delta exceeds the capacity of the 'same_frame' or
+          // 'same_frame_1_stack_item_frame' frame types.  We need to
+          // convert these frames to the extended versions, but the extended
+          // version is bigger and requires more room.  So we allocate a
+          // new array and copy the data, being sure to leave u2-sized hole
+          // right after the 'frame_type' for the new offset field.
+          //
+          // We can safely ignore the reverse situation as a small delta
+          // can still be used in an extended version of the frame.
+
+          size_t frame_offset = (address)frame - (address)data->byte_at_addr(0);
+
+          data = insert_hole_at(frame_offset + 1, 2, data);
+          if (data == NULL) {
+            return; // out-of-memory?
+          }
+
+          address frame_addr = (address)(data->byte_at_addr(0) + frame_offset);
+          frame = stack_map_frame::at(frame_addr);
+
+
+          // Now convert the frames in place
+          if (frame->is_same_frame()) {
+            same_frame_extended::create_at(frame_addr, new_offset_delta);
+          } else {
+            same_frame_1_stack_item_extended::create_at(
+              frame_addr, new_offset_delta, NULL);
+            // the verification_info_type should already be at the right spot
+          }
+        }
+        offset_adjusted = true; // needs to be done only once, since subsequent
+                                // values are offsets from the current
+      }
+
+      // The stack map frame may contain verification types, if so we need to
+      // check and update any Uninitialized type's bci (no matter where it is).
+      int number_of_types = frame->number_of_types();
+      verification_type_info* types = frame->types();
+
+      for (int i = 0; i < number_of_types; ++i) {
+        if (types->is_uninitialized() && types->bci() > bci) {
+          types->set_bci(types->bci() + delta);
+        }
+        types = types->next();
+      }
+
+      // Full frame has stack values too
+      full_frame* ff = frame->as_full_frame();
+      if (ff != NULL) {
+        address eol = (address)types;
+        number_of_types = ff->stack_slots(eol);
+        types = ff->stack(eol);
+        for (int i = 0; i < number_of_types; ++i) {
+          if (types->is_uninitialized() && types->bci() > bci) {
+            types->set_bci(types->bci() + delta);
+          }
+          types = types->next();
+        }
+      }
+
+      frame = frame->next();
+    }
+
+    method()->set_stackmap_data(data); // in case it has changed
+  }
+}
+
 
 bool Relocator::expand_code_array(int delta) {
   int length = MAX2(code_length() + delta, code_length() * (100+code_slop_pct()) / 100);
@@ -499,6 +613,9 @@
   // And local variable table...
   adjust_local_var_table(bci, delta);
 
+  // Adjust stack maps
+  adjust_stack_map_table(bci, delta);
+
   // Relocate the pending change stack...
   for (int j = 0; j < _changes->length(); j++) {
     ChangeItem* ci = _changes->at(j);
@@ -641,6 +758,7 @@
       memmove(addr_at(bci +1 + new_pad),
               addr_at(bci +1 + old_pad),
               len * 4);
+      memset(addr_at(bci + 1), 0, new_pad); // pad must be 0
     }
   }
   return true;
--- a/hotspot/src/share/vm/runtime/relocator.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/runtime/relocator.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -105,6 +105,7 @@
   void adjust_exception_table(int bci, int delta);
   void adjust_line_no_table  (int bci, int delta);
   void adjust_local_var_table(int bci, int delta);
+  void adjust_stack_map_table(int bci, int delta);
   int  get_orig_switch_pad   (int bci, bool is_lookup_switch);
   int  rc_instr_len          (int bci);
   bool expand_code_array     (int delta);
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -302,6 +302,9 @@
   return (f <= (double)0.0) ? (double)0.0 - f : f;
 }
 
+#endif
+
+#if defined(__SOFTFP__) || defined(PPC)
 double SharedRuntime::dsqrt(double f) {
   return sqrt(f);
 }
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -116,6 +116,9 @@
 
 #if defined(__SOFTFP__) || defined(E500V2)
   static double dabs(double f);
+#endif
+
+#if defined(__SOFTFP__) || defined(PPC)
   static double dsqrt(double f);
 #endif
 
--- a/hotspot/src/share/vm/runtime/synchronizer.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -32,15 +32,12 @@
   #define ATTR
 #endif
 
-// Native markword accessors for synchronization and hashCode().
-//
 // The "core" versions of monitor enter and exit reside in this file.
 // The interpreter and compilers contain specialized transliterated
 // variants of the enter-exit fast-path operations.  See i486.ad fast_lock(),
 // for instance.  If you make changes here, make sure to modify the
 // interpreter, and both C1 and C2 fast-path inline locking code emission.
 //
-// TODO: merge the objectMonitor and synchronizer classes.
 //
 // -----------------------------------------------------------------------------
 
@@ -53,16 +50,6 @@
   jlong, uintptr_t, char*, int, long);
 HS_DTRACE_PROBE_DECL4(hotspot, monitor__waited,
   jlong, uintptr_t, char*, int);
-HS_DTRACE_PROBE_DECL4(hotspot, monitor__notify,
-  jlong, uintptr_t, char*, int);
-HS_DTRACE_PROBE_DECL4(hotspot, monitor__notifyAll,
-  jlong, uintptr_t, char*, int);
-HS_DTRACE_PROBE_DECL4(hotspot, monitor__contended__enter,
-  jlong, uintptr_t, char*, int);
-HS_DTRACE_PROBE_DECL4(hotspot, monitor__contended__entered,
-  jlong, uintptr_t, char*, int);
-HS_DTRACE_PROBE_DECL4(hotspot, monitor__contended__exit,
-  jlong, uintptr_t, char*, int);
 
 #define DTRACE_MONITOR_PROBE_COMMON(klassOop, thread)                      \
   char* bytes = NULL;                                                      \
@@ -99,61 +86,300 @@
 
 #endif // ndef DTRACE_ENABLED
 
-// ObjectWaiter serves as a "proxy" or surrogate thread.
-// TODO-FIXME: Eliminate ObjectWaiter and use the thread-specific
-// ParkEvent instead.  Beware, however, that the JVMTI code
-// knows about ObjectWaiters, so we'll have to reconcile that code.
-// See next_waiter(), first_waiter(), etc.
+// This exists only as a workaround of dtrace bug 6254741
+int dtrace_waited_probe(ObjectMonitor* monitor, Handle obj, Thread* thr) {
+  DTRACE_MONITOR_PROBE(waited, monitor, obj(), thr);
+  return 0;
+}
+
+#define NINFLATIONLOCKS 256
+static volatile intptr_t InflationLocks [NINFLATIONLOCKS] ;
+
+ObjectMonitor * ObjectSynchronizer::gBlockList = NULL ;
+ObjectMonitor * volatile ObjectSynchronizer::gFreeList  = NULL ;
+ObjectMonitor * volatile ObjectSynchronizer::gOmInUseList  = NULL ;
+int ObjectSynchronizer::gOmInUseCount = 0;
+static volatile intptr_t ListLock = 0 ;      // protects global monitor free-list cache
+static volatile int MonitorFreeCount  = 0 ;      // # on gFreeList
+static volatile int MonitorPopulation = 0 ;      // # Extant -- in circulation
+#define CHAINMARKER ((oop)-1)
+
+// -----------------------------------------------------------------------------
+//  Fast Monitor Enter/Exit
+// This the fast monitor enter. The interpreter and compiler use
+// some assembly copies of this code. Make sure update those code
+// if the following function is changed. The implementation is
+// extremely sensitive to race condition. Be careful.
+
+void ObjectSynchronizer::fast_enter(Handle obj, BasicLock* lock, bool attempt_rebias, TRAPS) {
+ if (UseBiasedLocking) {
+    if (!SafepointSynchronize::is_at_safepoint()) {
+      BiasedLocking::Condition cond = BiasedLocking::revoke_and_rebias(obj, attempt_rebias, THREAD);
+      if (cond == BiasedLocking::BIAS_REVOKED_AND_REBIASED) {
+        return;
+      }
+    } else {
+      assert(!attempt_rebias, "can not rebias toward VM thread");
+      BiasedLocking::revoke_at_safepoint(obj);
+    }
+    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
+ }
+
+ slow_enter (obj, lock, THREAD) ;
+}
+
+void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) {
+  assert(!object->mark()->has_bias_pattern(), "should not see bias pattern here");
+  // if displaced header is null, the previous enter is recursive enter, no-op
+  markOop dhw = lock->displaced_header();
+  markOop mark ;
+  if (dhw == NULL) {
+     // Recursive stack-lock.
+     // Diagnostics -- Could be: stack-locked, inflating, inflated.
+     mark = object->mark() ;
+     assert (!mark->is_neutral(), "invariant") ;
+     if (mark->has_locker() && mark != markOopDesc::INFLATING()) {
+        assert(THREAD->is_lock_owned((address)mark->locker()), "invariant") ;
+     }
+     if (mark->has_monitor()) {
+        ObjectMonitor * m = mark->monitor() ;
+        assert(((oop)(m->object()))->mark() == mark, "invariant") ;
+        assert(m->is_entered(THREAD), "invariant") ;
+     }
+     return ;
+  }
+
+  mark = object->mark() ;
 
-class ObjectWaiter : public StackObj {
- public:
-  enum TStates { TS_UNDEF, TS_READY, TS_RUN, TS_WAIT, TS_ENTER, TS_CXQ } ;
-  enum Sorted  { PREPEND, APPEND, SORTED } ;
-  ObjectWaiter * volatile _next;
-  ObjectWaiter * volatile _prev;
-  Thread*       _thread;
-  ParkEvent *   _event;
-  volatile int  _notified ;
-  volatile TStates TState ;
-  Sorted        _Sorted ;           // List placement disposition
-  bool          _active ;           // Contention monitoring is enabled
- public:
-  ObjectWaiter(Thread* thread) {
-    _next     = NULL;
-    _prev     = NULL;
-    _notified = 0;
-    TState    = TS_RUN ;
-    _thread   = thread;
-    _event    = thread->_ParkEvent ;
-    _active   = false;
-    assert (_event != NULL, "invariant") ;
+  // If the object is stack-locked by the current thread, try to
+  // swing the displaced header from the box back to the mark.
+  if (mark == (markOop) lock) {
+     assert (dhw->is_neutral(), "invariant") ;
+     if ((markOop) Atomic::cmpxchg_ptr (dhw, object->mark_addr(), mark) == mark) {
+        TEVENT (fast_exit: release stacklock) ;
+        return;
+     }
+  }
+
+  ObjectSynchronizer::inflate(THREAD, object)->exit (THREAD) ;
+}
+
+// -----------------------------------------------------------------------------
+// Interpreter/Compiler Slow Case
+// This routine is used to handle interpreter/compiler slow case
+// We don't need to use fast path here, because it must have been
+// failed in the interpreter/compiler code.
+void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) {
+  markOop mark = obj->mark();
+  assert(!mark->has_bias_pattern(), "should not see bias pattern here");
+
+  if (mark->is_neutral()) {
+    // Anticipate successful CAS -- the ST of the displaced mark must
+    // be visible <= the ST performed by the CAS.
+    lock->set_displaced_header(mark);
+    if (mark == (markOop) Atomic::cmpxchg_ptr(lock, obj()->mark_addr(), mark)) {
+      TEVENT (slow_enter: release stacklock) ;
+      return ;
+    }
+    // Fall through to inflate() ...
+  } else
+  if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) {
+    assert(lock != mark->locker(), "must not re-lock the same lock");
+    assert(lock != (BasicLock*)obj->mark(), "don't relock with same BasicLock");
+    lock->set_displaced_header(NULL);
+    return;
+  }
+
+#if 0
+  // The following optimization isn't particularly useful.
+  if (mark->has_monitor() && mark->monitor()->is_entered(THREAD)) {
+    lock->set_displaced_header (NULL) ;
+    return ;
+  }
+#endif
+
+  // The object header will never be displaced to this lock,
+  // so it does not matter what the value is, except that it
+  // must be non-zero to avoid looking like a re-entrant lock,
+  // and must not look locked either.
+  lock->set_displaced_header(markOopDesc::unused_mark());
+  ObjectSynchronizer::inflate(THREAD, obj())->enter(THREAD);
+}
+
+// This routine is used to handle interpreter/compiler slow case
+// We don't need to use fast path here, because it must have
+// failed in the interpreter/compiler code. Simply use the heavy
+// weight monitor should be ok, unless someone find otherwise.
+void ObjectSynchronizer::slow_exit(oop object, BasicLock* lock, TRAPS) {
+  fast_exit (object, lock, THREAD) ;
+}
+
+// -----------------------------------------------------------------------------
+// Class Loader  support to workaround deadlocks on the class loader lock objects
+// Also used by GC
+// complete_exit()/reenter() are used to wait on a nested lock
+// i.e. to give up an outer lock completely and then re-enter
+// Used when holding nested locks - lock acquisition order: lock1 then lock2
+//  1) complete_exit lock1 - saving recursion count
+//  2) wait on lock2
+//  3) when notified on lock2, unlock lock2
+//  4) reenter lock1 with original recursion count
+//  5) lock lock2
+// NOTE: must use heavy weight monitor to handle complete_exit/reenter()
+intptr_t ObjectSynchronizer::complete_exit(Handle obj, TRAPS) {
+  TEVENT (complete_exit) ;
+  if (UseBiasedLocking) {
+    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
+    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
   }
 
-  void wait_reenter_begin(ObjectMonitor *mon) {
-    JavaThread *jt = (JavaThread *)this->_thread;
-    _active = JavaThreadBlockedOnMonitorEnterState::wait_reenter_begin(jt, mon);
+  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj());
+
+  return monitor->complete_exit(THREAD);
+}
+
+// NOTE: must use heavy weight monitor to handle complete_exit/reenter()
+void ObjectSynchronizer::reenter(Handle obj, intptr_t recursion, TRAPS) {
+  TEVENT (reenter) ;
+  if (UseBiasedLocking) {
+    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
+    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
+  }
+
+  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj());
+
+  monitor->reenter(recursion, THREAD);
+}
+// -----------------------------------------------------------------------------
+// JNI locks on java objects
+// NOTE: must use heavy weight monitor to handle jni monitor enter
+void ObjectSynchronizer::jni_enter(Handle obj, TRAPS) { // possible entry from jni enter
+  // the current locking is from JNI instead of Java code
+  TEVENT (jni_enter) ;
+  if (UseBiasedLocking) {
+    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
+    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
+  }
+  THREAD->set_current_pending_monitor_is_from_java(false);
+  ObjectSynchronizer::inflate(THREAD, obj())->enter(THREAD);
+  THREAD->set_current_pending_monitor_is_from_java(true);
+}
+
+// NOTE: must use heavy weight monitor to handle jni monitor enter
+bool ObjectSynchronizer::jni_try_enter(Handle obj, Thread* THREAD) {
+  if (UseBiasedLocking) {
+    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
+    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
   }
 
-  void wait_reenter_end(ObjectMonitor *mon) {
-    JavaThread *jt = (JavaThread *)this->_thread;
-    JavaThreadBlockedOnMonitorEnterState::wait_reenter_end(jt, _active);
+  ObjectMonitor* monitor = ObjectSynchronizer::inflate_helper(obj());
+  return monitor->try_enter(THREAD);
+}
+
+
+// NOTE: must use heavy weight monitor to handle jni monitor exit
+void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) {
+  TEVENT (jni_exit) ;
+  if (UseBiasedLocking) {
+    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
+  }
+  assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
+
+  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj);
+  // If this thread has locked the object, exit the monitor.  Note:  can't use
+  // monitor->check(CHECK); must exit even if an exception is pending.
+  if (monitor->check(THREAD)) {
+     monitor->exit(THREAD);
   }
-};
+}
+
+// -----------------------------------------------------------------------------
+// Internal VM locks on java objects
+// standard constructor, allows locking failures
+ObjectLocker::ObjectLocker(Handle obj, Thread* thread, bool doLock) {
+  _dolock = doLock;
+  _thread = thread;
+  debug_only(if (StrictSafepointChecks) _thread->check_for_valid_safepoint_state(false);)
+  _obj = obj;
 
-enum ManifestConstants {
-    ClearResponsibleAtSTW   = 0,
-    MaximumRecheckInterval  = 1000
-} ;
+  if (_dolock) {
+    TEVENT (ObjectLocker) ;
+
+    ObjectSynchronizer::fast_enter(_obj, &_lock, false, _thread);
+  }
+}
+
+ObjectLocker::~ObjectLocker() {
+  if (_dolock) {
+    ObjectSynchronizer::fast_exit(_obj(), &_lock, _thread);
+  }
+}
 
 
-#undef TEVENT
-#define TEVENT(nom) {if (SyncVerbose) FEVENT(nom); }
+// -----------------------------------------------------------------------------
+//  Wait/Notify/NotifyAll
+// NOTE: must use heavy weight monitor to handle wait()
+void ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
+  if (UseBiasedLocking) {
+    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
+    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
+  }
+  if (millis < 0) {
+    TEVENT (wait - throw IAX) ;
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
+  }
+  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj());
+  DTRACE_MONITOR_WAIT_PROBE(monitor, obj(), THREAD, millis);
+  monitor->wait(millis, true, THREAD);
+
+  /* This dummy call is in place to get around dtrace bug 6254741.  Once
+     that's fixed we can uncomment the following line and remove the call */
+  // DTRACE_MONITOR_PROBE(waited, monitor, obj(), THREAD);
+  dtrace_waited_probe(monitor, obj, THREAD);
+}
 
-#define FEVENT(nom) { static volatile int ctr = 0 ; int v = ++ctr ; if ((v & (v-1)) == 0) { ::printf (#nom " : %d \n", v); ::fflush(stdout); }}
+void ObjectSynchronizer::waitUninterruptibly (Handle obj, jlong millis, TRAPS) {
+  if (UseBiasedLocking) {
+    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
+    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
+  }
+  if (millis < 0) {
+    TEVENT (wait - throw IAX) ;
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
+  }
+  ObjectSynchronizer::inflate(THREAD, obj()) -> wait(millis, false, THREAD) ;
+}
+
+void ObjectSynchronizer::notify(Handle obj, TRAPS) {
+ if (UseBiasedLocking) {
+    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
+    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
+  }
 
-#undef  TEVENT
-#define TEVENT(nom) {;}
+  markOop mark = obj->mark();
+  if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) {
+    return;
+  }
+  ObjectSynchronizer::inflate(THREAD, obj())->notify(THREAD);
+}
 
+// NOTE: see comment of notify()
+void ObjectSynchronizer::notifyall(Handle obj, TRAPS) {
+  if (UseBiasedLocking) {
+    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
+    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
+  }
+
+  markOop mark = obj->mark();
+  if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) {
+    return;
+  }
+  ObjectSynchronizer::inflate(THREAD, obj())->notifyAll(THREAD);
+}
+
+// -----------------------------------------------------------------------------
+// Hash Code handling
+//
 // Performance concern:
 // OrderAccess::storestore() calls release() which STs 0 into the global volatile
 // OrderAccess::Dummy variable.  This store is unnecessary for correctness.
@@ -188,44 +414,73 @@
 static int MonitorScavengeThreshold = 1000000 ;
 static volatile int ForceMonitorScavenge = 0 ; // Scavenge required and pending
 
-
-// Tunables ...
-// The knob* variables are effectively final.  Once set they should
-// never be modified hence.  Consider using __read_mostly with GCC.
+static markOop ReadStableMark (oop obj) {
+  markOop mark = obj->mark() ;
+  if (!mark->is_being_inflated()) {
+    return mark ;       // normal fast-path return
+  }
 
-static int Knob_LogSpins           = 0 ;       // enable jvmstat tally for spins
-static int Knob_HandOff            = 0 ;
-static int Knob_Verbose            = 0 ;
-static int Knob_ReportSettings     = 0 ;
+  int its = 0 ;
+  for (;;) {
+    markOop mark = obj->mark() ;
+    if (!mark->is_being_inflated()) {
+      return mark ;    // normal fast-path return
+    }
+
+    // The object is being inflated by some other thread.
+    // The caller of ReadStableMark() must wait for inflation to complete.
+    // Avoid live-lock
+    // TODO: consider calling SafepointSynchronize::do_call_back() while
+    // spinning to see if there's a safepoint pending.  If so, immediately
+    // yielding or blocking would be appropriate.  Avoid spinning while
+    // there is a safepoint pending.
+    // TODO: add inflation contention performance counters.
+    // TODO: restrict the aggregate number of spinners.
 
-static int Knob_SpinLimit          = 5000 ;    // derived by an external tool -
-static int Knob_SpinBase           = 0 ;       // Floor AKA SpinMin
-static int Knob_SpinBackOff        = 0 ;       // spin-loop backoff
-static int Knob_CASPenalty         = -1 ;      // Penalty for failed CAS
-static int Knob_OXPenalty          = -1 ;      // Penalty for observed _owner change
-static int Knob_SpinSetSucc        = 1 ;       // spinners set the _succ field
-static int Knob_SpinEarly          = 1 ;
-static int Knob_SuccEnabled        = 1 ;       // futile wake throttling
-static int Knob_SuccRestrict       = 0 ;       // Limit successors + spinners to at-most-one
-static int Knob_MaxSpinners        = -1 ;      // Should be a function of # CPUs
-static int Knob_Bonus              = 100 ;     // spin success bonus
-static int Knob_BonusB             = 100 ;     // spin success bonus
-static int Knob_Penalty            = 200 ;     // spin failure penalty
-static int Knob_Poverty            = 1000 ;
-static int Knob_SpinAfterFutile    = 1 ;       // Spin after returning from park()
-static int Knob_FixedSpin          = 0 ;
-static int Knob_OState             = 3 ;       // Spinner checks thread state of _owner
-static int Knob_UsePause           = 1 ;
-static int Knob_ExitPolicy         = 0 ;
-static int Knob_PreSpin            = 10 ;      // 20-100 likely better
-static int Knob_ResetEvent         = 0 ;
-static int BackOffMask             = 0 ;
-
-static int Knob_FastHSSEC          = 0 ;
-static int Knob_MoveNotifyee       = 2 ;       // notify() - disposition of notifyee
-static int Knob_QMode              = 0 ;       // EntryList-cxq policy - queue discipline
-static volatile int InitDone       = 0 ;
-
+    ++its ;
+    if (its > 10000 || !os::is_MP()) {
+       if (its & 1) {
+         os::NakedYield() ;
+         TEVENT (Inflate: INFLATING - yield) ;
+       } else {
+         // Note that the following code attenuates the livelock problem but is not
+         // a complete remedy.  A more complete solution would require that the inflating
+         // thread hold the associated inflation lock.  The following code simply restricts
+         // the number of spinners to at most one.  We'll have N-2 threads blocked
+         // on the inflationlock, 1 thread holding the inflation lock and using
+         // a yield/park strategy, and 1 thread in the midst of inflation.
+         // A more refined approach would be to change the encoding of INFLATING
+         // to allow encapsulation of a native thread pointer.  Threads waiting for
+         // inflation to complete would use CAS to push themselves onto a singly linked
+         // list rooted at the markword.  Once enqueued, they'd loop, checking a per-thread flag
+         // and calling park().  When inflation was complete the thread that accomplished inflation
+         // would detach the list and set the markword to inflated with a single CAS and
+         // then for each thread on the list, set the flag and unpark() the thread.
+         // This is conceptually similar to muxAcquire-muxRelease, except that muxRelease
+         // wakes at most one thread whereas we need to wake the entire list.
+         int ix = (intptr_t(obj) >> 5) & (NINFLATIONLOCKS-1) ;
+         int YieldThenBlock = 0 ;
+         assert (ix >= 0 && ix < NINFLATIONLOCKS, "invariant") ;
+         assert ((NINFLATIONLOCKS & (NINFLATIONLOCKS-1)) == 0, "invariant") ;
+         Thread::muxAcquire (InflationLocks + ix, "InflationLock") ;
+         while (obj->mark() == markOopDesc::INFLATING()) {
+           // Beware: NakedYield() is advisory and has almost no effect on some platforms
+           // so we periodically call Self->_ParkEvent->park(1).
+           // We use a mixed spin/yield/block mechanism.
+           if ((YieldThenBlock++) >= 16) {
+              Thread::current()->_ParkEvent->park(1) ;
+           } else {
+              os::NakedYield() ;
+           }
+         }
+         Thread::muxRelease (InflationLocks + ix ) ;
+         TEVENT (Inflate: INFLATING - yield/park) ;
+       }
+    } else {
+       SpinPause() ;       // SMP-polite spinning
+    }
+  }
+}
 
 // hashCode() generation :
 //
@@ -290,416 +545,272 @@
   TEVENT (hashCode: GENERATE) ;
   return value;
 }
+//
+intptr_t ObjectSynchronizer::FastHashCode (Thread * Self, oop obj) {
+  if (UseBiasedLocking) {
+    // NOTE: many places throughout the JVM do not expect a safepoint
+    // to be taken here, in particular most operations on perm gen
+    // objects. However, we only ever bias Java instances and all of
+    // the call sites of identity_hash that might revoke biases have
+    // been checked to make sure they can handle a safepoint. The
+    // added check of the bias pattern is to avoid useless calls to
+    // thread-local storage.
+    if (obj->mark()->has_bias_pattern()) {
+      // Box and unbox the raw reference just in case we cause a STW safepoint.
+      Handle hobj (Self, obj) ;
+      // Relaxing assertion for bug 6320749.
+      assert (Universe::verify_in_progress() ||
+              !SafepointSynchronize::is_at_safepoint(),
+             "biases should not be seen by VM thread here");
+      BiasedLocking::revoke_and_rebias(hobj, false, JavaThread::current());
+      obj = hobj() ;
+      assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
+    }
+  }
 
-void BasicLock::print_on(outputStream* st) const {
-  st->print("monitor");
+  // hashCode() is a heap mutator ...
+  // Relaxing assertion for bug 6320749.
+  assert (Universe::verify_in_progress() ||
+          !SafepointSynchronize::is_at_safepoint(), "invariant") ;
+  assert (Universe::verify_in_progress() ||
+          Self->is_Java_thread() , "invariant") ;
+  assert (Universe::verify_in_progress() ||
+         ((JavaThread *)Self)->thread_state() != _thread_blocked, "invariant") ;
+
+  ObjectMonitor* monitor = NULL;
+  markOop temp, test;
+  intptr_t hash;
+  markOop mark = ReadStableMark (obj);
+
+  // object should remain ineligible for biased locking
+  assert (!mark->has_bias_pattern(), "invariant") ;
+
+  if (mark->is_neutral()) {
+    hash = mark->hash();              // this is a normal header
+    if (hash) {                       // if it has hash, just return it
+      return hash;
+    }
+    hash = get_next_hash(Self, obj);  // allocate a new hash code
+    temp = mark->copy_set_hash(hash); // merge the hash code into header
+    // use (machine word version) atomic operation to install the hash
+    test = (markOop) Atomic::cmpxchg_ptr(temp, obj->mark_addr(), mark);
+    if (test == mark) {
+      return hash;
+    }
+    // If atomic operation failed, we must inflate the header
+    // into heavy weight monitor. We could add more code here
+    // for fast path, but it does not worth the complexity.
+  } else if (mark->has_monitor()) {
+    monitor = mark->monitor();
+    temp = monitor->header();
+    assert (temp->is_neutral(), "invariant") ;
+    hash = temp->hash();
+    if (hash) {
+      return hash;
+    }
+    // Skip to the following code to reduce code size
+  } else if (Self->is_lock_owned((address)mark->locker())) {
+    temp = mark->displaced_mark_helper(); // this is a lightweight monitor owned
+    assert (temp->is_neutral(), "invariant") ;
+    hash = temp->hash();              // by current thread, check if the displaced
+    if (hash) {                       // header contains hash code
+      return hash;
+    }
+    // WARNING:
+    //   The displaced header is strictly immutable.
+    // It can NOT be changed in ANY cases. So we have
+    // to inflate the header into heavyweight monitor
+    // even the current thread owns the lock. The reason
+    // is the BasicLock (stack slot) will be asynchronously
+    // read by other threads during the inflate() function.
+    // Any change to stack may not propagate to other threads
+    // correctly.
+  }
+
+  // Inflate the monitor to set hash code
+  monitor = ObjectSynchronizer::inflate(Self, obj);
+  // Load displaced header and check it has hash code
+  mark = monitor->header();
+  assert (mark->is_neutral(), "invariant") ;
+  hash = mark->hash();
+  if (hash == 0) {
+    hash = get_next_hash(Self, obj);
+    temp = mark->copy_set_hash(hash); // merge hash code into header
+    assert (temp->is_neutral(), "invariant") ;
+    test = (markOop) Atomic::cmpxchg_ptr(temp, monitor, mark);
+    if (test != mark) {
+      // The only update to the header in the monitor (outside GC)
+      // is install the hash code. If someone add new usage of
+      // displaced header, please update this code
+      hash = test->hash();
+      assert (test->is_neutral(), "invariant") ;
+      assert (hash != 0, "Trivial unexpected object/monitor header usage.");
+    }
+  }
+  // We finally get the hash
+  return hash;
 }
 
-void BasicLock::move_to(oop obj, BasicLock* dest) {
-  // Check to see if we need to inflate the lock. This is only needed
-  // if an object is locked using "this" lightweight monitor. In that
-  // case, the displaced_header() is unlocked, because the
-  // displaced_header() contains the header for the originally unlocked
-  // object. However the object could have already been inflated. But it
-  // does not matter, the inflation will just a no-op. For other cases,
-  // the displaced header will be either 0x0 or 0x3, which are location
-  // independent, therefore the BasicLock is free to move.
-  //
-  // During OSR we may need to relocate a BasicLock (which contains a
-  // displaced word) from a location in an interpreter frame to a
-  // new location in a compiled frame.  "this" refers to the source
-  // basiclock in the interpreter frame.  "dest" refers to the destination
-  // basiclock in the new compiled frame.  We *always* inflate in move_to().
-  // The always-Inflate policy works properly, but in 1.5.0 it can sometimes
-  // cause performance problems in code that makes heavy use of a small # of
-  // uncontended locks.   (We'd inflate during OSR, and then sync performance
-  // would subsequently plummet because the thread would be forced thru the slow-path).
-  // This problem has been made largely moot on IA32 by inlining the inflated fast-path
-  // operations in Fast_Lock and Fast_Unlock in i486.ad.
-  //
-  // Note that there is a way to safely swing the object's markword from
-  // one stack location to another.  This avoids inflation.  Obviously,
-  // we need to ensure that both locations refer to the current thread's stack.
-  // There are some subtle concurrency issues, however, and since the benefit is
-  // is small (given the support for inflated fast-path locking in the fast_lock, etc)
-  // we'll leave that optimization for another time.
+// Deprecated -- use FastHashCode() instead.
 
-  if (displaced_header()->is_neutral()) {
-    ObjectSynchronizer::inflate_helper(obj);
-    // WARNING: We can not put check here, because the inflation
-    // will not update the displaced header. Once BasicLock is inflated,
-    // no one should ever look at its content.
-  } else {
-    // Typically the displaced header will be 0 (recursive stack lock) or
-    // unused_mark.  Naively we'd like to assert that the displaced mark
-    // value is either 0, neutral, or 3.  But with the advent of the
-    // store-before-CAS avoidance in fast_lock/compiler_lock_object
-    // we can find any flavor mark in the displaced mark.
-  }
-// [RGV] The next line appears to do nothing!
-  intptr_t dh = (intptr_t) displaced_header();
-  dest->set_displaced_header(displaced_header());
+intptr_t ObjectSynchronizer::identity_hash_value_for(Handle obj) {
+  return FastHashCode (Thread::current(), obj()) ;
 }
 
-// -----------------------------------------------------------------------------
 
-// standard constructor, allows locking failures
-ObjectLocker::ObjectLocker(Handle obj, Thread* thread, bool doLock) {
-  _dolock = doLock;
-  _thread = thread;
-  debug_only(if (StrictSafepointChecks) _thread->check_for_valid_safepoint_state(false);)
-  _obj = obj;
+bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* thread,
+                                                   Handle h_obj) {
+  if (UseBiasedLocking) {
+    BiasedLocking::revoke_and_rebias(h_obj, false, thread);
+    assert(!h_obj->mark()->has_bias_pattern(), "biases should be revoked by now");
+  }
+
+  assert(thread == JavaThread::current(), "Can only be called on current thread");
+  oop obj = h_obj();
+
+  markOop mark = ReadStableMark (obj) ;
 
-  if (_dolock) {
-    TEVENT (ObjectLocker) ;
-
-    ObjectSynchronizer::fast_enter(_obj, &_lock, false, _thread);
+  // Uncontended case, header points to stack
+  if (mark->has_locker()) {
+    return thread->is_lock_owned((address)mark->locker());
   }
-}
-
-ObjectLocker::~ObjectLocker() {
-  if (_dolock) {
-    ObjectSynchronizer::fast_exit(_obj(), &_lock, _thread);
+  // Contended case, header points to ObjectMonitor (tagged pointer)
+  if (mark->has_monitor()) {
+    ObjectMonitor* monitor = mark->monitor();
+    return monitor->is_entered(thread) != 0 ;
   }
+  // Unlocked case, header in place
+  assert(mark->is_neutral(), "sanity check");
+  return false;
 }
 
-// -----------------------------------------------------------------------------
+// Be aware of this method could revoke bias of the lock object.
+// This method querys the ownership of the lock handle specified by 'h_obj'.
+// If the current thread owns the lock, it returns owner_self. If no
+// thread owns the lock, it returns owner_none. Otherwise, it will return
+// ower_other.
+ObjectSynchronizer::LockOwnership ObjectSynchronizer::query_lock_ownership
+(JavaThread *self, Handle h_obj) {
+  // The caller must beware this method can revoke bias, and
+  // revocation can result in a safepoint.
+  assert (!SafepointSynchronize::is_at_safepoint(), "invariant") ;
+  assert (self->thread_state() != _thread_blocked , "invariant") ;
 
+  // Possible mark states: neutral, biased, stack-locked, inflated
+
+  if (UseBiasedLocking && h_obj()->mark()->has_bias_pattern()) {
+    // CASE: biased
+    BiasedLocking::revoke_and_rebias(h_obj, false, self);
+    assert(!h_obj->mark()->has_bias_pattern(),
+           "biases should be revoked by now");
+  }
 
-PerfCounter * ObjectSynchronizer::_sync_Inflations                  = NULL ;
-PerfCounter * ObjectSynchronizer::_sync_Deflations                  = NULL ;
-PerfCounter * ObjectSynchronizer::_sync_ContendedLockAttempts       = NULL ;
-PerfCounter * ObjectSynchronizer::_sync_FutileWakeups               = NULL ;
-PerfCounter * ObjectSynchronizer::_sync_Parks                       = NULL ;
-PerfCounter * ObjectSynchronizer::_sync_EmptyNotifications          = NULL ;
-PerfCounter * ObjectSynchronizer::_sync_Notifications               = NULL ;
-PerfCounter * ObjectSynchronizer::_sync_PrivateA                    = NULL ;
-PerfCounter * ObjectSynchronizer::_sync_PrivateB                    = NULL ;
-PerfCounter * ObjectSynchronizer::_sync_SlowExit                    = NULL ;
-PerfCounter * ObjectSynchronizer::_sync_SlowEnter                   = NULL ;
-PerfCounter * ObjectSynchronizer::_sync_SlowNotify                  = NULL ;
-PerfCounter * ObjectSynchronizer::_sync_SlowNotifyAll               = NULL ;
-PerfCounter * ObjectSynchronizer::_sync_FailedSpins                 = NULL ;
-PerfCounter * ObjectSynchronizer::_sync_SuccessfulSpins             = NULL ;
-PerfCounter * ObjectSynchronizer::_sync_MonInCirculation            = NULL ;
-PerfCounter * ObjectSynchronizer::_sync_MonScavenged                = NULL ;
-PerfLongVariable * ObjectSynchronizer::_sync_MonExtant              = NULL ;
+  assert(self == JavaThread::current(), "Can only be called on current thread");
+  oop obj = h_obj();
+  markOop mark = ReadStableMark (obj) ;
+
+  // CASE: stack-locked.  Mark points to a BasicLock on the owner's stack.
+  if (mark->has_locker()) {
+    return self->is_lock_owned((address)mark->locker()) ?
+      owner_self : owner_other;
+  }
 
-// One-shot global initialization for the sync subsystem.
-// We could also defer initialization and initialize on-demand
-// the first time we call inflate().  Initialization would
-// be protected - like so many things - by the MonitorCache_lock.
+  // CASE: inflated. Mark (tagged pointer) points to an objectMonitor.
+  // The Object:ObjectMonitor relationship is stable as long as we're
+  // not at a safepoint.
+  if (mark->has_monitor()) {
+    void * owner = mark->monitor()->_owner ;
+    if (owner == NULL) return owner_none ;
+    return (owner == self ||
+            self->is_lock_owned((address)owner)) ? owner_self : owner_other;
+  }
+
+  // CASE: neutral
+  assert(mark->is_neutral(), "sanity check");
+  return owner_none ;           // it's unlocked
+}
 
-void ObjectSynchronizer::Initialize () {
-  static int InitializationCompleted = 0 ;
-  assert (InitializationCompleted == 0, "invariant") ;
-  InitializationCompleted = 1 ;
-  if (UsePerfData) {
-      EXCEPTION_MARK ;
-      #define NEWPERFCOUNTER(n)   {n = PerfDataManager::create_counter(SUN_RT, #n, PerfData::U_Events,CHECK); }
-      #define NEWPERFVARIABLE(n)  {n = PerfDataManager::create_variable(SUN_RT, #n, PerfData::U_Events,CHECK); }
-      NEWPERFCOUNTER(_sync_Inflations) ;
-      NEWPERFCOUNTER(_sync_Deflations) ;
-      NEWPERFCOUNTER(_sync_ContendedLockAttempts) ;
-      NEWPERFCOUNTER(_sync_FutileWakeups) ;
-      NEWPERFCOUNTER(_sync_Parks) ;
-      NEWPERFCOUNTER(_sync_EmptyNotifications) ;
-      NEWPERFCOUNTER(_sync_Notifications) ;
-      NEWPERFCOUNTER(_sync_SlowEnter) ;
-      NEWPERFCOUNTER(_sync_SlowExit) ;
-      NEWPERFCOUNTER(_sync_SlowNotify) ;
-      NEWPERFCOUNTER(_sync_SlowNotifyAll) ;
-      NEWPERFCOUNTER(_sync_FailedSpins) ;
-      NEWPERFCOUNTER(_sync_SuccessfulSpins) ;
-      NEWPERFCOUNTER(_sync_PrivateA) ;
-      NEWPERFCOUNTER(_sync_PrivateB) ;
-      NEWPERFCOUNTER(_sync_MonInCirculation) ;
-      NEWPERFCOUNTER(_sync_MonScavenged) ;
-      NEWPERFVARIABLE(_sync_MonExtant) ;
-      #undef NEWPERFCOUNTER
+// FIXME: jvmti should call this
+JavaThread* ObjectSynchronizer::get_lock_owner(Handle h_obj, bool doLock) {
+  if (UseBiasedLocking) {
+    if (SafepointSynchronize::is_at_safepoint()) {
+      BiasedLocking::revoke_at_safepoint(h_obj);
+    } else {
+      BiasedLocking::revoke_and_rebias(h_obj, false, JavaThread::current());
+    }
+    assert(!h_obj->mark()->has_bias_pattern(), "biases should be revoked by now");
+  }
+
+  oop obj = h_obj();
+  address owner = NULL;
+
+  markOop mark = ReadStableMark (obj) ;
+
+  // Uncontended case, header points to stack
+  if (mark->has_locker()) {
+    owner = (address) mark->locker();
+  }
+
+  // Contended case, header points to ObjectMonitor (tagged pointer)
+  if (mark->has_monitor()) {
+    ObjectMonitor* monitor = mark->monitor();
+    assert(monitor != NULL, "monitor should be non-null");
+    owner = (address) monitor->owner();
+  }
+
+  if (owner != NULL) {
+    return Threads::owning_thread_from_monitor_owner(owner, doLock);
+  }
+
+  // Unlocked case, header in place
+  // Cannot have assertion since this object may have been
+  // locked by another thread when reaching here.
+  // assert(mark->is_neutral(), "sanity check");
+
+  return NULL;
+}
+// Visitors ...
+
+void ObjectSynchronizer::monitors_iterate(MonitorClosure* closure) {
+  ObjectMonitor* block = gBlockList;
+  ObjectMonitor* mid;
+  while (block) {
+    assert(block->object() == CHAINMARKER, "must be a block header");
+    for (int i = _BLOCKSIZE - 1; i > 0; i--) {
+      mid = block + i;
+      oop object = (oop) mid->object();
+      if (object != NULL) {
+        closure->do_monitor(mid);
+      }
+    }
+    block = (ObjectMonitor*) block->FreeNext;
   }
 }
 
-// Compile-time asserts
-// When possible, it's better to catch errors deterministically at
-// compile-time than at runtime.  The down-side to using compile-time
-// asserts is that error message -- often something about negative array
-// indices -- is opaque.
-
-#define CTASSERT(x) { int tag[1-(2*!(x))]; printf ("Tag @" INTPTR_FORMAT "\n", (intptr_t)tag); }
-
-void ObjectMonitor::ctAsserts() {
-  CTASSERT(offset_of (ObjectMonitor, _header) == 0);
-}
-
-static int Adjust (volatile int * adr, int dx) {
-  int v ;
-  for (v = *adr ; Atomic::cmpxchg (v + dx, adr, v) != v; v = *adr) ;
-  return v ;
-}
-
-// Ad-hoc mutual exclusion primitives: SpinLock and Mux
-//
-// We employ SpinLocks _only for low-contention, fixed-length
-// short-duration critical sections where we're concerned
-// about native mutex_t or HotSpot Mutex:: latency.
-// The mux construct provides a spin-then-block mutual exclusion
-// mechanism.
-//
-// Testing has shown that contention on the ListLock guarding gFreeList
-// is common.  If we implement ListLock as a simple SpinLock it's common
-// for the JVM to devolve to yielding with little progress.  This is true
-// despite the fact that the critical sections protected by ListLock are
-// extremely short.
-//
-// TODO-FIXME: ListLock should be of type SpinLock.
-// We should make this a 1st-class type, integrated into the lock
-// hierarchy as leaf-locks.  Critically, the SpinLock structure
-// should have sufficient padding to avoid false-sharing and excessive
-// cache-coherency traffic.
-
-
-typedef volatile int SpinLockT ;
-
-void Thread::SpinAcquire (volatile int * adr, const char * LockName) {
-  if (Atomic::cmpxchg (1, adr, 0) == 0) {
-     return ;   // normal fast-path return
-  }
-
-  // Slow-path : We've encountered contention -- Spin/Yield/Block strategy.
-  TEVENT (SpinAcquire - ctx) ;
-  int ctr = 0 ;
-  int Yields = 0 ;
-  for (;;) {
-     while (*adr != 0) {
-        ++ctr ;
-        if ((ctr & 0xFFF) == 0 || !os::is_MP()) {
-           if (Yields > 5) {
-             // Consider using a simple NakedSleep() instead.
-             // Then SpinAcquire could be called by non-JVM threads
-             Thread::current()->_ParkEvent->park(1) ;
-           } else {
-             os::NakedYield() ;
-             ++Yields ;
-           }
-        } else {
-           SpinPause() ;
-        }
-     }
-     if (Atomic::cmpxchg (1, adr, 0) == 0) return ;
-  }
-}
-
-void Thread::SpinRelease (volatile int * adr) {
-  assert (*adr != 0, "invariant") ;
-  OrderAccess::fence() ;      // guarantee at least release consistency.
-  // Roach-motel semantics.
-  // It's safe if subsequent LDs and STs float "up" into the critical section,
-  // but prior LDs and STs within the critical section can't be allowed
-  // to reorder or float past the ST that releases the lock.
-  *adr = 0 ;
+// Get the next block in the block list.
+static inline ObjectMonitor* next(ObjectMonitor* block) {
+  assert(block->object() == CHAINMARKER, "must be a block header");
+  block = block->FreeNext ;
+  assert(block == NULL || block->object() == CHAINMARKER, "must be a block header");
+  return block;
 }
 
-// muxAcquire and muxRelease:
-//
-// *  muxAcquire and muxRelease support a single-word lock-word construct.
-//    The LSB of the word is set IFF the lock is held.
-//    The remainder of the word points to the head of a singly-linked list
-//    of threads blocked on the lock.
-//
-// *  The current implementation of muxAcquire-muxRelease uses its own
-//    dedicated Thread._MuxEvent instance.  If we're interested in
-//    minimizing the peak number of extant ParkEvent instances then
-//    we could eliminate _MuxEvent and "borrow" _ParkEvent as long
-//    as certain invariants were satisfied.  Specifically, care would need
-//    to be taken with regards to consuming unpark() "permits".
-//    A safe rule of thumb is that a thread would never call muxAcquire()
-//    if it's enqueued (cxq, EntryList, WaitList, etc) and will subsequently
-//    park().  Otherwise the _ParkEvent park() operation in muxAcquire() could
-//    consume an unpark() permit intended for monitorenter, for instance.
-//    One way around this would be to widen the restricted-range semaphore
-//    implemented in park().  Another alternative would be to provide
-//    multiple instances of the PlatformEvent() for each thread.  One
-//    instance would be dedicated to muxAcquire-muxRelease, for instance.
-//
-// *  Usage:
-//    -- Only as leaf locks
-//    -- for short-term locking only as muxAcquire does not perform
-//       thread state transitions.
-//
-// Alternatives:
-// *  We could implement muxAcquire and muxRelease with MCS or CLH locks
-//    but with parking or spin-then-park instead of pure spinning.
-// *  Use Taura-Oyama-Yonenzawa locks.
-// *  It's possible to construct a 1-0 lock if we encode the lockword as
-//    (List,LockByte).  Acquire will CAS the full lockword while Release
-//    will STB 0 into the LockByte.  The 1-0 scheme admits stranding, so
-//    acquiring threads use timers (ParkTimed) to detect and recover from
-//    the stranding window.  Thread/Node structures must be aligned on 256-byte
-//    boundaries by using placement-new.
-// *  Augment MCS with advisory back-link fields maintained with CAS().
-//    Pictorially:  LockWord -> T1 <-> T2 <-> T3 <-> ... <-> Tn <-> Owner.
-//    The validity of the backlinks must be ratified before we trust the value.
-//    If the backlinks are invalid the exiting thread must back-track through the
-//    the forward links, which are always trustworthy.
-// *  Add a successor indication.  The LockWord is currently encoded as
-//    (List, LOCKBIT:1).  We could also add a SUCCBIT or an explicit _succ variable
-//    to provide the usual futile-wakeup optimization.
-//    See RTStt for details.
-// *  Consider schedctl.sc_nopreempt to cover the critical section.
-//
 
-
-typedef volatile intptr_t MutexT ;      // Mux Lock-word
-enum MuxBits { LOCKBIT = 1 } ;
-
-void Thread::muxAcquire (volatile intptr_t * Lock, const char * LockName) {
-  intptr_t w = Atomic::cmpxchg_ptr (LOCKBIT, Lock, 0) ;
-  if (w == 0) return ;
-  if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
-     return ;
-  }
-
-  TEVENT (muxAcquire - Contention) ;
-  ParkEvent * const Self = Thread::current()->_MuxEvent ;
-  assert ((intptr_t(Self) & LOCKBIT) == 0, "invariant") ;
-  for (;;) {
-     int its = (os::is_MP() ? 100 : 0) + 1 ;
-
-     // Optional spin phase: spin-then-park strategy
-     while (--its >= 0) {
-       w = *Lock ;
-       if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
-          return ;
-       }
-     }
-
-     Self->reset() ;
-     Self->OnList = intptr_t(Lock) ;
-     // The following fence() isn't _strictly necessary as the subsequent
-     // CAS() both serializes execution and ratifies the fetched *Lock value.
-     OrderAccess::fence();
-     for (;;) {
-        w = *Lock ;
-        if ((w & LOCKBIT) == 0) {
-            if (Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
-                Self->OnList = 0 ;   // hygiene - allows stronger asserts
-                return ;
-            }
-            continue ;      // Interference -- *Lock changed -- Just retry
-        }
-        assert (w & LOCKBIT, "invariant") ;
-        Self->ListNext = (ParkEvent *) (w & ~LOCKBIT );
-        if (Atomic::cmpxchg_ptr (intptr_t(Self)|LOCKBIT, Lock, w) == w) break ;
-     }
-
-     while (Self->OnList != 0) {
-        Self->park() ;
-     }
-  }
-}
-
-void Thread::muxAcquireW (volatile intptr_t * Lock, ParkEvent * ev) {
-  intptr_t w = Atomic::cmpxchg_ptr (LOCKBIT, Lock, 0) ;
-  if (w == 0) return ;
-  if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
-    return ;
-  }
-
-  TEVENT (muxAcquire - Contention) ;
-  ParkEvent * ReleaseAfter = NULL ;
-  if (ev == NULL) {
-    ev = ReleaseAfter = ParkEvent::Allocate (NULL) ;
-  }
-  assert ((intptr_t(ev) & LOCKBIT) == 0, "invariant") ;
-  for (;;) {
-    guarantee (ev->OnList == 0, "invariant") ;
-    int its = (os::is_MP() ? 100 : 0) + 1 ;
-
-    // Optional spin phase: spin-then-park strategy
-    while (--its >= 0) {
-      w = *Lock ;
-      if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
-        if (ReleaseAfter != NULL) {
-          ParkEvent::Release (ReleaseAfter) ;
-        }
-        return ;
+void ObjectSynchronizer::oops_do(OopClosure* f) {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+  for (ObjectMonitor* block = gBlockList; block != NULL; block = next(block)) {
+    assert(block->object() == CHAINMARKER, "must be a block header");
+    for (int i = 1; i < _BLOCKSIZE; i++) {
+      ObjectMonitor* mid = &block[i];
+      if (mid->object() != NULL) {
+        f->do_oop((oop*)mid->object_addr());
       }
     }
-
-    ev->reset() ;
-    ev->OnList = intptr_t(Lock) ;
-    // The following fence() isn't _strictly necessary as the subsequent
-    // CAS() both serializes execution and ratifies the fetched *Lock value.
-    OrderAccess::fence();
-    for (;;) {
-      w = *Lock ;
-      if ((w & LOCKBIT) == 0) {
-        if (Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
-          ev->OnList = 0 ;
-          // We call ::Release while holding the outer lock, thus
-          // artificially lengthening the critical section.
-          // Consider deferring the ::Release() until the subsequent unlock(),
-          // after we've dropped the outer lock.
-          if (ReleaseAfter != NULL) {
-            ParkEvent::Release (ReleaseAfter) ;
-          }
-          return ;
-        }
-        continue ;      // Interference -- *Lock changed -- Just retry
-      }
-      assert (w & LOCKBIT, "invariant") ;
-      ev->ListNext = (ParkEvent *) (w & ~LOCKBIT );
-      if (Atomic::cmpxchg_ptr (intptr_t(ev)|LOCKBIT, Lock, w) == w) break ;
-    }
-
-    while (ev->OnList != 0) {
-      ev->park() ;
-    }
   }
 }
 
-// Release() must extract a successor from the list and then wake that thread.
-// It can "pop" the front of the list or use a detach-modify-reattach (DMR) scheme
-// similar to that used by ParkEvent::Allocate() and ::Release().  DMR-based
-// Release() would :
-// (A) CAS() or swap() null to *Lock, releasing the lock and detaching the list.
-// (B) Extract a successor from the private list "in-hand"
-// (C) attempt to CAS() the residual back into *Lock over null.
-//     If there were any newly arrived threads and the CAS() would fail.
-//     In that case Release() would detach the RATs, re-merge the list in-hand
-//     with the RATs and repeat as needed.  Alternately, Release() might
-//     detach and extract a successor, but then pass the residual list to the wakee.
-//     The wakee would be responsible for reattaching and remerging before it
-//     competed for the lock.
-//
-// Both "pop" and DMR are immune from ABA corruption -- there can be
-// multiple concurrent pushers, but only one popper or detacher.
-// This implementation pops from the head of the list.  This is unfair,
-// but tends to provide excellent throughput as hot threads remain hot.
-// (We wake recently run threads first).
 
-void Thread::muxRelease (volatile intptr_t * Lock)  {
-  for (;;) {
-    const intptr_t w = Atomic::cmpxchg_ptr (0, Lock, LOCKBIT) ;
-    assert (w & LOCKBIT, "invariant") ;
-    if (w == LOCKBIT) return ;
-    ParkEvent * List = (ParkEvent *) (w & ~LOCKBIT) ;
-    assert (List != NULL, "invariant") ;
-    assert (List->OnList == intptr_t(Lock), "invariant") ;
-    ParkEvent * nxt = List->ListNext ;
-
-    // The following CAS() releases the lock and pops the head element.
-    if (Atomic::cmpxchg_ptr (intptr_t(nxt), Lock, w) != w) {
-      continue ;
-    }
-    List->OnList = 0 ;
-    OrderAccess::fence() ;
-    List->unpark () ;
-    return ;
-  }
-}
-
+// -----------------------------------------------------------------------------
 // ObjectMonitor Lifecycle
 // -----------------------
 // Inflation unlinks monitors from the global gFreeList and
@@ -718,41 +829,7 @@
 // --   assigned to an object.  The object is inflated and the mark refers
 //      to the objectmonitor.
 //
-// TODO-FIXME:
-//
-// *  We currently protect the gFreeList with a simple lock.
-//    An alternate lock-free scheme would be to pop elements from the gFreeList
-//    with CAS.  This would be safe from ABA corruption as long we only
-//    recycled previously appearing elements onto the list in deflate_idle_monitors()
-//    at STW-time.  Completely new elements could always be pushed onto the gFreeList
-//    with CAS.  Elements that appeared previously on the list could only
-//    be installed at STW-time.
-//
-// *  For efficiency and to help reduce the store-before-CAS penalty
-//    the objectmonitors on gFreeList or local free lists should be ready to install
-//    with the exception of _header and _object.  _object can be set after inflation.
-//    In particular, keep all objectMonitors on a thread's private list in ready-to-install
-//    state with m.Owner set properly.
-//
-// *  We could all diffuse contention by using multiple global (FreeList, Lock)
-//    pairs -- threads could use trylock() and a cyclic-scan strategy to search for
-//    an unlocked free list.
-//
-// *  Add lifecycle tags and assert()s.
-//
-// *  Be more consistent about when we clear an objectmonitor's fields:
-//    A.  After extracting the objectmonitor from a free list.
-//    B.  After adding an objectmonitor to a free list.
-//
 
-ObjectMonitor * ObjectSynchronizer::gBlockList = NULL ;
-ObjectMonitor * volatile ObjectSynchronizer::gFreeList  = NULL ;
-ObjectMonitor * volatile ObjectSynchronizer::gOmInUseList  = NULL ;
-int ObjectSynchronizer::gOmInUseCount = 0;
-static volatile intptr_t ListLock = 0 ;      // protects global monitor free-list cache
-static volatile int MonitorFreeCount  = 0 ;      // # on gFreeList
-static volatile int MonitorPopulation = 0 ;      // # Extant -- in circulation
-#define CHAINMARKER ((oop)-1)
 
 // Constraining monitor pool growth via MonitorBound ...
 //
@@ -768,41 +845,8 @@
 // we'll incur more safepoints, which are harmful to performance.
 // See also: GuaranteedSafepointInterval
 //
-// As noted elsewhere, the correct long-term solution is to deflate at
-// monitorexit-time, in which case the number of inflated objects is bounded
-// by the number of threads.  That policy obviates the need for scavenging at
-// STW safepoint time.   As an aside, scavenging can be time-consuming when the
-// # of extant monitors is large.   Unfortunately there's a day-1 assumption baked
-// into much HotSpot code that the object::monitor relationship, once established
-// or observed, will remain stable except over potential safepoints.
-//
-// We can use either a blocking synchronous VM operation or an async VM operation.
-// -- If we use a blocking VM operation :
-//    Calls to ScavengeCheck() should be inserted only into 'safe' locations in paths
-//    that lead to ::inflate() or ::omAlloc().
-//    Even though the safepoint will not directly induce GC, a GC might
-//    piggyback on the safepoint operation, so the caller should hold no naked oops.
-//    Furthermore, monitor::object relationships are NOT necessarily stable over this call
-//    unless the caller has made provisions to "pin" the object to the monitor, say
-//    by incrementing the monitor's _count field.
-// -- If we use a non-blocking asynchronous VM operation :
-//    the constraints above don't apply.  The safepoint will fire in the future
-//    at a more convenient time.  On the other hand the latency between posting and
-//    running the safepoint introduces or admits "slop" or laxity during which the
-//    monitor population can climb further above the threshold.  The monitor population,
-//    however, tends to converge asymptotically over time to a count that's slightly
-//    above the target value specified by MonitorBound.   That is, we avoid unbounded
-//    growth, albeit with some imprecision.
-//
 // The current implementation uses asynchronous VM operations.
 //
-// Ideally we'd check if (MonitorPopulation > MonitorBound) in omAlloc()
-// immediately before trying to grow the global list via allocation.
-// If the predicate was true then we'd induce a synchronous safepoint, wait
-// for the safepoint to complete, and then again to allocate from the global
-// free list.  This approach is much simpler and precise, admitting no "slop".
-// Unfortunately we can't safely safepoint in the midst of omAlloc(), so
-// instead we use asynchronous safepoints.
 
 static void InduceScavenge (Thread * Self, const char * Whence) {
   // Induce STW safepoint to trim monitors
@@ -812,7 +856,7 @@
   // TODO: assert thread state is reasonable
 
   if (ForceMonitorScavenge == 0 && Atomic::xchg (1, &ForceMonitorScavenge) == 0) {
-    if (Knob_Verbose) {
+    if (ObjectMonitor::Knob_Verbose) {
       ::printf ("Monitor scavenge - Induced STW @%s (%d)\n", Whence, ForceMonitorScavenge) ;
       ::fflush(stdout) ;
     }
@@ -822,7 +866,7 @@
     // The VMThread will delete the op when completed.
     VMThread::execute (new VM_ForceAsyncSafepoint()) ;
 
-    if (Knob_Verbose) {
+    if (ObjectMonitor::Knob_Verbose) {
       ::printf ("Monitor scavenge - STW posted @%s (%d)\n", Whence, ForceMonitorScavenge) ;
       ::fflush(stdout) ;
     }
@@ -844,7 +888,6 @@
    assert(freetally == Self->omFreeCount, "free count off");
 }
 */
-
 ObjectMonitor * ATTR ObjectSynchronizer::omAlloc (Thread * Self) {
     // A large MAXPRIVATE value reduces both list lock contention
     // and list coherency traffic, but also tends to increase the
@@ -974,12 +1017,6 @@
 // attempt failed.  This doesn't allow unbounded #s of monitors to
 // accumulate on a thread's free list.
 //
-// In the future the usage of omRelease() might change and monitors
-// could migrate between free lists.  In that case to avoid excessive
-// accumulation we could  limit omCount to (omProvision*2), otherwise return
-// the objectMonitor to the global list.  We should drain (return) in reasonable chunks.
-// That is, *not* one-at-a-time.
-
 
 void ObjectSynchronizer::omRelease (Thread * Self, ObjectMonitor * m, bool fromPerThreadAlloc) {
     guarantee (m->object() == NULL, "invariant") ;
@@ -1082,15 +1119,6 @@
     TEVENT (omFlush) ;
 }
 
-
-// Get the next block in the block list.
-static inline ObjectMonitor* next(ObjectMonitor* block) {
-  assert(block->object() == CHAINMARKER, "must be a block header");
-  block = block->FreeNext ;
-  assert(block == NULL || block->object() == CHAINMARKER, "must be a block header");
-  return block;
-}
-
 // Fast path code shared by multiple functions
 ObjectMonitor* ObjectSynchronizer::inflate_helper(oop obj) {
   markOop mark = obj->mark();
@@ -1102,79 +1130,10 @@
   return ObjectSynchronizer::inflate(Thread::current(), obj);
 }
 
+
 // Note that we could encounter some performance loss through false-sharing as
 // multiple locks occupy the same $ line.  Padding might be appropriate.
 
-#define NINFLATIONLOCKS 256
-static volatile intptr_t InflationLocks [NINFLATIONLOCKS] ;
-
-static markOop ReadStableMark (oop obj) {
-  markOop mark = obj->mark() ;
-  if (!mark->is_being_inflated()) {
-    return mark ;       // normal fast-path return
-  }
-
-  int its = 0 ;
-  for (;;) {
-    markOop mark = obj->mark() ;
-    if (!mark->is_being_inflated()) {
-      return mark ;    // normal fast-path return
-    }
-
-    // The object is being inflated by some other thread.
-    // The caller of ReadStableMark() must wait for inflation to complete.
-    // Avoid live-lock
-    // TODO: consider calling SafepointSynchronize::do_call_back() while
-    // spinning to see if there's a safepoint pending.  If so, immediately
-    // yielding or blocking would be appropriate.  Avoid spinning while
-    // there is a safepoint pending.
-    // TODO: add inflation contention performance counters.
-    // TODO: restrict the aggregate number of spinners.
-
-    ++its ;
-    if (its > 10000 || !os::is_MP()) {
-       if (its & 1) {
-         os::NakedYield() ;
-         TEVENT (Inflate: INFLATING - yield) ;
-       } else {
-         // Note that the following code attenuates the livelock problem but is not
-         // a complete remedy.  A more complete solution would require that the inflating
-         // thread hold the associated inflation lock.  The following code simply restricts
-         // the number of spinners to at most one.  We'll have N-2 threads blocked
-         // on the inflationlock, 1 thread holding the inflation lock and using
-         // a yield/park strategy, and 1 thread in the midst of inflation.
-         // A more refined approach would be to change the encoding of INFLATING
-         // to allow encapsulation of a native thread pointer.  Threads waiting for
-         // inflation to complete would use CAS to push themselves onto a singly linked
-         // list rooted at the markword.  Once enqueued, they'd loop, checking a per-thread flag
-         // and calling park().  When inflation was complete the thread that accomplished inflation
-         // would detach the list and set the markword to inflated with a single CAS and
-         // then for each thread on the list, set the flag and unpark() the thread.
-         // This is conceptually similar to muxAcquire-muxRelease, except that muxRelease
-         // wakes at most one thread whereas we need to wake the entire list.
-         int ix = (intptr_t(obj) >> 5) & (NINFLATIONLOCKS-1) ;
-         int YieldThenBlock = 0 ;
-         assert (ix >= 0 && ix < NINFLATIONLOCKS, "invariant") ;
-         assert ((NINFLATIONLOCKS & (NINFLATIONLOCKS-1)) == 0, "invariant") ;
-         Thread::muxAcquire (InflationLocks + ix, "InflationLock") ;
-         while (obj->mark() == markOopDesc::INFLATING()) {
-           // Beware: NakedYield() is advisory and has almost no effect on some platforms
-           // so we periodically call Self->_ParkEvent->park(1).
-           // We use a mixed spin/yield/block mechanism.
-           if ((YieldThenBlock++) >= 16) {
-              Thread::current()->_ParkEvent->park(1) ;
-           } else {
-              os::NakedYield() ;
-           }
-         }
-         Thread::muxRelease (InflationLocks + ix ) ;
-         TEVENT (Inflate: INFLATING - yield/park) ;
-       }
-    } else {
-       SpinPause() ;       // SMP-polite spinning
-    }
-  }
-}
 
 ObjectMonitor * ATTR ObjectSynchronizer::inflate (Thread * Self, oop object) {
   // Inflate mutates the heap ...
@@ -1242,7 +1201,7 @@
           m->_Responsible  = NULL ;
           m->OwnerIsThread = 0 ;
           m->_recursions   = 0 ;
-          m->_SpinDuration = Knob_SpinLimit ;   // Consider: maintain by type/class
+          m->_SpinDuration = ObjectMonitor::Knob_SpinLimit ;   // Consider: maintain by type/class
 
           markOop cmp = (markOop) Atomic::cmpxchg_ptr (markOopDesc::INFLATING(), object->mark_addr(), mark) ;
           if (cmp != mark) {
@@ -1302,7 +1261,7 @@
 
           // Hopefully the performance counters are allocated on distinct cache lines
           // to avoid false sharing on MP systems ...
-          if (_sync_Inflations != NULL) _sync_Inflations->inc() ;
+          if (ObjectMonitor::_sync_Inflations != NULL) ObjectMonitor::_sync_Inflations->inc() ;
           TEVENT(Inflate: overwrite stacklock) ;
           if (TraceMonitorInflation) {
             if (object->is_instance()) {
@@ -1335,7 +1294,7 @@
       m->OwnerIsThread = 1 ;
       m->_recursions   = 0 ;
       m->_Responsible  = NULL ;
-      m->_SpinDuration = Knob_SpinLimit ;       // consider: keep metastats by type/class
+      m->_SpinDuration = ObjectMonitor::Knob_SpinLimit ;       // consider: keep metastats by type/class
 
       if (Atomic::cmpxchg_ptr (markOopDesc::encode(m), object->mark_addr(), mark) != mark) {
           m->set_object (NULL) ;
@@ -1352,7 +1311,7 @@
 
       // Hopefully the performance counters are allocated on distinct
       // cache lines to avoid false sharing on MP systems ...
-      if (_sync_Inflations != NULL) _sync_Inflations->inc() ;
+      if (ObjectMonitor::_sync_Inflations != NULL) ObjectMonitor::_sync_Inflations->inc() ;
       TEVENT(Inflate: overwrite neutral) ;
       if (TraceMonitorInflation) {
         if (object->is_instance()) {
@@ -1366,547 +1325,9 @@
   }
 }
 
-
-// This the fast monitor enter. The interpreter and compiler use
-// some assembly copies of this code. Make sure update those code
-// if the following function is changed. The implementation is
-// extremely sensitive to race condition. Be careful.
-
-void ObjectSynchronizer::fast_enter(Handle obj, BasicLock* lock, bool attempt_rebias, TRAPS) {
- if (UseBiasedLocking) {
-    if (!SafepointSynchronize::is_at_safepoint()) {
-      BiasedLocking::Condition cond = BiasedLocking::revoke_and_rebias(obj, attempt_rebias, THREAD);
-      if (cond == BiasedLocking::BIAS_REVOKED_AND_REBIASED) {
-        return;
-      }
-    } else {
-      assert(!attempt_rebias, "can not rebias toward VM thread");
-      BiasedLocking::revoke_at_safepoint(obj);
-    }
-    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
- }
-
- slow_enter (obj, lock, THREAD) ;
-}
-
-void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) {
-  assert(!object->mark()->has_bias_pattern(), "should not see bias pattern here");
-  // if displaced header is null, the previous enter is recursive enter, no-op
-  markOop dhw = lock->displaced_header();
-  markOop mark ;
-  if (dhw == NULL) {
-     // Recursive stack-lock.
-     // Diagnostics -- Could be: stack-locked, inflating, inflated.
-     mark = object->mark() ;
-     assert (!mark->is_neutral(), "invariant") ;
-     if (mark->has_locker() && mark != markOopDesc::INFLATING()) {
-        assert(THREAD->is_lock_owned((address)mark->locker()), "invariant") ;
-     }
-     if (mark->has_monitor()) {
-        ObjectMonitor * m = mark->monitor() ;
-        assert(((oop)(m->object()))->mark() == mark, "invariant") ;
-        assert(m->is_entered(THREAD), "invariant") ;
-     }
-     return ;
-  }
-
-  mark = object->mark() ;
-
-  // If the object is stack-locked by the current thread, try to
-  // swing the displaced header from the box back to the mark.
-  if (mark == (markOop) lock) {
-     assert (dhw->is_neutral(), "invariant") ;
-     if ((markOop) Atomic::cmpxchg_ptr (dhw, object->mark_addr(), mark) == mark) {
-        TEVENT (fast_exit: release stacklock) ;
-        return;
-     }
-  }
-
-  ObjectSynchronizer::inflate(THREAD, object)->exit (THREAD) ;
-}
-
-// This routine is used to handle interpreter/compiler slow case
-// We don't need to use fast path here, because it must have been
-// failed in the interpreter/compiler code.
-void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) {
-  markOop mark = obj->mark();
-  assert(!mark->has_bias_pattern(), "should not see bias pattern here");
-
-  if (mark->is_neutral()) {
-    // Anticipate successful CAS -- the ST of the displaced mark must
-    // be visible <= the ST performed by the CAS.
-    lock->set_displaced_header(mark);
-    if (mark == (markOop) Atomic::cmpxchg_ptr(lock, obj()->mark_addr(), mark)) {
-      TEVENT (slow_enter: release stacklock) ;
-      return ;
-    }
-    // Fall through to inflate() ...
-  } else
-  if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) {
-    assert(lock != mark->locker(), "must not re-lock the same lock");
-    assert(lock != (BasicLock*)obj->mark(), "don't relock with same BasicLock");
-    lock->set_displaced_header(NULL);
-    return;
-  }
-
-#if 0
-  // The following optimization isn't particularly useful.
-  if (mark->has_monitor() && mark->monitor()->is_entered(THREAD)) {
-    lock->set_displaced_header (NULL) ;
-    return ;
-  }
-#endif
-
-  // The object header will never be displaced to this lock,
-  // so it does not matter what the value is, except that it
-  // must be non-zero to avoid looking like a re-entrant lock,
-  // and must not look locked either.
-  lock->set_displaced_header(markOopDesc::unused_mark());
-  ObjectSynchronizer::inflate(THREAD, obj())->enter(THREAD);
-}
-
-// This routine is used to handle interpreter/compiler slow case
-// We don't need to use fast path here, because it must have
-// failed in the interpreter/compiler code. Simply use the heavy
-// weight monitor should be ok, unless someone find otherwise.
-void ObjectSynchronizer::slow_exit(oop object, BasicLock* lock, TRAPS) {
-  fast_exit (object, lock, THREAD) ;
-}
-
-// NOTE: must use heavy weight monitor to handle jni monitor enter
-void ObjectSynchronizer::jni_enter(Handle obj, TRAPS) { // possible entry from jni enter
-  // the current locking is from JNI instead of Java code
-  TEVENT (jni_enter) ;
-  if (UseBiasedLocking) {
-    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
-    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
-  }
-  THREAD->set_current_pending_monitor_is_from_java(false);
-  ObjectSynchronizer::inflate(THREAD, obj())->enter(THREAD);
-  THREAD->set_current_pending_monitor_is_from_java(true);
-}
-
-// NOTE: must use heavy weight monitor to handle jni monitor enter
-bool ObjectSynchronizer::jni_try_enter(Handle obj, Thread* THREAD) {
-  if (UseBiasedLocking) {
-    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
-    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
-  }
-
-  ObjectMonitor* monitor = ObjectSynchronizer::inflate_helper(obj());
-  return monitor->try_enter(THREAD);
-}
-
-
-// NOTE: must use heavy weight monitor to handle jni monitor exit
-void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) {
-  TEVENT (jni_exit) ;
-  if (UseBiasedLocking) {
-    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
-  }
-  assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
-
-  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj);
-  // If this thread has locked the object, exit the monitor.  Note:  can't use
-  // monitor->check(CHECK); must exit even if an exception is pending.
-  if (monitor->check(THREAD)) {
-     monitor->exit(THREAD);
-  }
-}
-
-// complete_exit()/reenter() are used to wait on a nested lock
-// i.e. to give up an outer lock completely and then re-enter
-// Used when holding nested locks - lock acquisition order: lock1 then lock2
-//  1) complete_exit lock1 - saving recursion count
-//  2) wait on lock2
-//  3) when notified on lock2, unlock lock2
-//  4) reenter lock1 with original recursion count
-//  5) lock lock2
-// NOTE: must use heavy weight monitor to handle complete_exit/reenter()
-intptr_t ObjectSynchronizer::complete_exit(Handle obj, TRAPS) {
-  TEVENT (complete_exit) ;
-  if (UseBiasedLocking) {
-    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
-    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
-  }
-
-  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj());
-
-  return monitor->complete_exit(THREAD);
-}
-
-// NOTE: must use heavy weight monitor to handle complete_exit/reenter()
-void ObjectSynchronizer::reenter(Handle obj, intptr_t recursion, TRAPS) {
-  TEVENT (reenter) ;
-  if (UseBiasedLocking) {
-    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
-    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
-  }
-
-  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj());
-
-  monitor->reenter(recursion, THREAD);
-}
-
-// This exists only as a workaround of dtrace bug 6254741
-int dtrace_waited_probe(ObjectMonitor* monitor, Handle obj, Thread* thr) {
-  DTRACE_MONITOR_PROBE(waited, monitor, obj(), thr);
-  return 0;
-}
-
-// NOTE: must use heavy weight monitor to handle wait()
-void ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
-  if (UseBiasedLocking) {
-    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
-    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
-  }
-  if (millis < 0) {
-    TEVENT (wait - throw IAX) ;
-    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
-  }
-  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj());
-  DTRACE_MONITOR_WAIT_PROBE(monitor, obj(), THREAD, millis);
-  monitor->wait(millis, true, THREAD);
-
-  /* This dummy call is in place to get around dtrace bug 6254741.  Once
-     that's fixed we can uncomment the following line and remove the call */
-  // DTRACE_MONITOR_PROBE(waited, monitor, obj(), THREAD);
-  dtrace_waited_probe(monitor, obj, THREAD);
-}
-
-void ObjectSynchronizer::waitUninterruptibly (Handle obj, jlong millis, TRAPS) {
-  if (UseBiasedLocking) {
-    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
-    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
-  }
-  if (millis < 0) {
-    TEVENT (wait - throw IAX) ;
-    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
-  }
-  ObjectSynchronizer::inflate(THREAD, obj()) -> wait(millis, false, THREAD) ;
-}
-
-void ObjectSynchronizer::notify(Handle obj, TRAPS) {
- if (UseBiasedLocking) {
-    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
-    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
-  }
-
-  markOop mark = obj->mark();
-  if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) {
-    return;
-  }
-  ObjectSynchronizer::inflate(THREAD, obj())->notify(THREAD);
-}
-
-// NOTE: see comment of notify()
-void ObjectSynchronizer::notifyall(Handle obj, TRAPS) {
-  if (UseBiasedLocking) {
-    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
-    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
-  }
-
-  markOop mark = obj->mark();
-  if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) {
-    return;
-  }
-  ObjectSynchronizer::inflate(THREAD, obj())->notifyAll(THREAD);
-}
-
-intptr_t ObjectSynchronizer::FastHashCode (Thread * Self, oop obj) {
-  if (UseBiasedLocking) {
-    // NOTE: many places throughout the JVM do not expect a safepoint
-    // to be taken here, in particular most operations on perm gen
-    // objects. However, we only ever bias Java instances and all of
-    // the call sites of identity_hash that might revoke biases have
-    // been checked to make sure they can handle a safepoint. The
-    // added check of the bias pattern is to avoid useless calls to
-    // thread-local storage.
-    if (obj->mark()->has_bias_pattern()) {
-      // Box and unbox the raw reference just in case we cause a STW safepoint.
-      Handle hobj (Self, obj) ;
-      // Relaxing assertion for bug 6320749.
-      assert (Universe::verify_in_progress() ||
-              !SafepointSynchronize::is_at_safepoint(),
-             "biases should not be seen by VM thread here");
-      BiasedLocking::revoke_and_rebias(hobj, false, JavaThread::current());
-      obj = hobj() ;
-      assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
-    }
-  }
+// Note that we could encounter some performance loss through false-sharing as
+// multiple locks occupy the same $ line.  Padding might be appropriate.
 
-  // hashCode() is a heap mutator ...
-  // Relaxing assertion for bug 6320749.
-  assert (Universe::verify_in_progress() ||
-          !SafepointSynchronize::is_at_safepoint(), "invariant") ;
-  assert (Universe::verify_in_progress() ||
-          Self->is_Java_thread() , "invariant") ;
-  assert (Universe::verify_in_progress() ||
-         ((JavaThread *)Self)->thread_state() != _thread_blocked, "invariant") ;
-
-  ObjectMonitor* monitor = NULL;
-  markOop temp, test;
-  intptr_t hash;
-  markOop mark = ReadStableMark (obj);
-
-  // object should remain ineligible for biased locking
-  assert (!mark->has_bias_pattern(), "invariant") ;
-
-  if (mark->is_neutral()) {
-    hash = mark->hash();              // this is a normal header
-    if (hash) {                       // if it has hash, just return it
-      return hash;
-    }
-    hash = get_next_hash(Self, obj);  // allocate a new hash code
-    temp = mark->copy_set_hash(hash); // merge the hash code into header
-    // use (machine word version) atomic operation to install the hash
-    test = (markOop) Atomic::cmpxchg_ptr(temp, obj->mark_addr(), mark);
-    if (test == mark) {
-      return hash;
-    }
-    // If atomic operation failed, we must inflate the header
-    // into heavy weight monitor. We could add more code here
-    // for fast path, but it does not worth the complexity.
-  } else if (mark->has_monitor()) {
-    monitor = mark->monitor();
-    temp = monitor->header();
-    assert (temp->is_neutral(), "invariant") ;
-    hash = temp->hash();
-    if (hash) {
-      return hash;
-    }
-    // Skip to the following code to reduce code size
-  } else if (Self->is_lock_owned((address)mark->locker())) {
-    temp = mark->displaced_mark_helper(); // this is a lightweight monitor owned
-    assert (temp->is_neutral(), "invariant") ;
-    hash = temp->hash();              // by current thread, check if the displaced
-    if (hash) {                       // header contains hash code
-      return hash;
-    }
-    // WARNING:
-    //   The displaced header is strictly immutable.
-    // It can NOT be changed in ANY cases. So we have
-    // to inflate the header into heavyweight monitor
-    // even the current thread owns the lock. The reason
-    // is the BasicLock (stack slot) will be asynchronously
-    // read by other threads during the inflate() function.
-    // Any change to stack may not propagate to other threads
-    // correctly.
-  }
-
-  // Inflate the monitor to set hash code
-  monitor = ObjectSynchronizer::inflate(Self, obj);
-  // Load displaced header and check it has hash code
-  mark = monitor->header();
-  assert (mark->is_neutral(), "invariant") ;
-  hash = mark->hash();
-  if (hash == 0) {
-    hash = get_next_hash(Self, obj);
-    temp = mark->copy_set_hash(hash); // merge hash code into header
-    assert (temp->is_neutral(), "invariant") ;
-    test = (markOop) Atomic::cmpxchg_ptr(temp, monitor, mark);
-    if (test != mark) {
-      // The only update to the header in the monitor (outside GC)
-      // is install the hash code. If someone add new usage of
-      // displaced header, please update this code
-      hash = test->hash();
-      assert (test->is_neutral(), "invariant") ;
-      assert (hash != 0, "Trivial unexpected object/monitor header usage.");
-    }
-  }
-  // We finally get the hash
-  return hash;
-}
-
-// Deprecated -- use FastHashCode() instead.
-
-intptr_t ObjectSynchronizer::identity_hash_value_for(Handle obj) {
-  return FastHashCode (Thread::current(), obj()) ;
-}
-
-bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* thread,
-                                                   Handle h_obj) {
-  if (UseBiasedLocking) {
-    BiasedLocking::revoke_and_rebias(h_obj, false, thread);
-    assert(!h_obj->mark()->has_bias_pattern(), "biases should be revoked by now");
-  }
-
-  assert(thread == JavaThread::current(), "Can only be called on current thread");
-  oop obj = h_obj();
-
-  markOop mark = ReadStableMark (obj) ;
-
-  // Uncontended case, header points to stack
-  if (mark->has_locker()) {
-    return thread->is_lock_owned((address)mark->locker());
-  }
-  // Contended case, header points to ObjectMonitor (tagged pointer)
-  if (mark->has_monitor()) {
-    ObjectMonitor* monitor = mark->monitor();
-    return monitor->is_entered(thread) != 0 ;
-  }
-  // Unlocked case, header in place
-  assert(mark->is_neutral(), "sanity check");
-  return false;
-}
-
-// Be aware of this method could revoke bias of the lock object.
-// This method querys the ownership of the lock handle specified by 'h_obj'.
-// If the current thread owns the lock, it returns owner_self. If no
-// thread owns the lock, it returns owner_none. Otherwise, it will return
-// ower_other.
-ObjectSynchronizer::LockOwnership ObjectSynchronizer::query_lock_ownership
-(JavaThread *self, Handle h_obj) {
-  // The caller must beware this method can revoke bias, and
-  // revocation can result in a safepoint.
-  assert (!SafepointSynchronize::is_at_safepoint(), "invariant") ;
-  assert (self->thread_state() != _thread_blocked , "invariant") ;
-
-  // Possible mark states: neutral, biased, stack-locked, inflated
-
-  if (UseBiasedLocking && h_obj()->mark()->has_bias_pattern()) {
-    // CASE: biased
-    BiasedLocking::revoke_and_rebias(h_obj, false, self);
-    assert(!h_obj->mark()->has_bias_pattern(),
-           "biases should be revoked by now");
-  }
-
-  assert(self == JavaThread::current(), "Can only be called on current thread");
-  oop obj = h_obj();
-  markOop mark = ReadStableMark (obj) ;
-
-  // CASE: stack-locked.  Mark points to a BasicLock on the owner's stack.
-  if (mark->has_locker()) {
-    return self->is_lock_owned((address)mark->locker()) ?
-      owner_self : owner_other;
-  }
-
-  // CASE: inflated. Mark (tagged pointer) points to an objectMonitor.
-  // The Object:ObjectMonitor relationship is stable as long as we're
-  // not at a safepoint.
-  if (mark->has_monitor()) {
-    void * owner = mark->monitor()->_owner ;
-    if (owner == NULL) return owner_none ;
-    return (owner == self ||
-            self->is_lock_owned((address)owner)) ? owner_self : owner_other;
-  }
-
-  // CASE: neutral
-  assert(mark->is_neutral(), "sanity check");
-  return owner_none ;           // it's unlocked
-}
-
-// FIXME: jvmti should call this
-JavaThread* ObjectSynchronizer::get_lock_owner(Handle h_obj, bool doLock) {
-  if (UseBiasedLocking) {
-    if (SafepointSynchronize::is_at_safepoint()) {
-      BiasedLocking::revoke_at_safepoint(h_obj);
-    } else {
-      BiasedLocking::revoke_and_rebias(h_obj, false, JavaThread::current());
-    }
-    assert(!h_obj->mark()->has_bias_pattern(), "biases should be revoked by now");
-  }
-
-  oop obj = h_obj();
-  address owner = NULL;
-
-  markOop mark = ReadStableMark (obj) ;
-
-  // Uncontended case, header points to stack
-  if (mark->has_locker()) {
-    owner = (address) mark->locker();
-  }
-
-  // Contended case, header points to ObjectMonitor (tagged pointer)
-  if (mark->has_monitor()) {
-    ObjectMonitor* monitor = mark->monitor();
-    assert(monitor != NULL, "monitor should be non-null");
-    owner = (address) monitor->owner();
-  }
-
-  if (owner != NULL) {
-    return Threads::owning_thread_from_monitor_owner(owner, doLock);
-  }
-
-  // Unlocked case, header in place
-  // Cannot have assertion since this object may have been
-  // locked by another thread when reaching here.
-  // assert(mark->is_neutral(), "sanity check");
-
-  return NULL;
-}
-
-// Iterate through monitor cache and attempt to release thread's monitors
-// Gives up on a particular monitor if an exception occurs, but continues
-// the overall iteration, swallowing the exception.
-class ReleaseJavaMonitorsClosure: public MonitorClosure {
-private:
-  TRAPS;
-
-public:
-  ReleaseJavaMonitorsClosure(Thread* thread) : THREAD(thread) {}
-  void do_monitor(ObjectMonitor* mid) {
-    if (mid->owner() == THREAD) {
-      (void)mid->complete_exit(CHECK);
-    }
-  }
-};
-
-// Release all inflated monitors owned by THREAD.  Lightweight monitors are
-// ignored.  This is meant to be called during JNI thread detach which assumes
-// all remaining monitors are heavyweight.  All exceptions are swallowed.
-// Scanning the extant monitor list can be time consuming.
-// A simple optimization is to add a per-thread flag that indicates a thread
-// called jni_monitorenter() during its lifetime.
-//
-// Instead of No_Savepoint_Verifier it might be cheaper to
-// use an idiom of the form:
-//   auto int tmp = SafepointSynchronize::_safepoint_counter ;
-//   <code that must not run at safepoint>
-//   guarantee (((tmp ^ _safepoint_counter) | (tmp & 1)) == 0) ;
-// Since the tests are extremely cheap we could leave them enabled
-// for normal product builds.
-
-void ObjectSynchronizer::release_monitors_owned_by_thread(TRAPS) {
-  assert(THREAD == JavaThread::current(), "must be current Java thread");
-  No_Safepoint_Verifier nsv ;
-  ReleaseJavaMonitorsClosure rjmc(THREAD);
-  Thread::muxAcquire(&ListLock, "release_monitors_owned_by_thread");
-  ObjectSynchronizer::monitors_iterate(&rjmc);
-  Thread::muxRelease(&ListLock);
-  THREAD->clear_pending_exception();
-}
-
-// Visitors ...
-
-void ObjectSynchronizer::monitors_iterate(MonitorClosure* closure) {
-  ObjectMonitor* block = gBlockList;
-  ObjectMonitor* mid;
-  while (block) {
-    assert(block->object() == CHAINMARKER, "must be a block header");
-    for (int i = _BLOCKSIZE - 1; i > 0; i--) {
-      mid = block + i;
-      oop object = (oop) mid->object();
-      if (object != NULL) {
-        closure->do_monitor(mid);
-      }
-    }
-    block = (ObjectMonitor*) block->FreeNext;
-  }
-}
-
-void ObjectSynchronizer::oops_do(OopClosure* f) {
-  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
-  for (ObjectMonitor* block = gBlockList; block != NULL; block = next(block)) {
-    assert(block->object() == CHAINMARKER, "must be a block header");
-    for (int i = 1; i < _BLOCKSIZE; i++) {
-      ObjectMonitor* mid = &block[i];
-      if (mid->object() != NULL) {
-        f->do_oop((oop*)mid->object_addr());
-      }
-    }
-  }
-}
 
 // Deflate_idle_monitors() is called at all safepoints, immediately
 // after all mutators are stopped, but before any objects have moved.
@@ -1936,12 +1357,11 @@
 // which in turn can mean large(r) numbers of objectmonitors in circulation.
 // This is an unfortunate aspect of this design.
 //
-// Another refinement would be to refrain from calling deflate_idle_monitors()
-// except at stop-the-world points associated with garbage collections.
-//
-// An even better solution would be to deflate on-the-fly, aggressively,
-// at monitorexit-time as is done in EVM's metalock or Relaxed Locks.
 
+enum ManifestConstants {
+    ClearResponsibleAtSTW   = 0,
+    MaximumRecheckInterval  = 1000
+} ;
 
 // Deflate a single monitor if not in use
 // Return true if deflated, false if in use
@@ -2088,7 +1508,7 @@
 
   // Consider: audit gFreeList to ensure that MonitorFreeCount and list agree.
 
-  if (Knob_Verbose) {
+  if (ObjectMonitor::Knob_Verbose) {
     ::printf ("Deflate: InCirc=%d InUse=%d Scavenged=%d ForceMonitorScavenge=%d : pop=%d free=%d\n",
         nInCirculation, nInuse, nScavenged, ForceMonitorScavenge,
         MonitorPopulation, MonitorFreeCount) ;
@@ -2107,8 +1527,8 @@
   }
   Thread::muxRelease (&ListLock) ;
 
-  if (_sync_Deflations != NULL) _sync_Deflations->inc(nScavenged) ;
-  if (_sync_MonExtant  != NULL) _sync_MonExtant ->set_value(nInCirculation);
+  if (ObjectMonitor::_sync_Deflations != NULL) ObjectMonitor::_sync_Deflations->inc(nScavenged) ;
+  if (ObjectMonitor::_sync_MonExtant  != NULL) ObjectMonitor::_sync_MonExtant ->set_value(nInCirculation);
 
   // TODO: Add objectMonitor leak detection.
   // Audit/inventory the objectMonitors -- make sure they're all accounted for.
@@ -2116,2810 +1536,49 @@
   GVars.stwCycle ++ ;
 }
 
-// A macro is used below because there may already be a pending
-// exception which should not abort the execution of the routines
-// which use this (which is why we don't put this into check_slow and
-// call it with a CHECK argument).
-
-#define CHECK_OWNER()                                                             \
-  do {                                                                            \
-    if (THREAD != _owner) {                                                       \
-      if (THREAD->is_lock_owned((address) _owner)) {                              \
-        _owner = THREAD ;  /* Convert from basiclock addr to Thread addr */       \
-        _recursions = 0;                                                          \
-        OwnerIsThread = 1 ;                                                       \
-      } else {                                                                    \
-        TEVENT (Throw IMSX) ;                                                     \
-        THROW(vmSymbols::java_lang_IllegalMonitorStateException());               \
-      }                                                                           \
-    }                                                                             \
-  } while (false)
-
-// TODO-FIXME: eliminate ObjectWaiters.  Replace this visitor/enumerator
-// interface with a simple FirstWaitingThread(), NextWaitingThread() interface.
-
-ObjectWaiter* ObjectMonitor::first_waiter() {
-  return _WaitSet;
-}
-
-ObjectWaiter* ObjectMonitor::next_waiter(ObjectWaiter* o) {
-  return o->_next;
-}
-
-Thread* ObjectMonitor::thread_of_waiter(ObjectWaiter* o) {
-  return o->_thread;
-}
-
-// initialize the monitor, exception the semaphore, all other fields
-// are simple integers or pointers
-ObjectMonitor::ObjectMonitor() {
-  _header       = NULL;
-  _count        = 0;
-  _waiters      = 0,
-  _recursions   = 0;
-  _object       = NULL;
-  _owner        = NULL;
-  _WaitSet      = NULL;
-  _WaitSetLock  = 0 ;
-  _Responsible  = NULL ;
-  _succ         = NULL ;
-  _cxq          = NULL ;
-  FreeNext      = NULL ;
-  _EntryList    = NULL ;
-  _SpinFreq     = 0 ;
-  _SpinClock    = 0 ;
-  OwnerIsThread = 0 ;
-}
-
-ObjectMonitor::~ObjectMonitor() {
-   // TODO: Add asserts ...
-   // _cxq == 0 _succ == NULL _owner == NULL _waiters == 0
-   // _count == 0 _EntryList  == NULL etc
-}
+// Monitor cleanup on JavaThread::exit
 
-intptr_t ObjectMonitor::is_busy() const {
-  // TODO-FIXME: merge _count and _waiters.
-  // TODO-FIXME: assert _owner == null implies _recursions = 0
-  // TODO-FIXME: assert _WaitSet != null implies _count > 0
-  return _count|_waiters|intptr_t(_owner)|intptr_t(_cxq)|intptr_t(_EntryList ) ;
-}
-
-void ObjectMonitor::Recycle () {
-  // TODO: add stronger asserts ...
-  // _cxq == 0 _succ == NULL _owner == NULL _waiters == 0
-  // _count == 0 EntryList  == NULL
-  // _recursions == 0 _WaitSet == NULL
-  // TODO: assert (is_busy()|_recursions) == 0
-  _succ          = NULL ;
-  _EntryList     = NULL ;
-  _cxq           = NULL ;
-  _WaitSet       = NULL ;
-  _recursions    = 0 ;
-  _SpinFreq      = 0 ;
-  _SpinClock     = 0 ;
-  OwnerIsThread  = 0 ;
-}
-
-// WaitSet management ...
+// Iterate through monitor cache and attempt to release thread's monitors
+// Gives up on a particular monitor if an exception occurs, but continues
+// the overall iteration, swallowing the exception.
+class ReleaseJavaMonitorsClosure: public MonitorClosure {
+private:
+  TRAPS;
 
-inline void ObjectMonitor::AddWaiter(ObjectWaiter* node) {
-  assert(node != NULL, "should not dequeue NULL node");
-  assert(node->_prev == NULL, "node already in list");
-  assert(node->_next == NULL, "node already in list");
-  // put node at end of queue (circular doubly linked list)
-  if (_WaitSet == NULL) {
-    _WaitSet = node;
-    node->_prev = node;
-    node->_next = node;
-  } else {
-    ObjectWaiter* head = _WaitSet ;
-    ObjectWaiter* tail = head->_prev;
-    assert(tail->_next == head, "invariant check");
-    tail->_next = node;
-    head->_prev = node;
-    node->_next = head;
-    node->_prev = tail;
-  }
-}
-
-inline ObjectWaiter* ObjectMonitor::DequeueWaiter() {
-  // dequeue the very first waiter
-  ObjectWaiter* waiter = _WaitSet;
-  if (waiter) {
-    DequeueSpecificWaiter(waiter);
-  }
-  return waiter;
-}
-
-inline void ObjectMonitor::DequeueSpecificWaiter(ObjectWaiter* node) {
-  assert(node != NULL, "should not dequeue NULL node");
-  assert(node->_prev != NULL, "node already removed from list");
-  assert(node->_next != NULL, "node already removed from list");
-  // when the waiter has woken up because of interrupt,
-  // timeout or other spurious wake-up, dequeue the
-  // waiter from waiting list
-  ObjectWaiter* next = node->_next;
-  if (next == node) {
-    assert(node->_prev == node, "invariant check");
-    _WaitSet = NULL;
-  } else {
-    ObjectWaiter* prev = node->_prev;
-    assert(prev->_next == node, "invariant check");
-    assert(next->_prev == node, "invariant check");
-    next->_prev = prev;
-    prev->_next = next;
-    if (_WaitSet == node) {
-      _WaitSet = next;
+public:
+  ReleaseJavaMonitorsClosure(Thread* thread) : THREAD(thread) {}
+  void do_monitor(ObjectMonitor* mid) {
+    if (mid->owner() == THREAD) {
+      (void)mid->complete_exit(CHECK);
     }
   }
-  node->_next = NULL;
-  node->_prev = NULL;
-}
-
-static char * kvGet (char * kvList, const char * Key) {
-    if (kvList == NULL) return NULL ;
-    size_t n = strlen (Key) ;
-    char * Search ;
-    for (Search = kvList ; *Search ; Search += strlen(Search) + 1) {
-        if (strncmp (Search, Key, n) == 0) {
-            if (Search[n] == '=') return Search + n + 1 ;
-            if (Search[n] == 0)   return (char *) "1" ;
-        }
-    }
-    return NULL ;
-}
-
-static int kvGetInt (char * kvList, const char * Key, int Default) {
-    char * v = kvGet (kvList, Key) ;
-    int rslt = v ? ::strtol (v, NULL, 0) : Default ;
-    if (Knob_ReportSettings && v != NULL) {
-        ::printf ("  SyncKnob: %s %d(%d)\n", Key, rslt, Default) ;
-        ::fflush (stdout) ;
-    }
-    return rslt ;
-}
-
-// By convention we unlink a contending thread from EntryList|cxq immediately
-// after the thread acquires the lock in ::enter().  Equally, we could defer
-// unlinking the thread until ::exit()-time.
-
-void ObjectMonitor::UnlinkAfterAcquire (Thread * Self, ObjectWaiter * SelfNode)
-{
-    assert (_owner == Self, "invariant") ;
-    assert (SelfNode->_thread == Self, "invariant") ;
-
-    if (SelfNode->TState == ObjectWaiter::TS_ENTER) {
-        // Normal case: remove Self from the DLL EntryList .
-        // This is a constant-time operation.
-        ObjectWaiter * nxt = SelfNode->_next ;
-        ObjectWaiter * prv = SelfNode->_prev ;
-        if (nxt != NULL) nxt->_prev = prv ;
-        if (prv != NULL) prv->_next = nxt ;
-        if (SelfNode == _EntryList ) _EntryList = nxt ;
-        assert (nxt == NULL || nxt->TState == ObjectWaiter::TS_ENTER, "invariant") ;
-        assert (prv == NULL || prv->TState == ObjectWaiter::TS_ENTER, "invariant") ;
-        TEVENT (Unlink from EntryList) ;
-    } else {
-        guarantee (SelfNode->TState == ObjectWaiter::TS_CXQ, "invariant") ;
-        // Inopportune interleaving -- Self is still on the cxq.
-        // This usually means the enqueue of self raced an exiting thread.
-        // Normally we'll find Self near the front of the cxq, so
-        // dequeueing is typically fast.  If needbe we can accelerate
-        // this with some MCS/CHL-like bidirectional list hints and advisory
-        // back-links so dequeueing from the interior will normally operate
-        // in constant-time.
-        // Dequeue Self from either the head (with CAS) or from the interior
-        // with a linear-time scan and normal non-atomic memory operations.
-        // CONSIDER: if Self is on the cxq then simply drain cxq into EntryList
-        // and then unlink Self from EntryList.  We have to drain eventually,
-        // so it might as well be now.
-
-        ObjectWaiter * v = _cxq ;
-        assert (v != NULL, "invariant") ;
-        if (v != SelfNode || Atomic::cmpxchg_ptr (SelfNode->_next, &_cxq, v) != v) {
-            // The CAS above can fail from interference IFF a "RAT" arrived.
-            // In that case Self must be in the interior and can no longer be
-            // at the head of cxq.
-            if (v == SelfNode) {
-                assert (_cxq != v, "invariant") ;
-                v = _cxq ;          // CAS above failed - start scan at head of list
-            }
-            ObjectWaiter * p ;
-            ObjectWaiter * q = NULL ;
-            for (p = v ; p != NULL && p != SelfNode; p = p->_next) {
-                q = p ;
-                assert (p->TState == ObjectWaiter::TS_CXQ, "invariant") ;
-            }
-            assert (v != SelfNode,  "invariant") ;
-            assert (p == SelfNode,  "Node not found on cxq") ;
-            assert (p != _cxq,      "invariant") ;
-            assert (q != NULL,      "invariant") ;
-            assert (q->_next == p,  "invariant") ;
-            q->_next = p->_next ;
-        }
-        TEVENT (Unlink from cxq) ;
-    }
-
-    // Diagnostic hygiene ...
-    SelfNode->_prev  = (ObjectWaiter *) 0xBAD ;
-    SelfNode->_next  = (ObjectWaiter *) 0xBAD ;
-    SelfNode->TState = ObjectWaiter::TS_RUN ;
-}
-
-// Caveat: TryLock() is not necessarily serializing if it returns failure.
-// Callers must compensate as needed.
-
-int ObjectMonitor::TryLock (Thread * Self) {
-   for (;;) {
-      void * own = _owner ;
-      if (own != NULL) return 0 ;
-      if (Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {
-         // Either guarantee _recursions == 0 or set _recursions = 0.
-         assert (_recursions == 0, "invariant") ;
-         assert (_owner == Self, "invariant") ;
-         // CONSIDER: set or assert that OwnerIsThread == 1
-         return 1 ;
-      }
-      // The lock had been free momentarily, but we lost the race to the lock.
-      // Interference -- the CAS failed.
-      // We can either return -1 or retry.
-      // Retry doesn't make as much sense because the lock was just acquired.
-      if (true) return -1 ;
-   }
-}
-
-// NotRunnable() -- informed spinning
-//
-// Don't bother spinning if the owner is not eligible to drop the lock.
-// Peek at the owner's schedctl.sc_state and Thread._thread_values and
-// spin only if the owner thread is _thread_in_Java or _thread_in_vm.
-// The thread must be runnable in order to drop the lock in timely fashion.
-// If the _owner is not runnable then spinning will not likely be
-// successful (profitable).
-//
-// Beware -- the thread referenced by _owner could have died
-// so a simply fetch from _owner->_thread_state might trap.
-// Instead, we use SafeFetchXX() to safely LD _owner->_thread_state.
-// Because of the lifecycle issues the schedctl and _thread_state values
-// observed by NotRunnable() might be garbage.  NotRunnable must
-// tolerate this and consider the observed _thread_state value
-// as advisory.
-//
-// Beware too, that _owner is sometimes a BasicLock address and sometimes
-// a thread pointer.  We differentiate the two cases with OwnerIsThread.
-// Alternately, we might tag the type (thread pointer vs basiclock pointer)
-// with the LSB of _owner.  Another option would be to probablistically probe
-// the putative _owner->TypeTag value.
-//
-// Checking _thread_state isn't perfect.  Even if the thread is
-// in_java it might be blocked on a page-fault or have been preempted
-// and sitting on a ready/dispatch queue.  _thread state in conjunction
-// with schedctl.sc_state gives us a good picture of what the
-// thread is doing, however.
-//
-// TODO: check schedctl.sc_state.
-// We'll need to use SafeFetch32() to read from the schedctl block.
-// See RFE #5004247 and http://sac.sfbay.sun.com/Archives/CaseLog/arc/PSARC/2005/351/
-//
-// The return value from NotRunnable() is *advisory* -- the
-// result is based on sampling and is not necessarily coherent.
-// The caller must tolerate false-negative and false-positive errors.
-// Spinning, in general, is probabilistic anyway.
-
-
-int ObjectMonitor::NotRunnable (Thread * Self, Thread * ox) {
-    // Check either OwnerIsThread or ox->TypeTag == 2BAD.
-    if (!OwnerIsThread) return 0 ;
-
-    if (ox == NULL) return 0 ;
-
-    // Avoid transitive spinning ...
-    // Say T1 spins or blocks trying to acquire L.  T1._Stalled is set to L.
-    // Immediately after T1 acquires L it's possible that T2, also
-    // spinning on L, will see L.Owner=T1 and T1._Stalled=L.
-    // This occurs transiently after T1 acquired L but before
-    // T1 managed to clear T1.Stalled.  T2 does not need to abort
-    // its spin in this circumstance.
-    intptr_t BlockedOn = SafeFetchN ((intptr_t *) &ox->_Stalled, intptr_t(1)) ;
-
-    if (BlockedOn == 1) return 1 ;
-    if (BlockedOn != 0) {
-      return BlockedOn != intptr_t(this) && _owner == ox ;
-    }
-
-    assert (sizeof(((JavaThread *)ox)->_thread_state == sizeof(int)), "invariant") ;
-    int jst = SafeFetch32 ((int *) &((JavaThread *) ox)->_thread_state, -1) ; ;
-    // consider also: jst != _thread_in_Java -- but that's overspecific.
-    return jst == _thread_blocked || jst == _thread_in_native ;
-}
-
-
-// Adaptive spin-then-block - rational spinning
-//
-// Note that we spin "globally" on _owner with a classic SMP-polite TATAS
-// algorithm.  On high order SMP systems it would be better to start with
-// a brief global spin and then revert to spinning locally.  In the spirit of MCS/CLH,
-// a contending thread could enqueue itself on the cxq and then spin locally
-// on a thread-specific variable such as its ParkEvent._Event flag.
-// That's left as an exercise for the reader.  Note that global spinning is
-// not problematic on Niagara, as the L2$ serves the interconnect and has both
-// low latency and massive bandwidth.
-//
-// Broadly, we can fix the spin frequency -- that is, the % of contended lock
-// acquisition attempts where we opt to spin --  at 100% and vary the spin count
-// (duration) or we can fix the count at approximately the duration of
-// a context switch and vary the frequency.   Of course we could also
-// vary both satisfying K == Frequency * Duration, where K is adaptive by monitor.
-// See http://j2se.east/~dice/PERSIST/040824-AdaptiveSpinning.html.
-//
-// This implementation varies the duration "D", where D varies with
-// the success rate of recent spin attempts. (D is capped at approximately
-// length of a round-trip context switch).  The success rate for recent
-// spin attempts is a good predictor of the success rate of future spin
-// attempts.  The mechanism adapts automatically to varying critical
-// section length (lock modality), system load and degree of parallelism.
-// D is maintained per-monitor in _SpinDuration and is initialized
-// optimistically.  Spin frequency is fixed at 100%.
-//
-// Note that _SpinDuration is volatile, but we update it without locks
-// or atomics.  The code is designed so that _SpinDuration stays within
-// a reasonable range even in the presence of races.  The arithmetic
-// operations on _SpinDuration are closed over the domain of legal values,
-// so at worst a race will install and older but still legal value.
-// At the very worst this introduces some apparent non-determinism.
-// We might spin when we shouldn't or vice-versa, but since the spin
-// count are relatively short, even in the worst case, the effect is harmless.
-//
-// Care must be taken that a low "D" value does not become an
-// an absorbing state.  Transient spinning failures -- when spinning
-// is overall profitable -- should not cause the system to converge
-// on low "D" values.  We want spinning to be stable and predictable
-// and fairly responsive to change and at the same time we don't want
-// it to oscillate, become metastable, be "too" non-deterministic,
-// or converge on or enter undesirable stable absorbing states.
-//
-// We implement a feedback-based control system -- using past behavior
-// to predict future behavior.  We face two issues: (a) if the
-// input signal is random then the spin predictor won't provide optimal
-// results, and (b) if the signal frequency is too high then the control
-// system, which has some natural response lag, will "chase" the signal.
-// (b) can arise from multimodal lock hold times.  Transient preemption
-// can also result in apparent bimodal lock hold times.
-// Although sub-optimal, neither condition is particularly harmful, as
-// in the worst-case we'll spin when we shouldn't or vice-versa.
-// The maximum spin duration is rather short so the failure modes aren't bad.
-// To be conservative, I've tuned the gain in system to bias toward
-// _not spinning.  Relatedly, the system can sometimes enter a mode where it
-// "rings" or oscillates between spinning and not spinning.  This happens
-// when spinning is just on the cusp of profitability, however, so the
-// situation is not dire.  The state is benign -- there's no need to add
-// hysteresis control to damp the transition rate between spinning and
-// not spinning.
-//
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-//
-// Spin-then-block strategies ...
-//
-// Thoughts on ways to improve spinning :
-//
-// *  Periodically call {psr_}getloadavg() while spinning, and
-//    permit unbounded spinning if the load average is <
-//    the number of processors.  Beware, however, that getloadavg()
-//    is exceptionally fast on solaris (about 1/10 the cost of a full
-//    spin cycle, but quite expensive on linux.  Beware also, that
-//    multiple JVMs could "ring" or oscillate in a feedback loop.
-//    Sufficient damping would solve that problem.
-//
-// *  We currently use spin loops with iteration counters to approximate
-//    spinning for some interval.  Given the availability of high-precision
-//    time sources such as gethrtime(), %TICK, %STICK, RDTSC, etc., we should
-//    someday reimplement the spin loops to duration-based instead of iteration-based.
-//
-// *  Don't spin if there are more than N = (CPUs/2) threads
-//        currently spinning on the monitor (or globally).
-//    That is, limit the number of concurrent spinners.
-//    We might also limit the # of spinners in the JVM, globally.
-//
-// *  If a spinning thread observes _owner change hands it should
-//    abort the spin (and park immediately) or at least debit
-//    the spin counter by a large "penalty".
-//
-// *  Classically, the spin count is either K*(CPUs-1) or is a
-//        simple constant that approximates the length of a context switch.
-//    We currently use a value -- computed by a special utility -- that
-//    approximates round-trip context switch times.
-//
-// *  Normally schedctl_start()/_stop() is used to advise the kernel
-//    to avoid preempting threads that are running in short, bounded
-//    critical sections.  We could use the schedctl hooks in an inverted
-//    sense -- spinners would set the nopreempt flag, but poll the preempt
-//    pending flag.  If a spinner observed a pending preemption it'd immediately
-//    abort the spin and park.   As such, the schedctl service acts as
-//    a preemption warning mechanism.
-//
-// *  In lieu of spinning, if the system is running below saturation
-//    (that is, loadavg() << #cpus), we can instead suppress futile
-//    wakeup throttling, or even wake more than one successor at exit-time.
-//    The net effect is largely equivalent to spinning.  In both cases,
-//    contending threads go ONPROC and opportunistically attempt to acquire
-//    the lock, decreasing lock handover latency at the expense of wasted
-//    cycles and context switching.
-//
-// *  We might to spin less after we've parked as the thread will
-//    have less $ and TLB affinity with the processor.
-//    Likewise, we might spin less if we come ONPROC on a different
-//    processor or after a long period (>> rechose_interval).
-//
-// *  A table-driven state machine similar to Solaris' dispadmin scheduling
-//    tables might be a better design.  Instead of encoding information in
-//    _SpinDuration, _SpinFreq and _SpinClock we'd just use explicit,
-//    discrete states.   Success or failure during a spin would drive
-//    state transitions, and each state node would contain a spin count.
-//
-// *  If the processor is operating in a mode intended to conserve power
-//    (such as Intel's SpeedStep) or to reduce thermal output (thermal
-//    step-down mode) then the Java synchronization subsystem should
-//    forgo spinning.
-//
-// *  The minimum spin duration should be approximately the worst-case
-//    store propagation latency on the platform.  That is, the time
-//    it takes a store on CPU A to become visible on CPU B, where A and
-//    B are "distant".
-//
-// *  We might want to factor a thread's priority in the spin policy.
-//    Threads with a higher priority might spin for slightly longer.
-//    Similarly, if we use back-off in the TATAS loop, lower priority
-//    threads might back-off longer.  We don't currently use a
-//    thread's priority when placing it on the entry queue.  We may
-//    want to consider doing so in future releases.
-//
-// *  We might transiently drop a thread's scheduling priority while it spins.
-//    SCHED_BATCH on linux and FX scheduling class at priority=0 on Solaris
-//    would suffice.  We could even consider letting the thread spin indefinitely at
-//    a depressed or "idle" priority.  This brings up fairness issues, however --
-//    in a saturated system a thread would with a reduced priority could languish
-//    for extended periods on the ready queue.
-//
-// *  While spinning try to use the otherwise wasted time to help the VM make
-//    progress:
-//
-//    -- YieldTo() the owner, if the owner is OFFPROC but ready
-//       Done our remaining quantum directly to the ready thread.
-//       This helps "push" the lock owner through the critical section.
-//       It also tends to improve affinity/locality as the lock
-//       "migrates" less frequently between CPUs.
-//    -- Walk our own stack in anticipation of blocking.  Memoize the roots.
-//    -- Perform strand checking for other thread.  Unpark potential strandees.
-//    -- Help GC: trace or mark -- this would need to be a bounded unit of work.
-//       Unfortunately this will pollute our $ and TLBs.  Recall that we
-//       spin to avoid context switching -- context switching has an
-//       immediate cost in latency, a disruptive cost to other strands on a CMT
-//       processor, and an amortized cost because of the D$ and TLB cache
-//       reload transient when the thread comes back ONPROC and repopulates
-//       $s and TLBs.
-//    -- call getloadavg() to see if the system is saturated.  It'd probably
-//       make sense to call getloadavg() half way through the spin.
-//       If the system isn't at full capacity the we'd simply reset
-//       the spin counter to and extend the spin attempt.
-//    -- Doug points out that we should use the same "helping" policy
-//       in thread.yield().
-//
-// *  Try MONITOR-MWAIT on systems that support those instructions.
-//
-// *  The spin statistics that drive spin decisions & frequency are
-//    maintained in the objectmonitor structure so if we deflate and reinflate
-//    we lose spin state.  In practice this is not usually a concern
-//    as the default spin state after inflation is aggressive (optimistic)
-//    and tends toward spinning.  So in the worst case for a lock where
-//    spinning is not profitable we may spin unnecessarily for a brief
-//    period.  But then again, if a lock is contended it'll tend not to deflate
-//    in the first place.
-
-
-intptr_t ObjectMonitor::SpinCallbackArgument = 0 ;
-int (*ObjectMonitor::SpinCallbackFunction)(intptr_t, int) = NULL ;
-
-// Spinning: Fixed frequency (100%), vary duration
-
-int ObjectMonitor::TrySpin_VaryDuration (Thread * Self) {
-
-    // Dumb, brutal spin.  Good for comparative measurements against adaptive spinning.
-    int ctr = Knob_FixedSpin ;
-    if (ctr != 0) {
-        while (--ctr >= 0) {
-            if (TryLock (Self) > 0) return 1 ;
-            SpinPause () ;
-        }
-        return 0 ;
-    }
-
-    for (ctr = Knob_PreSpin + 1; --ctr >= 0 ; ) {
-      if (TryLock(Self) > 0) {
-        // Increase _SpinDuration ...
-        // Note that we don't clamp SpinDuration precisely at SpinLimit.
-        // Raising _SpurDuration to the poverty line is key.
-        int x = _SpinDuration ;
-        if (x < Knob_SpinLimit) {
-           if (x < Knob_Poverty) x = Knob_Poverty ;
-           _SpinDuration = x + Knob_BonusB ;
-        }
-        return 1 ;
-      }
-      SpinPause () ;
-    }
-
-    // Admission control - verify preconditions for spinning
-    //
-    // We always spin a little bit, just to prevent _SpinDuration == 0 from
-    // becoming an absorbing state.  Put another way, we spin briefly to
-    // sample, just in case the system load, parallelism, contention, or lock
-    // modality changed.
-    //
-    // Consider the following alternative:
-    // Periodically set _SpinDuration = _SpinLimit and try a long/full
-    // spin attempt.  "Periodically" might mean after a tally of
-    // the # of failed spin attempts (or iterations) reaches some threshold.
-    // This takes us into the realm of 1-out-of-N spinning, where we
-    // hold the duration constant but vary the frequency.
-
-    ctr = _SpinDuration  ;
-    if (ctr < Knob_SpinBase) ctr = Knob_SpinBase ;
-    if (ctr <= 0) return 0 ;
-
-    if (Knob_SuccRestrict && _succ != NULL) return 0 ;
-    if (Knob_OState && NotRunnable (Self, (Thread *) _owner)) {
-       TEVENT (Spin abort - notrunnable [TOP]);
-       return 0 ;
-    }
-
-    int MaxSpin = Knob_MaxSpinners ;
-    if (MaxSpin >= 0) {
-       if (_Spinner > MaxSpin) {
-          TEVENT (Spin abort -- too many spinners) ;
-          return 0 ;
-       }
-       // Slighty racy, but benign ...
-       Adjust (&_Spinner, 1) ;
-    }
-
-    // We're good to spin ... spin ingress.
-    // CONSIDER: use Prefetch::write() to avoid RTS->RTO upgrades
-    // when preparing to LD...CAS _owner, etc and the CAS is likely
-    // to succeed.
-    int hits    = 0 ;
-    int msk     = 0 ;
-    int caspty  = Knob_CASPenalty ;
-    int oxpty   = Knob_OXPenalty ;
-    int sss     = Knob_SpinSetSucc ;
-    if (sss && _succ == NULL ) _succ = Self ;
-    Thread * prv = NULL ;
-
-    // There are three ways to exit the following loop:
-    // 1.  A successful spin where this thread has acquired the lock.
-    // 2.  Spin failure with prejudice
-    // 3.  Spin failure without prejudice
-
-    while (--ctr >= 0) {
-
-      // Periodic polling -- Check for pending GC
-      // Threads may spin while they're unsafe.
-      // We don't want spinning threads to delay the JVM from reaching
-      // a stop-the-world safepoint or to steal cycles from GC.
-      // If we detect a pending safepoint we abort in order that
-      // (a) this thread, if unsafe, doesn't delay the safepoint, and (b)
-      // this thread, if safe, doesn't steal cycles from GC.
-      // This is in keeping with the "no loitering in runtime" rule.
-      // We periodically check to see if there's a safepoint pending.
-      if ((ctr & 0xFF) == 0) {
-         if (SafepointSynchronize::do_call_back()) {
-            TEVENT (Spin: safepoint) ;
-            goto Abort ;           // abrupt spin egress
-         }
-         if (Knob_UsePause & 1) SpinPause () ;
-
-         int (*scb)(intptr_t,int) = SpinCallbackFunction ;
-         if (hits > 50 && scb != NULL) {
-            int abend = (*scb)(SpinCallbackArgument, 0) ;
-         }
-      }
-
-      if (Knob_UsePause & 2) SpinPause() ;
-
-      // Exponential back-off ...  Stay off the bus to reduce coherency traffic.
-      // This is useful on classic SMP systems, but is of less utility on
-      // N1-style CMT platforms.
-      //
-      // Trade-off: lock acquisition latency vs coherency bandwidth.
-      // Lock hold times are typically short.  A histogram
-      // of successful spin attempts shows that we usually acquire
-      // the lock early in the spin.  That suggests we want to
-      // sample _owner frequently in the early phase of the spin,
-      // but then back-off and sample less frequently as the spin
-      // progresses.  The back-off makes a good citizen on SMP big
-      // SMP systems.  Oversampling _owner can consume excessive
-      // coherency bandwidth.  Relatedly, if we _oversample _owner we
-      // can inadvertently interfere with the the ST m->owner=null.
-      // executed by the lock owner.
-      if (ctr & msk) continue ;
-      ++hits ;
-      if ((hits & 0xF) == 0) {
-        // The 0xF, above, corresponds to the exponent.
-        // Consider: (msk+1)|msk
-        msk = ((msk << 2)|3) & BackOffMask ;
-      }
-
-      // Probe _owner with TATAS
-      // If this thread observes the monitor transition or flicker
-      // from locked to unlocked to locked, then the odds that this
-      // thread will acquire the lock in this spin attempt go down
-      // considerably.  The same argument applies if the CAS fails
-      // or if we observe _owner change from one non-null value to
-      // another non-null value.   In such cases we might abort
-      // the spin without prejudice or apply a "penalty" to the
-      // spin count-down variable "ctr", reducing it by 100, say.
-
-      Thread * ox = (Thread *) _owner ;
-      if (ox == NULL) {
-         ox = (Thread *) Atomic::cmpxchg_ptr (Self, &_owner, NULL) ;
-         if (ox == NULL) {
-            // The CAS succeeded -- this thread acquired ownership
-            // Take care of some bookkeeping to exit spin state.
-            if (sss && _succ == Self) {
-               _succ = NULL ;
-            }
-            if (MaxSpin > 0) Adjust (&_Spinner, -1) ;
-
-            // Increase _SpinDuration :
-            // The spin was successful (profitable) so we tend toward
-            // longer spin attempts in the future.
-            // CONSIDER: factor "ctr" into the _SpinDuration adjustment.
-            // If we acquired the lock early in the spin cycle it
-            // makes sense to increase _SpinDuration proportionally.
-            // Note that we don't clamp SpinDuration precisely at SpinLimit.
-            int x = _SpinDuration ;
-            if (x < Knob_SpinLimit) {
-                if (x < Knob_Poverty) x = Knob_Poverty ;
-                _SpinDuration = x + Knob_Bonus ;
-            }
-            return 1 ;
-         }
-
-         // The CAS failed ... we can take any of the following actions:
-         // * penalize: ctr -= Knob_CASPenalty
-         // * exit spin with prejudice -- goto Abort;
-         // * exit spin without prejudice.
-         // * Since CAS is high-latency, retry again immediately.
-         prv = ox ;
-         TEVENT (Spin: cas failed) ;
-         if (caspty == -2) break ;
-         if (caspty == -1) goto Abort ;
-         ctr -= caspty ;
-         continue ;
-      }
-
-      // Did lock ownership change hands ?
-      if (ox != prv && prv != NULL ) {
-          TEVENT (spin: Owner changed)
-          if (oxpty == -2) break ;
-          if (oxpty == -1) goto Abort ;
-          ctr -= oxpty ;
-      }
-      prv = ox ;
-
-      // Abort the spin if the owner is not executing.
-      // The owner must be executing in order to drop the lock.
-      // Spinning while the owner is OFFPROC is idiocy.
-      // Consider: ctr -= RunnablePenalty ;
-      if (Knob_OState && NotRunnable (Self, ox)) {
-         TEVENT (Spin abort - notrunnable);
-         goto Abort ;
-      }
-      if (sss && _succ == NULL ) _succ = Self ;
-   }
-
-   // Spin failed with prejudice -- reduce _SpinDuration.
-   // TODO: Use an AIMD-like policy to adjust _SpinDuration.
-   // AIMD is globally stable.
-   TEVENT (Spin failure) ;
-   {
-     int x = _SpinDuration ;
-     if (x > 0) {
-        // Consider an AIMD scheme like: x -= (x >> 3) + 100
-        // This is globally sample and tends to damp the response.
-        x -= Knob_Penalty ;
-        if (x < 0) x = 0 ;
-        _SpinDuration = x ;
-     }
-   }
-
- Abort:
-   if (MaxSpin >= 0) Adjust (&_Spinner, -1) ;
-   if (sss && _succ == Self) {
-      _succ = NULL ;
-      // Invariant: after setting succ=null a contending thread
-      // must recheck-retry _owner before parking.  This usually happens
-      // in the normal usage of TrySpin(), but it's safest
-      // to make TrySpin() as foolproof as possible.
-      OrderAccess::fence() ;
-      if (TryLock(Self) > 0) return 1 ;
-   }
-   return 0 ;
-}
-
-#define TrySpin TrySpin_VaryDuration
-
-static void DeferredInitialize () {
-  if (InitDone > 0) return ;
-  if (Atomic::cmpxchg (-1, &InitDone, 0) != 0) {
-      while (InitDone != 1) ;
-      return ;
-  }
-
-  // One-shot global initialization ...
-  // The initialization is idempotent, so we don't need locks.
-  // In the future consider doing this via os::init_2().
-  // SyncKnobs consist of <Key>=<Value> pairs in the style
-  // of environment variables.  Start by converting ':' to NUL.
-
-  if (SyncKnobs == NULL) SyncKnobs = "" ;
-
-  size_t sz = strlen (SyncKnobs) ;
-  char * knobs = (char *) malloc (sz + 2) ;
-  if (knobs == NULL) {
-     vm_exit_out_of_memory (sz + 2, "Parse SyncKnobs") ;
-     guarantee (0, "invariant") ;
-  }
-  strcpy (knobs, SyncKnobs) ;
-  knobs[sz+1] = 0 ;
-  for (char * p = knobs ; *p ; p++) {
-     if (*p == ':') *p = 0 ;
-  }
-
-  #define SETKNOB(x) { Knob_##x = kvGetInt (knobs, #x, Knob_##x); }
-  SETKNOB(ReportSettings) ;
-  SETKNOB(Verbose) ;
-  SETKNOB(FixedSpin) ;
-  SETKNOB(SpinLimit) ;
-  SETKNOB(SpinBase) ;
-  SETKNOB(SpinBackOff);
-  SETKNOB(CASPenalty) ;
-  SETKNOB(OXPenalty) ;
-  SETKNOB(LogSpins) ;
-  SETKNOB(SpinSetSucc) ;
-  SETKNOB(SuccEnabled) ;
-  SETKNOB(SuccRestrict) ;
-  SETKNOB(Penalty) ;
-  SETKNOB(Bonus) ;
-  SETKNOB(BonusB) ;
-  SETKNOB(Poverty) ;
-  SETKNOB(SpinAfterFutile) ;
-  SETKNOB(UsePause) ;
-  SETKNOB(SpinEarly) ;
-  SETKNOB(OState) ;
-  SETKNOB(MaxSpinners) ;
-  SETKNOB(PreSpin) ;
-  SETKNOB(ExitPolicy) ;
-  SETKNOB(QMode);
-  SETKNOB(ResetEvent) ;
-  SETKNOB(MoveNotifyee) ;
-  SETKNOB(FastHSSEC) ;
-  #undef SETKNOB
-
-  if (os::is_MP()) {
-     BackOffMask = (1 << Knob_SpinBackOff) - 1 ;
-     if (Knob_ReportSettings) ::printf ("BackOffMask=%X\n", BackOffMask) ;
-     // CONSIDER: BackOffMask = ROUNDUP_NEXT_POWER2 (ncpus-1)
-  } else {
-     Knob_SpinLimit = 0 ;
-     Knob_SpinBase  = 0 ;
-     Knob_PreSpin   = 0 ;
-     Knob_FixedSpin = -1 ;
-  }
-
-  if (Knob_LogSpins == 0) {
-     ObjectSynchronizer::_sync_FailedSpins = NULL ;
-  }
-
-  free (knobs) ;
-  OrderAccess::fence() ;
-  InitDone = 1 ;
-}
-
-// Theory of operations -- Monitors lists, thread residency, etc:
-//
-// * A thread acquires ownership of a monitor by successfully
-//   CAS()ing the _owner field from null to non-null.
-//
-// * Invariant: A thread appears on at most one monitor list --
-//   cxq, EntryList or WaitSet -- at any one time.
-//
-// * Contending threads "push" themselves onto the cxq with CAS
-//   and then spin/park.
-//
-// * After a contending thread eventually acquires the lock it must
-//   dequeue itself from either the EntryList or the cxq.
-//
-// * The exiting thread identifies and unparks an "heir presumptive"
-//   tentative successor thread on the EntryList.  Critically, the
-//   exiting thread doesn't unlink the successor thread from the EntryList.
-//   After having been unparked, the wakee will recontend for ownership of
-//   the monitor.   The successor (wakee) will either acquire the lock or
-//   re-park itself.
-//
-//   Succession is provided for by a policy of competitive handoff.
-//   The exiting thread does _not_ grant or pass ownership to the
-//   successor thread.  (This is also referred to as "handoff" succession").
-//   Instead the exiting thread releases ownership and possibly wakes
-//   a successor, so the successor can (re)compete for ownership of the lock.
-//   If the EntryList is empty but the cxq is populated the exiting
-//   thread will drain the cxq into the EntryList.  It does so by
-//   by detaching the cxq (installing null with CAS) and folding
-//   the threads from the cxq into the EntryList.  The EntryList is
-//   doubly linked, while the cxq is singly linked because of the
-//   CAS-based "push" used to enqueue recently arrived threads (RATs).
-//
-// * Concurrency invariants:
-//
-//   -- only the monitor owner may access or mutate the EntryList.
-//      The mutex property of the monitor itself protects the EntryList
-//      from concurrent interference.
-//   -- Only the monitor owner may detach the cxq.
-//
-// * The monitor entry list operations avoid locks, but strictly speaking
-//   they're not lock-free.  Enter is lock-free, exit is not.
-//   See http://j2se.east/~dice/PERSIST/040825-LockFreeQueues.html
-//
-// * The cxq can have multiple concurrent "pushers" but only one concurrent
-//   detaching thread.  This mechanism is immune from the ABA corruption.
-//   More precisely, the CAS-based "push" onto cxq is ABA-oblivious.
-//
-// * Taken together, the cxq and the EntryList constitute or form a
-//   single logical queue of threads stalled trying to acquire the lock.
-//   We use two distinct lists to improve the odds of a constant-time
-//   dequeue operation after acquisition (in the ::enter() epilog) and
-//   to reduce heat on the list ends.  (c.f. Michael Scott's "2Q" algorithm).
-//   A key desideratum is to minimize queue & monitor metadata manipulation
-//   that occurs while holding the monitor lock -- that is, we want to
-//   minimize monitor lock holds times.  Note that even a small amount of
-//   fixed spinning will greatly reduce the # of enqueue-dequeue operations
-//   on EntryList|cxq.  That is, spinning relieves contention on the "inner"
-//   locks and monitor metadata.
-//
-//   Cxq points to the the set of Recently Arrived Threads attempting entry.
-//   Because we push threads onto _cxq with CAS, the RATs must take the form of
-//   a singly-linked LIFO.  We drain _cxq into EntryList  at unlock-time when
-//   the unlocking thread notices that EntryList is null but _cxq is != null.
-//
-//   The EntryList is ordered by the prevailing queue discipline and
-//   can be organized in any convenient fashion, such as a doubly-linked list or
-//   a circular doubly-linked list.  Critically, we want insert and delete operations
-//   to operate in constant-time.  If we need a priority queue then something akin
-//   to Solaris' sleepq would work nicely.  Viz.,
-//   http://agg.eng/ws/on10_nightly/source/usr/src/uts/common/os/sleepq.c.
-//   Queue discipline is enforced at ::exit() time, when the unlocking thread
-//   drains the cxq into the EntryList, and orders or reorders the threads on the
-//   EntryList accordingly.
-//
-//   Barring "lock barging", this mechanism provides fair cyclic ordering,
-//   somewhat similar to an elevator-scan.
-//
-// * The monitor synchronization subsystem avoids the use of native
-//   synchronization primitives except for the narrow platform-specific
-//   park-unpark abstraction.  See the comments in os_solaris.cpp regarding
-//   the semantics of park-unpark.  Put another way, this monitor implementation
-//   depends only on atomic operations and park-unpark.  The monitor subsystem
-//   manages all RUNNING->BLOCKED and BLOCKED->READY transitions while the
-//   underlying OS manages the READY<->RUN transitions.
-//
-// * Waiting threads reside on the WaitSet list -- wait() puts
-//   the caller onto the WaitSet.
-//
-// * notify() or notifyAll() simply transfers threads from the WaitSet to
-//   either the EntryList or cxq.  Subsequent exit() operations will
-//   unpark the notifyee.  Unparking a notifee in notify() is inefficient -
-//   it's likely the notifyee would simply impale itself on the lock held
-//   by the notifier.
-//
-// * An interesting alternative is to encode cxq as (List,LockByte) where
-//   the LockByte is 0 iff the monitor is owned.  _owner is simply an auxiliary
-//   variable, like _recursions, in the scheme.  The threads or Events that form
-//   the list would have to be aligned in 256-byte addresses.  A thread would
-//   try to acquire the lock or enqueue itself with CAS, but exiting threads
-//   could use a 1-0 protocol and simply STB to set the LockByte to 0.
-//   Note that is is *not* word-tearing, but it does presume that full-word
-//   CAS operations are coherent with intermix with STB operations.  That's true
-//   on most common processors.
-//
-// * See also http://blogs.sun.com/dave
-
-
-void ATTR ObjectMonitor::EnterI (TRAPS) {
-    Thread * Self = THREAD ;
-    assert (Self->is_Java_thread(), "invariant") ;
-    assert (((JavaThread *) Self)->thread_state() == _thread_blocked   , "invariant") ;
-
-    // Try the lock - TATAS
-    if (TryLock (Self) > 0) {
-        assert (_succ != Self              , "invariant") ;
-        assert (_owner == Self             , "invariant") ;
-        assert (_Responsible != Self       , "invariant") ;
-        return ;
-    }
-
-    DeferredInitialize () ;
-
-    // We try one round of spinning *before* enqueueing Self.
-    //
-    // If the _owner is ready but OFFPROC we could use a YieldTo()
-    // operation to donate the remainder of this thread's quantum
-    // to the owner.  This has subtle but beneficial affinity
-    // effects.
-
-    if (TrySpin (Self) > 0) {
-        assert (_owner == Self        , "invariant") ;
-        assert (_succ != Self         , "invariant") ;
-        assert (_Responsible != Self  , "invariant") ;
-        return ;
-    }
-
-    // The Spin failed -- Enqueue and park the thread ...
-    assert (_succ  != Self            , "invariant") ;
-    assert (_owner != Self            , "invariant") ;
-    assert (_Responsible != Self      , "invariant") ;
-
-    // Enqueue "Self" on ObjectMonitor's _cxq.
-    //
-    // Node acts as a proxy for Self.
-    // As an aside, if were to ever rewrite the synchronization code mostly
-    // in Java, WaitNodes, ObjectMonitors, and Events would become 1st-class
-    // Java objects.  This would avoid awkward lifecycle and liveness issues,
-    // as well as eliminate a subset of ABA issues.
-    // TODO: eliminate ObjectWaiter and enqueue either Threads or Events.
-    //
-
-    ObjectWaiter node(Self) ;
-    Self->_ParkEvent->reset() ;
-    node._prev   = (ObjectWaiter *) 0xBAD ;
-    node.TState  = ObjectWaiter::TS_CXQ ;
-
-    // Push "Self" onto the front of the _cxq.
-    // Once on cxq/EntryList, Self stays on-queue until it acquires the lock.
-    // Note that spinning tends to reduce the rate at which threads
-    // enqueue and dequeue on EntryList|cxq.
-    ObjectWaiter * nxt ;
-    for (;;) {
-        node._next = nxt = _cxq ;
-        if (Atomic::cmpxchg_ptr (&node, &_cxq, nxt) == nxt) break ;
-
-        // Interference - the CAS failed because _cxq changed.  Just retry.
-        // As an optional optimization we retry the lock.
-        if (TryLock (Self) > 0) {
-            assert (_succ != Self         , "invariant") ;
-            assert (_owner == Self        , "invariant") ;
-            assert (_Responsible != Self  , "invariant") ;
-            return ;
-        }
-    }
-
-    // Check for cxq|EntryList edge transition to non-null.  This indicates
-    // the onset of contention.  While contention persists exiting threads
-    // will use a ST:MEMBAR:LD 1-1 exit protocol.  When contention abates exit
-    // operations revert to the faster 1-0 mode.  This enter operation may interleave
-    // (race) a concurrent 1-0 exit operation, resulting in stranding, so we
-    // arrange for one of the contending thread to use a timed park() operations
-    // to detect and recover from the race.  (Stranding is form of progress failure
-    // where the monitor is unlocked but all the contending threads remain parked).
-    // That is, at least one of the contended threads will periodically poll _owner.
-    // One of the contending threads will become the designated "Responsible" thread.
-    // The Responsible thread uses a timed park instead of a normal indefinite park
-    // operation -- it periodically wakes and checks for and recovers from potential
-    // strandings admitted by 1-0 exit operations.   We need at most one Responsible
-    // thread per-monitor at any given moment.  Only threads on cxq|EntryList may
-    // be responsible for a monitor.
-    //
-    // Currently, one of the contended threads takes on the added role of "Responsible".
-    // A viable alternative would be to use a dedicated "stranding checker" thread
-    // that periodically iterated over all the threads (or active monitors) and unparked
-    // successors where there was risk of stranding.  This would help eliminate the
-    // timer scalability issues we see on some platforms as we'd only have one thread
-    // -- the checker -- parked on a timer.
-
-    if ((SyncFlags & 16) == 0 && nxt == NULL && _EntryList == NULL) {
-        // Try to assume the role of responsible thread for the monitor.
-        // CONSIDER:  ST vs CAS vs { if (Responsible==null) Responsible=Self }
-        Atomic::cmpxchg_ptr (Self, &_Responsible, NULL) ;
-    }
-
-    // The lock have been released while this thread was occupied queueing
-    // itself onto _cxq.  To close the race and avoid "stranding" and
-    // progress-liveness failure we must resample-retry _owner before parking.
-    // Note the Dekker/Lamport duality: ST cxq; MEMBAR; LD Owner.
-    // In this case the ST-MEMBAR is accomplished with CAS().
-    //
-    // TODO: Defer all thread state transitions until park-time.
-    // Since state transitions are heavy and inefficient we'd like
-    // to defer the state transitions until absolutely necessary,
-    // and in doing so avoid some transitions ...
-
-    TEVENT (Inflated enter - Contention) ;
-    int nWakeups = 0 ;
-    int RecheckInterval = 1 ;
-
-    for (;;) {
-
-        if (TryLock (Self) > 0) break ;
-        assert (_owner != Self, "invariant") ;
-
-        if ((SyncFlags & 2) && _Responsible == NULL) {
-           Atomic::cmpxchg_ptr (Self, &_Responsible, NULL) ;
-        }
-
-        // park self
-        if (_Responsible == Self || (SyncFlags & 1)) {
-            TEVENT (Inflated enter - park TIMED) ;
-            Self->_ParkEvent->park ((jlong) RecheckInterval) ;
-            // Increase the RecheckInterval, but clamp the value.
-            RecheckInterval *= 8 ;
-            if (RecheckInterval > 1000) RecheckInterval = 1000 ;
-        } else {
-            TEVENT (Inflated enter - park UNTIMED) ;
-            Self->_ParkEvent->park() ;
-        }
-
-        if (TryLock(Self) > 0) break ;
-
-        // The lock is still contested.
-        // Keep a tally of the # of futile wakeups.
-        // Note that the counter is not protected by a lock or updated by atomics.
-        // That is by design - we trade "lossy" counters which are exposed to
-        // races during updates for a lower probe effect.
-        TEVENT (Inflated enter - Futile wakeup) ;
-        if (ObjectSynchronizer::_sync_FutileWakeups != NULL) {
-           ObjectSynchronizer::_sync_FutileWakeups->inc() ;
-        }
-        ++ nWakeups ;
-
-        // Assuming this is not a spurious wakeup we'll normally find _succ == Self.
-        // We can defer clearing _succ until after the spin completes
-        // TrySpin() must tolerate being called with _succ == Self.
-        // Try yet another round of adaptive spinning.
-        if ((Knob_SpinAfterFutile & 1) && TrySpin (Self) > 0) break ;
-
-        // We can find that we were unpark()ed and redesignated _succ while
-        // we were spinning.  That's harmless.  If we iterate and call park(),
-        // park() will consume the event and return immediately and we'll
-        // just spin again.  This pattern can repeat, leaving _succ to simply
-        // spin on a CPU.  Enable Knob_ResetEvent to clear pending unparks().
-        // Alternately, we can sample fired() here, and if set, forgo spinning
-        // in the next iteration.
-
-        if ((Knob_ResetEvent & 1) && Self->_ParkEvent->fired()) {
-           Self->_ParkEvent->reset() ;
-           OrderAccess::fence() ;
-        }
-        if (_succ == Self) _succ = NULL ;
-
-        // Invariant: after clearing _succ a thread *must* retry _owner before parking.
-        OrderAccess::fence() ;
-    }
-
-    // Egress :
-    // Self has acquired the lock -- Unlink Self from the cxq or EntryList.
-    // Normally we'll find Self on the EntryList .
-    // From the perspective of the lock owner (this thread), the
-    // EntryList is stable and cxq is prepend-only.
-    // The head of cxq is volatile but the interior is stable.
-    // In addition, Self.TState is stable.
-
-    assert (_owner == Self      , "invariant") ;
-    assert (object() != NULL    , "invariant") ;
-    // I'd like to write:
-    //   guarantee (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
-    // but as we're at a safepoint that's not safe.
-
-    UnlinkAfterAcquire (Self, &node) ;
-    if (_succ == Self) _succ = NULL ;
-
-    assert (_succ != Self, "invariant") ;
-    if (_Responsible == Self) {
-        _Responsible = NULL ;
-        // Dekker pivot-point.
-        // Consider OrderAccess::storeload() here
-
-        // We may leave threads on cxq|EntryList without a designated
-        // "Responsible" thread.  This is benign.  When this thread subsequently
-        // exits the monitor it can "see" such preexisting "old" threads --
-        // threads that arrived on the cxq|EntryList before the fence, above --
-        // by LDing cxq|EntryList.  Newly arrived threads -- that is, threads
-        // that arrive on cxq after the ST:MEMBAR, above -- will set Responsible
-        // non-null and elect a new "Responsible" timer thread.
-        //
-        // This thread executes:
-        //    ST Responsible=null; MEMBAR    (in enter epilog - here)
-        //    LD cxq|EntryList               (in subsequent exit)
-        //
-        // Entering threads in the slow/contended path execute:
-        //    ST cxq=nonnull; MEMBAR; LD Responsible (in enter prolog)
-        //    The (ST cxq; MEMBAR) is accomplished with CAS().
-        //
-        // The MEMBAR, above, prevents the LD of cxq|EntryList in the subsequent
-        // exit operation from floating above the ST Responsible=null.
-        //
-        // In *practice* however, EnterI() is always followed by some atomic
-        // operation such as the decrement of _count in ::enter().  Those atomics
-        // obviate the need for the explicit MEMBAR, above.
-    }
-
-    // We've acquired ownership with CAS().
-    // CAS is serializing -- it has MEMBAR/FENCE-equivalent semantics.
-    // But since the CAS() this thread may have also stored into _succ,
-    // EntryList, cxq or Responsible.  These meta-data updates must be
-    // visible __before this thread subsequently drops the lock.
-    // Consider what could occur if we didn't enforce this constraint --
-    // STs to monitor meta-data and user-data could reorder with (become
-    // visible after) the ST in exit that drops ownership of the lock.
-    // Some other thread could then acquire the lock, but observe inconsistent
-    // or old monitor meta-data and heap data.  That violates the JMM.
-    // To that end, the 1-0 exit() operation must have at least STST|LDST
-    // "release" barrier semantics.  Specifically, there must be at least a
-    // STST|LDST barrier in exit() before the ST of null into _owner that drops
-    // the lock.   The barrier ensures that changes to monitor meta-data and data
-    // protected by the lock will be visible before we release the lock, and
-    // therefore before some other thread (CPU) has a chance to acquire the lock.
-    // See also: http://gee.cs.oswego.edu/dl/jmm/cookbook.html.
-    //
-    // Critically, any prior STs to _succ or EntryList must be visible before
-    // the ST of null into _owner in the *subsequent* (following) corresponding
-    // monitorexit.  Recall too, that in 1-0 mode monitorexit does not necessarily
-    // execute a serializing instruction.
-
-    if (SyncFlags & 8) {
-       OrderAccess::fence() ;
-    }
-    return ;
-}
-
-// ExitSuspendEquivalent:
-// A faster alternate to handle_special_suspend_equivalent_condition()
-//
-// handle_special_suspend_equivalent_condition() unconditionally
-// acquires the SR_lock.  On some platforms uncontended MutexLocker()
-// operations have high latency.  Note that in ::enter() we call HSSEC
-// while holding the monitor, so we effectively lengthen the critical sections.
-//
-// There are a number of possible solutions:
-//
-// A.  To ameliorate the problem we might also defer state transitions
-//     to as late as possible -- just prior to parking.
-//     Given that, we'd call HSSEC after having returned from park(),
-//     but before attempting to acquire the monitor.  This is only a
-//     partial solution.  It avoids calling HSSEC while holding the
-//     monitor (good), but it still increases successor reacquisition latency --
-//     the interval between unparking a successor and the time the successor
-//     resumes and retries the lock.  See ReenterI(), which defers state transitions.
-//     If we use this technique we can also avoid EnterI()-exit() loop
-//     in ::enter() where we iteratively drop the lock and then attempt
-//     to reacquire it after suspending.
-//
-// B.  In the future we might fold all the suspend bits into a
-//     composite per-thread suspend flag and then update it with CAS().
-//     Alternately, a Dekker-like mechanism with multiple variables
-//     would suffice:
-//       ST Self->_suspend_equivalent = false
-//       MEMBAR
-//       LD Self_>_suspend_flags
-//
-
-
-bool ObjectMonitor::ExitSuspendEquivalent (JavaThread * jSelf) {
-   int Mode = Knob_FastHSSEC ;
-   if (Mode && !jSelf->is_external_suspend()) {
-      assert (jSelf->is_suspend_equivalent(), "invariant") ;
-      jSelf->clear_suspend_equivalent() ;
-      if (2 == Mode) OrderAccess::storeload() ;
-      if (!jSelf->is_external_suspend()) return false ;
-      // We raced a suspension -- fall thru into the slow path
-      TEVENT (ExitSuspendEquivalent - raced) ;
-      jSelf->set_suspend_equivalent() ;
-   }
-   return jSelf->handle_special_suspend_equivalent_condition() ;
-}
-
-
-// ReenterI() is a specialized inline form of the latter half of the
-// contended slow-path from EnterI().  We use ReenterI() only for
-// monitor reentry in wait().
-//
-// In the future we should reconcile EnterI() and ReenterI(), adding
-// Knob_Reset and Knob_SpinAfterFutile support and restructuring the
-// loop accordingly.
-
-void ATTR ObjectMonitor::ReenterI (Thread * Self, ObjectWaiter * SelfNode) {
-    assert (Self != NULL                , "invariant") ;
-    assert (SelfNode != NULL            , "invariant") ;
-    assert (SelfNode->_thread == Self   , "invariant") ;
-    assert (_waiters > 0                , "invariant") ;
-    assert (((oop)(object()))->mark() == markOopDesc::encode(this) , "invariant") ;
-    assert (((JavaThread *)Self)->thread_state() != _thread_blocked, "invariant") ;
-    JavaThread * jt = (JavaThread *) Self ;
-
-    int nWakeups = 0 ;
-    for (;;) {
-        ObjectWaiter::TStates v = SelfNode->TState ;
-        guarantee (v == ObjectWaiter::TS_ENTER || v == ObjectWaiter::TS_CXQ, "invariant") ;
-        assert    (_owner != Self, "invariant") ;
-
-        if (TryLock (Self) > 0) break ;
-        if (TrySpin (Self) > 0) break ;
-
-        TEVENT (Wait Reentry - parking) ;
-
-        // State transition wrappers around park() ...
-        // ReenterI() wisely defers state transitions until
-        // it's clear we must park the thread.
-        {
-           OSThreadContendState osts(Self->osthread());
-           ThreadBlockInVM tbivm(jt);
-
-           // cleared by handle_special_suspend_equivalent_condition()
-           // or java_suspend_self()
-           jt->set_suspend_equivalent();
-           if (SyncFlags & 1) {
-              Self->_ParkEvent->park ((jlong)1000) ;
-           } else {
-              Self->_ParkEvent->park () ;
-           }
-
-           // were we externally suspended while we were waiting?
-           for (;;) {
-              if (!ExitSuspendEquivalent (jt)) break ;
-              if (_succ == Self) { _succ = NULL; OrderAccess::fence(); }
-              jt->java_suspend_self();
-              jt->set_suspend_equivalent();
-           }
-        }
-
-        // Try again, but just so we distinguish between futile wakeups and
-        // successful wakeups.  The following test isn't algorithmically
-        // necessary, but it helps us maintain sensible statistics.
-        if (TryLock(Self) > 0) break ;
-
-        // The lock is still contested.
-        // Keep a tally of the # of futile wakeups.
-        // Note that the counter is not protected by a lock or updated by atomics.
-        // That is by design - we trade "lossy" counters which are exposed to
-        // races during updates for a lower probe effect.
-        TEVENT (Wait Reentry - futile wakeup) ;
-        ++ nWakeups ;
-
-        // Assuming this is not a spurious wakeup we'll normally
-        // find that _succ == Self.
-        if (_succ == Self) _succ = NULL ;
-
-        // Invariant: after clearing _succ a contending thread
-        // *must* retry  _owner before parking.
-        OrderAccess::fence() ;
-
-        if (ObjectSynchronizer::_sync_FutileWakeups != NULL) {
-          ObjectSynchronizer::_sync_FutileWakeups->inc() ;
-        }
-    }
-
-    // Self has acquired the lock -- Unlink Self from the cxq or EntryList .
-    // Normally we'll find Self on the EntryList.
-    // Unlinking from the EntryList is constant-time and atomic-free.
-    // From the perspective of the lock owner (this thread), the
-    // EntryList is stable and cxq is prepend-only.
-    // The head of cxq is volatile but the interior is stable.
-    // In addition, Self.TState is stable.
-
-    assert (_owner == Self, "invariant") ;
-    assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
-    UnlinkAfterAcquire (Self, SelfNode) ;
-    if (_succ == Self) _succ = NULL ;
-    assert (_succ != Self, "invariant") ;
-    SelfNode->TState = ObjectWaiter::TS_RUN ;
-    OrderAccess::fence() ;      // see comments at the end of EnterI()
-}
-
-bool ObjectMonitor::try_enter(Thread* THREAD) {
-  if (THREAD != _owner) {
-    if (THREAD->is_lock_owned ((address)_owner)) {
-       assert(_recursions == 0, "internal state error");
-       _owner = THREAD ;
-       _recursions = 1 ;
-       OwnerIsThread = 1 ;
-       return true;
-    }
-    if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
-      return false;
-    }
-    return true;
-  } else {
-    _recursions++;
-    return true;
-  }
-}
-
-void ATTR ObjectMonitor::enter(TRAPS) {
-  // The following code is ordered to check the most common cases first
-  // and to reduce RTS->RTO cache line upgrades on SPARC and IA32 processors.
-  Thread * const Self = THREAD ;
-  void * cur ;
-
-  cur = Atomic::cmpxchg_ptr (Self, &_owner, NULL) ;
-  if (cur == NULL) {
-     // Either ASSERT _recursions == 0 or explicitly set _recursions = 0.
-     assert (_recursions == 0   , "invariant") ;
-     assert (_owner      == Self, "invariant") ;
-     // CONSIDER: set or assert OwnerIsThread == 1
-     return ;
-  }
-
-  if (cur == Self) {
-     // TODO-FIXME: check for integer overflow!  BUGID 6557169.
-     _recursions ++ ;
-     return ;
-  }
-
-  if (Self->is_lock_owned ((address)cur)) {
-    assert (_recursions == 0, "internal state error");
-    _recursions = 1 ;
-    // Commute owner from a thread-specific on-stack BasicLockObject address to
-    // a full-fledged "Thread *".
-    _owner = Self ;
-    OwnerIsThread = 1 ;
-    return ;
-  }
-
-  // We've encountered genuine contention.
-  assert (Self->_Stalled == 0, "invariant") ;
-  Self->_Stalled = intptr_t(this) ;
-
-  // Try one round of spinning *before* enqueueing Self
-  // and before going through the awkward and expensive state
-  // transitions.  The following spin is strictly optional ...
-  // Note that if we acquire the monitor from an initial spin
-  // we forgo posting JVMTI events and firing DTRACE probes.
-  if (Knob_SpinEarly && TrySpin (Self) > 0) {
-     assert (_owner == Self      , "invariant") ;
-     assert (_recursions == 0    , "invariant") ;
-     assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
-     Self->_Stalled = 0 ;
-     return ;
-  }
-
-  assert (_owner != Self          , "invariant") ;
-  assert (_succ  != Self          , "invariant") ;
-  assert (Self->is_Java_thread()  , "invariant") ;
-  JavaThread * jt = (JavaThread *) Self ;
-  assert (!SafepointSynchronize::is_at_safepoint(), "invariant") ;
-  assert (jt->thread_state() != _thread_blocked   , "invariant") ;
-  assert (this->object() != NULL  , "invariant") ;
-  assert (_count >= 0, "invariant") ;
-
-  // Prevent deflation at STW-time.  See deflate_idle_monitors() and is_busy().
-  // Ensure the object-monitor relationship remains stable while there's contention.
-  Atomic::inc_ptr(&_count);
-
-  { // Change java thread status to indicate blocked on monitor enter.
-    JavaThreadBlockedOnMonitorEnterState jtbmes(jt, this);
-
-    DTRACE_MONITOR_PROBE(contended__enter, this, object(), jt);
-    if (JvmtiExport::should_post_monitor_contended_enter()) {
-      JvmtiExport::post_monitor_contended_enter(jt, this);
-    }
-
-    OSThreadContendState osts(Self->osthread());
-    ThreadBlockInVM tbivm(jt);
-
-    Self->set_current_pending_monitor(this);
-
-    // TODO-FIXME: change the following for(;;) loop to straight-line code.
-    for (;;) {
-      jt->set_suspend_equivalent();
-      // cleared by handle_special_suspend_equivalent_condition()
-      // or java_suspend_self()
-
-      EnterI (THREAD) ;
-
-      if (!ExitSuspendEquivalent(jt)) break ;
-
-      //
-      // We have acquired the contended monitor, but while we were
-      // waiting another thread suspended us. We don't want to enter
-      // the monitor while suspended because that would surprise the
-      // thread that suspended us.
-      //
-          _recursions = 0 ;
-      _succ = NULL ;
-      exit (Self) ;
-
-      jt->java_suspend_self();
-    }
-    Self->set_current_pending_monitor(NULL);
-  }
-
-  Atomic::dec_ptr(&_count);
-  assert (_count >= 0, "invariant") ;
-  Self->_Stalled = 0 ;
-
-  // Must either set _recursions = 0 or ASSERT _recursions == 0.
-  assert (_recursions == 0     , "invariant") ;
-  assert (_owner == Self       , "invariant") ;
-  assert (_succ  != Self       , "invariant") ;
-  assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
-
-  // The thread -- now the owner -- is back in vm mode.
-  // Report the glorious news via TI,DTrace and jvmstat.
-  // The probe effect is non-trivial.  All the reportage occurs
-  // while we hold the monitor, increasing the length of the critical
-  // section.  Amdahl's parallel speedup law comes vividly into play.
-  //
-  // Another option might be to aggregate the events (thread local or
-  // per-monitor aggregation) and defer reporting until a more opportune
-  // time -- such as next time some thread encounters contention but has
-  // yet to acquire the lock.  While spinning that thread could
-  // spinning we could increment JVMStat counters, etc.
-
-  DTRACE_MONITOR_PROBE(contended__entered, this, object(), jt);
-  if (JvmtiExport::should_post_monitor_contended_entered()) {
-    JvmtiExport::post_monitor_contended_entered(jt, this);
-  }
-  if (ObjectSynchronizer::_sync_ContendedLockAttempts != NULL) {
-     ObjectSynchronizer::_sync_ContendedLockAttempts->inc() ;
-  }
-}
-
-void ObjectMonitor::ExitEpilog (Thread * Self, ObjectWaiter * Wakee) {
-   assert (_owner == Self, "invariant") ;
-
-   // Exit protocol:
-   // 1. ST _succ = wakee
-   // 2. membar #loadstore|#storestore;
-   // 2. ST _owner = NULL
-   // 3. unpark(wakee)
-
-   _succ = Knob_SuccEnabled ? Wakee->_thread : NULL ;
-   ParkEvent * Trigger = Wakee->_event ;
+};
 
-   // Hygiene -- once we've set _owner = NULL we can't safely dereference Wakee again.
-   // The thread associated with Wakee may have grabbed the lock and "Wakee" may be
-   // out-of-scope (non-extant).
-   Wakee  = NULL ;
-
-   // Drop the lock
-   OrderAccess::release_store_ptr (&_owner, NULL) ;
-   OrderAccess::fence() ;                               // ST _owner vs LD in unpark()
-
-   // TODO-FIXME:
-   // If there's a safepoint pending the best policy would be to
-   // get _this thread to a safepoint and only wake the successor
-   // after the safepoint completed.  monitorexit uses a "leaf"
-   // state transition, however, so this thread can't become
-   // safe at this point in time.  (Its stack isn't walkable).
-   // The next best thing is to defer waking the successor by
-   // adding to a list of thread to be unparked after at the
-   // end of the forthcoming STW).
-   if (SafepointSynchronize::do_call_back()) {
-      TEVENT (unpark before SAFEPOINT) ;
-   }
-
-   // Possible optimizations ...
-   //
-   // * Consider: set Wakee->UnparkTime = timeNow()
-   //   When the thread wakes up it'll compute (timeNow() - Self->UnparkTime()).
-   //   By measuring recent ONPROC latency we can approximate the
-   //   system load.  In turn, we can feed that information back
-   //   into the spinning & succession policies.
-   //   (ONPROC latency correlates strongly with load).
-   //
-   // * Pull affinity:
-   //   If the wakee is cold then transiently setting it's affinity
-   //   to the current CPU is a good idea.
-   //   See http://j2se.east/~dice/PERSIST/050624-PullAffinity.txt
-   DTRACE_MONITOR_PROBE(contended__exit, this, object(), Self);
-   Trigger->unpark() ;
-
-   // Maintain stats and report events to JVMTI
-   if (ObjectSynchronizer::_sync_Parks != NULL) {
-      ObjectSynchronizer::_sync_Parks->inc() ;
-   }
-}
-
-
-// exit()
-// ~~~~~~
-// Note that the collector can't reclaim the objectMonitor or deflate
-// the object out from underneath the thread calling ::exit() as the
-// thread calling ::exit() never transitions to a stable state.
-// This inhibits GC, which in turn inhibits asynchronous (and
-// inopportune) reclamation of "this".
-//
-// We'd like to assert that: (THREAD->thread_state() != _thread_blocked) ;
-// There's one exception to the claim above, however.  EnterI() can call
-// exit() to drop a lock if the acquirer has been externally suspended.
-// In that case exit() is called with _thread_state as _thread_blocked,
-// but the monitor's _count field is > 0, which inhibits reclamation.
-//
-// 1-0 exit
-// ~~~~~~~~
-// ::exit() uses a canonical 1-1 idiom with a MEMBAR although some of
-// the fast-path operators have been optimized so the common ::exit()
-// operation is 1-0.  See i486.ad fast_unlock(), for instance.
-// The code emitted by fast_unlock() elides the usual MEMBAR.  This
-// greatly improves latency -- MEMBAR and CAS having considerable local
-// latency on modern processors -- but at the cost of "stranding".  Absent the
-// MEMBAR, a thread in fast_unlock() can race a thread in the slow
-// ::enter() path, resulting in the entering thread being stranding
-// and a progress-liveness failure.   Stranding is extremely rare.
-// We use timers (timed park operations) & periodic polling to detect
-// and recover from stranding.  Potentially stranded threads periodically
-// wake up and poll the lock.  See the usage of the _Responsible variable.
-//
-// The CAS() in enter provides for safety and exclusion, while the CAS or
-// MEMBAR in exit provides for progress and avoids stranding.  1-0 locking
-// eliminates the CAS/MEMBAR from the exist path, but it admits stranding.
-// We detect and recover from stranding with timers.
+// Release all inflated monitors owned by THREAD.  Lightweight monitors are
+// ignored.  This is meant to be called during JNI thread detach which assumes
+// all remaining monitors are heavyweight.  All exceptions are swallowed.
+// Scanning the extant monitor list can be time consuming.
+// A simple optimization is to add a per-thread flag that indicates a thread
+// called jni_monitorenter() during its lifetime.
 //
-// If a thread transiently strands it'll park until (a) another
-// thread acquires the lock and then drops the lock, at which time the
-// exiting thread will notice and unpark the stranded thread, or, (b)
-// the timer expires.  If the lock is high traffic then the stranding latency
-// will be low due to (a).  If the lock is low traffic then the odds of
-// stranding are lower, although the worst-case stranding latency
-// is longer.  Critically, we don't want to put excessive load in the
-// platform's timer subsystem.  We want to minimize both the timer injection
-// rate (timers created/sec) as well as the number of timers active at
-// any one time.  (more precisely, we want to minimize timer-seconds, which is
-// the integral of the # of active timers at any instant over time).
-// Both impinge on OS scalability.  Given that, at most one thread parked on
-// a monitor will use a timer.
-
-void ATTR ObjectMonitor::exit(TRAPS) {
-   Thread * Self = THREAD ;
-   if (THREAD != _owner) {
-     if (THREAD->is_lock_owned((address) _owner)) {
-       // Transmute _owner from a BasicLock pointer to a Thread address.
-       // We don't need to hold _mutex for this transition.
-       // Non-null to Non-null is safe as long as all readers can
-       // tolerate either flavor.
-       assert (_recursions == 0, "invariant") ;
-       _owner = THREAD ;
-       _recursions = 0 ;
-       OwnerIsThread = 1 ;
-     } else {
-       // NOTE: we need to handle unbalanced monitor enter/exit
-       // in native code by throwing an exception.
-       // TODO: Throw an IllegalMonitorStateException ?
-       TEVENT (Exit - Throw IMSX) ;
-       assert(false, "Non-balanced monitor enter/exit!");
-       if (false) {
-          THROW(vmSymbols::java_lang_IllegalMonitorStateException());
-       }
-       return;
-     }
-   }
-
-   if (_recursions != 0) {
-     _recursions--;        // this is simple recursive enter
-     TEVENT (Inflated exit - recursive) ;
-     return ;
-   }
-
-   // Invariant: after setting Responsible=null an thread must execute
-   // a MEMBAR or other serializing instruction before fetching EntryList|cxq.
-   if ((SyncFlags & 4) == 0) {
-      _Responsible = NULL ;
-   }
-
-   for (;;) {
-      assert (THREAD == _owner, "invariant") ;
-
-      // Fast-path monitor exit:
-      //
-      // Observe the Dekker/Lamport duality:
-      // A thread in ::exit() executes:
-      //   ST Owner=null; MEMBAR; LD EntryList|cxq.
-      // A thread in the contended ::enter() path executes the complementary:
-      //   ST EntryList|cxq = nonnull; MEMBAR; LD Owner.
-      //
-      // Note that there's a benign race in the exit path.  We can drop the
-      // lock, another thread can reacquire the lock immediately, and we can
-      // then wake a thread unnecessarily (yet another flavor of futile wakeup).
-      // This is benign, and we've structured the code so the windows are short
-      // and the frequency of such futile wakeups is low.
-      //
-      // We could eliminate the race by encoding both the "LOCKED" state and
-      // the queue head in a single word.  Exit would then use either CAS to
-      // clear the LOCKED bit/byte.  This precludes the desirable 1-0 optimization,
-      // however.
-      //
-      // Possible fast-path ::exit() optimization:
-      // The current fast-path exit implementation fetches both cxq and EntryList.
-      // See also i486.ad fast_unlock().  Testing has shown that two LDs
-      // isn't measurably slower than a single LD on any platforms.
-      // Still, we could reduce the 2 LDs to one or zero by one of the following:
-      //
-      // - Use _count instead of cxq|EntryList
-      //   We intend to eliminate _count, however, when we switch
-      //   to on-the-fly deflation in ::exit() as is used in
-      //   Metalocks and RelaxedLocks.
-      //
-      // - Establish the invariant that cxq == null implies EntryList == null.
-      //   set cxq == EMPTY (1) to encode the state where cxq is empty
-      //   by EntryList != null.  EMPTY is a distinguished value.
-      //   The fast-path exit() would fetch cxq but not EntryList.
-      //
-      // - Encode succ as follows:
-      //   succ = t :  Thread t is the successor -- t is ready or is spinning.
-      //               Exiting thread does not need to wake a successor.
-      //   succ = 0 :  No successor required -> (EntryList|cxq) == null
-      //               Exiting thread does not need to wake a successor
-      //   succ = 1 :  Successor required    -> (EntryList|cxq) != null and
-      //               logically succ == null.
-      //               Exiting thread must wake a successor.
-      //
-      //   The 1-1 fast-exit path would appear as :
-      //     _owner = null ; membar ;
-      //     if (_succ == 1 && CAS (&_owner, null, Self) == null) goto SlowPath
-      //     goto FastPathDone ;
-      //
-      //   and the 1-0 fast-exit path would appear as:
-      //      if (_succ == 1) goto SlowPath
-      //      Owner = null ;
-      //      goto FastPathDone
-      //
-      // - Encode the LSB of _owner as 1 to indicate that exit()
-      //   must use the slow-path and make a successor ready.
-      //   (_owner & 1) == 0 IFF succ != null || (EntryList|cxq) == null
-      //   (_owner & 1) == 0 IFF succ == null && (EntryList|cxq) != null (obviously)
-      //   The 1-0 fast exit path would read:
-      //      if (_owner != Self) goto SlowPath
-      //      _owner = null
-      //      goto FastPathDone
-
-      if (Knob_ExitPolicy == 0) {
-         // release semantics: prior loads and stores from within the critical section
-         // must not float (reorder) past the following store that drops the lock.
-         // On SPARC that requires MEMBAR #loadstore|#storestore.
-         // But of course in TSO #loadstore|#storestore is not required.
-         // I'd like to write one of the following:
-         // A.  OrderAccess::release() ; _owner = NULL
-         // B.  OrderAccess::loadstore(); OrderAccess::storestore(); _owner = NULL;
-         // Unfortunately OrderAccess::release() and OrderAccess::loadstore() both
-         // store into a _dummy variable.  That store is not needed, but can result
-         // in massive wasteful coherency traffic on classic SMP systems.
-         // Instead, I use release_store(), which is implemented as just a simple
-         // ST on x64, x86 and SPARC.
-         OrderAccess::release_store_ptr (&_owner, NULL) ;   // drop the lock
-         OrderAccess::storeload() ;                         // See if we need to wake a successor
-         if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {
-            TEVENT (Inflated exit - simple egress) ;
-            return ;
-         }
-         TEVENT (Inflated exit - complex egress) ;
-
-         // Normally the exiting thread is responsible for ensuring succession,
-         // but if other successors are ready or other entering threads are spinning
-         // then this thread can simply store NULL into _owner and exit without
-         // waking a successor.  The existence of spinners or ready successors
-         // guarantees proper succession (liveness).  Responsibility passes to the
-         // ready or running successors.  The exiting thread delegates the duty.
-         // More precisely, if a successor already exists this thread is absolved
-         // of the responsibility of waking (unparking) one.
-         //
-         // The _succ variable is critical to reducing futile wakeup frequency.
-         // _succ identifies the "heir presumptive" thread that has been made
-         // ready (unparked) but that has not yet run.  We need only one such
-         // successor thread to guarantee progress.
-         // See http://www.usenix.org/events/jvm01/full_papers/dice/dice.pdf
-         // section 3.3 "Futile Wakeup Throttling" for details.
-         //
-         // Note that spinners in Enter() also set _succ non-null.
-         // In the current implementation spinners opportunistically set
-         // _succ so that exiting threads might avoid waking a successor.
-         // Another less appealing alternative would be for the exiting thread
-         // to drop the lock and then spin briefly to see if a spinner managed
-         // to acquire the lock.  If so, the exiting thread could exit
-         // immediately without waking a successor, otherwise the exiting
-         // thread would need to dequeue and wake a successor.
-         // (Note that we'd need to make the post-drop spin short, but no
-         // shorter than the worst-case round-trip cache-line migration time.
-         // The dropped lock needs to become visible to the spinner, and then
-         // the acquisition of the lock by the spinner must become visible to
-         // the exiting thread).
-         //
-
-         // It appears that an heir-presumptive (successor) must be made ready.
-         // Only the current lock owner can manipulate the EntryList or
-         // drain _cxq, so we need to reacquire the lock.  If we fail
-         // to reacquire the lock the responsibility for ensuring succession
-         // falls to the new owner.
-         //
-         if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
-            return ;
-         }
-         TEVENT (Exit - Reacquired) ;
-      } else {
-         if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {
-            OrderAccess::release_store_ptr (&_owner, NULL) ;   // drop the lock
-            OrderAccess::storeload() ;
-            // Ratify the previously observed values.
-            if (_cxq == NULL || _succ != NULL) {
-                TEVENT (Inflated exit - simple egress) ;
-                return ;
-            }
-
-            // inopportune interleaving -- the exiting thread (this thread)
-            // in the fast-exit path raced an entering thread in the slow-enter
-            // path.
-            // We have two choices:
-            // A.  Try to reacquire the lock.
-            //     If the CAS() fails return immediately, otherwise
-            //     we either restart/rerun the exit operation, or simply
-            //     fall-through into the code below which wakes a successor.
-            // B.  If the elements forming the EntryList|cxq are TSM
-            //     we could simply unpark() the lead thread and return
-            //     without having set _succ.
-            if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
-               TEVENT (Inflated exit - reacquired succeeded) ;
-               return ;
-            }
-            TEVENT (Inflated exit - reacquired failed) ;
-         } else {
-            TEVENT (Inflated exit - complex egress) ;
-         }
-      }
-
-      guarantee (_owner == THREAD, "invariant") ;
-
-      // Select an appropriate successor ("heir presumptive") from the EntryList
-      // and make it ready.  Generally we just wake the head of EntryList .
-      // There's no algorithmic constraint that we use the head - it's just
-      // a policy decision.   Note that the thread at head of the EntryList
-      // remains at the head until it acquires the lock.  This means we'll
-      // repeatedly wake the same thread until it manages to grab the lock.
-      // This is generally a good policy - if we're seeing lots of futile wakeups
-      // at least we're waking/rewaking a thread that's like to be hot or warm
-      // (have residual D$ and TLB affinity).
-      //
-      // "Wakeup locality" optimization:
-      // http://j2se.east/~dice/PERSIST/040825-WakeLocality.txt
-      // In the future we'll try to bias the selection mechanism
-      // to preferentially pick a thread that recently ran on
-      // a processor element that shares cache with the CPU on which
-      // the exiting thread is running.   We need access to Solaris'
-      // schedctl.sc_cpu to make that work.
-      //
-      ObjectWaiter * w = NULL ;
-      int QMode = Knob_QMode ;
-
-      if (QMode == 2 && _cxq != NULL) {
-          // QMode == 2 : cxq has precedence over EntryList.
-          // Try to directly wake a successor from the cxq.
-          // If successful, the successor will need to unlink itself from cxq.
-          w = _cxq ;
-          assert (w != NULL, "invariant") ;
-          assert (w->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
-          ExitEpilog (Self, w) ;
-          return ;
-      }
-
-      if (QMode == 3 && _cxq != NULL) {
-          // Aggressively drain cxq into EntryList at the first opportunity.
-          // This policy ensure that recently-run threads live at the head of EntryList.
-          // Drain _cxq into EntryList - bulk transfer.
-          // First, detach _cxq.
-          // The following loop is tantamount to: w = swap (&cxq, NULL)
-          w = _cxq ;
-          for (;;) {
-             assert (w != NULL, "Invariant") ;
-             ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;
-             if (u == w) break ;
-             w = u ;
-          }
-          assert (w != NULL              , "invariant") ;
-
-          ObjectWaiter * q = NULL ;
-          ObjectWaiter * p ;
-          for (p = w ; p != NULL ; p = p->_next) {
-              guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
-              p->TState = ObjectWaiter::TS_ENTER ;
-              p->_prev = q ;
-              q = p ;
-          }
-
-          // Append the RATs to the EntryList
-          // TODO: organize EntryList as a CDLL so we can locate the tail in constant-time.
-          ObjectWaiter * Tail ;
-          for (Tail = _EntryList ; Tail != NULL && Tail->_next != NULL ; Tail = Tail->_next) ;
-          if (Tail == NULL) {
-              _EntryList = w ;
-          } else {
-              Tail->_next = w ;
-              w->_prev = Tail ;
-          }
-
-          // Fall thru into code that tries to wake a successor from EntryList
-      }
-
-      if (QMode == 4 && _cxq != NULL) {
-          // Aggressively drain cxq into EntryList at the first opportunity.
-          // This policy ensure that recently-run threads live at the head of EntryList.
-
-          // Drain _cxq into EntryList - bulk transfer.
-          // First, detach _cxq.
-          // The following loop is tantamount to: w = swap (&cxq, NULL)
-          w = _cxq ;
-          for (;;) {
-             assert (w != NULL, "Invariant") ;
-             ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;
-             if (u == w) break ;
-             w = u ;
-          }
-          assert (w != NULL              , "invariant") ;
-
-          ObjectWaiter * q = NULL ;
-          ObjectWaiter * p ;
-          for (p = w ; p != NULL ; p = p->_next) {
-              guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
-              p->TState = ObjectWaiter::TS_ENTER ;
-              p->_prev = q ;
-              q = p ;
-          }
-
-          // Prepend the RATs to the EntryList
-          if (_EntryList != NULL) {
-              q->_next = _EntryList ;
-              _EntryList->_prev = q ;
-          }
-          _EntryList = w ;
-
-          // Fall thru into code that tries to wake a successor from EntryList
-      }
-
-      w = _EntryList  ;
-      if (w != NULL) {
-          // I'd like to write: guarantee (w->_thread != Self).
-          // But in practice an exiting thread may find itself on the EntryList.
-          // Lets say thread T1 calls O.wait().  Wait() enqueues T1 on O's waitset and
-          // then calls exit().  Exit release the lock by setting O._owner to NULL.
-          // Lets say T1 then stalls.  T2 acquires O and calls O.notify().  The
-          // notify() operation moves T1 from O's waitset to O's EntryList. T2 then
-          // release the lock "O".  T2 resumes immediately after the ST of null into
-          // _owner, above.  T2 notices that the EntryList is populated, so it
-          // reacquires the lock and then finds itself on the EntryList.
-          // Given all that, we have to tolerate the circumstance where "w" is
-          // associated with Self.
-          assert (w->TState == ObjectWaiter::TS_ENTER, "invariant") ;
-          ExitEpilog (Self, w) ;
-          return ;
-      }
-
-      // If we find that both _cxq and EntryList are null then just
-      // re-run the exit protocol from the top.
-      w = _cxq ;
-      if (w == NULL) continue ;
-
-      // Drain _cxq into EntryList - bulk transfer.
-      // First, detach _cxq.
-      // The following loop is tantamount to: w = swap (&cxq, NULL)
-      for (;;) {
-          assert (w != NULL, "Invariant") ;
-          ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;
-          if (u == w) break ;
-          w = u ;
-      }
-      TEVENT (Inflated exit - drain cxq into EntryList) ;
-
-      assert (w != NULL              , "invariant") ;
-      assert (_EntryList  == NULL    , "invariant") ;
-
-      // Convert the LIFO SLL anchored by _cxq into a DLL.
-      // The list reorganization step operates in O(LENGTH(w)) time.
-      // It's critical that this step operate quickly as
-      // "Self" still holds the outer-lock, restricting parallelism
-      // and effectively lengthening the critical section.
-      // Invariant: s chases t chases u.
-      // TODO-FIXME: consider changing EntryList from a DLL to a CDLL so
-      // we have faster access to the tail.
-
-      if (QMode == 1) {
-         // QMode == 1 : drain cxq to EntryList, reversing order
-         // We also reverse the order of the list.
-         ObjectWaiter * s = NULL ;
-         ObjectWaiter * t = w ;
-         ObjectWaiter * u = NULL ;
-         while (t != NULL) {
-             guarantee (t->TState == ObjectWaiter::TS_CXQ, "invariant") ;
-             t->TState = ObjectWaiter::TS_ENTER ;
-             u = t->_next ;
-             t->_prev = u ;
-             t->_next = s ;
-             s = t;
-             t = u ;
-         }
-         _EntryList  = s ;
-         assert (s != NULL, "invariant") ;
-      } else {
-         // QMode == 0 or QMode == 2
-         _EntryList = w ;
-         ObjectWaiter * q = NULL ;
-         ObjectWaiter * p ;
-         for (p = w ; p != NULL ; p = p->_next) {
-             guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
-             p->TState = ObjectWaiter::TS_ENTER ;
-             p->_prev = q ;
-             q = p ;
-         }
-      }
-
-      // In 1-0 mode we need: ST EntryList; MEMBAR #storestore; ST _owner = NULL
-      // The MEMBAR is satisfied by the release_store() operation in ExitEpilog().
-
-      // See if we can abdicate to a spinner instead of waking a thread.
-      // A primary goal of the implementation is to reduce the
-      // context-switch rate.
-      if (_succ != NULL) continue;
-
-      w = _EntryList  ;
-      if (w != NULL) {
-          guarantee (w->TState == ObjectWaiter::TS_ENTER, "invariant") ;
-          ExitEpilog (Self, w) ;
-          return ;
-      }
-   }
-}
-// complete_exit exits a lock returning recursion count
-// complete_exit/reenter operate as a wait without waiting
-// complete_exit requires an inflated monitor
-// The _owner field is not always the Thread addr even with an
-// inflated monitor, e.g. the monitor can be inflated by a non-owning
-// thread due to contention.
-intptr_t ObjectMonitor::complete_exit(TRAPS) {
-   Thread * const Self = THREAD;
-   assert(Self->is_Java_thread(), "Must be Java thread!");
-   JavaThread *jt = (JavaThread *)THREAD;
-
-   DeferredInitialize();
-
-   if (THREAD != _owner) {
-    if (THREAD->is_lock_owned ((address)_owner)) {
-       assert(_recursions == 0, "internal state error");
-       _owner = THREAD ;   /* Convert from basiclock addr to Thread addr */
-       _recursions = 0 ;
-       OwnerIsThread = 1 ;
-    }
-   }
-
-   guarantee(Self == _owner, "complete_exit not owner");
-   intptr_t save = _recursions; // record the old recursion count
-   _recursions = 0;        // set the recursion level to be 0
-   exit (Self) ;           // exit the monitor
-   guarantee (_owner != Self, "invariant");
-   return save;
-}
-
-// reenter() enters a lock and sets recursion count
-// complete_exit/reenter operate as a wait without waiting
-void ObjectMonitor::reenter(intptr_t recursions, TRAPS) {
-   Thread * const Self = THREAD;
-   assert(Self->is_Java_thread(), "Must be Java thread!");
-   JavaThread *jt = (JavaThread *)THREAD;
-
-   guarantee(_owner != Self, "reenter already owner");
-   enter (THREAD);       // enter the monitor
-   guarantee (_recursions == 0, "reenter recursion");
-   _recursions = recursions;
-   return;
-}
-
-// Note: a subset of changes to ObjectMonitor::wait()
-// will need to be replicated in complete_exit above
-void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
-   Thread * const Self = THREAD ;
-   assert(Self->is_Java_thread(), "Must be Java thread!");
-   JavaThread *jt = (JavaThread *)THREAD;
-
-   DeferredInitialize () ;
-
-   // Throw IMSX or IEX.
-   CHECK_OWNER();
-
-   // check for a pending interrupt
-   if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {
-     // post monitor waited event.  Note that this is past-tense, we are done waiting.
-     if (JvmtiExport::should_post_monitor_waited()) {
-        // Note: 'false' parameter is passed here because the
-        // wait was not timed out due to thread interrupt.
-        JvmtiExport::post_monitor_waited(jt, this, false);
-     }
-     TEVENT (Wait - Throw IEX) ;
-     THROW(vmSymbols::java_lang_InterruptedException());
-     return ;
-   }
-   TEVENT (Wait) ;
-
-   assert (Self->_Stalled == 0, "invariant") ;
-   Self->_Stalled = intptr_t(this) ;
-   jt->set_current_waiting_monitor(this);
-
-   // create a node to be put into the queue
-   // Critically, after we reset() the event but prior to park(), we must check
-   // for a pending interrupt.
-   ObjectWaiter node(Self);
-   node.TState = ObjectWaiter::TS_WAIT ;
-   Self->_ParkEvent->reset() ;
-   OrderAccess::fence();          // ST into Event; membar ; LD interrupted-flag
-
-   // Enter the waiting queue, which is a circular doubly linked list in this case
-   // but it could be a priority queue or any data structure.
-   // _WaitSetLock protects the wait queue.  Normally the wait queue is accessed only
-   // by the the owner of the monitor *except* in the case where park()
-   // returns because of a timeout of interrupt.  Contention is exceptionally rare
-   // so we use a simple spin-lock instead of a heavier-weight blocking lock.
-
-   Thread::SpinAcquire (&_WaitSetLock, "WaitSet - add") ;
-   AddWaiter (&node) ;
-   Thread::SpinRelease (&_WaitSetLock) ;
-
-   if ((SyncFlags & 4) == 0) {
-      _Responsible = NULL ;
-   }
-   intptr_t save = _recursions; // record the old recursion count
-   _waiters++;                  // increment the number of waiters
-   _recursions = 0;             // set the recursion level to be 1
-   exit (Self) ;                    // exit the monitor
-   guarantee (_owner != Self, "invariant") ;
-
-   // As soon as the ObjectMonitor's ownership is dropped in the exit()
-   // call above, another thread can enter() the ObjectMonitor, do the
-   // notify(), and exit() the ObjectMonitor. If the other thread's
-   // exit() call chooses this thread as the successor and the unpark()
-   // call happens to occur while this thread is posting a
-   // MONITOR_CONTENDED_EXIT event, then we run the risk of the event
-   // handler using RawMonitors and consuming the unpark().
-   //
-   // To avoid the problem, we re-post the event. This does no harm
-   // even if the original unpark() was not consumed because we are the
-   // chosen successor for this monitor.
-   if (node._notified != 0 && _succ == Self) {
-      node._event->unpark();
-   }
-
-   // The thread is on the WaitSet list - now park() it.
-   // On MP systems it's conceivable that a brief spin before we park
-   // could be profitable.
-   //
-   // TODO-FIXME: change the following logic to a loop of the form
-   //   while (!timeout && !interrupted && _notified == 0) park()
-
-   int ret = OS_OK ;
-   int WasNotified = 0 ;
-   { // State transition wrappers
-     OSThread* osthread = Self->osthread();
-     OSThreadWaitState osts(osthread, true);
-     {
-       ThreadBlockInVM tbivm(jt);
-       // Thread is in thread_blocked state and oop access is unsafe.
-       jt->set_suspend_equivalent();
-
-       if (interruptible && (Thread::is_interrupted(THREAD, false) || HAS_PENDING_EXCEPTION)) {
-           // Intentionally empty
-       } else
-       if (node._notified == 0) {
-         if (millis <= 0) {
-            Self->_ParkEvent->park () ;
-         } else {
-            ret = Self->_ParkEvent->park (millis) ;
-         }
-       }
-
-       // were we externally suspended while we were waiting?
-       if (ExitSuspendEquivalent (jt)) {
-          // TODO-FIXME: add -- if succ == Self then succ = null.
-          jt->java_suspend_self();
-       }
-
-     } // Exit thread safepoint: transition _thread_blocked -> _thread_in_vm
-
-
-     // Node may be on the WaitSet, the EntryList (or cxq), or in transition
-     // from the WaitSet to the EntryList.
-     // See if we need to remove Node from the WaitSet.
-     // We use double-checked locking to avoid grabbing _WaitSetLock
-     // if the thread is not on the wait queue.
-     //
-     // Note that we don't need a fence before the fetch of TState.
-     // In the worst case we'll fetch a old-stale value of TS_WAIT previously
-     // written by the is thread. (perhaps the fetch might even be satisfied
-     // by a look-aside into the processor's own store buffer, although given
-     // the length of the code path between the prior ST and this load that's
-     // highly unlikely).  If the following LD fetches a stale TS_WAIT value
-     // then we'll acquire the lock and then re-fetch a fresh TState value.
-     // That is, we fail toward safety.
-
-     if (node.TState == ObjectWaiter::TS_WAIT) {
-         Thread::SpinAcquire (&_WaitSetLock, "WaitSet - unlink") ;
-         if (node.TState == ObjectWaiter::TS_WAIT) {
-            DequeueSpecificWaiter (&node) ;       // unlink from WaitSet
-            assert(node._notified == 0, "invariant");
-            node.TState = ObjectWaiter::TS_RUN ;
-         }
-         Thread::SpinRelease (&_WaitSetLock) ;
-     }
+// Instead of No_Savepoint_Verifier it might be cheaper to
+// use an idiom of the form:
+//   auto int tmp = SafepointSynchronize::_safepoint_counter ;
+//   <code that must not run at safepoint>
+//   guarantee (((tmp ^ _safepoint_counter) | (tmp & 1)) == 0) ;
+// Since the tests are extremely cheap we could leave them enabled
+// for normal product builds.
 
-     // The thread is now either on off-list (TS_RUN),
-     // on the EntryList (TS_ENTER), or on the cxq (TS_CXQ).
-     // The Node's TState variable is stable from the perspective of this thread.
-     // No other threads will asynchronously modify TState.
-     guarantee (node.TState != ObjectWaiter::TS_WAIT, "invariant") ;
-     OrderAccess::loadload() ;
-     if (_succ == Self) _succ = NULL ;
-     WasNotified = node._notified ;
-
-     // Reentry phase -- reacquire the monitor.
-     // re-enter contended monitor after object.wait().
-     // retain OBJECT_WAIT state until re-enter successfully completes
-     // Thread state is thread_in_vm and oop access is again safe,
-     // although the raw address of the object may have changed.
-     // (Don't cache naked oops over safepoints, of course).
-
-     // post monitor waited event. Note that this is past-tense, we are done waiting.
-     if (JvmtiExport::should_post_monitor_waited()) {
-       JvmtiExport::post_monitor_waited(jt, this, ret == OS_TIMEOUT);
-     }
-     OrderAccess::fence() ;
-
-     assert (Self->_Stalled != 0, "invariant") ;
-     Self->_Stalled = 0 ;
-
-     assert (_owner != Self, "invariant") ;
-     ObjectWaiter::TStates v = node.TState ;
-     if (v == ObjectWaiter::TS_RUN) {
-         enter (Self) ;
-     } else {
-         guarantee (v == ObjectWaiter::TS_ENTER || v == ObjectWaiter::TS_CXQ, "invariant") ;
-         ReenterI (Self, &node) ;
-         node.wait_reenter_end(this);
-     }
-
-     // Self has reacquired the lock.
-     // Lifecycle - the node representing Self must not appear on any queues.
-     // Node is about to go out-of-scope, but even if it were immortal we wouldn't
-     // want residual elements associated with this thread left on any lists.
-     guarantee (node.TState == ObjectWaiter::TS_RUN, "invariant") ;
-     assert    (_owner == Self, "invariant") ;
-     assert    (_succ != Self , "invariant") ;
-   } // OSThreadWaitState()
-
-   jt->set_current_waiting_monitor(NULL);
-
-   guarantee (_recursions == 0, "invariant") ;
-   _recursions = save;     // restore the old recursion count
-   _waiters--;             // decrement the number of waiters
-
-   // Verify a few postconditions
-   assert (_owner == Self       , "invariant") ;
-   assert (_succ  != Self       , "invariant") ;
-   assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
-
-   if (SyncFlags & 32) {
-      OrderAccess::fence() ;
-   }
-
-   // check if the notification happened
-   if (!WasNotified) {
-     // no, it could be timeout or Thread.interrupt() or both
-     // check for interrupt event, otherwise it is timeout
-     if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {
-       TEVENT (Wait - throw IEX from epilog) ;
-       THROW(vmSymbols::java_lang_InterruptedException());
-     }
-   }
-
-   // NOTE: Spurious wake up will be consider as timeout.
-   // Monitor notify has precedence over thread interrupt.
-}
-
-
-// Consider:
-// If the lock is cool (cxq == null && succ == null) and we're on an MP system
-// then instead of transferring a thread from the WaitSet to the EntryList
-// we might just dequeue a thread from the WaitSet and directly unpark() it.
-
-void ObjectMonitor::notify(TRAPS) {
-  CHECK_OWNER();
-  if (_WaitSet == NULL) {
-     TEVENT (Empty-Notify) ;
-     return ;
-  }
-  DTRACE_MONITOR_PROBE(notify, this, object(), THREAD);
-
-  int Policy = Knob_MoveNotifyee ;
-
-  Thread::SpinAcquire (&_WaitSetLock, "WaitSet - notify") ;
-  ObjectWaiter * iterator = DequeueWaiter() ;
-  if (iterator != NULL) {
-     TEVENT (Notify1 - Transfer) ;
-     guarantee (iterator->TState == ObjectWaiter::TS_WAIT, "invariant") ;
-     guarantee (iterator->_notified == 0, "invariant") ;
-     // Disposition - what might we do with iterator ?
-     // a.  add it directly to the EntryList - either tail or head.
-     // b.  push it onto the front of the _cxq.
-     // For now we use (a).
-     if (Policy != 4) {
-        iterator->TState = ObjectWaiter::TS_ENTER ;
-     }
-     iterator->_notified = 1 ;
-
-     ObjectWaiter * List = _EntryList ;
-     if (List != NULL) {
-        assert (List->_prev == NULL, "invariant") ;
-        assert (List->TState == ObjectWaiter::TS_ENTER, "invariant") ;
-        assert (List != iterator, "invariant") ;
-     }
-
-     if (Policy == 0) {       // prepend to EntryList
-         if (List == NULL) {
-             iterator->_next = iterator->_prev = NULL ;
-             _EntryList = iterator ;
-         } else {
-             List->_prev = iterator ;
-             iterator->_next = List ;
-             iterator->_prev = NULL ;
-             _EntryList = iterator ;
-        }
-     } else
-     if (Policy == 1) {      // append to EntryList
-         if (List == NULL) {
-             iterator->_next = iterator->_prev = NULL ;
-             _EntryList = iterator ;
-         } else {
-            // CONSIDER:  finding the tail currently requires a linear-time walk of
-            // the EntryList.  We can make tail access constant-time by converting to
-            // a CDLL instead of using our current DLL.
-            ObjectWaiter * Tail ;
-            for (Tail = List ; Tail->_next != NULL ; Tail = Tail->_next) ;
-            assert (Tail != NULL && Tail->_next == NULL, "invariant") ;
-            Tail->_next = iterator ;
-            iterator->_prev = Tail ;
-            iterator->_next = NULL ;
-        }
-     } else
-     if (Policy == 2) {      // prepend to cxq
-         // prepend to cxq
-         if (List == NULL) {
-             iterator->_next = iterator->_prev = NULL ;
-             _EntryList = iterator ;
-         } else {
-            iterator->TState = ObjectWaiter::TS_CXQ ;
-            for (;;) {
-                ObjectWaiter * Front = _cxq ;
-                iterator->_next = Front ;
-                if (Atomic::cmpxchg_ptr (iterator, &_cxq, Front) == Front) {
-                    break ;
-                }
-            }
-         }
-     } else
-     if (Policy == 3) {      // append to cxq
-        iterator->TState = ObjectWaiter::TS_CXQ ;
-        for (;;) {
-            ObjectWaiter * Tail ;
-            Tail = _cxq ;
-            if (Tail == NULL) {
-                iterator->_next = NULL ;
-                if (Atomic::cmpxchg_ptr (iterator, &_cxq, NULL) == NULL) {
-                   break ;
-                }
-            } else {
-                while (Tail->_next != NULL) Tail = Tail->_next ;
-                Tail->_next = iterator ;
-                iterator->_prev = Tail ;
-                iterator->_next = NULL ;
-                break ;
-            }
-        }
-     } else {
-        ParkEvent * ev = iterator->_event ;
-        iterator->TState = ObjectWaiter::TS_RUN ;
-        OrderAccess::fence() ;
-        ev->unpark() ;
-     }
-
-     if (Policy < 4) {
-       iterator->wait_reenter_begin(this);
-     }
-
-     // _WaitSetLock protects the wait queue, not the EntryList.  We could
-     // move the add-to-EntryList operation, above, outside the critical section
-     // protected by _WaitSetLock.  In practice that's not useful.  With the
-     // exception of  wait() timeouts and interrupts the monitor owner
-     // is the only thread that grabs _WaitSetLock.  There's almost no contention
-     // on _WaitSetLock so it's not profitable to reduce the length of the
-     // critical section.
-  }
-
-  Thread::SpinRelease (&_WaitSetLock) ;
-
-  if (iterator != NULL && ObjectSynchronizer::_sync_Notifications != NULL) {
-     ObjectSynchronizer::_sync_Notifications->inc() ;
-  }
-}
-
-
-void ObjectMonitor::notifyAll(TRAPS) {
-  CHECK_OWNER();
-  ObjectWaiter* iterator;
-  if (_WaitSet == NULL) {
-      TEVENT (Empty-NotifyAll) ;
-      return ;
-  }
-  DTRACE_MONITOR_PROBE(notifyAll, this, object(), THREAD);
-
-  int Policy = Knob_MoveNotifyee ;
-  int Tally = 0 ;
-  Thread::SpinAcquire (&_WaitSetLock, "WaitSet - notifyall") ;
-
-  for (;;) {
-     iterator = DequeueWaiter () ;
-     if (iterator == NULL) break ;
-     TEVENT (NotifyAll - Transfer1) ;
-     ++Tally ;
-
-     // Disposition - what might we do with iterator ?
-     // a.  add it directly to the EntryList - either tail or head.
-     // b.  push it onto the front of the _cxq.
-     // For now we use (a).
-     //
-     // TODO-FIXME: currently notifyAll() transfers the waiters one-at-a-time from the waitset
-     // to the EntryList.  This could be done more efficiently with a single bulk transfer,
-     // but in practice it's not time-critical.  Beware too, that in prepend-mode we invert the
-     // order of the waiters.  Lets say that the waitset is "ABCD" and the EntryList is "XYZ".
-     // After a notifyAll() in prepend mode the waitset will be empty and the EntryList will
-     // be "DCBAXYZ".
-
-     guarantee (iterator->TState == ObjectWaiter::TS_WAIT, "invariant") ;
-     guarantee (iterator->_notified == 0, "invariant") ;
-     iterator->_notified = 1 ;
-     if (Policy != 4) {
-        iterator->TState = ObjectWaiter::TS_ENTER ;
-     }
-
-     ObjectWaiter * List = _EntryList ;
-     if (List != NULL) {
-        assert (List->_prev == NULL, "invariant") ;
-        assert (List->TState == ObjectWaiter::TS_ENTER, "invariant") ;
-        assert (List != iterator, "invariant") ;
-     }
-
-     if (Policy == 0) {       // prepend to EntryList
-         if (List == NULL) {
-             iterator->_next = iterator->_prev = NULL ;
-             _EntryList = iterator ;
-         } else {
-             List->_prev = iterator ;
-             iterator->_next = List ;
-             iterator->_prev = NULL ;
-             _EntryList = iterator ;
-        }
-     } else
-     if (Policy == 1) {      // append to EntryList
-         if (List == NULL) {
-             iterator->_next = iterator->_prev = NULL ;
-             _EntryList = iterator ;
-         } else {
-            // CONSIDER:  finding the tail currently requires a linear-time walk of
-            // the EntryList.  We can make tail access constant-time by converting to
-            // a CDLL instead of using our current DLL.
-            ObjectWaiter * Tail ;
-            for (Tail = List ; Tail->_next != NULL ; Tail = Tail->_next) ;
-            assert (Tail != NULL && Tail->_next == NULL, "invariant") ;
-            Tail->_next = iterator ;
-            iterator->_prev = Tail ;
-            iterator->_next = NULL ;
-        }
-     } else
-     if (Policy == 2) {      // prepend to cxq
-         // prepend to cxq
-         iterator->TState = ObjectWaiter::TS_CXQ ;
-         for (;;) {
-             ObjectWaiter * Front = _cxq ;
-             iterator->_next = Front ;
-             if (Atomic::cmpxchg_ptr (iterator, &_cxq, Front) == Front) {
-                 break ;
-             }
-         }
-     } else
-     if (Policy == 3) {      // append to cxq
-        iterator->TState = ObjectWaiter::TS_CXQ ;
-        for (;;) {
-            ObjectWaiter * Tail ;
-            Tail = _cxq ;
-            if (Tail == NULL) {
-                iterator->_next = NULL ;
-                if (Atomic::cmpxchg_ptr (iterator, &_cxq, NULL) == NULL) {
-                   break ;
-                }
-            } else {
-                while (Tail->_next != NULL) Tail = Tail->_next ;
-                Tail->_next = iterator ;
-                iterator->_prev = Tail ;
-                iterator->_next = NULL ;
-                break ;
-            }
-        }
-     } else {
-        ParkEvent * ev = iterator->_event ;
-        iterator->TState = ObjectWaiter::TS_RUN ;
-        OrderAccess::fence() ;
-        ev->unpark() ;
-     }
-
-     if (Policy < 4) {
-       iterator->wait_reenter_begin(this);
-     }
-
-     // _WaitSetLock protects the wait queue, not the EntryList.  We could
-     // move the add-to-EntryList operation, above, outside the critical section
-     // protected by _WaitSetLock.  In practice that's not useful.  With the
-     // exception of  wait() timeouts and interrupts the monitor owner
-     // is the only thread that grabs _WaitSetLock.  There's almost no contention
-     // on _WaitSetLock so it's not profitable to reduce the length of the
-     // critical section.
-  }
-
-  Thread::SpinRelease (&_WaitSetLock) ;
-
-  if (Tally != 0 && ObjectSynchronizer::_sync_Notifications != NULL) {
-     ObjectSynchronizer::_sync_Notifications->inc(Tally) ;
-  }
+void ObjectSynchronizer::release_monitors_owned_by_thread(TRAPS) {
+  assert(THREAD == JavaThread::current(), "must be current Java thread");
+  No_Safepoint_Verifier nsv ;
+  ReleaseJavaMonitorsClosure rjmc(THREAD);
+  Thread::muxAcquire(&ListLock, "release_monitors_owned_by_thread");
+  ObjectSynchronizer::monitors_iterate(&rjmc);
+  Thread::muxRelease(&ListLock);
+  THREAD->clear_pending_exception();
 }
 
-// check_slow() is a misnomer.  It's called to simply to throw an IMSX exception.
-// TODO-FIXME: remove check_slow() -- it's likely dead.
-
-void ObjectMonitor::check_slow(TRAPS) {
-  TEVENT (check_slow - throw IMSX) ;
-  assert(THREAD != _owner && !THREAD->is_lock_owned((address) _owner), "must not be owner");
-  THROW_MSG(vmSymbols::java_lang_IllegalMonitorStateException(), "current thread not owner");
-}
-
-
-// -------------------------------------------------------------------------
-// The raw monitor subsystem is entirely distinct from normal
-// java-synchronization or jni-synchronization.  raw monitors are not
-// associated with objects.  They can be implemented in any manner
-// that makes sense.  The original implementors decided to piggy-back
-// the raw-monitor implementation on the existing Java objectMonitor mechanism.
-// This flaw needs to fixed.  We should reimplement raw monitors as sui-generis.
-// Specifically, we should not implement raw monitors via java monitors.
-// Time permitting, we should disentangle and deconvolve the two implementations
-// and move the resulting raw monitor implementation over to the JVMTI directories.
-// Ideally, the raw monitor implementation would be built on top of
-// park-unpark and nothing else.
-//
-// raw monitors are used mainly by JVMTI
-// The raw monitor implementation borrows the ObjectMonitor structure,
-// but the operators are degenerate and extremely simple.
-//
-// Mixed use of a single objectMonitor instance -- as both a raw monitor
-// and a normal java monitor -- is not permissible.
-//
-// Note that we use the single RawMonitor_lock to protect queue operations for
-// _all_ raw monitors.  This is a scalability impediment, but since raw monitor usage
-// is deprecated and rare, this is not of concern.  The RawMonitor_lock can not
-// be held indefinitely.  The critical sections must be short and bounded.
-//
-// -------------------------------------------------------------------------
-
-int ObjectMonitor::SimpleEnter (Thread * Self) {
-  for (;;) {
-    if (Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {
-       return OS_OK ;
-    }
-
-    ObjectWaiter Node (Self) ;
-    Self->_ParkEvent->reset() ;     // strictly optional
-    Node.TState = ObjectWaiter::TS_ENTER ;
-
-    RawMonitor_lock->lock_without_safepoint_check() ;
-    Node._next  = _EntryList ;
-    _EntryList  = &Node ;
-    OrderAccess::fence() ;
-    if (_owner == NULL && Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {
-        _EntryList = Node._next ;
-        RawMonitor_lock->unlock() ;
-        return OS_OK ;
-    }
-    RawMonitor_lock->unlock() ;
-    while (Node.TState == ObjectWaiter::TS_ENTER) {
-       Self->_ParkEvent->park() ;
-    }
-  }
-}
-
-int ObjectMonitor::SimpleExit (Thread * Self) {
-  guarantee (_owner == Self, "invariant") ;
-  OrderAccess::release_store_ptr (&_owner, NULL) ;
-  OrderAccess::fence() ;
-  if (_EntryList == NULL) return OS_OK ;
-  ObjectWaiter * w ;
-
-  RawMonitor_lock->lock_without_safepoint_check() ;
-  w = _EntryList ;
-  if (w != NULL) {
-      _EntryList = w->_next ;
-  }
-  RawMonitor_lock->unlock() ;
-  if (w != NULL) {
-      guarantee (w ->TState == ObjectWaiter::TS_ENTER, "invariant") ;
-      ParkEvent * ev = w->_event ;
-      w->TState = ObjectWaiter::TS_RUN ;
-      OrderAccess::fence() ;
-      ev->unpark() ;
-  }
-  return OS_OK ;
-}
-
-int ObjectMonitor::SimpleWait (Thread * Self, jlong millis) {
-  guarantee (_owner == Self  , "invariant") ;
-  guarantee (_recursions == 0, "invariant") ;
-
-  ObjectWaiter Node (Self) ;
-  Node._notified = 0 ;
-  Node.TState    = ObjectWaiter::TS_WAIT ;
-
-  RawMonitor_lock->lock_without_safepoint_check() ;
-  Node._next     = _WaitSet ;
-  _WaitSet       = &Node ;
-  RawMonitor_lock->unlock() ;
-
-  SimpleExit (Self) ;
-  guarantee (_owner != Self, "invariant") ;
-
-  int ret = OS_OK ;
-  if (millis <= 0) {
-    Self->_ParkEvent->park();
-  } else {
-    ret = Self->_ParkEvent->park(millis);
-  }
-
-  // If thread still resides on the waitset then unlink it.
-  // Double-checked locking -- the usage is safe in this context
-  // as we TState is volatile and the lock-unlock operators are
-  // serializing (barrier-equivalent).
-
-  if (Node.TState == ObjectWaiter::TS_WAIT) {
-    RawMonitor_lock->lock_without_safepoint_check() ;
-    if (Node.TState == ObjectWaiter::TS_WAIT) {
-      // Simple O(n) unlink, but performance isn't critical here.
-      ObjectWaiter * p ;
-      ObjectWaiter * q = NULL ;
-      for (p = _WaitSet ; p != &Node; p = p->_next) {
-         q = p ;
-      }
-      guarantee (p == &Node, "invariant") ;
-      if (q == NULL) {
-        guarantee (p == _WaitSet, "invariant") ;
-        _WaitSet = p->_next ;
-      } else {
-        guarantee (p == q->_next, "invariant") ;
-        q->_next = p->_next ;
-      }
-      Node.TState = ObjectWaiter::TS_RUN ;
-    }
-    RawMonitor_lock->unlock() ;
-  }
-
-  guarantee (Node.TState == ObjectWaiter::TS_RUN, "invariant") ;
-  SimpleEnter (Self) ;
-
-  guarantee (_owner == Self, "invariant") ;
-  guarantee (_recursions == 0, "invariant") ;
-  return ret ;
-}
-
-int ObjectMonitor::SimpleNotify (Thread * Self, bool All) {
-  guarantee (_owner == Self, "invariant") ;
-  if (_WaitSet == NULL) return OS_OK ;
-
-  // We have two options:
-  // A. Transfer the threads from the WaitSet to the EntryList
-  // B. Remove the thread from the WaitSet and unpark() it.
-  //
-  // We use (B), which is crude and results in lots of futile
-  // context switching.  In particular (B) induces lots of contention.
-
-  ParkEvent * ev = NULL ;       // consider using a small auto array ...
-  RawMonitor_lock->lock_without_safepoint_check() ;
-  for (;;) {
-      ObjectWaiter * w = _WaitSet ;
-      if (w == NULL) break ;
-      _WaitSet = w->_next ;
-      if (ev != NULL) { ev->unpark(); ev = NULL; }
-      ev = w->_event ;
-      OrderAccess::loadstore() ;
-      w->TState = ObjectWaiter::TS_RUN ;
-      OrderAccess::storeload();
-      if (!All) break ;
-  }
-  RawMonitor_lock->unlock() ;
-  if (ev != NULL) ev->unpark();
-  return OS_OK ;
-}
-
-// Any JavaThread will enter here with state _thread_blocked
-int ObjectMonitor::raw_enter(TRAPS) {
-  TEVENT (raw_enter) ;
-  void * Contended ;
-
-  // don't enter raw monitor if thread is being externally suspended, it will
-  // surprise the suspender if a "suspended" thread can still enter monitor
-  JavaThread * jt = (JavaThread *)THREAD;
-  if (THREAD->is_Java_thread()) {
-    jt->SR_lock()->lock_without_safepoint_check();
-    while (jt->is_external_suspend()) {
-      jt->SR_lock()->unlock();
-      jt->java_suspend_self();
-      jt->SR_lock()->lock_without_safepoint_check();
-    }
-    // guarded by SR_lock to avoid racing with new external suspend requests.
-    Contended = Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) ;
-    jt->SR_lock()->unlock();
-  } else {
-    Contended = Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) ;
-  }
-
-  if (Contended == THREAD) {
-     _recursions ++ ;
-     return OM_OK ;
-  }
-
-  if (Contended == NULL) {
-     guarantee (_owner == THREAD, "invariant") ;
-     guarantee (_recursions == 0, "invariant") ;
-     return OM_OK ;
-  }
-
-  THREAD->set_current_pending_monitor(this);
-
-  if (!THREAD->is_Java_thread()) {
-     // No other non-Java threads besides VM thread would acquire
-     // a raw monitor.
-     assert(THREAD->is_VM_thread(), "must be VM thread");
-     SimpleEnter (THREAD) ;
-   } else {
-     guarantee (jt->thread_state() == _thread_blocked, "invariant") ;
-     for (;;) {
-       jt->set_suspend_equivalent();
-       // cleared by handle_special_suspend_equivalent_condition() or
-       // java_suspend_self()
-       SimpleEnter (THREAD) ;
-
-       // were we externally suspended while we were waiting?
-       if (!jt->handle_special_suspend_equivalent_condition()) break ;
-
-       // This thread was externally suspended
-       //
-       // This logic isn't needed for JVMTI raw monitors,
-       // but doesn't hurt just in case the suspend rules change. This
-           // logic is needed for the ObjectMonitor.wait() reentry phase.
-           // We have reentered the contended monitor, but while we were
-           // waiting another thread suspended us. We don't want to reenter
-           // the monitor while suspended because that would surprise the
-           // thread that suspended us.
-           //
-           // Drop the lock -
-       SimpleExit (THREAD) ;
-
-           jt->java_suspend_self();
-         }
-
-     assert(_owner == THREAD, "Fatal error with monitor owner!");
-     assert(_recursions == 0, "Fatal error with monitor recursions!");
-  }
-
-  THREAD->set_current_pending_monitor(NULL);
-  guarantee (_recursions == 0, "invariant") ;
-  return OM_OK;
-}
-
-// Used mainly for JVMTI raw monitor implementation
-// Also used for ObjectMonitor::wait().
-int ObjectMonitor::raw_exit(TRAPS) {
-  TEVENT (raw_exit) ;
-  if (THREAD != _owner) {
-    return OM_ILLEGAL_MONITOR_STATE;
-  }
-  if (_recursions > 0) {
-    --_recursions ;
-    return OM_OK ;
-  }
-
-  void * List = _EntryList ;
-  SimpleExit (THREAD) ;
-
-  return OM_OK;
-}
-
-// Used for JVMTI raw monitor implementation.
-// All JavaThreads will enter here with state _thread_blocked
-
-int ObjectMonitor::raw_wait(jlong millis, bool interruptible, TRAPS) {
-  TEVENT (raw_wait) ;
-  if (THREAD != _owner) {
-    return OM_ILLEGAL_MONITOR_STATE;
-  }
-
-  // To avoid spurious wakeups we reset the parkevent -- This is strictly optional.
-  // The caller must be able to tolerate spurious returns from raw_wait().
-  THREAD->_ParkEvent->reset() ;
-  OrderAccess::fence() ;
-
-  // check interrupt event
-  if (interruptible && Thread::is_interrupted(THREAD, true)) {
-    return OM_INTERRUPTED;
-  }
-
-  intptr_t save = _recursions ;
-  _recursions = 0 ;
-  _waiters ++ ;
-  if (THREAD->is_Java_thread()) {
-    guarantee (((JavaThread *) THREAD)->thread_state() == _thread_blocked, "invariant") ;
-    ((JavaThread *)THREAD)->set_suspend_equivalent();
-  }
-  int rv = SimpleWait (THREAD, millis) ;
-  _recursions = save ;
-  _waiters -- ;
-
-  guarantee (THREAD == _owner, "invariant") ;
-  if (THREAD->is_Java_thread()) {
-     JavaThread * jSelf = (JavaThread *) THREAD ;
-     for (;;) {
-        if (!jSelf->handle_special_suspend_equivalent_condition()) break ;
-        SimpleExit (THREAD) ;
-        jSelf->java_suspend_self();
-        SimpleEnter (THREAD) ;
-        jSelf->set_suspend_equivalent() ;
-     }
-  }
-  guarantee (THREAD == _owner, "invariant") ;
-
-  if (interruptible && Thread::is_interrupted(THREAD, true)) {
-    return OM_INTERRUPTED;
-  }
-  return OM_OK ;
-}
-
-int ObjectMonitor::raw_notify(TRAPS) {
-  TEVENT (raw_notify) ;
-  if (THREAD != _owner) {
-    return OM_ILLEGAL_MONITOR_STATE;
-  }
-  SimpleNotify (THREAD, false) ;
-  return OM_OK;
-}
-
-int ObjectMonitor::raw_notifyAll(TRAPS) {
-  TEVENT (raw_notifyAll) ;
-  if (THREAD != _owner) {
-    return OM_ILLEGAL_MONITOR_STATE;
-  }
-  SimpleNotify (THREAD, true) ;
-  return OM_OK;
-}
-
-#ifndef PRODUCT
-void ObjectMonitor::verify() {
-}
-
-void ObjectMonitor::print() {
-}
-#endif
-
 //------------------------------------------------------------------------------
 // Non-product code
 
--- a/hotspot/src/share/vm/runtime/synchronizer.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/runtime/synchronizer.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -22,53 +22,6 @@
  *
  */
 
-class BasicLock VALUE_OBJ_CLASS_SPEC {
-  friend class VMStructs;
- private:
-  volatile markOop _displaced_header;
- public:
-  markOop      displaced_header() const               { return _displaced_header; }
-  void         set_displaced_header(markOop header)   { _displaced_header = header; }
-
-  void print_on(outputStream* st) const;
-
-  // move a basic lock (used during deoptimization
-  void move_to(oop obj, BasicLock* dest);
-
-  static int displaced_header_offset_in_bytes()       { return offset_of(BasicLock, _displaced_header); }
-};
-
-// A BasicObjectLock associates a specific Java object with a BasicLock.
-// It is currently embedded in an interpreter frame.
-
-// Because some machines have alignment restrictions on the control stack,
-// the actual space allocated by the interpreter may include padding words
-// after the end of the BasicObjectLock.  Also, in order to guarantee
-// alignment of the embedded BasicLock objects on such machines, we
-// put the embedded BasicLock at the beginning of the struct.
-
-class BasicObjectLock VALUE_OBJ_CLASS_SPEC {
-  friend class VMStructs;
- private:
-  BasicLock _lock;                                    // the lock, must be double word aligned
-  oop       _obj;                                     // object holds the lock;
-
- public:
-  // Manipulation
-  oop      obj() const                                { return _obj;  }
-  void set_obj(oop obj)                               { _obj = obj; }
-  BasicLock* lock()                                   { return &_lock; }
-
-  // Note: Use frame::interpreter_frame_monitor_size() for the size of BasicObjectLocks
-  //       in interpreter activation frames since it includes machine-specific padding.
-  static int size()                                   { return sizeof(BasicObjectLock)/wordSize; }
-
-  // GC support
-  void oops_do(OopClosure* f) { f->do_oop(&_obj); }
-
-  static int obj_offset_in_bytes()                    { return offset_of(BasicObjectLock, _obj);  }
-  static int lock_offset_in_bytes()                   { return offset_of(BasicObjectLock, _lock); }
-};
 
 class ObjectMonitor;
 
@@ -163,6 +116,8 @@
   static void verify() PRODUCT_RETURN;
   static int  verify_objmon_isinpool(ObjectMonitor *addr) PRODUCT_RETURN0;
 
+  static void RegisterSpinCallback (int (*)(intptr_t, int), intptr_t) ;
+
  private:
   enum { _BLOCKSIZE = 128 };
   static ObjectMonitor* gBlockList;
@@ -170,30 +125,6 @@
   static ObjectMonitor * volatile gOmInUseList; // for moribund thread, so monitors they inflated still get scanned
   static int gOmInUseCount;
 
- public:
-  static void Initialize () ;
-  static PerfCounter * _sync_ContendedLockAttempts ;
-  static PerfCounter * _sync_FutileWakeups ;
-  static PerfCounter * _sync_Parks ;
-  static PerfCounter * _sync_EmptyNotifications ;
-  static PerfCounter * _sync_Notifications ;
-  static PerfCounter * _sync_SlowEnter ;
-  static PerfCounter * _sync_SlowExit ;
-  static PerfCounter * _sync_SlowNotify ;
-  static PerfCounter * _sync_SlowNotifyAll ;
-  static PerfCounter * _sync_FailedSpins ;
-  static PerfCounter * _sync_SuccessfulSpins ;
-  static PerfCounter * _sync_PrivateA ;
-  static PerfCounter * _sync_PrivateB ;
-  static PerfCounter * _sync_MonInCirculation ;
-  static PerfCounter * _sync_MonScavenged ;
-  static PerfCounter * _sync_Inflations ;
-  static PerfCounter * _sync_Deflations ;
-  static PerfLongVariable * _sync_MonExtant ;
-
- public:
-  static void RegisterSpinCallback (int (*)(intptr_t, int), intptr_t) ;
-
 };
 
 // ObjectLocker enforced balanced locking and can never thrown an
--- a/hotspot/src/share/vm/runtime/thread.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -2921,6 +2921,9 @@
   // So that JDK version can be used as a discrimintor when parsing arguments
   JDK_Version_init();
 
+  // Update/Initialize System properties after JDK version number is known
+  Arguments::init_version_specific_system_properties();
+
   // Parse arguments
   jint parse_result = Arguments::parse(args);
   if (parse_result != JNI_OK) return parse_result;
@@ -2992,8 +2995,8 @@
   // crash Linux VM, see notes in os_linux.cpp.
   main_thread->create_stack_guard_pages();
 
-  // Initialize Java-Leve synchronization subsystem
-  ObjectSynchronizer::Initialize() ;
+  // Initialize Java-Level synchronization subsystem
+  ObjectMonitor::Initialize() ;
 
   // Initialize global modules
   jint status = init_globals();
@@ -3962,215 +3965,272 @@
   }
 }
 
-
-// Lifecycle management for TSM ParkEvents.
-// ParkEvents are type-stable (TSM).
-// In our particular implementation they happen to be immortal.
+// Internal SpinLock and Mutex
+// Based on ParkEvent
+
+// Ad-hoc mutual exclusion primitives: SpinLock and Mux
 //
-// We manage concurrency on the FreeList with a CAS-based
-// detach-modify-reattach idiom that avoids the ABA problems
-// that would otherwise be present in a simple CAS-based
-// push-pop implementation.   (push-one and pop-all)
+// We employ SpinLocks _only for low-contention, fixed-length
+// short-duration critical sections where we're concerned
+// about native mutex_t or HotSpot Mutex:: latency.
+// The mux construct provides a spin-then-block mutual exclusion
+// mechanism.
+//
+// Testing has shown that contention on the ListLock guarding gFreeList
+// is common.  If we implement ListLock as a simple SpinLock it's common
+// for the JVM to devolve to yielding with little progress.  This is true
+// despite the fact that the critical sections protected by ListLock are
+// extremely short.
 //
-// Caveat: Allocate() and Release() may be called from threads
-// other than the thread associated with the Event!
-// If we need to call Allocate() when running as the thread in
-// question then look for the PD calls to initialize native TLS.
-// Native TLS (Win32/Linux/Solaris) can only be initialized or
-// accessed by the associated thread.
-// See also pd_initialize().
-//
-// Note that we could defer associating a ParkEvent with a thread
-// until the 1st time the thread calls park().  unpark() calls to
-// an unprovisioned thread would be ignored.  The first park() call
-// for a thread would allocate and associate a ParkEvent and return
-// immediately.
-
-volatile int ParkEvent::ListLock = 0 ;
-ParkEvent * volatile ParkEvent::FreeList = NULL ;
-
-ParkEvent * ParkEvent::Allocate (Thread * t) {
-  // In rare cases -- JVM_RawMonitor* operations -- we can find t == null.
-  ParkEvent * ev ;
-
-  // Start by trying to recycle an existing but unassociated
-  // ParkEvent from the global free list.
+// TODO-FIXME: ListLock should be of type SpinLock.
+// We should make this a 1st-class type, integrated into the lock
+// hierarchy as leaf-locks.  Critically, the SpinLock structure
+// should have sufficient padding to avoid false-sharing and excessive
+// cache-coherency traffic.
+
+
+typedef volatile int SpinLockT ;
+
+void Thread::SpinAcquire (volatile int * adr, const char * LockName) {
+  if (Atomic::cmpxchg (1, adr, 0) == 0) {
+     return ;   // normal fast-path return
+  }
+
+  // Slow-path : We've encountered contention -- Spin/Yield/Block strategy.
+  TEVENT (SpinAcquire - ctx) ;
+  int ctr = 0 ;
+  int Yields = 0 ;
   for (;;) {
-    ev = FreeList ;
-    if (ev == NULL) break ;
-    // 1: Detach - sequester or privatize the list
-    // Tantamount to ev = Swap (&FreeList, NULL)
-    if (Atomic::cmpxchg_ptr (NULL, &FreeList, ev) != ev) {
-       continue ;
-    }
-
-    // We've detached the list.  The list in-hand is now
-    // local to this thread.   This thread can operate on the
-    // list without risk of interference from other threads.
-    // 2: Extract -- pop the 1st element from the list.
-    ParkEvent * List = ev->FreeNext ;
-    if (List == NULL) break ;
-    for (;;) {
-        // 3: Try to reattach the residual list
-        guarantee (List != NULL, "invariant") ;
-        ParkEvent * Arv =  (ParkEvent *) Atomic::cmpxchg_ptr (List, &FreeList, NULL) ;
-        if (Arv == NULL) break ;
-
-        // New nodes arrived.  Try to detach the recent arrivals.
-        if (Atomic::cmpxchg_ptr (NULL, &FreeList, Arv) != Arv) {
-            continue ;
+     while (*adr != 0) {
+        ++ctr ;
+        if ((ctr & 0xFFF) == 0 || !os::is_MP()) {
+           if (Yields > 5) {
+             // Consider using a simple NakedSleep() instead.
+             // Then SpinAcquire could be called by non-JVM threads
+             Thread::current()->_ParkEvent->park(1) ;
+           } else {
+             os::NakedYield() ;
+             ++Yields ;
+           }
+        } else {
+           SpinPause() ;
         }
-        guarantee (Arv != NULL, "invariant") ;
-        // 4: Merge Arv into List
-        ParkEvent * Tail = List ;
-        while (Tail->FreeNext != NULL) Tail = Tail->FreeNext ;
-        Tail->FreeNext = Arv ;
-    }
-    break ;
-  }
-
-  if (ev != NULL) {
-    guarantee (ev->AssociatedWith == NULL, "invariant") ;
-  } else {
-    // Do this the hard way -- materialize a new ParkEvent.
-    // In rare cases an allocating thread might detach a long list --
-    // installing null into FreeList -- and then stall or be obstructed.
-    // A 2nd thread calling Allocate() would see FreeList == null.
-    // The list held privately by the 1st thread is unavailable to the 2nd thread.
-    // In that case the 2nd thread would have to materialize a new ParkEvent,
-    // even though free ParkEvents existed in the system.  In this case we end up
-    // with more ParkEvents in circulation than we need, but the race is
-    // rare and the outcome is benign.  Ideally, the # of extant ParkEvents
-    // is equal to the maximum # of threads that existed at any one time.
-    // Because of the race mentioned above, segments of the freelist
-    // can be transiently inaccessible.  At worst we may end up with the
-    // # of ParkEvents in circulation slightly above the ideal.
-    // Note that if we didn't have the TSM/immortal constraint, then
-    // when reattaching, above, we could trim the list.
-    ev = new ParkEvent () ;
-    guarantee ((intptr_t(ev) & 0xFF) == 0, "invariant") ;
-  }
-  ev->reset() ;                     // courtesy to caller
-  ev->AssociatedWith = t ;          // Associate ev with t
-  ev->FreeNext       = NULL ;
-  return ev ;
-}
-
-void ParkEvent::Release (ParkEvent * ev) {
-  if (ev == NULL) return ;
-  guarantee (ev->FreeNext == NULL      , "invariant") ;
-  ev->AssociatedWith = NULL ;
-  for (;;) {
-    // Push ev onto FreeList
-    // The mechanism is "half" lock-free.
-    ParkEvent * List = FreeList ;
-    ev->FreeNext = List ;
-    if (Atomic::cmpxchg_ptr (ev, &FreeList, List) == List) break ;
+     }
+     if (Atomic::cmpxchg (1, adr, 0) == 0) return ;
   }
 }
 
-// Override operator new and delete so we can ensure that the
-// least significant byte of ParkEvent addresses is 0.
-// Beware that excessive address alignment is undesirable
-// as it can result in D$ index usage imbalance as
-// well as bank access imbalance on Niagara-like platforms,
-// although Niagara's hash function should help.
-
-void * ParkEvent::operator new (size_t sz) {
-  return (void *) ((intptr_t (CHeapObj::operator new (sz + 256)) + 256) & -256) ;
-}
-
-void ParkEvent::operator delete (void * a) {
-  // ParkEvents are type-stable and immortal ...
-  ShouldNotReachHere();
+void Thread::SpinRelease (volatile int * adr) {
+  assert (*adr != 0, "invariant") ;
+  OrderAccess::fence() ;      // guarantee at least release consistency.
+  // Roach-motel semantics.
+  // It's safe if subsequent LDs and STs float "up" into the critical section,
+  // but prior LDs and STs within the critical section can't be allowed
+  // to reorder or float past the ST that releases the lock.
+  *adr = 0 ;
 }
 
-
-// 6399321 As a temporary measure we copied & modified the ParkEvent::
-// allocate() and release() code for use by Parkers.  The Parker:: forms
-// will eventually be removed as we consolide and shift over to ParkEvents
-// for both builtin synchronization and JSR166 operations.
-
-volatile int Parker::ListLock = 0 ;
-Parker * volatile Parker::FreeList = NULL ;
-
-Parker * Parker::Allocate (JavaThread * t) {
-  guarantee (t != NULL, "invariant") ;
-  Parker * p ;
-
-  // Start by trying to recycle an existing but unassociated
-  // Parker from the global free list.
+// muxAcquire and muxRelease:
+//
+// *  muxAcquire and muxRelease support a single-word lock-word construct.
+//    The LSB of the word is set IFF the lock is held.
+//    The remainder of the word points to the head of a singly-linked list
+//    of threads blocked on the lock.
+//
+// *  The current implementation of muxAcquire-muxRelease uses its own
+//    dedicated Thread._MuxEvent instance.  If we're interested in
+//    minimizing the peak number of extant ParkEvent instances then
+//    we could eliminate _MuxEvent and "borrow" _ParkEvent as long
+//    as certain invariants were satisfied.  Specifically, care would need
+//    to be taken with regards to consuming unpark() "permits".
+//    A safe rule of thumb is that a thread would never call muxAcquire()
+//    if it's enqueued (cxq, EntryList, WaitList, etc) and will subsequently
+//    park().  Otherwise the _ParkEvent park() operation in muxAcquire() could
+//    consume an unpark() permit intended for monitorenter, for instance.
+//    One way around this would be to widen the restricted-range semaphore
+//    implemented in park().  Another alternative would be to provide
+//    multiple instances of the PlatformEvent() for each thread.  One
+//    instance would be dedicated to muxAcquire-muxRelease, for instance.
+//
+// *  Usage:
+//    -- Only as leaf locks
+//    -- for short-term locking only as muxAcquire does not perform
+//       thread state transitions.
+//
+// Alternatives:
+// *  We could implement muxAcquire and muxRelease with MCS or CLH locks
+//    but with parking or spin-then-park instead of pure spinning.
+// *  Use Taura-Oyama-Yonenzawa locks.
+// *  It's possible to construct a 1-0 lock if we encode the lockword as
+//    (List,LockByte).  Acquire will CAS the full lockword while Release
+//    will STB 0 into the LockByte.  The 1-0 scheme admits stranding, so
+//    acquiring threads use timers (ParkTimed) to detect and recover from
+//    the stranding window.  Thread/Node structures must be aligned on 256-byte
+//    boundaries by using placement-new.
+// *  Augment MCS with advisory back-link fields maintained with CAS().
+//    Pictorially:  LockWord -> T1 <-> T2 <-> T3 <-> ... <-> Tn <-> Owner.
+//    The validity of the backlinks must be ratified before we trust the value.
+//    If the backlinks are invalid the exiting thread must back-track through the
+//    the forward links, which are always trustworthy.
+// *  Add a successor indication.  The LockWord is currently encoded as
+//    (List, LOCKBIT:1).  We could also add a SUCCBIT or an explicit _succ variable
+//    to provide the usual futile-wakeup optimization.
+//    See RTStt for details.
+// *  Consider schedctl.sc_nopreempt to cover the critical section.
+//
+
+
+typedef volatile intptr_t MutexT ;      // Mux Lock-word
+enum MuxBits { LOCKBIT = 1 } ;
+
+void Thread::muxAcquire (volatile intptr_t * Lock, const char * LockName) {
+  intptr_t w = Atomic::cmpxchg_ptr (LOCKBIT, Lock, 0) ;
+  if (w == 0) return ;
+  if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
+     return ;
+  }
+
+  TEVENT (muxAcquire - Contention) ;
+  ParkEvent * const Self = Thread::current()->_MuxEvent ;
+  assert ((intptr_t(Self) & LOCKBIT) == 0, "invariant") ;
   for (;;) {
-    p = FreeList ;
-    if (p  == NULL) break ;
-    // 1: Detach
-    // Tantamount to p = Swap (&FreeList, NULL)
-    if (Atomic::cmpxchg_ptr (NULL, &FreeList, p) != p) {
-       continue ;
-    }
-
-    // We've detached the list.  The list in-hand is now
-    // local to this thread.   This thread can operate on the
-    // list without risk of interference from other threads.
-    // 2: Extract -- pop the 1st element from the list.
-    Parker * List = p->FreeNext ;
-    if (List == NULL) break ;
-    for (;;) {
-        // 3: Try to reattach the residual list
-        guarantee (List != NULL, "invariant") ;
-        Parker * Arv =  (Parker *) Atomic::cmpxchg_ptr (List, &FreeList, NULL) ;
-        if (Arv == NULL) break ;
-
-        // New nodes arrived.  Try to detach the recent arrivals.
-        if (Atomic::cmpxchg_ptr (NULL, &FreeList, Arv) != Arv) {
-            continue ;
+     int its = (os::is_MP() ? 100 : 0) + 1 ;
+
+     // Optional spin phase: spin-then-park strategy
+     while (--its >= 0) {
+       w = *Lock ;
+       if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
+          return ;
+       }
+     }
+
+     Self->reset() ;
+     Self->OnList = intptr_t(Lock) ;
+     // The following fence() isn't _strictly necessary as the subsequent
+     // CAS() both serializes execution and ratifies the fetched *Lock value.
+     OrderAccess::fence();
+     for (;;) {
+        w = *Lock ;
+        if ((w & LOCKBIT) == 0) {
+            if (Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
+                Self->OnList = 0 ;   // hygiene - allows stronger asserts
+                return ;
+            }
+            continue ;      // Interference -- *Lock changed -- Just retry
         }
-        guarantee (Arv != NULL, "invariant") ;
-        // 4: Merge Arv into List
-        Parker * Tail = List ;
-        while (Tail->FreeNext != NULL) Tail = Tail->FreeNext ;
-        Tail->FreeNext = Arv ;
-    }
-    break ;
-  }
-
-  if (p != NULL) {
-    guarantee (p->AssociatedWith == NULL, "invariant") ;
-  } else {
-    // Do this the hard way -- materialize a new Parker..
-    // In rare cases an allocating thread might detach
-    // a long list -- installing null into FreeList --and
-    // then stall.  Another thread calling Allocate() would see
-    // FreeList == null and then invoke the ctor.  In this case we
-    // end up with more Parkers in circulation than we need, but
-    // the race is rare and the outcome is benign.
-    // Ideally, the # of extant Parkers is equal to the
-    // maximum # of threads that existed at any one time.
-    // Because of the race mentioned above, segments of the
-    // freelist can be transiently inaccessible.  At worst
-    // we may end up with the # of Parkers in circulation
-    // slightly above the ideal.
-    p = new Parker() ;
-  }
-  p->AssociatedWith = t ;          // Associate p with t
-  p->FreeNext       = NULL ;
-  return p ;
-}
-
-
-void Parker::Release (Parker * p) {
-  if (p == NULL) return ;
-  guarantee (p->AssociatedWith != NULL, "invariant") ;
-  guarantee (p->FreeNext == NULL      , "invariant") ;
-  p->AssociatedWith = NULL ;
-  for (;;) {
-    // Push p onto FreeList
-    Parker * List = FreeList ;
-    p->FreeNext = List ;
-    if (Atomic::cmpxchg_ptr (p, &FreeList, List) == List) break ;
+        assert (w & LOCKBIT, "invariant") ;
+        Self->ListNext = (ParkEvent *) (w & ~LOCKBIT );
+        if (Atomic::cmpxchg_ptr (intptr_t(Self)|LOCKBIT, Lock, w) == w) break ;
+     }
+
+     while (Self->OnList != 0) {
+        Self->park() ;
+     }
   }
 }
 
+void Thread::muxAcquireW (volatile intptr_t * Lock, ParkEvent * ev) {
+  intptr_t w = Atomic::cmpxchg_ptr (LOCKBIT, Lock, 0) ;
+  if (w == 0) return ;
+  if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
+    return ;
+  }
+
+  TEVENT (muxAcquire - Contention) ;
+  ParkEvent * ReleaseAfter = NULL ;
+  if (ev == NULL) {
+    ev = ReleaseAfter = ParkEvent::Allocate (NULL) ;
+  }
+  assert ((intptr_t(ev) & LOCKBIT) == 0, "invariant") ;
+  for (;;) {
+    guarantee (ev->OnList == 0, "invariant") ;
+    int its = (os::is_MP() ? 100 : 0) + 1 ;
+
+    // Optional spin phase: spin-then-park strategy
+    while (--its >= 0) {
+      w = *Lock ;
+      if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
+        if (ReleaseAfter != NULL) {
+          ParkEvent::Release (ReleaseAfter) ;
+        }
+        return ;
+      }
+    }
+
+    ev->reset() ;
+    ev->OnList = intptr_t(Lock) ;
+    // The following fence() isn't _strictly necessary as the subsequent
+    // CAS() both serializes execution and ratifies the fetched *Lock value.
+    OrderAccess::fence();
+    for (;;) {
+      w = *Lock ;
+      if ((w & LOCKBIT) == 0) {
+        if (Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
+          ev->OnList = 0 ;
+          // We call ::Release while holding the outer lock, thus
+          // artificially lengthening the critical section.
+          // Consider deferring the ::Release() until the subsequent unlock(),
+          // after we've dropped the outer lock.
+          if (ReleaseAfter != NULL) {
+            ParkEvent::Release (ReleaseAfter) ;
+          }
+          return ;
+        }
+        continue ;      // Interference -- *Lock changed -- Just retry
+      }
+      assert (w & LOCKBIT, "invariant") ;
+      ev->ListNext = (ParkEvent *) (w & ~LOCKBIT );
+      if (Atomic::cmpxchg_ptr (intptr_t(ev)|LOCKBIT, Lock, w) == w) break ;
+    }
+
+    while (ev->OnList != 0) {
+      ev->park() ;
+    }
+  }
+}
+
+// Release() must extract a successor from the list and then wake that thread.
+// It can "pop" the front of the list or use a detach-modify-reattach (DMR) scheme
+// similar to that used by ParkEvent::Allocate() and ::Release().  DMR-based
+// Release() would :
+// (A) CAS() or swap() null to *Lock, releasing the lock and detaching the list.
+// (B) Extract a successor from the private list "in-hand"
+// (C) attempt to CAS() the residual back into *Lock over null.
+//     If there were any newly arrived threads and the CAS() would fail.
+//     In that case Release() would detach the RATs, re-merge the list in-hand
+//     with the RATs and repeat as needed.  Alternately, Release() might
+//     detach and extract a successor, but then pass the residual list to the wakee.
+//     The wakee would be responsible for reattaching and remerging before it
+//     competed for the lock.
+//
+// Both "pop" and DMR are immune from ABA corruption -- there can be
+// multiple concurrent pushers, but only one popper or detacher.
+// This implementation pops from the head of the list.  This is unfair,
+// but tends to provide excellent throughput as hot threads remain hot.
+// (We wake recently run threads first).
+
+void Thread::muxRelease (volatile intptr_t * Lock)  {
+  for (;;) {
+    const intptr_t w = Atomic::cmpxchg_ptr (0, Lock, LOCKBIT) ;
+    assert (w & LOCKBIT, "invariant") ;
+    if (w == LOCKBIT) return ;
+    ParkEvent * List = (ParkEvent *) (w & ~LOCKBIT) ;
+    assert (List != NULL, "invariant") ;
+    assert (List->OnList == intptr_t(Lock), "invariant") ;
+    ParkEvent * nxt = List->ListNext ;
+
+    // The following CAS() releases the lock and pops the head element.
+    if (Atomic::cmpxchg_ptr (intptr_t(nxt), Lock, w) != w) {
+      continue ;
+    }
+    List->OnList = 0 ;
+    OrderAccess::fence() ;
+    List->unpark () ;
+    return ;
+  }
+}
+
+
 void Threads::verify() {
   ALL_JAVA_THREADS(p) {
     p->verify();
--- a/hotspot/src/share/vm/runtime/thread.hpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/runtime/thread.hpp	Wed Jul 05 17:26:57 2017 +0200
@@ -30,6 +30,7 @@
 class ThreadStatistics;
 class ConcurrentLocksDump;
 class ParkEvent ;
+class Parker;
 
 class ciEnv;
 class CompileThread;
@@ -544,7 +545,6 @@
   static void muxAcquire  (volatile intptr_t * Lock, const char * Name) ;
   static void muxAcquireW (volatile intptr_t * Lock, ParkEvent * ev) ;
   static void muxRelease  (volatile intptr_t * Lock) ;
-
 };
 
 // Inline implementation of Thread::current()
@@ -1769,100 +1769,3 @@
   }
 };
 
-// ParkEvents are type-stable and immortal.
-//
-// Lifecycle: Once a ParkEvent is associated with a thread that ParkEvent remains
-// associated with the thread for the thread's entire lifetime - the relationship is
-// stable. A thread will be associated at most one ParkEvent.  When the thread
-// expires, the ParkEvent moves to the EventFreeList.  New threads attempt to allocate from
-// the EventFreeList before creating a new Event.  Type-stability frees us from
-// worrying about stale Event or Thread references in the objectMonitor subsystem.
-// (A reference to ParkEvent is always valid, even though the event may no longer be associated
-// with the desired or expected thread.  A key aspect of this design is that the callers of
-// park, unpark, etc must tolerate stale references and spurious wakeups).
-//
-// Only the "associated" thread can block (park) on the ParkEvent, although
-// any other thread can unpark a reachable parkevent.  Park() is allowed to
-// return spuriously.  In fact park-unpark a really just an optimization to
-// avoid unbounded spinning and surrender the CPU to be a polite system citizen.
-// A degenerate albeit "impolite" park-unpark implementation could simply return.
-// See http://blogs.sun.com/dave for more details.
-//
-// Eventually I'd like to eliminate Events and ObjectWaiters, both of which serve as
-// thread proxies, and simply make the THREAD structure type-stable and persistent.
-// Currently, we unpark events associated with threads, but ideally we'd just
-// unpark threads.
-//
-// The base-class, PlatformEvent, is platform-specific while the ParkEvent is
-// platform-independent.  PlatformEvent provides park(), unpark(), etc., and
-// is abstract -- that is, a PlatformEvent should never be instantiated except
-// as part of a ParkEvent.
-// Equivalently we could have defined a platform-independent base-class that
-// exported Allocate(), Release(), etc.  The platform-specific class would extend
-// that base-class, adding park(), unpark(), etc.
-//
-// A word of caution: The JVM uses 2 very similar constructs:
-// 1. ParkEvent are used for Java-level "monitor" synchronization.
-// 2. Parkers are used by JSR166-JUC park-unpark.
-//
-// We'll want to eventually merge these redundant facilities and use ParkEvent.
-
-
-class ParkEvent : public os::PlatformEvent {
-  private:
-    ParkEvent * FreeNext ;
-
-    // Current association
-    Thread * AssociatedWith ;
-    intptr_t RawThreadIdentity ;        // LWPID etc
-    volatile int Incarnation ;
-
-    // diagnostic : keep track of last thread to wake this thread.
-    // this is useful for construction of dependency graphs.
-    void * LastWaker ;
-
-  public:
-    // MCS-CLH list linkage and Native Mutex/Monitor
-    ParkEvent * volatile ListNext ;
-    ParkEvent * volatile ListPrev ;
-    volatile intptr_t OnList ;
-    volatile int TState ;
-    volatile int Notified ;             // for native monitor construct
-    volatile int IsWaiting ;            // Enqueued on WaitSet
-
-
-  private:
-    static ParkEvent * volatile FreeList ;
-    static volatile int ListLock ;
-
-    // It's prudent to mark the dtor as "private"
-    // ensuring that it's not visible outside the package.
-    // Unfortunately gcc warns about such usage, so
-    // we revert to the less desirable "protected" visibility.
-    // The other compilers accept private dtors.
-
-  protected:        // Ensure dtor is never invoked
-    ~ParkEvent() { guarantee (0, "invariant") ; }
-
-    ParkEvent() : PlatformEvent() {
-       AssociatedWith = NULL ;
-       FreeNext       = NULL ;
-       ListNext       = NULL ;
-       ListPrev       = NULL ;
-       OnList         = 0 ;
-       TState         = 0 ;
-       Notified       = 0 ;
-       IsWaiting      = 0 ;
-    }
-
-    // We use placement-new to force ParkEvent instances to be
-    // aligned on 256-byte address boundaries.  This ensures that the least
-    // significant byte of a ParkEvent address is always 0.
-
-    void * operator new (size_t sz) ;
-    void operator delete (void * a) ;
-
-  public:
-    static ParkEvent * Allocate (Thread * t) ;
-    static void Release (ParkEvent * e) ;
-} ;
--- a/hotspot/src/share/vm/utilities/debug.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/utilities/debug.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -51,14 +51,16 @@
 
 
 void warning(const char* format, ...) {
-  // In case error happens before init or during shutdown
-  if (tty == NULL) ostream_init();
+  if (PrintWarnings) {
+    // In case error happens before init or during shutdown
+    if (tty == NULL) ostream_init();
 
-  tty->print("%s warning: ", VM_Version::vm_name());
-  va_list ap;
-  va_start(ap, format);
-  tty->vprint_cr(format, ap);
-  va_end(ap);
+    tty->print("%s warning: ", VM_Version::vm_name());
+    va_list ap;
+    va_start(ap, format);
+    tty->vprint_cr(format, ap);
+    va_end(ap);
+  }
   if (BreakAtWarning) BREAKPOINT;
 }
 
--- a/hotspot/src/share/vm/utilities/exceptions.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/hotspot/src/share/vm/utilities/exceptions.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -61,6 +61,18 @@
    ShouldNotReachHere();
   }
 
+#ifdef ASSERT
+  // Check for trying to throw stack overflow before initialization is complete
+  // to prevent infinite recursion trying to initialize stack overflow without
+  // adequate stack space.
+  // This can happen with stress testing a large value of StackShadowPages
+  if (h_exception()->klass() == SystemDictionary::StackOverflowError_klass()) {
+    instanceKlass* ik = instanceKlass::cast(h_exception->klass());
+    assert(ik->is_initialized(),
+           "need to increase min_stack_allowed calculation");
+  }
+#endif // ASSERT
+
   if (thread->is_VM_thread()
       || thread->is_Compiler_thread() ) {
     // We do not care what kind of exception we get for the vm-thread or a thread which
@@ -91,7 +103,6 @@
     thread->set_pending_exception(Universe::vm_exception(), file, line);
     return true;
   }
-
   return false;
 }
 
@@ -193,6 +204,7 @@
     klassOop k = SystemDictionary::StackOverflowError_klass();
     oop e = instanceKlass::cast(k)->allocate_instance(CHECK);
     exception = Handle(THREAD, e);  // fill_in_stack trace does gc
+    assert(instanceKlass::cast(k)->is_initialized(), "need to increase min_stack_allowed calculation");
     if (StackTraceInThrowable) {
       java_lang_Throwable::fill_in_stack_trace(exception);
     }
--- a/jaxp/.hgtags	Wed Jul 05 17:26:05 2017 +0200
+++ b/jaxp/.hgtags	Wed Jul 05 17:26:57 2017 +0200
@@ -91,3 +91,4 @@
 d57197d22c2bfc39d1a860040f655b466ab46f52 jdk7-b114
 dc1612e1d3ac08eb8fcad764daff21c9247d33c9 jdk7-b115
 f8d4e6c6cfce1cda23fcbd144628a9791a9e1a63 jdk7-b116
+9ee4d96e893436a48607924227dadd2d93b9b00d jdk7-b117
--- a/jaxws/.hgtags	Wed Jul 05 17:26:05 2017 +0200
+++ b/jaxws/.hgtags	Wed Jul 05 17:26:57 2017 +0200
@@ -91,3 +91,4 @@
 400f494c81c5ec87714b705648afbb3cb680bf73 jdk7-b114
 824cc44bd6eba9abae07cc420f7fe3926c1adbd9 jdk7-b115
 376ac153078dd3b5f6d4a0981feee092c1492c96 jdk7-b116
+1320fb3bb588298c79716bd2d10b5b4afacb9370 jdk7-b117
--- a/jdk/.hgtags	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/.hgtags	Wed Jul 05 17:26:57 2017 +0200
@@ -91,3 +91,4 @@
 e250cef36ea05e627e7e6f7d75e5e19f529e2ba3 jdk7-b114
 449bad8d67b5808ecf0f927683acc0a5940f8c85 jdk7-b115
 1657ed4e1d86c8aa2028ab5a41f9da1ac4a369f8 jdk7-b116
+3e6726bbf80a4254ecd01051c8ed77ee19325e46 jdk7-b117
--- a/jdk/make/java/java/FILES_java.gmk	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/make/java/java/FILES_java.gmk	Wed Jul 05 17:26:57 2017 +0200
@@ -413,6 +413,7 @@
     java/io/FilePermission.java \
     java/io/Serializable.java \
     java/io/Externalizable.java \
+    java/io/SerialCallbackContext.java \
 	java/io/Bits.java \
 	java/io/ObjectInput.java \
 	java/io/ObjectInputStream.java \
--- a/jdk/make/java/jli/Makefile	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/make/java/jli/Makefile	Wed Jul 05 17:26:57 2017 +0200
@@ -148,14 +148,9 @@
 #
 ifeq ($(PLATFORM), windows)
 
-STATIC_LIBRARY_DIR = $(OBJDIR)/static
-STATIC_LIBRARY_NAME = $(LIBPREFIX)$(LIBRARY).lib
-STATIC_LIBRARY = $(STATIC_LIBRARY_DIR)/$(STATIC_LIBRARY_NAME)
+STATIC_LIBRARY = $(OBJDIR)/static/$(LIBPREFIX)$(LIBRARY).lib
 
-$(STATIC_LIBRARY_DIR): $(OBJDIR)
-	@$(MKDIR) $(STATIC_LIBRARY_DIR)
-
-$(STATIC_LIBRARY): $(STATIC_LIBRARY_DIR)
+$(STATIC_LIBRARY): $(FILES_o)
 	@$(prep-target)
 	$(LIBEXE) -nologo -out:$@ $(FILES_o)
 
--- a/jdk/make/java/nio/FILES_java.gmk	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/make/java/nio/FILES_java.gmk	Wed Jul 05 17:26:57 2017 +0200
@@ -33,7 +33,6 @@
 	java/nio/channels/AsynchronousByteChannel.java \
 	java/nio/channels/AsynchronousChannel.java \
 	java/nio/channels/AsynchronousChannelGroup.java \
-	java/nio/channels/AsynchronousDatagramChannel.java \
 	java/nio/channels/AsynchronousFileChannel.java \
 	java/nio/channels/AsynchronousServerSocketChannel.java \
 	java/nio/channels/AsynchronousSocketChannel.java \
@@ -207,7 +206,6 @@
 	sun/nio/ch/SelChImpl.java \
 	sun/nio/ch/ServerSocketAdaptor.java \
 	sun/nio/ch/ServerSocketChannelImpl.java \
-	sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java \
         sun/nio/ch/SinkChannelImpl.java \
 	sun/nio/ch/SocketAdaptor.java \
 	sun/nio/ch/SocketChannelImpl.java \
--- a/jdk/make/javax/sound/jsoundds/Makefile	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/make/javax/sound/jsoundds/Makefile	Wed Jul 05 17:26:57 2017 +0200
@@ -53,7 +53,7 @@
 #
 # Extra cc/linker flags.
 #
-LDLIBS += dsound.lib winmm.lib user32.lib
+LDLIBS += dsound.lib winmm.lib user32.lib ole32.lib
 CPPFLAGS += \
 	-DUSE_DAUDIO=TRUE \
 	-I$(SHARE_SRC)/native/com/sun/media/sound \
--- a/jdk/make/netbeans/jmx/build.properties	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/make/netbeans/jmx/build.properties	Wed Jul 05 17:26:57 2017 +0200
@@ -48,8 +48,8 @@
 jar.jmx.sealed				= true
 jar.jmx.spec.title			= JSR 003, 160, 255 - JMX API
 jar.jmx.spec.version			= ${project.spec.version}
-jar.jmx.spec.vendor			= Sun Microsystems, Inc.
-jar.jmx.impl.title			= JSR 003, 160, 255 - OpenJDK 7 JMX API 
+jar.jmx.spec.vendor			= Oracle Corporation
+jar.jmx.impl.title			= JSR 003, 160, 255 - OpenJDK 7 JMX API
 jar.jmx.impl.vendor			= Project OpenJDK
 
 javadoc.options=-J-Xmx256m
--- a/jdk/make/sun/javazic/tzdata/VERSION	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/make/sun/javazic/tzdata/VERSION	Wed Jul 05 17:26:57 2017 +0200
@@ -21,4 +21,4 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-tzdata2010l
+tzdata2010o
--- a/jdk/make/sun/javazic/tzdata/asia	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/make/sun/javazic/tzdata/asia	Wed Jul 05 17:26:57 2017 +0200
@@ -569,8 +569,8 @@
 Rule	HK	1954	1964	-	Mar	Sun>=18	3:30	1:00	S
 Rule	HK	1954	only	-	Oct	31	3:30	0	-
 Rule	HK	1955	1964	-	Nov	Sun>=1	3:30	0	-
-Rule	HK	1965	1977	-	Apr	Sun>=16	3:30	1:00	S
-Rule	HK	1965	1977	-	Oct	Sun>=16	3:30	0	-
+Rule	HK	1965	1976	-	Apr	Sun>=16	3:30	1:00	S
+Rule	HK	1965	1976	-	Oct	Sun>=16	3:30	0	-
 Rule	HK	1973	only	-	Dec	30	3:30	1:00	S
 Rule	HK	1979	only	-	May	Sun>=8	3:30	1:00	S
 Rule	HK	1979	only	-	Oct	Sun>=16	3:30	0	-
--- a/jdk/make/sun/javazic/tzdata/australasia	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/make/sun/javazic/tzdata/australasia	Wed Jul 05 17:26:57 2017 +0200
@@ -306,13 +306,26 @@
 # http://www.timeanddate.com/news/time/fiji-dst-ends-march-2010.html
 # </a>
 
+# From Alexander Krivenyshev (2010-10-24):
+# According to Radio Fiji and Fiji Times online, Fiji will end DST 3 
+# weeks earlier than expected - on March 6, 2011, not March 27, 2011...
+# Here is confirmation from Government of the Republic of the Fiji Islands, 
+# Ministry of Information (fiji.gov.fj) web site:
+# <a href="http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155">
+# http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155
+# </a>
+# or
+# <a href="http://www.worldtimezone.com/dst_news/dst_news_fiji04.html">
+# http://www.worldtimezone.com/dst_news/dst_news_fiji04.html
+# </a>
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Fiji	1998	1999	-	Nov	Sun>=1	2:00	1:00	S
 Rule	Fiji	1999	2000	-	Feb	lastSun	3:00	0	-
 Rule	Fiji	2009	only	-	Nov	29	2:00	1:00	S
 Rule	Fiji	2010	only	-	Mar	lastSun	3:00	0	-
 Rule	Fiji	2010	only	-	Oct	24	2:00	1:00	S
-Rule	Fiji	2011	only	-	Mar	lastSun 3:00	0	-
+Rule	Fiji	2011	only	-	Mar	Sun>=1	3:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Fiji	11:53:40 -	LMT	1915 Oct 26	# Suva
 			12:00	Fiji	FJ%sT	# Fiji Time
@@ -509,11 +522,21 @@
 # http://www.parliament.gov.ws/documents/acts/Daylight%20Saving%20Act%20%202009%20%28English%29%20-%20Final%207-7-091.pdf
 # </a>
 
+# From Raymond Hughes (2010-10-07):
+# Please see
+# <a href="http://www.mcil.gov.ws">
+# http://www.mcil.gov.ws
+# </a>,
+# the Ministry of Commerce, Industry and Labour (sideframe) "Last Sunday
+# September 2010 (26/09/10) - adjust clocks forward from 12:00 midnight
+# to 01:00am and First Sunday April 2011 (03/04/11) - adjust clocks
+# backwards from 1:00am to 12:00am"
+
 Zone Pacific/Apia	 12:33:04 -	LMT	1879 Jul  5
 			-11:26:56 -	LMT	1911
 			-11:30	-	SAMT	1950		# Samoa Time
 			-11:00	-	WST	2010 Sep 26
-			-11:00	1:00	WSDT	2011 Apr 3
+			-11:00	1:00	WSDT	2011 Apr 3 1:00
 			-11:00	-	WST
 
 # Solomon Is
--- a/jdk/make/sun/javazic/tzdata/zone.tab	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/make/sun/javazic/tzdata/zone.tab	Wed Jul 05 17:26:57 2017 +0200
@@ -63,7 +63,7 @@
 AQ	-6736+06253	Antarctica/Mawson	Mawson Station, Holme Bay
 AQ	-6835+07758	Antarctica/Davis	Davis Station, Vestfold Hills
 AQ	-6617+11031	Antarctica/Casey	Casey Station, Bailey Peninsula
-AQ	-7824+10654	Antarctica/Vostok	Vostok Station, S Magnetic Pole
+AQ	-7824+10654	Antarctica/Vostok	Vostok Station, Lake Vostok
 AQ	-6640+14001	Antarctica/DumontDUrville	Dumont-d'Urville Station, Terre Adelie
 AQ	-690022+0393524	Antarctica/Syowa	Syowa Station, E Ongul I
 AQ	-5430+15857	Antarctica/Macquarie	Macquarie Island Station, Macquarie Island
--- a/jdk/src/share/bin/java.c	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/bin/java.c	Wed Jul 05 17:26:57 2017 +0200
@@ -355,7 +355,6 @@
 
     JavaVM *vm = 0;
     JNIEnv *env = 0;
-    jstring mainClassName;
     jclass mainClass;
     jmethodID mainID;
     jobjectArray mainArgs;
--- a/jdk/src/share/bin/parse_manifest.c	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/bin/parse_manifest.c	Wed Jul 05 17:26:57 2017 +0200
@@ -72,7 +72,7 @@
     if (entry->how == STORED) {
         *(char *)((size_t)in + entry->csize) = '\0';
         if (size_out) {
-            *size_out = entry->csize;
+            *size_out = (int)entry->csize;
         }
         return (in);
     } else if (entry->how == DEFLATED) {
@@ -103,7 +103,7 @@
             return (NULL);
         }
         if (size_out) {
-            *size_out = entry->isize;
+            *size_out = (int)entry->isize;
         }
         return (out);
     } else
@@ -317,7 +317,7 @@
          * manifest.  If so, build the entry record from the data found in
          * the header located and return success.
          */
-        if (CENNAM(p) == JLI_StrLen(file_name) &&
+        if ((size_t)CENNAM(p) == JLI_StrLen(file_name) &&
           memcmp((p + CENHDR), file_name, JLI_StrLen(file_name)) == 0) {
             if (lseek(fd, base_offset + CENOFF(p), SEEK_SET) < (off_t)0) {
                 free(buffer);
@@ -606,8 +606,5 @@
     }
     free(mp);
     close(fd);
-    if (rc == 0)
-        return (0);
-    else
-        return (-2);
+    return (rc == 0) ? 0 : -2;
 }
--- a/jdk/src/share/bin/wildcard.c	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/bin/wildcard.c	Wed Jul 05 17:26:57 2017 +0200
@@ -290,12 +290,12 @@
     char *path;
     char *p;
     for (i = 0, size = 1; i < fl->size; i++)
-        size += JLI_StrLen(fl->files[i]) + 1;
+        size += (int)JLI_StrLen(fl->files[i]) + 1;
 
     path = JLI_MemAlloc(size);
 
     for (i = 0, p = path; i < fl->size; i++) {
-        int len = JLI_StrLen(fl->files[i]);
+        int len = (int)JLI_StrLen(fl->files[i]);
         if (i > 0) *p++ = sep;
         memcpy(p, fl->files[i], len);
         p += len;
@@ -309,7 +309,7 @@
 FileList_split(const char *path, char sep)
 {
     const char *p, *q;
-    int len = JLI_StrLen(path);
+    int len = (int)JLI_StrLen(path);
     int count;
     FileList fl;
     for (count = 1, p = path; p < path + len; p++)
@@ -330,7 +330,7 @@
 static int
 isJarFileName(const char *filename)
 {
-    int len = JLI_StrLen(filename);
+    int len = (int)JLI_StrLen(filename);
     return (len >= 4) &&
         (filename[len - 4] == '.') &&
         (equal(filename + len - 3, "jar") ||
@@ -342,8 +342,8 @@
 static char *
 wildcardConcat(const char *wildcard, const char *basename)
 {
-    int wildlen = JLI_StrLen(wildcard);
-    int baselen = JLI_StrLen(basename);
+    int wildlen = (int)JLI_StrLen(wildcard);
+    int baselen = (int)JLI_StrLen(basename);
     char *filename = (char *) JLI_MemAlloc(wildlen + baselen);
     /* Replace the trailing '*' with basename */
     memcpy(filename, wildcard, wildlen-1);
@@ -369,7 +369,7 @@
 static int
 isWildcard(const char *filename)
 {
-    int len = JLI_StrLen(filename);
+    int len = (int)JLI_StrLen(filename);
     return (len > 0) &&
         (filename[len - 1] == '*') &&
         (len == 1 || IS_FILE_SEPARATOR(filename[len - 2])) &&
--- a/jdk/src/share/classes/com/sun/crypto/provider/AESCrypt.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/AESCrypt.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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
@@ -253,7 +253,8 @@
             for (j = 0; j < 8; j++) {
                 if (AA[i][j] != 0) {
                     AA[i][j] = (byte)
-                        alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF]) % 255];
+                        alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF])
+                        % 255];
                 }
             }
             for (t = 0; t < 4; t++) {
--- a/jdk/src/share/classes/com/sun/crypto/provider/ARCFOURCipher.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/ARCFOURCipher.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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
@@ -92,7 +92,8 @@
     }
 
     // core crypt code. OFB style, so works for both encryption and decryption
-    private void crypt(byte[] in, int inOfs, int inLen, byte[] out, int outOfs) {
+    private void crypt(byte[] in, int inOfs, int inLen, byte[] out,
+            int outOfs) {
         if (is < 0) {
             // doFinal() was called, need to reset the cipher to initial state
             init(lastKey);
--- a/jdk/src/share/classes/com/sun/crypto/provider/DESedeCipher.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DESedeCipher.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -31,8 +31,8 @@
 import javax.crypto.spec.*;
 
 /**
- * This class implements the DESede algorithm (DES-EDE, tripleDES) in its various
- * modes (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>,
+ * This class implements the DESede algorithm (DES-EDE, tripleDES) in
+ * its various modes (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>,
  * <code>CBC</code>, <code>PCBC</code>) and padding schemes
  * (<code>PKCS5Padding</code>, <code>NoPadding</code>,
  * <code>ISO10126Padding</code>).
--- a/jdk/src/share/classes/com/sun/crypto/provider/DHPrivateKey.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DHPrivateKey.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -190,7 +190,8 @@
             ike.initCause(e);
             throw ike;
         } catch (IOException e) {
-            InvalidKeyException ike = new InvalidKeyException("Error parsing key encoding: " + e.getMessage());
+            InvalidKeyException ike = new InvalidKeyException(
+                "Error parsing key encoding: " + e.getMessage());
             ike.initCause(e);
             throw ike;
         }
@@ -300,7 +301,8 @@
             DerInputStream in = new DerInputStream(this.key);
             this.x = in.getBigInteger();
         } catch (IOException e) {
-            InvalidKeyException ike = new InvalidKeyException("Error parsing key encoding: " + e.getMessage());
+            InvalidKeyException ike = new InvalidKeyException(
+                "Error parsing key encoding: " + e.getMessage());
             ike.initCause(e);
             throw ike;
         }
--- a/jdk/src/share/classes/com/sun/crypto/provider/DHPublicKey.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DHPublicKey.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -180,7 +180,8 @@
             throw new InvalidKeyException("Private-value length too big");
 
         } catch (IOException e) {
-            throw new InvalidKeyException("Error parsing key encoding: " + e.toString());
+            throw new InvalidKeyException(
+                "Error parsing key encoding: " + e.toString());
         }
     }
 
@@ -281,7 +282,8 @@
             DerInputStream in = new DerInputStream(this.key);
             this.y = in.getBigInteger();
         } catch (IOException e) {
-            throw new InvalidKeyException("Error parsing key encoding: " + e.toString());
+            throw new InvalidKeyException(
+                "Error parsing key encoding: " + e.toString());
         }
     }
 
--- a/jdk/src/share/classes/com/sun/crypto/provider/JceKeyStore.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/JceKeyStore.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, 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
@@ -764,7 +764,8 @@
                                     cf = (CertificateFactory)cfs.get(certType);
                                 } else {
                                 // create new certificate factory
-                                    cf = CertificateFactory.getInstance(certType);
+                                    cf = CertificateFactory.getInstance(
+                                        certType);
                                 // store the certificate factory so we can
                                 // reuse it later
                                     cfs.put(certType, cf);
@@ -863,8 +864,9 @@
                     dis.readFully(actual);
                     for (int i = 0; i < computed.length; i++) {
                         if (computed[i] != actual[i]) {
-                            throw new IOException("Keystore was tampered with, or "
-                                                  + "password was incorrect");
+                            throw new IOException(
+                                "Keystore was tampered with, or "
+                                + "password was incorrect");
                         }
                     }
                 }
--- a/jdk/src/share/classes/com/sun/crypto/provider/OAEPParameters.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/OAEPParameters.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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
@@ -139,7 +139,8 @@
                 if (!val.getOID().equals((Object) OID_MGF1)) {
                     throw new IOException("Only MGF1 mgf is supported");
                 }
-                AlgorithmId params = AlgorithmId.parse(new DerValue(val.getEncodedParams()));
+                AlgorithmId params = AlgorithmId.parse(
+                    new DerValue(val.getEncodedParams()));
                 String mgfDigestName = convertToStandardName(params.getName());
                 if (mgfDigestName.equals("SHA-1")) {
                     mgfSpec = MGF1ParameterSpec.SHA1;
@@ -150,7 +151,8 @@
                 } else if (mgfDigestName.equals("SHA-512")) {
                     mgfSpec = MGF1ParameterSpec.SHA512;
                 } else {
-                    throw new IOException("Unrecognized message digest algorithm");
+                    throw new IOException(
+                        "Unrecognized message digest algorithm");
                 }
             } else if (data.isContextSpecific((byte) 0x02)) {
                 // pSource algid
--- a/jdk/src/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -121,8 +121,8 @@
         this.key = deriveKey(prf, passwdBytes, salt, iterCount, keyLength);
     }
 
-    private static byte[] deriveKey(final Mac prf, final byte[] password, byte[] salt,
-                                    int iterCount, int keyLengthInBit) {
+    private static byte[] deriveKey(final Mac prf, final byte[] password,
+            byte[] salt, int iterCount, int keyLengthInBit) {
         int keyLength = keyLengthInBit/8;
         byte[] key = new byte[keyLength];
         try {
@@ -155,8 +155,9 @@
                     if (this == obj) return true;
                     if (this.getClass() != obj.getClass()) return false;
                     SecretKey sk = (SecretKey)obj;
-                    return prf.getAlgorithm().equalsIgnoreCase(sk.getAlgorithm()) &&
-                            Arrays.equals(password, sk.getEncoded());
+                    return prf.getAlgorithm().equalsIgnoreCase(
+                        sk.getAlgorithm()) &&
+                        Arrays.equals(password, sk.getEncoded());
                 }
             };
             prf.init(macKey);
--- a/jdk/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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
@@ -206,7 +206,8 @@
                 (algo.equalsIgnoreCase("RC2")?"RC2_40":algo), "SunJCE");
         } catch (GeneralSecurityException gse) {
             // should never happen
-            throw new RuntimeException("SunJCE provider is not configured properly");
+            throw new RuntimeException(
+                "SunJCE provider is not configured properly");
         }
         try {
             params.init(pbeSpec);
@@ -316,7 +317,8 @@
             try {
                 paramSpec = params.getParameterSpec(PBEParameterSpec.class);
             } catch (InvalidParameterSpecException ipse) {
-                throw new InvalidAlgorithmParameterException("requires PBE parameters");
+                throw new InvalidAlgorithmParameterException(
+                    "requires PBE parameters");
             }
         }
         implInit(opmode, key, paramSpec, random);
--- a/jdk/src/share/classes/com/sun/crypto/provider/SunJCE.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/SunJCE.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -423,15 +423,31 @@
 
                 /*
                  * SSL/TLS mechanisms
+                 *
+                 * These are strictly internal implementations and may
+                 * be changed at any time.  These names were chosen
+                 * because PKCS11/SunPKCS11 does not yet have TLS1.2
+                 * mechanisms, and it will cause calls to come here.
                  */
                 put("KeyGenerator.SunTlsPrf",
-                        "com.sun.crypto.provider.TlsPrfGenerator");
-                put("KeyGenerator.SunTlsRsaPremasterSecret",
-                        "com.sun.crypto.provider.TlsRsaPremasterSecretGenerator");
+                        "com.sun.crypto.provider.TlsPrfGenerator$V10");
+                put("KeyGenerator.SunTls12Prf",
+                        "com.sun.crypto.provider.TlsPrfGenerator$V12");
+
                 put("KeyGenerator.SunTlsMasterSecret",
-                        "com.sun.crypto.provider.TlsMasterSecretGenerator");
+                    "com.sun.crypto.provider.TlsMasterSecretGenerator");
+                put("Alg.Alias.KeyGenerator.SunTls12MasterSecret",
+                    "SunTlsMasterSecret");
+
                 put("KeyGenerator.SunTlsKeyMaterial",
-                        "com.sun.crypto.provider.TlsKeyMaterialGenerator");
+                    "com.sun.crypto.provider.TlsKeyMaterialGenerator");
+                put("Alg.Alias.KeyGenerator.SunTls12KeyMaterial",
+                    "SunTlsKeyMaterial");
+
+                put("KeyGenerator.SunTlsRsaPremasterSecret",
+                    "com.sun.crypto.provider.TlsRsaPremasterSecretGenerator");
+                put("Alg.Alias.KeyGenerator.SunTls12RsaPremasterSecret",
+                    "SunTlsRsaPremasterSecret");
 
                 return null;
             }
--- a/jdk/src/share/classes/com/sun/crypto/provider/TlsKeyMaterialGenerator.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/TlsKeyMaterialGenerator.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -65,12 +65,14 @@
         }
         this.spec = (TlsKeyMaterialParameterSpec)params;
         if ("RAW".equals(spec.getMasterSecret().getFormat()) == false) {
-            throw new InvalidAlgorithmParameterException("Key format must be RAW");
+            throw new InvalidAlgorithmParameterException(
+                "Key format must be RAW");
         }
-        protocolVersion = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
-        if ((protocolVersion < 0x0300) || (protocolVersion > 0x0302)) {
-            throw new InvalidAlgorithmParameterException
-                ("Only SSL 3.0, TLS 1.0, and TLS 1.1 supported");
+        protocolVersion = (spec.getMajorVersion() << 8)
+            | spec.getMinorVersion();
+        if ((protocolVersion < 0x0300) || (protocolVersion > 0x0303)) {
+            throw new InvalidAlgorithmParameterException(
+                "Only SSL 3.0, TLS 1.0/1.1/1.2 supported");
         }
     }
 
@@ -80,8 +82,8 @@
 
     protected SecretKey engineGenerateKey() {
         if (spec == null) {
-            throw new IllegalStateException
-                ("TlsKeyMaterialGenerator must be initialized");
+            throw new IllegalStateException(
+                "TlsKeyMaterialGenerator must be initialized");
         }
         try {
             return engineGenerateKey0();
@@ -99,8 +101,8 @@
         SecretKey clientMacKey = null;
         SecretKey serverMacKey = null;
         SecretKey clientCipherKey = null;
+        SecretKey serverCipherKey = null;
         IvParameterSpec clientIv = null;
-        SecretKey serverCipherKey = null;
         IvParameterSpec serverIv = null;
 
         int macLength = spec.getMacKeyLength();
@@ -109,21 +111,33 @@
         int keyLength = spec.getCipherKeyLength();
         int ivLength = spec.getIvLength();
 
-        int keyBlockLen = macLength + keyLength + (isExportable ? 0 : ivLength);
+        int keyBlockLen = macLength + keyLength
+            + (isExportable ? 0 : ivLength);
         keyBlockLen <<= 1;
         byte[] keyBlock = new byte[keyBlockLen];
 
-        MessageDigest md5 = MessageDigest.getInstance("MD5");
-        MessageDigest sha = MessageDigest.getInstance("SHA1");
+        // These may be used again later for exportable suite calculations.
+        MessageDigest md5 = null;
+        MessageDigest sha = null;
 
         // generate key block
-        if (protocolVersion >= 0x0301) {
-            // TLS
+        if (protocolVersion >= 0x0303) {
+            // TLS 1.2
             byte[] seed = concat(serverRandom, clientRandom);
-            keyBlock = doPRF(masterSecret, LABEL_KEY_EXPANSION, seed,
+            keyBlock = doTLS12PRF(masterSecret, LABEL_KEY_EXPANSION, seed,
+                        keyBlockLen, spec.getPRFHashAlg(),
+                        spec.getPRFHashLength(), spec.getPRFBlockSize());
+        } else if (protocolVersion >= 0x0301) {
+            // TLS 1.0/1.1
+            md5 = MessageDigest.getInstance("MD5");
+            sha = MessageDigest.getInstance("SHA1");
+            byte[] seed = concat(serverRandom, clientRandom);
+            keyBlock = doTLS10PRF(masterSecret, LABEL_KEY_EXPANSION, seed,
                         keyBlockLen, md5, sha);
         } else {
             // SSL
+            md5 = MessageDigest.getInstance("MD5");
+            sha = MessageDigest.getInstance("SHA1");
             keyBlock = new byte[keyBlockLen];
 
             byte[] tmp = new byte[20];
@@ -169,6 +183,7 @@
 
         String alg = spec.getCipherAlgorithm();
 
+        // cipher keys
         byte[] clientKeyBytes = new byte[keyLength];
         System.arraycopy(keyBlock, ofs, clientKeyBytes, 0, keyLength);
         ofs += keyLength;
@@ -182,6 +197,7 @@
             clientCipherKey = new SecretKeySpec(clientKeyBytes, alg);
             serverCipherKey = new SecretKeySpec(serverKeyBytes, alg);
 
+            // IV keys if needed.
             if (ivLength != 0) {
                 tmp = new byte[ivLength];
 
@@ -194,21 +210,28 @@
                 serverIv = new IvParameterSpec(tmp);
             }
         } else {
+            // if exportable suites, calculate the alternate
             // cipher key expansion and IV generation
-            if (protocolVersion >= 0x0301) {
+            if (protocolVersion >= 0x0302) {
+                // TLS 1.1+
+                throw new RuntimeException(
+                    "Internal Error:  TLS 1.1+ should not be negotiating" +
+                    "exportable ciphersuites");
+            } else if (protocolVersion == 0x0301) {
+                // TLS 1.0
                 byte[] seed = concat(clientRandom, serverRandom);
 
-                tmp = doPRF(clientKeyBytes, LABEL_CLIENT_WRITE_KEY, seed,
+                tmp = doTLS10PRF(clientKeyBytes, LABEL_CLIENT_WRITE_KEY, seed,
                             expandedKeyLength, md5, sha);
                 clientCipherKey = new SecretKeySpec(tmp, alg);
 
-                tmp = doPRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed,
+                tmp = doTLS10PRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed,
                             expandedKeyLength, md5, sha);
                 serverCipherKey = new SecretKeySpec(tmp, alg);
 
                 if (ivLength != 0) {
                     tmp = new byte[ivLength];
-                    byte[] block = doPRF(null, LABEL_IV_BLOCK, seed,
+                    byte[] block = doTLS10PRF(null, LABEL_IV_BLOCK, seed,
                                 ivLength << 1, md5, sha);
                     System.arraycopy(block, 0, tmp, 0, ivLength);
                     clientIv = new IvParameterSpec(tmp);
@@ -216,6 +239,7 @@
                     serverIv = new IvParameterSpec(tmp);
                 }
             } else {
+                // SSLv3
                 tmp = new byte[expandedKeyLength];
 
                 md5.update(clientKeyBytes);
--- a/jdk/src/share/classes/com/sun/crypto/provider/TlsMasterSecretGenerator.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/TlsMasterSecretGenerator.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -64,12 +64,14 @@
         }
         this.spec = (TlsMasterSecretParameterSpec)params;
         if ("RAW".equals(spec.getPremasterSecret().getFormat()) == false) {
-            throw new InvalidAlgorithmParameterException("Key format must be RAW");
+            throw new InvalidAlgorithmParameterException(
+                "Key format must be RAW");
         }
-        protocolVersion = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
-        if ((protocolVersion < 0x0300) || (protocolVersion > 0x0302)) {
-            throw new InvalidAlgorithmParameterException
-                ("Only SSL 3.0, TLS 1.0, and TLS 1.1 supported");
+        protocolVersion = (spec.getMajorVersion() << 8)
+            | spec.getMinorVersion();
+        if ((protocolVersion < 0x0300) || (protocolVersion > 0x0303)) {
+            throw new InvalidAlgorithmParameterException(
+                "Only SSL 3.0, TLS 1.0/1.1/1.2 supported");
         }
     }
 
@@ -79,8 +81,8 @@
 
     protected SecretKey engineGenerateKey() {
         if (spec == null) {
-            throw new IllegalStateException
-                ("TlsMasterSecretGenerator must be initialized");
+            throw new IllegalStateException(
+                "TlsMasterSecretGenerator must be initialized");
         }
         SecretKey premasterKey = spec.getPremasterSecret();
         byte[] premaster = premasterKey.getEncoded();
@@ -103,7 +105,11 @@
 
             if (protocolVersion >= 0x0301) {
                 byte[] seed = concat(clientRandom, serverRandom);
-                master = doPRF(premaster, LABEL_MASTER_SECRET, seed, 48);
+                master = ((protocolVersion >= 0x0303) ?
+                    doTLS12PRF(premaster, LABEL_MASTER_SECRET, seed, 48,
+                        spec.getPRFHashAlg(), spec.getPRFHashLength(),
+                        spec.getPRFBlockSize()) :
+                    doTLS10PRF(premaster, LABEL_MASTER_SECRET, seed, 48));
             } else {
                 master = new byte[48];
                 MessageDigest md5 = MessageDigest.getInstance("MD5");
@@ -124,7 +130,8 @@
 
             }
 
-            return new TlsMasterSecretKey(master, premasterMajor, premasterMinor);
+            return new TlsMasterSecretKey(master, premasterMajor,
+                premasterMinor);
         } catch (NoSuchAlgorithmException e) {
             throw new ProviderException(e);
         } catch (DigestException e) {
--- a/jdk/src/share/classes/com/sun/crypto/provider/TlsPrfGenerator.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/TlsPrfGenerator.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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,11 +37,15 @@
 
 /**
  * KeyGenerator implementation for the TLS PRF function.
+ * <p>
+ * This class duplicates the HMAC functionality (RFC 2104) with
+ * performance optimizations (e.g. XOR'ing keys with padding doesn't
+ * need to be redone for each HMAC operation).
  *
  * @author  Andreas Sterbenz
  * @since   1.6
  */
-public final class TlsPrfGenerator extends KeyGeneratorSpi {
+abstract class TlsPrfGenerator extends KeyGeneratorSpi {
 
     // magic constants and utility functions, also used by other files
     // in this package
@@ -69,8 +73,10 @@
      * TLS HMAC "inner" and "outer" padding.  This isn't a function
      * of the digest algorithm.
      */
-    private static final byte[] HMAC_ipad = genPad((byte)0x36, 64);
-    private static final byte[] HMAC_opad = genPad((byte)0x5c, 64);
+    private static final byte[] HMAC_ipad64  = genPad((byte)0x36, 64);
+    private static final byte[] HMAC_ipad128 = genPad((byte)0x36, 128);
+    private static final byte[] HMAC_opad64  = genPad((byte)0x5c, 64);
+    private static final byte[] HMAC_opad128 = genPad((byte)0x5c, 128);
 
     // SSL3 magic mix constants ("A", "BB", "CCC", ...)
     final static byte[][] SSL3_CONST = genConst();
@@ -123,8 +129,8 @@
         this.spec = (TlsPrfParameterSpec)params;
         SecretKey key = spec.getSecret();
         if ((key != null) && ("RAW".equals(key.getFormat()) == false)) {
-            throw new InvalidAlgorithmParameterException
-                ("Key encoding format must be RAW");
+            throw new InvalidAlgorithmParameterException(
+                "Key encoding format must be RAW");
         }
     }
 
@@ -132,17 +138,21 @@
         throw new InvalidParameterException(MSG);
     }
 
-    protected SecretKey engineGenerateKey() {
+    SecretKey engineGenerateKey0(boolean tls12) {
         if (spec == null) {
-            throw new IllegalStateException
-                ("TlsPrfGenerator must be initialized");
+            throw new IllegalStateException(
+                "TlsPrfGenerator must be initialized");
         }
         SecretKey key = spec.getSecret();
         byte[] secret = (key == null) ? null : key.getEncoded();
         try {
             byte[] labelBytes = spec.getLabel().getBytes("UTF8");
             int n = spec.getOutputLength();
-            byte[] prfBytes = doPRF(secret, labelBytes, spec.getSeed(), n);
+            byte[] prfBytes = (tls12 ?
+                doTLS12PRF(secret, labelBytes, spec.getSeed(), n,
+                    spec.getPRFHashAlg(), spec.getPRFHashLength(),
+                    spec.getPRFBlockSize()) :
+                doTLS10PRF(secret, labelBytes, spec.getSeed(), n));
             return new SecretKeySpec(prfBytes, "TlsPrf");
         } catch (GeneralSecurityException e) {
             throw new ProviderException("Could not generate PRF", e);
@@ -151,16 +161,67 @@
         }
     }
 
-    static final byte[] doPRF(byte[] secret, byte[] labelBytes, byte[] seed,
-            int outputLength) throws NoSuchAlgorithmException, DigestException {
+    static byte[] doTLS12PRF(byte[] secret, byte[] labelBytes,
+            byte[] seed, int outputLength,
+            String prfHash, int prfHashLength, int prfBlockSize)
+            throws NoSuchAlgorithmException, DigestException {
+        if (prfHash == null) {
+            throw new NoSuchAlgorithmException("Unspecified PRF algorithm");
+        }
+        MessageDigest prfMD = MessageDigest.getInstance(prfHash);
+        return doTLS12PRF(secret, labelBytes, seed, outputLength,
+            prfMD, prfHashLength, prfBlockSize);
+    }
+
+    static byte[] doTLS12PRF(byte[] secret, byte[] labelBytes,
+            byte[] seed, int outputLength,
+            MessageDigest mdPRF, int mdPRFLen, int mdPRFBlockSize)
+            throws DigestException {
+
+        if (secret == null) {
+            secret = B0;
+        }
+
+        // If we have a long secret, digest it first.
+        if (secret.length > mdPRFBlockSize) {
+            secret = mdPRF.digest(secret);
+        }
+
+        byte[] output = new byte[outputLength];
+        byte [] ipad;
+        byte [] opad;
+
+        switch (mdPRFBlockSize) {
+        case 64:
+            ipad = HMAC_ipad64.clone();
+            opad = HMAC_opad64.clone();
+            break;
+        case 128:
+            ipad = HMAC_ipad128.clone();
+            opad = HMAC_opad128.clone();
+            break;
+        default:
+            throw new DigestException("Unexpected block size.");
+        }
+
+        // P_HASH(Secret, label + seed)
+        expand(mdPRF, mdPRFLen, secret, 0, secret.length, labelBytes,
+            seed, output, ipad, opad);
+
+        return output;
+    }
+
+    static byte[] doTLS10PRF(byte[] secret, byte[] labelBytes,
+            byte[] seed, int outputLength) throws NoSuchAlgorithmException,
+            DigestException {
         MessageDigest md5 = MessageDigest.getInstance("MD5");
         MessageDigest sha = MessageDigest.getInstance("SHA1");
-        return doPRF(secret, labelBytes, seed, outputLength, md5, sha);
+        return doTLS10PRF(secret, labelBytes, seed, outputLength, md5, sha);
     }
 
-    static final byte[] doPRF(byte[] secret, byte[] labelBytes, byte[] seed,
-            int outputLength, MessageDigest md5, MessageDigest sha)
-            throws DigestException {
+    static byte[] doTLS10PRF(byte[] secret, byte[] labelBytes,
+            byte[] seed, int outputLength, MessageDigest md5,
+            MessageDigest sha) throws DigestException {
         /*
          * Split the secret into two halves S1 and S2 of same length.
          * S1 is taken from the first half of the secret, S2 from the
@@ -183,10 +244,12 @@
         byte[] output = new byte[outputLength];
 
         // P_MD5(S1, label + seed)
-        expand(md5, 16, secret, 0, seclen, labelBytes, seed, output);
+        expand(md5, 16, secret, 0, seclen, labelBytes, seed, output,
+            HMAC_ipad64.clone(), HMAC_opad64.clone());
 
         // P_SHA-1(S2, label + seed)
-        expand(sha, 20, secret, off, seclen, labelBytes, seed, output);
+        expand(sha, 20, secret, off, seclen, labelBytes, seed, output,
+            HMAC_ipad64.clone(), HMAC_opad64.clone());
 
         return output;
     }
@@ -201,16 +264,13 @@
      * @param seed the seed
      * @param output the output array
      */
-    private static final void expand(MessageDigest digest, int hmacSize,
+    private static void expand(MessageDigest digest, int hmacSize,
             byte[] secret, int secOff, int secLen, byte[] label, byte[] seed,
-            byte[] output) throws DigestException {
+            byte[] output, byte[] pad1, byte[] pad2) throws DigestException {
         /*
          * modify the padding used, by XORing the key into our copy of that
          * padding.  That's to avoid doing that for each HMAC computation.
          */
-        byte[] pad1 = HMAC_ipad.clone();
-        byte[] pad2 = HMAC_opad.clone();
-
         for (int i = 0; i < secLen; i++) {
             pad1[i] ^= secret[i + secOff];
             pad2[i] ^= secret[i + secOff];
@@ -275,7 +335,34 @@
             }
             remaining -= k;
         }
-
     }
 
+    /**
+     * A KeyGenerator implementation that supports TLS 1.2.
+     * <p>
+     * TLS 1.2 uses a different hash algorithm than 1.0/1.1 for the PRF
+     * calculations.  As of 2010, there is no PKCS11-level support for TLS
+     * 1.2 PRF calculations, and no known OS's have an internal variant
+     * we could use.  Therefore for TLS 1.2, we are updating JSSE to request
+     * a different provider algorithm:  "SunTls12Prf".  If we reused the
+     * name "SunTlsPrf", the PKCS11 provider would need be updated to
+     * fail correctly when presented with the wrong version number
+     * (via Provider.Service.supportsParameters()), and add the
+     * appropriate supportsParamters() checks into KeyGenerators (not
+     * currently there).
+     */
+    static public class V12 extends TlsPrfGenerator {
+        protected SecretKey engineGenerateKey() {
+            return engineGenerateKey0(true);
+        }
+    }
+
+    /**
+     * A KeyGenerator implementation that supports TLS 1.0/1.1.
+     */
+    static public class V10 extends TlsPrfGenerator {
+        protected SecretKey engineGenerateKey() {
+            return engineGenerateKey0(false);
+        }
+    }
 }
--- a/jdk/src/share/classes/com/sun/crypto/provider/TlsRsaPremasterSecretGenerator.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/com/sun/crypto/provider/TlsRsaPremasterSecretGenerator.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -69,8 +69,8 @@
 
     protected SecretKey engineGenerateKey() {
         if (spec == null) {
-            throw new IllegalStateException
-                    ("TlsRsaPremasterSecretGenerator must be initialized");
+            throw new IllegalStateException(
+                "TlsRsaPremasterSecretGenerator must be initialized");
         }
         if (random == null) {
             random = new SecureRandom();
--- a/jdk/src/share/classes/com/sun/jmx/defaults/ServiceName.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/com/sun/jmx/defaults/ServiceName.java	Wed Jul 05 17:26:57 2017 +0200
@@ -76,9 +76,9 @@
     /**
      * The vendor of the JMX specification implemented by this product.
      * <BR>
-     * The value is <CODE>Sun Microsystems</CODE>.
+     * The value is <CODE>Oracle Corporation</CODE>.
      */
-    public static final String JMX_SPEC_VENDOR = "Sun Microsystems";
+    public static final String JMX_SPEC_VENDOR = "Oracle Corporation";
 
     /**
      * The name of this product implementing the  JMX specification.
@@ -91,7 +91,7 @@
      * The name of the vendor of this product implementing the
      * JMX specification.
      * <BR>
-     * The value is <CODE>Sun Microsystems</CODE>.
+     * The value is <CODE>Oracle Corporation</CODE>.
      */
-    public static final String JMX_IMPL_VENDOR = "Sun Microsystems";
+    public static final String JMX_IMPL_VENDOR = "Oracle Corporation";
 }
--- a/jdk/src/share/classes/com/sun/jmx/snmp/ServiceName.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/ServiceName.java	Wed Jul 05 17:26:57 2017 +0200
@@ -27,7 +27,7 @@
 
 /**
  * Used for storing default values used by SNMP Runtime services.
- * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * <p><b>This API is an Oracle Corporation internal API  and is subject
  * to change without notice.</b></p>
  */
 public class ServiceName {
@@ -144,16 +144,16 @@
     /**
      * The vendor of the JMX specification implemented by this product.
      * <BR>
-     * The value is <CODE>Sun Microsystems</CODE>.
+     * The value is <CODE>Oracle Corporation</CODE>.
      */
-    public static final String JMX_SPEC_VENDOR = "Sun Microsystems";
+    public static final String JMX_SPEC_VENDOR = "Oracle Corporation";
 
     /**
      * The name of the vendor of this product implementing the  JMX specification.
      * <BR>
-     * The value is <CODE>Sun Microsystems</CODE>.
+     * The value is <CODE>Oracle Corporation</CODE>.
      */
-    public static final String JMX_IMPL_VENDOR = "Sun Microsystems";
+    public static final String JMX_IMPL_VENDOR = "Oracle Corporation";
 
     /**
       * The build number of the current product version, of the form <CODE>rXX</CODE>.
--- a/jdk/src/share/classes/com/sun/management/package.html	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/com/sun/management/package.html	Wed Jul 05 17:26:57 2017 +0200
@@ -30,7 +30,7 @@
 </head>
 <body bgcolor="white">
 
-This package contains Sun Microsystem's platform extension to
+This package contains Oracle Corporation's platform extension to
 the implementation of the
 <a href="{@docRoot}/../../../../api/java/lang/management/package-summary.html">
 java.lang.management</a> API and also defines the management
--- a/jdk/src/share/classes/java/awt/BasicStroke.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/awt/BasicStroke.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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,6 +25,8 @@
 
 package java.awt;
 
+import java.beans.ConstructorProperties;
+
 /**
  * The <code>BasicStroke</code> class defines a basic set of rendering
  * attributes for the outlines of graphics primitives, which are rendered
@@ -183,6 +185,7 @@
      *         <code>dash</code> is zero
      * @throws IllegalArgumentException if dash lengths are all zero.
      */
+    @ConstructorProperties({ "lineWidth", "endCap", "lineJoin", "miterLimit", "dashArray", "dashPhase" })
     public BasicStroke(float width, int cap, int join, float miterlimit,
                        float dash[], float dash_phase) {
         if (width < 0.0f) {
--- a/jdk/src/share/classes/java/awt/GradientPaint.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/awt/GradientPaint.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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.awt.geom.Rectangle2D;
 import java.awt.geom.AffineTransform;
 import java.awt.image.ColorModel;
+import java.beans.ConstructorProperties;
 
 /**
  * The <code>GradientPaint</code> class provides a way to fill
@@ -166,6 +167,7 @@
      * @throws NullPointerException if either one of colors or points
      * is null
      */
+    @ConstructorProperties({ "point1", "color1", "point2", "color2", "cyclic" })
     public GradientPaint(Point2D pt1,
                          Color color1,
                          Point2D pt2,
--- a/jdk/src/share/classes/java/awt/GridBagConstraints.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/awt/GridBagConstraints.java	Wed Jul 05 17:26:57 2017 +0200
@@ -126,7 +126,7 @@
     /**
      * Place the component centered along the edge of its display area
      * associated with the start of a page for the current
-     * <code>ComponentOrienation</code>.  Equal to NORTH for horizontal
+     * {@code ComponentOrientation}.  Equal to NORTH for horizontal
      * orientations.
      */
     public static final int PAGE_START = 19;
@@ -134,7 +134,7 @@
     /**
      * Place the component centered along the edge of its display area
      * associated with the end of a page for the current
-     * <code>ComponentOrienation</code>.  Equal to SOUTH for horizontal
+     * {@code ComponentOrientation}.  Equal to SOUTH for horizontal
      * orientations.
      */
     public static final int PAGE_END = 20;
@@ -142,7 +142,7 @@
     /**
      * Place the component centered along the edge of its display area where
      * lines of text would normally begin for the current
-     * <code>ComponentOrienation</code>.  Equal to WEST for horizontal,
+     * {@code ComponentOrientation}.  Equal to WEST for horizontal,
      * left-to-right orientations and EAST for horizontal, right-to-left
      * orientations.
      */
@@ -151,7 +151,7 @@
     /**
      * Place the component centered along the edge of its display area where
      * lines of text would normally end for the current
-     * <code>ComponentOrienation</code>.  Equal to EAST for horizontal,
+     * {@code ComponentOrientation}.  Equal to EAST for horizontal,
      * left-to-right orientations and WEST for horizontal, right-to-left
      * orientations.
      */
@@ -160,7 +160,7 @@
     /**
      * Place the component in the corner of its display area where
      * the first line of text on a page would normally begin for the current
-     * <code>ComponentOrienation</code>.  Equal to NORTHWEST for horizontal,
+     * {@code ComponentOrientation}.  Equal to NORTHWEST for horizontal,
      * left-to-right orientations and NORTHEAST for horizontal, right-to-left
      * orientations.
      */
@@ -169,7 +169,7 @@
     /**
      * Place the component in the corner of its display area where
      * the first line of text on a page would normally end for the current
-     * <code>ComponentOrienation</code>.  Equal to NORTHEAST for horizontal,
+     * {@code ComponentOrientation}.  Equal to NORTHEAST for horizontal,
      * left-to-right orientations and NORTHWEST for horizontal, right-to-left
      * orientations.
      */
@@ -178,7 +178,7 @@
     /**
      * Place the component in the corner of its display area where
      * the last line of text on a page would normally start for the current
-     * <code>ComponentOrienation</code>.  Equal to SOUTHWEST for horizontal,
+     * {@code ComponentOrientation}.  Equal to SOUTHWEST for horizontal,
      * left-to-right orientations and SOUTHEAST for horizontal, right-to-left
      * orientations.
      */
@@ -187,7 +187,7 @@
     /**
      * Place the component in the corner of its display area where
      * the last line of text on a page would normally end for the current
-     * <code>ComponentOrienation</code>.  Equal to SOUTHEAST for horizontal,
+     * {@code ComponentOrientation}.  Equal to SOUTHEAST for horizontal,
      * left-to-right orientations and SOUTHWEST for horizontal, right-to-left
      * orientations.
      */
@@ -437,7 +437,7 @@
      * <code>LINE_START</code>, <code>LINE_END</code>,
      * <code>FIRST_LINE_START</code>, <code>FIRST_LINE_END</code>,
      * <code>LAST_LINE_START</code> and <code>LAST_LINE_END</code>.  The
-     * baseline relvative values are:
+     * baseline relative values are:
      * <code>BASELINE</code>, <code>BASELINE_LEADING</code>,
      * <code>BASELINE_TRAILING</code>,
      * <code>ABOVE_BASELINE</code>, <code>ABOVE_BASELINE_LEADING</code>,
--- a/jdk/src/share/classes/java/awt/LinearGradientPaint.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/awt/LinearGradientPaint.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2010, 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,10 +26,10 @@
 package java.awt;
 
 import java.awt.geom.AffineTransform;
-import java.awt.geom.NoninvertibleTransformException;
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.ColorModel;
+import java.beans.ConstructorProperties;
 
 /**
  * The {@code LinearGradientPaint} class provides a way to fill
@@ -271,6 +271,7 @@
      * or a {@code fractions} value is less than 0.0 or greater than 1.0,
      * or the {@code fractions} are not provided in strictly increasing order
      */
+    @ConstructorProperties({ "startPoint", "endPoint", "fractions", "colors", "cycleMethod", "colorSpace", "transform" })
     public LinearGradientPaint(Point2D start, Point2D end,
                                float[] fractions, Color[] colors,
                                CycleMethod cycleMethod,
--- a/jdk/src/share/classes/java/awt/RadialGradientPaint.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/awt/RadialGradientPaint.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2010, 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.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.ColorModel;
+import java.beans.ConstructorProperties;
 
 /**
  * The {@code RadialGradientPaint} class provides a way to fill a shape with
@@ -428,6 +429,7 @@
      * or a {@code fractions} value is less than 0.0 or greater than 1.0,
      * or the {@code fractions} are not provided in strictly increasing order
      */
+    @ConstructorProperties({ "centerPoint", "radius", "focusPoint", "fractions", "colors", "cycleMethod", "colorSpace", "transform" })
     public RadialGradientPaint(Point2D center,
                                float radius,
                                Point2D focus,
--- a/jdk/src/share/classes/java/awt/Scrollbar.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/awt/Scrollbar.java	Wed Jul 05 17:26:57 2017 +0200
@@ -213,7 +213,8 @@
      * The size of the <code>Scrollbar</code>'s bubble.
      * When a scroll bar is used to select a range of values,
      * the visibleAmount represents the size of this range.
-     * This is visually indicated by the size of the bubble.
+     * Depending on platform, this may be visually indicated
+     * by the size of the bubble.
      *
      * @serial
      * @see #getVisibleAmount
@@ -637,6 +638,8 @@
      * bubble (also called a thumb or scroll box), usually gives a
      * visual representation of the relationship of the visible
      * amount to the range of the scroll bar.
+     * Note that depending on platform, the value of the visible amount property
+     * may not be visually indicated by the size of the bubble.
      * <p>
      * The scroll bar's bubble may not be displayed when it is not
      * moveable (e.g. when it takes up the entire length of the
@@ -670,6 +673,8 @@
      * bubble (also called a thumb or scroll box), usually gives a
      * visual representation of the relationship of the visible
      * amount to the range of the scroll bar.
+     * Note that depending on platform, the value of the visible amount property
+     * may not be visually indicated by the size of the bubble.
      * <p>
      * The scroll bar's bubble may not be displayed when it is not
      * moveable (e.g. when it takes up the entire length of the
--- a/jdk/src/share/classes/java/awt/Toolkit.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/awt/Toolkit.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1831,7 +1831,11 @@
             desktopProperties.put(name, newValue);
         }
 
-        desktopPropsSupport.firePropertyChange(name, oldValue, newValue);
+        // Don't fire change event if old and new values are null.
+        // It helps to avoid recursive resending of WM_THEMECHANGED
+        if (oldValue != null || newValue != null) {
+            desktopPropsSupport.firePropertyChange(name, oldValue, newValue);
+        }
     }
 
     /**
--- a/jdk/src/share/classes/java/awt/geom/AffineTransform.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/awt/geom/AffineTransform.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, 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.awt.geom;
 
 import java.awt.Shape;
+import java.beans.ConstructorProperties;
 
 /**
  * The <code>AffineTransform</code> class represents a 2D affine transform
@@ -508,6 +509,7 @@
      * @param m12 the Y coordinate translation element of the 3x3 matrix
      * @since 1.2
      */
+    @ConstructorProperties({ "scaleX", "shearY", "shearX", "scaleY", "translateX", "translateY" })
     public AffineTransform(float m00, float m10,
                            float m01, float m11,
                            float m02, float m12) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/dyn/BootstrapMethod.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+package java.dyn;
+
+import java.lang.annotation.*;
+
+/**
+ * Annotation on InvokeDynamic method calls which requests the JVM to use a specific
+ * <a href="package-summary.html#bsm">bootstrap method</a>
+ * to link the call.  This annotation is not retained as such in the class file,
+ * but is transformed into a constant-pool entry for the invokedynamic instruction which
+ * specifies the desired bootstrap method.
+ * <p>
+ * If only the <code>value</code> is given, it must name a subclass of {@link CallSite}
+ * with a constructor which accepts a class, string, and method type.
+ * If the <code>value</code> and <code>name</code> are both given, there must be
+ * a static method in the given class of the given name which accepts a class, string,
+ * and method type, and returns a reference coercible to {@link CallSite}.
+ * <p>
+ * This annotation can be placed either on the return type of a single {@link InvokeDynamic}
+ * call (see examples) or else it can be placed on an enclosing class or method, where it
+ * determines a default bootstrap method for any {@link InvokeDynamic} calls which are not
+ * specifically annotated with a bootstrap method.
+ * Every {@link InvokeDynamic} call must be given a bootstrap method.
+ * <p>
+ * Examples:
+<blockquote><pre>
+&#064;BootstrapMethod(value=MyLanguageRuntime.class, name="bootstrapDynamic")
+String x = (String) InvokeDynamic.greet();
+//BSM => MyLanguageRuntime.bootstrapDynamic(Here.class, "greet", methodType(String.class))
+&#064;BootstrapMethod(MyCallSite.class)
+void example() throws Throwable {
+    InvokeDynamic.greet();
+    //BSM => new MyCallSite(Here.class, "greet", methodType(void.class))
+}
+</pre></blockquote>
+ * <p>
+ */
+@Target({ElementType.TYPE_USE,
+            // For defaulting every indy site within a class or method; cf. @SuppressWarnings:
+            ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR
+            })
+@Retention(RetentionPolicy.SOURCE)
+public @interface BootstrapMethod {
+    /** The class containing the bootstrap method. */
+    Class<?> value();
+
+    /** The name of the bootstrap method.
+     *  If this is the empty string, an instance of the bootstrap class is created,
+     *  and a constructor is invoked.
+     *  Otherwise, there must be a static method of the required name.
+     */
+    String name() default "";  // empty string denotes a constructor with 'new'
+
+    /** The argument types of the bootstrap method, as passed out by the JVM.
+     *  There is usually no reason to override the default.
+     */
+    Class<?>[] arguments() default {Class.class, String.class, MethodType.class};
+}
--- a/jdk/src/share/classes/java/dyn/CallSite.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/dyn/CallSite.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,56 +25,26 @@
 
 package java.dyn;
 
-import sun.dyn.Access;
-import sun.dyn.MemberName;
-import sun.dyn.CallSiteImpl;
+import sun.dyn.*;
+import java.util.Collection;
 
 /**
- * A {@code CallSite} reifies an {@code invokedynamic} instruction from bytecode,
- * and controls its linkage.
- * Every linked {@code CallSite} object corresponds to a distinct instance
- * of the {@code invokedynamic} instruction, and vice versa.
- * <p>
- * Every linked {@code CallSite} object has one state variable,
- * a {@link MethodHandle} reference called the {@code target}.
- * This reference is never null.  Though it can change its value
- * successive values must always have exactly the {@link MethodType method type}
- * called for by the bytecodes of the associated {@code invokedynamic} instruction
- * <p>
- * It is the responsibility of each class's
- * {@link Linkage#registerBootstrapMethod(Class, MethodHandle) bootstrap method}
- * to produce call sites which have been pre-linked to an initial target method.
- * The required {@link MethodType type} for the target method is a parameter
- * to each bootstrap method call.
- * <p>
- * The bootstrap method may elect to produce call sites of a
- * language-specific subclass of {@code CallSite}.  In such a case,
- * the subclass may claim responsibility for initializing its target to
- * a non-null value, by overriding {@link #initialTarget}.
+ * A {@code CallSite} is a holder for a variable {@link MethodHandle},
+ * which is called its {@code target}.
+ * Every call to a {@code CallSite} is delegated to the site's current target.
  * <p>
- * An {@code invokedynamic} instruction which has not yet been executed
- * is said to be <em>unlinked</em>.  When an unlinked call site is executed,
- * the containing class's bootstrap method is called to manufacture a call site,
- * for the instruction.  If the bootstrap method does not assign a non-null
- * value to the new call site's target variable, the method {@link #initialTarget}
- * is called to produce the new call site's first target method.
+ * A call site is initially created in an <em>unlinked</em> state,
+ * which is distinguished by a null target variable.
+ * Before the call site may be invoked (and before certain other
+ * operations are attempted), the call site must be linked to
+ * a non-null target.
  * <p>
- * A freshly-created {@code CallSite} object is not yet in a linked state.
- * An unlinked {@code CallSite} object reports null for its {@code callerClass}.
- * When the JVM receives a {@code CallSite} object from a bootstrap method,
- * it first ensures that its target is non-null and of the correct type.
- * The JVM then links the {@code CallSite} object to the call site instruction,
- * enabling the {@code callerClass} to return the class in which the instruction occurs.
- * <p>
- * Next, the JVM links the instruction to the {@code CallSite}, at which point
- * any further execution of the {@code invokedynamic} instruction implicitly
- * invokes the current target of the {@code CallSite} object.
- * After this two-way linkage, both the instruction and the {@code CallSite}
- * object are said to be linked.
- * <p>
- * This state of linkage continues until the method containing the
- * dynamic call site is garbage collected, or the dynamic call site
- * is invalidated by an explicit request.
+ * A call site may be <em>relinked</em> by changing its target.
+ * The new target must be non-null and must have the same
+ * {@linkplain MethodHandle#type() type}
+ * as the previous target.
+ * Thus, though a call site can be relinked to a series of
+ * successive targets, it cannot change its type.
  * <p>
  * Linkage happens once in the lifetime of any given {@code CallSite} object.
  * Because of call site invalidation, this linkage can be repeated for
@@ -87,6 +57,10 @@
  * Here is a sample use of call sites and bootstrap methods which links every
  * dynamic call site to print its arguments:
 <blockquote><pre><!-- see indy-demo/src/PrintArgsDemo.java -->
+&#064;BootstrapMethod(value=PrintArgsDemo.class, name="bootstrapDynamic")
+static void test() throws Throwable {
+    InvokeDynamic.baz("baz arg", 2, 3.14);
+}
 private static void printArgs(Object... args) {
   System.out.println(java.util.Arrays.deepToString(args));
 }
@@ -96,17 +70,16 @@
   Class thisClass = lookup.lookupClass();  // (who am I?)
   printArgs = lookup.findStatic(thisClass,
       "printArgs", MethodType.methodType(void.class, Object[].class));
-  Linkage.registerBootstrapMethod("bootstrapDynamic");
 }
 private static CallSite bootstrapDynamic(Class caller, String name, MethodType type) {
   // ignore caller and name, but match the type:
   return new CallSite(MethodHandles.collectArguments(printArgs, type));
 }
 </pre></blockquote>
- * @see Linkage#registerBootstrapMethod(java.lang.Class, java.dyn.MethodHandle)
  * @author John Rose, JSR 292 EG
  */
 public class CallSite
+    implements MethodHandleProvider
 {
     private static final Access IMPL_TOKEN = Access.getToken();
 
@@ -209,6 +182,7 @@
      * {@code InvokeDynamicBootstrapError}, which in turn causes the
      * linkage of the {@code invokedynamic} instruction to terminate
      * abnormally.
+     * @deprecated transitional form defined in EDR but removed in PFD
      */
     protected MethodHandle initialTarget(Class<?> callerClass, String name, MethodType type) {
         throw new InvokeDynamicBootstrapError("target must be initialized before call site is linked: "+name+type);
@@ -278,16 +252,44 @@
      */
     @Override
     public String toString() {
-        StringBuilder buf = new StringBuilder("CallSite#");
-        buf.append(hashCode());
-        if (!isLinked())
-            buf.append("[unlinked]");
-        else
-            buf.append("[")
-                .append("from ").append(vmmethod.getDeclaringClass().getName())
-                .append(" : ").append(getTarget().type())
-                .append(" => ").append(getTarget())
-                .append("]");
-        return buf.toString();
+        return "CallSite"+(target == null ? "" : target.type());
     }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce a method handle equivalent to an invokedynamic instruction
+     * which has been linked to this call site.
+     * <p>If this call site is a {@link ConstantCallSite}, this method
+     * simply returns the call site's target, since that will not change.
+     * <p>Otherwise, this method is equivalent to the following code:
+     * <p><blockquote><pre>
+     * MethodHandle getTarget, invoker, result;
+     * getTarget = MethodHandles.lookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class));
+     * invoker = MethodHandles.exactInvoker(this.type());
+     * result = MethodHandles.foldArguments(invoker, getTarget)
+     * </pre></blockquote>
+     * @return a method handle which always invokes this call site's current target
+     */
+    public final MethodHandle dynamicInvoker() {
+        if (this instanceof ConstantCallSite)
+            return getTarget();  // will not change dynamically
+        MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, GET_TARGET, this);
+        MethodHandle invoker = MethodHandles.exactInvoker(this.type());
+        return MethodHandles.foldArguments(invoker, getTarget);
+    }
+    private static final MethodHandle GET_TARGET;
+    static {
+        try {
+            GET_TARGET = MethodHandles.Lookup.IMPL_LOOKUP.
+                findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
+        } catch (NoAccessException ignore) {
+            throw new InternalError();
+        }
+    }
+
+    /** Implementation of {@link MethodHandleProvider} which returns {@code this.dynamicInvoker()}. */
+    public final MethodHandle asMethodHandle() { return dynamicInvoker(); }
+
+    /** Implementation of {@link MethodHandleProvider}, which returns {@code this.dynamicInvoker().asType(type)}. */
+    public final MethodHandle asMethodHandle(MethodType type) { return dynamicInvoker().asType(type); }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/dyn/ClassValue.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+package java.dyn;
+
+import java.util.WeakHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Lazily associate a computed value with (potentially) every class.
+ * @author John Rose, JSR 292 EG
+ */
+public abstract class ClassValue<T> {
+    /**
+     * Compute the given class's derived value for this {@code ClassValue}.
+     * <p>
+     * This method will be invoked within the first thread that accesses
+     * the value with the {@link #get}.
+     * <p>
+     * Normally, this method is invoked at most once per class,
+     * but it may be invoked again in case of subsequent invocations
+     * of {@link #remove} followed by {@link #get}.
+     *
+     * @return the computed value for this thread-local
+     */
+    protected abstract T computeValue(Class<?> type);
+
+    /**
+     * Creates a new class value.
+     */
+    protected ClassValue() {
+    }
+
+    /**
+     * Returns the value for the given class.
+     * If no value has yet been computed, it is obtained by
+     * by an invocation of the {@link #computeValue} method.
+     * <p>
+     * The actual installation of the value on the class
+     * is performed while the class's synchronization lock
+     * is held.  At that point, if racing threads have
+     * computed values, one is chosen, and returned to
+     * all the racing threads.
+     *
+     * @return the current thread's value of this thread-local
+     */
+    public T get(Class<?> type) {
+        ClassValueMap map = getMap(type);
+        if (map != null) {
+            Object x = map.get(this);
+            if (x != null) {
+                return (T) map.unmaskNull(x);
+            }
+        }
+        return setComputedValue(type);
+    }
+
+    /**
+     * Removes the associated value for the given class.
+     * If this value is subsequently {@linkplain #get read} for the same class,
+     * its value will be reinitialized by invoking its {@link #computeValue} method.
+     * This may result in an additional invocation of the
+     * {@code computeValue} method for the given class.
+     */
+    public void remove(Class<?> type) {
+        ClassValueMap map = getMap(type);
+        if (map != null) {
+            synchronized (map) {
+                map.remove(this);
+            }
+        }
+    }
+
+    /// Implementation...
+
+    /** The hash code for this type is based on the identity of the object,
+     *  and is well-dispersed for power-of-two tables.
+     */
+    public final int hashCode() { return hashCode; }
+    private final int hashCode = HASH_CODES.getAndAdd(0x61c88647);
+    private static final AtomicInteger HASH_CODES = new AtomicInteger();
+
+    private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
+
+    /** Slow path for {@link #get}. */
+    private T setComputedValue(Class<?> type) {
+        ClassValueMap map = getMap(type);
+        if (map == null) {
+            map = initializeMap(type);
+        }
+        T value = computeValue(type);
+        STORE_BARRIER.lazySet(0);
+        // All stores pending from computeValue are completed.
+        synchronized (map) {
+            // Warm up the table with a null entry.
+            map.preInitializeEntry(this);
+        }
+        // All stores pending from table expansion are completed.
+        synchronized (map) {
+            value = (T) map.initializeEntry(this, value);
+            // One might fear a possible race condition here
+            // if the code for map.put has flushed the write
+            // to map.table[*] before the writes to the Map.Entry
+            // are done.  This is not possible, since we have
+            // warmed up the table with an empty entry.
+        }
+        return value;
+    }
+
+    // Replace this map by a per-class slot.
+    private static final WeakHashMap<Class<?>, ClassValueMap> ROOT
+        = new WeakHashMap<Class<?>, ClassValueMap>();
+
+    private static ClassValueMap getMap(Class<?> type) {
+        return ROOT.get(type);
+    }
+
+    private static ClassValueMap initializeMap(Class<?> type) {
+        synchronized (ClassValue.class) {
+            ClassValueMap map = ROOT.get(type);
+            if (map == null)
+                ROOT.put(type, map = new ClassValueMap());
+            return map;
+        }
+    }
+
+    static class ClassValueMap extends WeakHashMap<ClassValue, Object> {
+        /** Make sure this table contains an Entry for the given key, even if it is empty. */
+        void preInitializeEntry(ClassValue key) {
+            if (!this.containsKey(key))
+                this.put(key, null);
+        }
+        /** Make sure this table contains a non-empty Entry for the given key. */
+        Object initializeEntry(ClassValue key, Object value) {
+            Object prior = this.get(key);
+            if (prior != null) {
+                return unmaskNull(prior);
+            }
+            this.put(key, maskNull(value));
+            return value;
+        }
+
+        Object maskNull(Object x) {
+            return x == null ? this : x;
+        }
+        Object unmaskNull(Object x) {
+            return x == this ? null : x;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/dyn/ConstantCallSite.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+package java.dyn;
+
+/**
+ * A {@code ConstantCallSite} is a {@link CallSite} whose target is permanent, and can never be changed.
+ * The only way to relink an {@code invokedynamic} instruction bound to a {@code ConstantCallSite} is
+ * to invalidate the instruction as a whole.
+ * @author John Rose, JSR 292 EG
+ */
+public class ConstantCallSite extends CallSite {
+    /** Create a call site with a permanent target. */
+    public ConstantCallSite(MethodHandle target) {
+        super(target);
+    }
+    /** Throw an {@link IllegalArgumentException}, because this kind of call site cannot change its target. */
+    @Override public final void setTarget(MethodHandle ignore) {
+        throw new IllegalArgumentException("ConstantCallSite");
+    }
+}
--- a/jdk/src/share/classes/java/dyn/InvokeDynamic.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/dyn/InvokeDynamic.java	Wed Jul 05 17:26:57 2017 +0200
@@ -35,7 +35,7 @@
  * The target method is a property of the reified {@linkplain CallSite call site object}
  * which is linked to each active {@code invokedynamic} instruction.
  * The call site object is initially produced by a
- * {@linkplain java.dyn.Linkage#registerBootstrapMethod(Class, MethodHandle) bootstrap method}
+ * {@linkplain BootstrapMethod bootstrap method}
  * associated with the class whose bytecodes include the dynamic call site.
  * <p>
  * The type {@code InvokeDynamic} has no particular meaning as a
@@ -45,22 +45,31 @@
  * It may be imported for ease of use.
  * <p>
  * Here are some examples:
- * <p><blockquote><pre>
- * Object x; String s; int i;
- * x = InvokeDynamic.greet("world"); // greet(Ljava/lang/String;)Ljava/lang/Object;
- * s = InvokeDynamic.&lt;String&gt;hail(x); // hail(Ljava/lang/Object;)Ljava/lang/String;
- * InvokeDynamic.&lt;void&gt;cogito(); // cogito()V
- * i = InvokeDynamic.&lt;int&gt;#"op:+"(2, 3); // "op:+"(II)I
- * </pre></blockquote>
+<blockquote><pre><!-- see indy-demo/src/JavaDocExamples.java -->
+&#064;BootstrapMethod(value=Here.class, name="bootstrapDynamic")
+static void example() throws Throwable {
+    Object x; String s; int i;
+    x = InvokeDynamic.greet("world"); // greet(Ljava/lang/String;)Ljava/lang/Object;
+    s = (String) InvokeDynamic.hail(x); // hail(Ljava/lang/Object;)Ljava/lang/String;
+    InvokeDynamic.cogito(); // cogito()V
+    i = (int) InvokeDynamic.#"op:+"(2, 3); // "op:+"(II)I
+}
+static MethodHandle bootstrapDynamic(Class caller, String name, MethodType type) { ... }
+</pre></blockquote>
  * Each of the above calls generates a single invokedynamic instruction
  * with the name-and-type descriptors indicated in the comments.
+ * <p>
  * The argument types are taken directly from the actual arguments,
- * while the return type is taken from the type parameter.
- * (This type parameter may be a primtive, and it defaults to {@code Object}.)
+ * while the return type corresponds to the target of the assignment.
+ * (Currently, the return type must be given as a false type parameter.
+ * This type parameter is an irregular use of the generic type syntax,
+ * and is likely to change in favor of a convention based on target typing.)
+ * <p>
  * The final example uses a special syntax for uttering non-Java names.
  * Any name legal to the JVM may be given between the double quotes.
+ * <p>
  * None of these calls is complete without a bootstrap method,
- * which must be registered by the static initializer of the enclosing class.
+ * which must be declared for the enclosing class or method.
  * @author John Rose, JSR 292 EG
  */
 @MethodHandle.PolymorphicSignature
--- a/jdk/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java	Wed Jul 05 17:26:57 2017 +0200
@@ -28,15 +28,11 @@
 /**
  * Thrown to indicate that an {@code invokedynamic} instruction has
  * failed to find its
- * {@linkplain Linkage#registerBootstrapMethod(Class, MethodHandle) bootstrap method},
+ * {@linkplain BootstrapMethod bootstrap method},
  * or the bootstrap method has
  * failed to provide a
  * {@linkplain CallSite} call site with a non-null {@linkplain MethodHandle target}
  * of the correct {@linkplain MethodType method type}.
- * <p>
- * The bootstrap method must have been declared during a class's initialization
- * by a call to one of the overloadings of
- * {@link Linkage#registerBootstrapMethod registerBootstrapMethod}.
  *
  * @author John Rose, JSR 292 EG
  * @since 1.7
--- a/jdk/src/share/classes/java/dyn/JavaMethodHandle.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,237 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 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.
- */
-
-package java.dyn;
-
-import sun.dyn.Access;
-
-/**
- * A Java method handle is a deprecated proposal for extending
- * the basic method handle type with additional
- * programmer defined methods and fields.
- * Its behavior as a method handle is determined at instance creation time,
- * by providing the new instance with an "entry point" method handle
- * to handle calls.  This entry point must accept a leading argument
- * whose type is the Java method handle itself or a supertype, and the
- * entry point is always called with the Java method handle itself as
- * the first argument.  This is similar to ordinary virtual methods, which also
- * accept the receiver object {@code this} as an implicit leading argument.
- * The {@code MethodType} of the Java method handle is the same as that
- * of the entry point method handle, with the leading parameter type
- * omitted.
- * <p>
- * Here is an example of usage, creating a hybrid object/functional datum:
- * <p><blockquote><pre>
- * class Greeter extends JavaMethodHandle {
- *     private String greeting = "hello";
- *     public void setGreeting(String s) { greeting = s; }
- *     public void run() { System.out.println(greeting+", "+greetee); }
- *     private final String greetee;
- *     Greeter(String greetee) {
- *         super(RUN); // alternatively, super("run")
- *         this.greetee = greetee;
- *     }
- *     // the entry point function is computed once:
- *     private static final MethodHandle RUN
- *         = MethodHandles.lookup().findVirtual(Greeter.class, "run",
- *               MethodType.make(void.class));
- * }
- * // class Main { public static void main(String... av) { ...
- * Greeter greeter = new Greeter("world");
- * greeter.run();  // prints "hello, world"
- * // Statically typed method handle invocation (most direct):
- * MethodHandle mh = greeter;
- * mh.&lt;void&gt;invokeExact();  // also prints "hello, world"
- * // Dynamically typed method handle invocation:
- * MethodHandles.invokeExact(greeter);  // also prints "hello, world"
- * greeter.setGreeting("howdy");
- * mh.invokeExact();  // prints "howdy, world" (object-like mutable behavior)
- * </pre></blockquote>
- * <p>
- * In the example of {@code Greeter}, the method {@code run} provides the entry point.
- * The entry point need not be a constant value; it may be independently
- * computed in each call to the constructor.  The entry point does not
- * even need to be a method on the {@code Greeter} class, though
- * that is the typical case.
- * <p>
- * The entry point may also be provided symbolically, in which case the the
- * {@code JavaMethodHandle} constructor performs the lookup of the entry point.
- * This makes it possible to use {@code JavaMethodHandle} to create an anonymous
- * inner class:
- * <p><blockquote><pre>
- * // We can also do this with symbolic names and/or inner classes:
- * MethodHandles.invokeExact(new JavaMethodHandle("yow") {
- *     void yow() { System.out.println("yow, world"); }
- * });
- * </pre></blockquote>
- * <p>
- * Here is similar lower-level code which works in terms of a bound method handle.
- * <p><blockquote><pre>
- *     class Greeter {
- *         public void run() { System.out.println("hello, "+greetee); }
- *         private final String greetee;
- *         Greeter(String greetee) { this.greetee = greetee; }
- *         // the entry point function is computed once:
- *         private static final MethodHandle RUN
- *             = MethodHandles.findVirtual(Greeter.class, "run",
- *                   MethodType.make(void.class));
- *     }
- *     // class Main { public static void main(String... av) { ...
- *     Greeter greeter = new Greeter("world");
- *     greeter.run();  // prints "hello, world"
- *     MethodHandle mh = MethodHanndles.insertArgument(Greeter.RUN, 0, greeter);
- *     mh.invokeExact();  // also prints "hello, world"
- * </pre></blockquote>
- * Note that the method handle must be separately created as a view on the base object.
- * This increases footprint, complexity, and dynamic indirections.
- * <p>
- * Here is a pure functional value expressed most concisely as an anonymous inner class:
- * <p><blockquote><pre>
- *     // class Main { public static void main(String... av) { ...
- *     final String greetee = "world";
- *     MethodHandle greeter = new JavaMethodHandle("run") {
- *         private void run() { System.out.println("hello, "+greetee); }
- *     }
- *     greeter.invokeExact();  // prints "hello, world"
- * </pre></blockquote>
- * <p>
- * Here is an abstract parameterized lvalue, efficiently expressed as a subtype of MethodHandle,
- * and instantiated as an anonymous class.  The data structure is a handle to 1-D array,
- * with a specialized index type (long).  It is created by inner class, and uses
- * signature-polymorphic APIs throughout.
- * <p><blockquote><pre>
- *     abstract class AssignableMethodHandle extends JavaMethodHandle {
- *       private final MethodHandle setter;
- *       public MethodHandle setter() { return setter; }
- *       public AssignableMethodHandle(String get, String set) {
- *         super(get);
- *         MethodType getType = this.type();
- *         MethodType setType = getType.insertParameterType(getType.parameterCount(), getType.returnType()).changeReturnType(void.class);
- *         this.setter = MethodHandles.publicLookup().bind(this, set, setType);
- *       }
- *     }
- *     // class Main { public static void main(String... av) { ...
- *     final Number[] stuff = { 123, 456 };
- *     AssignableMethodHandle stuffPtr = new AssignableMethodHandle("get", "set") {
- *         public Number get(long i)           { return stuff[(int)i]; }
- *         public void   set(long i, Object x) {        stuff[(int)i] = x; }
- *     }
- *     int x = (Integer) stuffPtr.&lt;Number&gt;invokeExact(1L);  // 456
- *     stuffPtr.setter().&lt;void&gt;invokeExact(0L, (Number) 789);  // replaces 123 with 789
- * </pre></blockquote>
- * @see MethodHandle
- * @deprecated The JSR 292 EG intends to replace {@code JavaMethodHandle} with
- * an interface-based API for mixing method handle behavior with other classes.
- * @author John Rose, JSR 292 EG
- */
-public abstract class JavaMethodHandle
-        // Note: This is an implementation inheritance hack, and will be removed
-        // with a JVM change which moves the required hidden behavior onto this class.
-        extends sun.dyn.BoundMethodHandle
-{
-    private static final Access IMPL_TOKEN = Access.getToken();
-
-    /**
-     * When creating a {@code JavaMethodHandle}, the actual method handle
-     * invocation behavior will be delegated to the specified {@code entryPoint}.
-     * This may be any method handle which can take the newly constructed object
-     * as a leading parameter.
-     * <p>
-     * The method handle type of {@code this} (i.e, the fully constructed object)
-     * will be {@code entryPoint}, minus the leading argument.
-     * The leading argument will be bound to {@code this} on every method
-     * handle invocation.
-     * @param entryPoint the method handle to handle calls
-     */
-    protected JavaMethodHandle(MethodHandle entryPoint) {
-        super(entryPoint);
-    }
-
-    /**
-     * Create a method handle whose entry point is a non-static method
-     * visible in the exact (most specific) class of
-     * the newly constructed object.
-     * <p>
-     * The method is specified by name and type, as if via this expression:
-     * {@code MethodHandles.lookup().findVirtual(this.getClass(), name, type)}.
-     * The class defining the method might be an anonymous inner class.
-     * <p>
-     * The method handle type of {@code this} (i.e, the fully constructed object)
-     * will be the given method handle type.
-     * A call to {@code this} will invoke the selected method.
-     * The receiver argument will be bound to {@code this} on every method
-     * handle invocation.
-     * <p>
-     * <i>Rationale:</i>
-     * Although this constructor may seem to be a mere luxury,
-     * it is not subsumed by the more general constructor which
-     * takes any {@code MethodHandle} as the entry point argument.
-     * In order to convert an entry point name to a method handle,
-     * the self-class of the object is required (in order to do
-     * the lookup).  The self-class, in turn, is generally not
-     * available at the time of the constructor invocation,
-     * due to the rules of Java and the JVM verifier.
-     * One cannot call {@code this.getClass()}, because
-     * the value of {@code this} is inaccessible at the point
-     * of the constructor call.  (Changing this would require
-     * change to the Java language, verifiers, and compilers.)
-     * In particular, this constructor allows {@code JavaMethodHandle}s
-     * to be created in combination with the anonymous inner class syntax.
-     * @param entryPointName the name of the entry point method
-     * @param type (optional) the desired type of the method handle
-     */
-    protected JavaMethodHandle(String entryPointName, MethodType type) {
-        super(entryPointName, type, true);
-
-    }
-
-    /**
-     * Create a method handle whose entry point is a non-static method
-     * visible in the exact (most specific) class of
-     * the newly constructed object.
-     * <p>
-     * The method is specified only by name.
-     * There must be exactly one method of that name visible in the object class,
-     * either inherited or locally declared.
-     * (That is, the method must not be overloaded.)
-     * <p>
-     * The method handle type of {@code this} (i.e, the fully constructed object)
-     * will be the same as the type of the selected non-static method.
-     * The receiver argument will be bound to {@code this} on every method
-     * handle invocation.
-     * <p>ISSUE: This signature wildcarding feature does not correspond to
-     * any MethodHandles.Lookup API element.  Can we eliminate it?
-     * Alternatively, it is useful for naming non-overloaded methods.
-     * Shall we make type arguments optional in the Lookup methods,
-     * throwing an error in cases of ambiguity?
-     * <p>
-     * For this method's rationale, see the documentation
-     * for {@link #JavaMethodHandle(String,MethodType)}.
-     * @param entryPointName the name of the entry point method
-     */
-    protected JavaMethodHandle(String entryPointName) {
-        super(entryPointName, (MethodType) null, false);
-    }
-}
--- a/jdk/src/share/classes/java/dyn/Linkage.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/dyn/Linkage.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,7 +25,6 @@
 
 package java.dyn;
 
-import java.lang.annotation.Annotation;
 import java.dyn.MethodHandles.Lookup;
 import java.util.WeakHashMap;
 import sun.dyn.Access;
@@ -56,11 +55,7 @@
      * <li>the class containing the {@code invokedynamic} instruction, for which the bootstrap method was registered
      * <li>the name of the method being invoked (a {@link String})
      * <li>the type of the method being invoked (a {@link MethodType})
-     * <li><em>TBD</em> optionally, an unordered array of {@link Annotation}s attached to the call site
-     *     <em>(Until this feature is implemented, this will always receive an empty array.)</em>
      * </ul>
-     * <em>(TBD: The final argument type may be missing from the method handle's type.
-     * Additional arguments may be added in the future.)</em>
      * The bootstrap method acts as a factory method which accepts the given arguments
      * and returns a {@code CallSite} object (possibly of a subclass of {@code CallSite}).
      * <p>
@@ -86,6 +81,7 @@
      *            or is already running in another thread
      * @exception SecurityException if there is a security manager installed,
      *            and a {@link LinkagePermission} check fails for "registerBootstrapMethod"
+     * @deprecated Use @{@link BootstrapMethod} annotations instead
      */
     public static
     void registerBootstrapMethod(Class callerClass, MethodHandle bootstrapMethod) {
@@ -97,14 +93,9 @@
 
     static private void checkBSM(MethodHandle mh) {
         if (mh == null)  throw newIllegalArgumentException("null bootstrap method");
-        if (mh.type() == BOOTSTRAP_METHOD_TYPE_2)
-            // For now, always pass an empty array for the Annotations argument
-            mh = MethodHandles.insertArguments(mh, BOOTSTRAP_METHOD_TYPE_2.parameterCount()-1,
-                                               (Object)NO_ANNOTATIONS);
         if (mh.type() == BOOTSTRAP_METHOD_TYPE)  return;
         throw new WrongMethodTypeException(mh.toString());
     }
-    static private final Annotation[] NO_ANNOTATIONS = { };
 
     /**
      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
@@ -115,6 +106,7 @@
      * @throws NoSuchMethodException if there is no such method
      * @throws IllegalStateException if the caller class's static initializer
      *         has already run, or is already running in another thread
+     * @deprecated Use @{@link BootstrapMethod} annotations instead
      */
     public static
     void registerBootstrapMethod(Class<?> runtime, String name) {
@@ -131,6 +123,7 @@
      * @throws IllegalArgumentException if there is no such method
      * @throws IllegalStateException if the caller class's static initializer
      *         has already run, or is already running in another thread
+     * @deprecated Use @{@link BootstrapMethod} annotations instead
      */
     public static
     void registerBootstrapMethod(String name) {
@@ -142,18 +135,10 @@
     void registerBootstrapMethodLookup(Class<?> callerClass, Class<?> runtime, String name) {
         Lookup lookup = new Lookup(IMPL_TOKEN, callerClass);
         MethodHandle bootstrapMethod;
-        // Try both types.  TBD
         try {
-            bootstrapMethod = lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE_2);
+            bootstrapMethod = lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE);
         } catch (NoAccessException ex) {
-            bootstrapMethod = null;
-        }
-        if (bootstrapMethod == null) {
-            try {
-                bootstrapMethod = lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE);
-            } catch (NoAccessException ex) {
-                throw new IllegalArgumentException("no such bootstrap method in "+runtime+": "+name, ex);
-            }
+            throw new IllegalArgumentException("no such bootstrap method in "+runtime+": "+name, ex);
         }
         checkBSM(bootstrapMethod);
         MethodHandleImpl.registerBootstrap(IMPL_TOKEN, callerClass, bootstrapMethod);
@@ -172,6 +157,7 @@
      *            and the immediate caller of this method is not in the same
      *            package as the caller class
      *            and a {@link LinkagePermission} check fails for "getBootstrapMethod"
+     * @deprecated
      */
     public static
     MethodHandle getBootstrapMethod(Class callerClass) {
@@ -188,10 +174,6 @@
     public static final MethodType BOOTSTRAP_METHOD_TYPE
             = MethodType.methodType(CallSite.class,
                                     Class.class, String.class, MethodType.class);
-    static final MethodType BOOTSTRAP_METHOD_TYPE_2
-            = MethodType.methodType(CallSite.class,
-                                    Class.class, String.class, MethodType.class,
-                                    Annotation[].class);
 
     /**
      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
--- a/jdk/src/share/classes/java/dyn/LinkagePermission.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/dyn/LinkagePermission.java	Wed Jul 05 17:26:57 2017 +0200
@@ -31,6 +31,7 @@
 import java.util.StringTokenizer;
 
 /**
+ * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  * This class is for managing runtime permission checking for
  * operations performed by methods in the {@link Linkage} class.
  * Like a {@link RuntimePermission}, on which it is modeled,
@@ -52,13 +53,6 @@
  * </tr>
  *
  * <tr>
- *   <td>registerBootstrapMethod.{class name}</td>
- *   <td>Specifying a bootstrap method for {@code invokedynamic} instructions within a class of the given name</td>
- *   <td>An attacker could attempt to attach a bootstrap method to a class which
- *       has just been loaded, thus gaining control of its {@code invokedynamic} calls.</td>
- * </tr>
- *
- * <tr>
  *   <td>invalidateAll</td>
  *   <td>Force the relinking of invokedynamic call sites everywhere.</td>
  *   <td>This could allow an attacker to slow down the system,
@@ -73,8 +67,9 @@
  *   <td>See {@code invalidateAll}.</td>
  * </tr>
  * </table>
+ * <p>ISSUE: Is this still needed?
  *
- * @see java.security.RuntimePermission
+ * @see java.lang.RuntimePermission
  * @see java.lang.SecurityManager
  *
  * @author John Rose, JSR 292 EG
@@ -86,7 +81,7 @@
     /**
      * Create a new LinkagePermission with the given name.
      * The name is the symbolic name of the LinkagePermission, such as
-     * "registerBootstrapMethod", "invalidateCallerClass.*", etc. An asterisk
+     * "invalidateCallerClass.*", etc. An asterisk
      * may appear at the end of the name, following a ".", or by itself, to
      * signify a wildcard match.
      *
--- a/jdk/src/share/classes/java/dyn/MethodHandle.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/dyn/MethodHandle.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2010, 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
@@ -36,11 +36,13 @@
 /**
  * A method handle is a typed, directly executable reference to a method,
  * constructor, field, or similar low-level operation, with optional
- * conversion or substitution of arguments or return values.
+ * transformations of arguments or return values.
+ * (These transformations include conversion, insertion, deletion,
+ * substitution.  See the methods of this class and of {@link MethodHandles}.)
  * <p>
  * Method handles are strongly typed according to signature.
  * They are not distinguished by method name or enclosing class.
- * A method handle must be invoked under a signature which exactly matches
+ * A method handle must be invoked under a signature which matches
  * the method handle's own {@link MethodType method type}.
  * <p>
  * Every method handle confesses its type via the {@code type} accessor.
@@ -174,9 +176,10 @@
  * merely a documentation convention.  These type parameters do
  * not play a role in type-checking method handle invocations.
  * <p>
- * Note: Like classes and strings, method handles that correspond directly
- * to fields and methods can be represented directly as constants to be
- * loaded by {@code ldc} bytecodes.
+ * Like classes and strings, method handles that correspond to accessible
+ * fields, methods, and constructors can be represented directly
+ * in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes.
+ * Loading such a constant causes the component classes of its type to be loaded as necessary.
  *
  * @see MethodType
  * @see MethodHandles
@@ -186,6 +189,7 @@
         // Note: This is an implementation inheritance hack, and will be removed
         // with a JVM change which moves the required hidden state onto this class.
         extends MethodHandleImpl
+        implements MethodHandleProvider
 {
     private static Access IMPL_TOKEN = Access.getToken();
 
@@ -197,7 +201,7 @@
      * those methods which are signature polymorphic.
      */
     @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD,java.lang.annotation.ElementType.TYPE})
-    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS)
+    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
     @interface PolymorphicSignature { }
 
     private MethodType type;
@@ -274,10 +278,14 @@
      * and performing simple conversions for arguments and return types.
      * The signature at the call site of {@code invokeGeneric} must
      * have the same arity as this method handle's {@code type}.
-     * The same conversions are allowed on arguments or return values as are supported by
-     * by {@link MethodHandles#convertArguments}.
+     * <p>
      * If the call site signature exactly matches this method handle's {@code type},
      * the call proceeds as if by {@link #invokeExact}.
+     * <p>
+     * Otherwise, the call proceeds as if this method handle were first
+     * adjusted by calling {@link #asType} to adjust this method handle
+     * to the required type, and then the call proceeds as if by
+     * {@link #invokeExact} on the adjusted method handle.
      */
     public final native @PolymorphicSignature <R,A> R invokeGeneric(A... args) throws Throwable;
 
@@ -538,4 +546,10 @@
     public final MethodHandle bindTo(Object x) {
         return MethodHandles.insertArguments(this, 0, x);
     }
+
+    /** Implementation of {@link MethodHandleProvider}, which returns {@code this}. */
+    public final MethodHandle asMethodHandle() { return this; }
+
+    /** Implementation of {@link MethodHandleProvider}, which returns {@code this.asType(type)}. */
+    public final MethodHandle asMethodHandle(MethodType type) { return this.asType(type); }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/dyn/MethodHandleProvider.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2009, 2010, 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.
+ */
+
+package java.dyn;
+
+/**
+ * An interface for an object to provide a target {@linkplain MethodHandle method handle} to a {@code invokedynamic} instruction.
+ * There are many function-like objects in various Java APIs.
+ * This interface provides a standard way for such function-like objects to be bound
+ * to a dynamic call site, by providing a view of their behavior in the form of a low-level method handle.
+ * <p>
+ * The type {@link MethodHandle} is a concrete class whose implementation
+ * hierarchy (if any) may be tightly coupled to the underlying JVM implementation.
+ * It cannot also serve as a base type for user-defined functional APIs.
+ * For this reason, {@code MethodHandle} cannot be subclassed to add new
+ * behavior to method handles.  But this interface can be used to provide
+ * a link between a user-defined function and the {@code invokedynamic}
+ * instruction and the method handle API.
+ */
+public interface MethodHandleProvider {
+    /** Produce a method handle which will serve as a behavioral proxy for the current object.
+     *  The type and invocation behavior of the proxy method handle are user-defined,
+     *  and should have some relation to the intended meaning of the original object itself.
+     *  <p>
+     *  The current object may have a changeable behavior.
+     *  For example, {@link CallSite} has a {@code setTarget} method which changes its invocation.
+     *  In such a case, it is <em>incorrect</em> for {@code asMethodHandle} to return
+     *  a method handle whose behavior may diverge from that of the current object.
+     *  Rather, the returned method handle must stably and permanently access
+     *  the behavior of the current object, even if that behavior is changeable.
+     *  <p>
+     *  The reference identity of the proxy method handle is not guaranteed to
+     *  have any particular relation to the reference identity of the object.
+     *  In particular, several objects with the same intended meaning could
+     *  share a common method handle, or the same object could return different
+     *  method handles at different times.  In the latter case, the different
+     *  method handles should have the same type and invocation behavior,
+     *  and be usable from any thread at any time.
+     *  In particular, if a MethodHandleProvider is bound to an <code>invokedynamic</code>
+     *  call site, the proxy method handle extracted at the time of binding
+     *  will be used for an unlimited time, until the call site is rebound.
+     *  <p>
+     *  The type {@link MethodHandle} itself implements {@code MethodHandleProvider}, and
+     *  for this method simply returns {@code this}.
+     */
+    public MethodHandle asMethodHandle();
+
+    /** Produce a method handle of a given type which will serve as a behavioral proxy for the current object.
+     *  As for the no-argument version {@link #asMethodHandle()}, the invocation behavior of the
+     *  proxy method handle is user-defined.  But the type must be the given type,
+     *  or else a {@link WrongMethodTypeException} must be thrown.
+     *  <p>
+     *  If the current object somehow represents a variadic or overloaded behavior,
+     *  the method handle returned for a given type might represent only a subset of
+     *  the current object's repertoire of behaviors, which correspond to that type.
+     */
+    public MethodHandle asMethodHandle(MethodType type) throws WrongMethodTypeException;
+}
--- a/jdk/src/share/classes/java/dyn/MethodHandles.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/dyn/MethodHandles.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,15 +25,12 @@
 
 package java.dyn;
 
-import java.lang.reflect.Constructor;
+import java.lang.reflect.*;
 import sun.dyn.Access;
 import sun.dyn.MemberName;
 import sun.dyn.MethodHandleImpl;
 import sun.dyn.util.VerifyAccess;
 import sun.dyn.util.Wrapper;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
 import java.util.List;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -81,6 +78,14 @@
      * Return a {@link Lookup lookup object} which is trusted minimally.
      * It can only be used to create method handles to
      * publicly accessible fields and methods.
+     * <p>
+     * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class}
+     * of this lookup object will be {@link java.lang.Object}.
+     * <p>
+     * The lookup class can be changed to any other class {@code C} using an expression of the form
+     * {@linkplain Lookup#in <code>publicLookup().in(C.class)</code>}.
+     * Since all classes have equal access to public names,
+     * such a change would confer no new access rights.
      */
     public static Lookup publicLookup() {
         return Lookup.PUBLIC_LOOKUP;
@@ -90,9 +95,10 @@
      * A <em>lookup object</em> is a factory for creating method handles,
      * when the creation requires access checking.
      * Method handles do not perform
-     * access checks when they are called; this is a major difference
+     * access checks when they are called, but rather when they are created.
+     * (This is a major difference
      * from reflective {@link Method}, which performs access checking
-     * against every caller, on every call.
+     * against every caller, on every call.)
      * Therefore, method handle access
      * restrictions must be enforced when a method handle is created.
      * The caller class against which those restrictions are enforced
@@ -107,7 +113,7 @@
      * It may then use this factory to create method handles on
      * all of its methods, including private ones.
      * It may also delegate the lookup (e.g., to a metaobject protocol)
-     * by passing the {@code Lookup} object to other code.
+     * by passing the lookup object to other code.
      * If this other code creates method handles, they will be access
      * checked against the original lookup class, and not with any higher
      * privileges.
@@ -125,23 +131,28 @@
      * It can also fail if a security manager is installed and refuses
      * access.  In any of these cases, an exception will be
      * thrown from the attempted lookup.
+     * <p>
      * In general, the conditions under which a method handle may be
      * created for a method {@code M} are exactly as restrictive as the conditions
      * under which the lookup class could have compiled a call to {@code M}.
-     * At least some of these error conditions are likely to be
-     * represented by checked exceptions in the final version of this API.
+     * This rule is applied even if the Java compiler might have created
+     * an wrapper method to access a private method of another class
+     * in the same top-level declaration.
+     * For example, a lookup object created for a nested class {@code C.D}
+     * can access private members within other related classes such as
+     * {@code C}, {@code C.D.E}, or {@code C.B}.
      */
     public static final
     class Lookup {
         /** The class on behalf of whom the lookup is being performed. */
         private final Class<?> lookupClass;
 
-        /** The allowed sorts of members which may be looked up (public, etc.), with STRICT for package. */
+        /** The allowed sorts of members which may be looked up (public, etc.), with STATIC for package. */
         private final int allowedModes;
 
         private static final int
             PUBLIC    = Modifier.PUBLIC,
-            PACKAGE   = Modifier.STRICT,
+            PACKAGE   = Modifier.STATIC,
             PROTECTED = Modifier.PROTECTED,
             PRIVATE   = Modifier.PRIVATE,
             ALL_MODES = (PUBLIC | PACKAGE | PROTECTED | PRIVATE),
@@ -155,8 +166,10 @@
         /** Which class is performing the lookup?  It is this class against
          *  which checks are performed for visibility and access permissions.
          *  <p>
-         *  This value is null if and only if this lookup was produced
-         *  by {@link MethodHandles#publicLookup}.
+         *  The class implies a maximum level of access permission,
+         *  but the permissions may be additionally limited by the bitmask
+         *  {@link #lookupModes}, which controls whether non-public members
+         *  can be accessed.
          */
         public Class<?> lookupClass() {
             return lookupClass;
@@ -168,10 +181,15 @@
         }
 
         /** Which types of members can this lookup object produce?
-         *  The result is a bit-mask of the modifier bits PUBLIC, PROTECTED, PRIVATE, and STRICT.
-         *  The modifier bit STRICT stands in for the (non-existent) package protection mode.
+         *  The result is a bit-mask of the {@link Modifier} bits
+         *  {@linkplain Modifier#PUBLIC PUBLIC (0x01)},
+         *  {@linkplain Modifier#PROTECTED PROTECTED (0x02)},
+         *  {@linkplain Modifier#PRIVATE PRIVATE (0x04)},
+         *  and {@linkplain Modifier#STATIC STATIC (0x08)}.
+         *  The modifier bit {@code STATIC} stands in for the package protection mode,
+         *  which does not have an explicit modifier bit.
          */
-        int lookupModes() {
+        public int lookupModes() {
             return allowedModes & ALL_MODES;
         }
 
@@ -621,32 +639,32 @@
 
         /// Helper methods, all package-private.
 
-        MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) {
+        MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) throws NoAccessException {
             checkSymbolicClass(refc);  // do this before attempting to resolve
             int mods = (isStatic ? Modifier.STATIC : 0);
             return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull());
         }
 
-        MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) {
+        MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) throws NoAccessException {
             checkSymbolicClass(refc);  // do this before attempting to resolve
             int mods = (isStatic ? Modifier.STATIC : 0);
             return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull());
         }
 
         MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic,
-                                 boolean searchSupers, Class<?> specialCaller) {
+                                 boolean searchSupers, Class<?> specialCaller) throws NoAccessException {
             checkSymbolicClass(refc);  // do this before attempting to resolve
             int mods = (isStatic ? Modifier.STATIC : 0);
             return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), searchSupers, specialCaller);
         }
 
-        void checkSymbolicClass(Class<?> refc) {
+        void checkSymbolicClass(Class<?> refc) throws NoAccessException {
             Class<?> caller = lookupClassOrNull();
             if (caller != null && !VerifyAccess.isClassAccessible(refc, caller))
                 throw newNoAccessException("symbolic reference class is not public", new MemberName(refc), caller);
         }
 
-        void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) {
+        void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) throws NoAccessException {
             String message;
             if (m.isConstructor())
                 message = "expected a method, not a constructor";
@@ -659,7 +677,7 @@
             throw newNoAccessException(message, m, lookupClass());
         }
 
-        void checkAccess(Class<?> refc, MemberName m) {
+        void checkAccess(Class<?> refc, MemberName m) throws NoAccessException {
             int allowedModes = this.allowedModes;
             if (allowedModes == TRUSTED)  return;
             int mods = m.getModifiers();
@@ -695,14 +713,14 @@
             return "member is private to package";
         }
 
-        void checkSpecialCaller(Class<?> specialCaller) {
+        void checkSpecialCaller(Class<?> specialCaller) throws NoAccessException {
             if (allowedModes == TRUSTED)  return;
             if (!VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))
                 throw newNoAccessException("no private access for invokespecial",
                                            new MemberName(specialCaller), lookupClass());
         }
 
-        MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) {
+        MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) throws NoAccessException {
             // The accessing class only has the right to use a protected member
             // on itself or a subclass.  Enforce that restriction, from JVMS 5.4.4, etc.
             if (!method.isProtected() || method.isStatic()
@@ -712,7 +730,7 @@
             else
                 return restrictReceiver(method, mh, lookupClass());
         }
-        MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) {
+        MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) throws NoAccessException {
             assert(!method.isStatic());
             Class<?> defc = method.getDeclaringClass();  // receiver type of mh is too wide
             if (defc.isInterface() || !defc.isAssignableFrom(caller)) {
@@ -898,11 +916,16 @@
      * @return a method handle which always invokes the call site's target
      */
     public static
-    MethodHandle dynamicInvoker(CallSite site) {
+    MethodHandle dynamicInvoker(CallSite site) throws NoAccessException {
         MethodHandle getCSTarget = GET_TARGET;
-        if (getCSTarget == null)
-            GET_TARGET = getCSTarget = Lookup.IMPL_LOOKUP.
-                findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
+        if (getCSTarget == null) {
+            try {
+                GET_TARGET = getCSTarget = Lookup.IMPL_LOOKUP.
+                    findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
+            } catch (NoAccessException ex) {
+                throw new InternalError();
+            }
+        }
         MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, getCSTarget, site);
         MethodHandle invoker = exactInvoker(site.type());
         return foldArguments(invoker, getTarget);
@@ -1260,17 +1283,20 @@
      * <p>
      * <b>Example:</b>
      * <p><blockquote><pre>
-     *   MethodHandle cat = MethodHandles.lookup().
-     *     findVirtual(String.class, "concat", String.class, String.class);
-     *   System.out.println(cat.&lt;String&gt;invokeExact("x", "y")); // xy
+     *   import static java.dyn.MethodHandles.*;
+     *   import static java.dyn.MethodType.*;
+     *   ...
+     *   MethodHandle cat = lookup().findVirtual(String.class,
+     *     "concat", methodType(String.class, String.class));
+     *   System.out.println((String) cat.invokeExact("x", "y")); // xy
      *   MethodHandle d0 = dropArguments(cat, 0, String.class);
-     *   System.out.println(d0.&lt;String&gt;invokeExact("x", "y", "z")); // xy
+     *   System.out.println((String) d0.invokeExact("x", "y", "z")); // yz
      *   MethodHandle d1 = dropArguments(cat, 1, String.class);
-     *   System.out.println(d1.&lt;String&gt;invokeExact("x", "y", "z")); // xz
+     *   System.out.println((String) d1.invokeExact("x", "y", "z")); // xz
      *   MethodHandle d2 = dropArguments(cat, 2, String.class);
-     *   System.out.println(d2.&lt;String&gt;invokeExact("x", "y", "z")); // yz
-     *   MethodHandle d12 = dropArguments(cat, 1, String.class, String.class);
-     *   System.out.println(d12.&lt;String&gt;invokeExact("w", "x", "y", "z")); // wz
+     *   System.out.println((String) d2.invokeExact("x", "y", "z")); // xy
+     *   MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
+     *   System.out.println((String) d12.invokeExact("x", 12, true, "z")); // xz
      * </pre></blockquote>
      * @param target the method handle to invoke after the argument is dropped
      * @param valueTypes the type(s) of the argument to drop
@@ -1562,4 +1588,107 @@
     MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
         return MethodHandleImpl.throwException(IMPL_TOKEN, MethodType.methodType(returnType, exType));
     }
+
+    /**
+     * Produce a wrapper instance of the given "SAM" type which redirects its calls to the given method handle.
+     * A SAM type is a type which declares a single abstract method.
+     * Additionally, it must have either no constructor (as an interface)
+     * or have a public or protected constructor of zero arguments (as a class).
+     * <p>
+     * The resulting instance of the required SAM type will respond to
+     * invocation of the SAM type's single abstract method by calling
+     * the given {@code target} on the incoming arguments,
+     * and returning or throwing whatever the {@code target}
+     * returns or throws.  The invocation will be as if by
+     * {@code target.invokeExact}.
+     * <p>
+     * The method handle may throw an <em>undeclared exception</em>,
+     * which means any checked exception (or other checked throwable)
+     * not declared by the SAM type's single abstract method.
+     * If this happens, the throwable will be wrapped in an instance
+     * of {@link UndeclaredThrowableException} and thrown in that
+     * wrapped form.
+     * <p>
+     * The wrapper instance is guaranteed to be of a non-public
+     * implementation class C in a package containing no classes
+     * or methods except system-defined classes and methods.
+     * The implementation class C will have no public supertypes
+     * or public methods beyond the following:
+     * <ul>
+     * <li>the SAM type itself and any methods in the SAM type
+     * <li>the supertypes of the SAM type (if any) and their methods
+     * <li>{@link Object} and its methods
+     * <li>{@link MethodHandleProvider} and its methods
+     * </ul>
+     * <p>
+     * No stable mapping is promised between the SAM type and
+     * the implementation class C.  Over time, several implementation
+     * classes might be used for the same SAM type.
+     * <p>
+     * This method is not guaranteed to return a distinct
+     * wrapper object for each separate call.  If the JVM is able
+     * to prove that a wrapper has already been created for a given
+     * method handle, or for another method handle with the
+     * same behavior, the JVM may return that wrapper in place of
+     * a new wrapper.
+     * @param target the method handle to invoke from the wrapper
+     * @param samType the desired type of the wrapper, a SAM type
+     * @return a correctly-typed wrapper for the given {@code target}
+     * @throws IllegalArgumentException if the {@code target} throws
+     *         an undeclared exception
+     */
+    // ISSUE: Should we delegate equals/hashCode to the targets?
+    // Not useful unless there is a stable equals/hashCode behavior
+    // for MethodHandle, and for MethodHandleProvider.asMethodHandle.
+    public static
+    <T> T asInstance(MethodHandle target, Class<T> samType) {
+        // POC implementation only; violates the above contract several ways
+        final Method sam = getSamMethod(samType);
+        if (sam == null)
+            throw new IllegalArgumentException("not a SAM type: "+samType.getName());
+        MethodType samMT = MethodType.methodType(sam.getReturnType(), sam.getParameterTypes());
+        if (!samMT.equals(target.type()))
+            throw new IllegalArgumentException("wrong method type");
+        final MethodHandle mh = target;
+        return samType.cast(Proxy.newProxyInstance(
+                samType.getClassLoader(),
+                new Class[]{ samType, MethodHandleProvider.class },
+                new InvocationHandler() {
+                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+                        if (method.getDeclaringClass() == MethodHandleProvider.class) {
+                            return method.invoke(mh, args);
+                        }
+                        assert method.equals(sam) : method;
+                        return mh.invokeVarargs(args);
+                    }
+                }));
+    }
+
+    private static
+    Method getSamMethod(Class<?> samType) {
+        Method sam = null;
+        for (Method m : samType.getMethods()) {
+            int mod = m.getModifiers();
+            if (Modifier.isAbstract(mod)) {
+                if (sam != null)
+                    return null;  // too many abstract methods
+                sam = m;
+            }
+        }
+        if (!samType.isInterface() && getSamConstructor(samType) == null)
+            return null;  // wrong kind of constructor
+        return sam;
+    }
+
+    private static
+    Constructor getSamConstructor(Class<?> samType) {
+        for (Constructor c : samType.getDeclaredConstructors()) {
+            if (c.getParameterTypes().length == 0) {
+                int mod = c.getModifiers();
+                if (Modifier.isPublic(mod) || Modifier.isProtected(mod))
+                    return c;
+            }
+        }
+        return null;
+    }
 }
--- a/jdk/src/share/classes/java/dyn/MethodType.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/dyn/MethodType.java	Wed Jul 05 17:26:57 2017 +0200
@@ -40,24 +40,37 @@
  * returned by a method handle, or the arguments and return type passed
  * and expected  by a method handle caller.  Method types must be properly
  * matched between a method handle and all its callers,
- * and the JVM's operations enforce this matching at all times.
+ * and the JVM's operations enforce this matching at, specifically
+ * during calls to {@link MethodHandle#invokeExact}
+ * and {@link MethodHandle#invokeGeneric}, and during execution
+ * of {@code invokedynamic} instructions.
  * <p>
  * The structure is a return type accompanied by any number of parameter types.
- * The types (primitive, void, and reference) are represented by Class objects.
+ * The types (primitive, {@code void}, and reference) are represented by {@link Class} objects.
+ * (For ease of exposition, we treat {@code void} as if it were a type.
+ * In fact, it denotes the absence of a return type.)
  * <p>
- * All instances of <code>MethodType</code> are immutable.
+ * All instances of {@code MethodType} are immutable.
  * Two instances are completely interchangeable if they compare equal.
  * Equality depends on pairwise correspondence of the return and parameter types and on nothing else.
  * <p>
  * This type can be created only by factory methods.
  * All factory methods may cache values, though caching is not guaranteed.
  * <p>
- * Note: Like classes and strings, method types can be represented directly
- * as constants to be loaded by {@code ldc} bytecodes.
+ * {@code MethodType} objects are sometimes derived from bytecode instructions
+ * such as {@code invokedynamic}, specifically from the type descriptor strings associated
+ * with the instructions in a class file's constant pool.
+ * When this occurs, any classes named in the descriptor strings must be loaded.
+ * (But they need not be initialized.)
+ * This loading may occur at any time before the {@code MethodType} object is first derived.
+ * <p>
+ * Like classes and strings, method types can be represented directly
+ * in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes.
+ * Loading such a constant causes its component classes to be loaded as necessary.
  * @author John Rose, JSR 292 EG
  */
 public final
-class MethodType {
+class MethodType implements java.lang.reflect.Type {
     private final Class<?>   rtype;
     private final Class<?>[] ptypes;
     private MethodTypeForm form; // erased form, plus cached data about primitives
@@ -636,11 +649,11 @@
 
     /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
      * Find or create an instance of the given method type.
-     * Any class or interface name embedded in the signature string
+     * Any class or interface name embedded in the descriptor string
      * will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)}
      * on the given loader (or if it is null, on the system class loader).
      * <p>
-     * Note that it is possible to build method types which cannot be
+     * Note that it is possible to encounter method types which cannot be
      * constructed by this method, because their component types are
      * not all reachable from a common class loader.
      * <p>
@@ -662,8 +675,11 @@
     }
 
     /**
-     * Create a bytecode signature representation of the type.
-     * Note that this is not a strict inverse of
+     * Create a bytecode descriptor representation of the method type.
+     * <p>
+     * Note that this is not a strict inverse of {@link #fromMethodDescriptorString}.
+     * Two distinct classes which share a common name but have different class loaders
+     * will appear identical when viewed within descriptor strings.
      * <p>
      * This method is included for the benfit of applications that must
      * generate bytecodes that process method handles and invokedynamic.
--- a/jdk/src/share/classes/java/dyn/NoAccessException.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/dyn/NoAccessException.java	Wed Jul 05 17:26:57 2017 +0200
@@ -37,7 +37,7 @@
  * @author John Rose, JSR 292 EG
  * @since 1.7
  */
-public class NoAccessException extends RuntimeException {
+public class NoAccessException extends ReflectiveOperationException {
     private static final long serialVersionUID = 292L;
 
     /**
--- a/jdk/src/share/classes/java/dyn/package-info.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/dyn/package-info.java	Wed Jul 05 17:26:57 2017 +0200
@@ -40,20 +40,18 @@
  * The JVM links any such call (regardless of signature) to a dynamically
  * typed method handle invocation.  In the case of {@code invokeGeneric},
  * argument and return value conversions are applied.
+ * </li>
  *
- * <li>In source code, the class {@link java.dyn.InvokeDynamic} appears to accept
+ * <li>In source code, the class {@link java.dyn.InvokeDynamic InvokeDynamic} appears to accept
  * any static method invocation, of any name and any signature.
  * But instead of emitting
  * an {@code invokestatic} instruction for such a call, the Java compiler emits
  * an {@code invokedynamic} instruction with the given name and signature.
- *
- * <li>When the JVM links an {@code invokedynamic} instruction, it calls the
- * {@linkplain java.dyn.Linkage#registerBootstrapMethod(Class, MethodHandle) bootstrap method}
- * of the containing class to obtain a {@linkplain java.dyn.CallSite call site} object through which
- * the call site will link its target {@linkplain java.dyn.MethodHandle method handle}.
+ * </li>
  *
  * <li>The JVM bytecode format supports immediate constants of
- * the classes {@link java.dyn.MethodHandle} and {@link java.dyn.MethodType}.
+ * the classes {@link java.dyn.MethodHandle MethodHandle} and {@link java.dyn.MethodType MethodType}.
+ * </li>
  * </ul>
  *
  * <h2><a name="jvm_mods"></a>Corresponding JVM bytecode format changes</h2>
@@ -65,18 +63,50 @@
  * The first byte is the opcode 186 (hexadecimal {@code BA}).
  * The next two bytes are a constant pool index (in the same format as for the other {@code invoke} instructions).
  * The final two bytes are reserved for future use and required to be zero.
- * The constant pool reference is to a entry with tag {@code CONSTANT_NameAndType}
- * (decimal 12).  It is thus not a method reference of any sort, but merely
- * the method name, argument types, and return type of the dynamic call site.
- * <em>(TBD: The EG is discussing the possibility of a special constant pool entry type,
- * so that other information may be added, such as a per-instruction bootstrap
- * method and/or annotations.)</em>
+ * The constant pool reference of an {@code invokedynamic} instruction is to a entry
+ * with tag {@code CONSTANT_InvokeDynamic} (decimal 17).  See below for its format.
+ * The entry specifies the bootstrap method (a {@link java.dyn.MethodHandle MethodHandle} constant),
+ * the dynamic invocation name, and the argument types and return type of the call.
+ * <p>
+ * Each instance of an {@code invokedynamic} instruction is called a <em>dynamic call site</em>.
+ * Multiple instances of an {@code invokedynamic} instruction can share a single
+ * {@code CONSTANT_InvokeDynamic} entry.
+ * In any case, distinct call sites always have distinct linkage state.
+ * <p>
+ * Moreover, for the purpose of distinguishing dynamic call sites,
+ * the JVM is allowed (but not required) to make internal copies
+ * of {@code invokedynamic} instructions, each one
+ * constituting a separate dynamic call site with its own linkage state.
+ * Such copying, if it occurs, cannot be observed except indirectly via
+ * execution of bootstrap methods and target methods.
+ * <p>
+ * A dynamic call site is originally in an unlinked state.  In this state, there is
+ * no target method for the call site to invoke.
+ * A dynamic call site is linked by means of a bootstrap method,
+ * as <a href="#bsm">described below</a>.
+ * <p>
+ * <em>(Historic Note: Some older JVMs may allow the index of a {@code CONSTANT_NameAndType}
+ * instead of a {@code CONSTANT_InvokeDynamic}.  In earlier, obsolete versions of this API, the
+ * bootstrap method was specified dynamically, in a per-class basis, during class initialization.)</em>
+ *
+ * <h3>constant pool entries for {@code invokedynamic} instructions</h3>
+ * If a constant pool entry has the tag {@code CONSTANT_InvokeDynamic} (decimal 17),
+ * it must contain exactly four more bytes.
+ * The first two bytes after the tag must be an index to a {@code CONSTANT_MethodHandle}
+ * entry, and the second two bytes must be an index to a {@code CONSTANT_NameAndType}.
+ * The first index specifies a bootstrap method used by the associated dynamic call sites.
+ * The second index specifies the method name, argument types, and return type of the dynamic call site.
+ * The structure of such an entry is therefore analogous to a {@code CONSTANT_Methodref},
+ * except that the {@code CONSTANT_Class} reference in a {@code CONSTANT_Methodref} entry
+ * is replaced by a bootstrap method reference.
  *
  * <h3>constant pool entries for {@code MethodType}s</h3>
  * If a constant pool entry has the tag {@code CONSTANT_MethodType} (decimal 16),
- * it must contain exactly two more bytes, which are an index to a {@code CONSTANT_Utf8}
- * entry which represents a method type signature.  The JVM will ensure that on first
- * execution of an {@code ldc} instruction for this entry, a {@link java.dyn.MethodType}
+ * it must contain exactly two more bytes, which must be an index to a {@code CONSTANT_Utf8}
+ * entry which represents a method type signature.
+ * <p>
+ * The JVM will ensure that on first
+ * execution of an {@code ldc} instruction for this entry, a {@link java.dyn.MethodType MethodType}
  * will be created which represents the signature.
  * Any classes mentioned in the {@code MethodType} will be loaded if necessary,
  * but not initialized.
@@ -86,12 +116,15 @@
  * <h3>constant pool entries for {@code MethodHandle}s</h3>
  * If a constant pool entry has the tag {@code CONSTANT_MethodHandle} (decimal 15),
  * it must contain exactly three more bytes.  The first byte after the tag is a subtag
- * value in the range 1 through 9, and the last two are an index to a
+ * value which must be in the range 1 through 9, and the last two must be an index to a
  * {@code CONSTANT_Fieldref}, {@code CONSTANT_Methodref}, or
  * {@code CONSTANT_InterfaceMethodref} entry which represents a field or method
  * for which a method handle is to be created.
+ * Furthermore, the subtag value and the type of the constant index value
+ * must agree according to the table below.
+ * <p>
  * The JVM will ensure that on first execution of an {@code ldc} instruction
- * for this entry, a {@link java.dyn.MethodHandle} will be created which represents
+ * for this entry, a {@link java.dyn.MethodHandle MethodHandle} will be created which represents
  * the field or method reference, according to the specific mode implied by the subtag.
  * <p>
  * As with {@code CONSTANT_Class} and {@code CONSTANT_MethodType} constants,
@@ -126,6 +159,129 @@
  * Method handles for subtags {@code REF_getStatic}, {@code REF_putStatic}, and {@code REF_invokeStatic}
  * may force class initialization on their first invocation, just like the corresponding bytecodes.
  *
+ * <h2><a name="bsm"></a>Bootstrap Methods</h2>
+ * Before the JVM can execute a dynamic call site (an {@code invokedynamic} instruction),
+ * the call site must first be <em>linked</em>.
+ * Linking is accomplished by calling a <em>bootstrap method</em>
+ * which is given the static information content of the call site,
+ * and which must produce a {@link java.dyn.MethodHandle method handle}
+ * that gives the behavior of the call site.
+ * <p>
+ * Each {@code invokedynamic} instruction statically specifies its own
+ * bootstrap method as a constant pool reference.
+ * The constant pool reference also specifies the call site's name and type signature,
+ * just like {@code invokevirtual} and the other invoke instructions.
+ * <p>
+ * Linking starts with resolving the constant pool entry for the
+ * bootstrap method, and resolving a {@link java.dyn.MethodType MethodType} object for
+ * the type signature of the dynamic call site.
+ * This resolution process may trigger class loading.
+ * It may therefore throw an error if a class fails to load.
+ * This error becomes the abnormal termination of the dynamic
+ * call site execution.
+ * Linkage does not trigger class initialization.
+ * <p>
+ * Next, the bootstrap method call is started, with four values being stacked:
+ * <ul>
+ * <li>a {@code MethodHandle}, the resolved bootstrap method itself </li>
+ * <li>a {@code Class}, the <em>caller class</em> in which dynamic call site occurs </li>
+ * <li>a {@code String}, the method name mentioned in the call site </li>
+ * <li>a {@code MethodType}, the resolved type signature of the call </li>
+ * </ul>
+ * The method handle is then applied to the other values as if by
+ * {@linkplain java.dyn.MethodHandle#invokeGeneric the <code>invokeGeneric</code> method}.
+ * The returned result must be a {@link java.dyn.CallSite CallSite}, a {@link java.dyn.MethodHandle MethodHandle},
+ * or another {@link java.dyn.MethodHandleProvider MethodHandleProvider} value.
+ * The method {@linkplain java.dyn.MethodHandleProvider#asMethodHandle asMethodHandle}
+ * is then called on the returned value.  The result of that second
+ * call is the {@code MethodHandle} which becomes the
+ * permanent binding for the dynamic call site.
+ * That method handle's type must be exactly equal to the type
+ * derived from the dynamic call site signature and passed to
+ * the bootstrap method.
+ * <p>
+ * After resolution, the linkage process may fail in a variety of ways.
+ * All failures are reported by an {@link java.dyn.InvokeDynamicBootstrapError InvokeDynamicBootstrapError},
+ * which is thrown as the abnormal termination of the dynamic call
+ * site execution.
+ * The following circumstances will cause this:
+ * <ul>
+ * <li>the bootstrap method invocation completes abnormally </li>
+ * <li>the result from the bootstrap invocation is not a reference to
+ *     an object of type {@link java.dyn.MethodHandleProvider MethodHandleProvider} </li>
+ * <li>the call to {@code asMethodHandle} completes abnormally </li>
+ * <li>the call to {@code asMethodHandle} fails to return a reference to
+ *     an object of type {@link java.dyn.MethodHandle MethodHandle} </li>
+ * <li>the method handle produced by {@code asMethodHandle} does not have
+ *     the expected {@code MethodType} </li>
+ * </ul>
+ * <h3>timing of linkage</h3>
+ * A dynamic call site is linked just before its first execution.
+ * The bootstrap method call implementing the linkage occurs within
+ * a thread that is attempting a first execution.
+ * <p>
+ * If there are several such threads, the JVM picks one thread
+ * and runs the bootstrap method while the others wait for the
+ * invocation to terminate normally or abnormally.
+ * <p>
+ * After a bootstrap method is called and a method handle target
+ * successfully extracted, the JVM attempts to link the instruction
+ * being executed to the target method handle.
+ * This may fail if there has been intervening linkage
+ * or invalidation event for the same instruction.
+ * If such a failure occurs, the dynamic call site must be
+ * re-executed from the beginning, either re-linking it
+ * (if it has been invalidated) or invoking the target
+ * (if it the instruction has been linked by some other means).
+ * <p>
+ * If the instruction is linked successfully, the target method
+ * handle is invoked to complete the instruction execution.
+ * The state of linkage continues until the method containing the
+ * dynamic call site is garbage collected, or the dynamic call site
+ * is invalidated by an explicit request,
+ * such as {@link java.dyn.Linkage#invalidateCallerClass Linkage.invalidateCallerClass}.
+ * <p>
+ * In an application which requires dynamic call sites with individually
+ * mutable behaviors, their bootstrap methods should produce distinct
+ * {@link java.dyn.CallSite CallSite} objects, one for each linkage request.
+ * <p>
+ * If a class containing {@code invokedynamic} instructions
+ * is {@linkplain java.dyn.Linkage#invalidateCallerClass(Class) invalidated},
+ * subsequent execution of those {@code invokedynamic} instructions
+ * will require linking.
+ * It is as if they had never been executed in the first place.
+ * (However, invalidation does not cause constant pool entries to be
+ * resolved a second time.)
+ * <p>
+ * Invalidation events and bootstrap method calls for a particular
+ * dynamic call site are globally ordered relative to each other.
+ * When an invokedynamic instruction is invalidated, if there is
+ * simultaneously a bootstrap method invocation in process
+ * (in the same thread or a different thread), the result
+ * eventually returned must not be used to link the call site.
+ * Put another way, when a call site is invalidated, its
+ * subsequent linkage (if any) must be performed by a bootstrap method
+ * call initiated after the invalidation occurred.
+ * <p>
+ * If several threads simultaneously execute a bootstrap method for a single dynamic
+ * call site, the JVM must choose one target object and installs it visibly to
+ * all threads.  Any other bootstrap method calls are allowed to complete, but their
+ * results are ignored, and their dynamic call site invocations proceed with the originally
+ * chosen target object.
+ * <p>
+ * The JVM is free to duplicate dynamic call sites.
+ * This means that, even if a class contains just one {@code invokedynamic}
+ * instruction, its bootstrap method may be executed several times,
+ * once for each duplicate.  Thus, bootstrap method code should not
+ * assume an exclusive one-to-one correspondence between particular occurrences
+ * of {@code invokedynamic} bytecodes in class files and linkage events.
+ * <p>
+ * In principle, each individual execution of an {@code invokedynamic}
+ * instruction could be deemed (by a conforming implementation) to be a separate
+ * duplicate, requiring its own execution of the bootstrap method.
+ * However, implementations are expected to perform code duplication
+ * (if at all) in order to improve performance, not make it worse.
+ *
  * @author John Rose, JSR 292 EG
  */
 
--- a/jdk/src/share/classes/java/io/ObjectInputStream.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/io/ObjectInputStream.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, 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
@@ -265,7 +265,7 @@
      * object currently being deserialized and descriptor for current class.
      * Null when not during readObject upcall.
      */
-    private CallbackContext curContext;
+    private SerialCallbackContext curContext;
 
     /**
      * Creates an ObjectInputStream that reads from the specified InputStream.
@@ -1798,7 +1798,7 @@
     private void readExternalData(Externalizable obj, ObjectStreamClass desc)
         throws IOException
     {
-        CallbackContext oldContext = curContext;
+        SerialCallbackContext oldContext = curContext;
         curContext = null;
         try {
             boolean blocked = desc.hasBlockExternalData();
@@ -1857,10 +1857,10 @@
                     slotDesc.hasReadObjectMethod() &&
                     handles.lookupException(passHandle) == null)
                 {
-                    CallbackContext oldContext = curContext;
+                    SerialCallbackContext oldContext = curContext;
 
                     try {
-                        curContext = new CallbackContext(obj, slotDesc);
+                        curContext = new SerialCallbackContext(obj, slotDesc);
 
                         bin.setBlockDataMode(true);
                         slotDesc.invokeReadObject(obj, this);
@@ -3505,42 +3505,4 @@
         }
     }
 
-    /**
-     * Context that during upcalls to class-defined readObject methods; holds
-     * object currently being deserialized and descriptor for current class.
-     * This context keeps a boolean state to indicate that defaultReadObject
-     * or readFields has already been invoked with this context or the class's
-     * readObject method has returned; if true, the getObj method throws
-     * NotActiveException.
-     */
-    private static class CallbackContext {
-        private final Object obj;
-        private final ObjectStreamClass desc;
-        private final AtomicBoolean used = new AtomicBoolean();
-
-        public CallbackContext(Object obj, ObjectStreamClass desc) {
-            this.obj = obj;
-            this.desc = desc;
-        }
-
-        public Object getObj() throws NotActiveException {
-            checkAndSetUsed();
-            return obj;
-        }
-
-        public ObjectStreamClass getDesc() {
-            return desc;
-        }
-
-        private void checkAndSetUsed() throws NotActiveException {
-            if (!used.compareAndSet(false, true)) {
-                 throw new NotActiveException(
-                      "not in readObject invocation or fields already read");
-            }
-        }
-
-        public void setUsed() {
-            used.set(true);
-        }
-    }
 }
--- a/jdk/src/share/classes/java/io/ObjectOutputStream.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/io/ObjectOutputStream.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import static java.io.ObjectStreamClass.processQueue;
+import java.io.SerialCallbackContext;
 
 /**
  * An ObjectOutputStream writes primitive data types and graphs of Java objects
@@ -191,10 +192,12 @@
     private boolean enableReplace;
 
     // values below valid only during upcalls to writeObject()/writeExternal()
-    /** object currently being serialized */
-    private Object curObj;
-    /** descriptor for current class (null if in writeExternal()) */
-    private ObjectStreamClass curDesc;
+    /**
+     * Context during upcalls to class-defined writeObject methods; holds
+     * object currently being serialized and descriptor for current class.
+     * Null when not during writeObject upcall.
+     */
+    private SerialCallbackContext curContext;
     /** current PutField object */
     private PutFieldImpl curPut;
 
@@ -426,9 +429,11 @@
      *          <code>OutputStream</code>
      */
     public void defaultWriteObject() throws IOException {
-        if (curObj == null || curDesc == null) {
+        if ( curContext == null ) {
             throw new NotActiveException("not in call to writeObject");
         }
+        Object curObj = curContext.getObj();
+        ObjectStreamClass curDesc = curContext.getDesc();
         bout.setBlockDataMode(false);
         defaultWriteFields(curObj, curDesc);
         bout.setBlockDataMode(true);
@@ -446,9 +451,11 @@
      */
     public ObjectOutputStream.PutField putFields() throws IOException {
         if (curPut == null) {
-            if (curObj == null || curDesc == null) {
+            if (curContext == null) {
                 throw new NotActiveException("not in call to writeObject");
             }
+            Object curObj = curContext.getObj();
+            ObjectStreamClass curDesc = curContext.getDesc();
             curPut = new PutFieldImpl(curDesc);
         }
         return curPut;
@@ -1420,17 +1427,15 @@
      * writeExternal() method.
      */
     private void writeExternalData(Externalizable obj) throws IOException {
-        Object oldObj = curObj;
-        ObjectStreamClass oldDesc = curDesc;
         PutFieldImpl oldPut = curPut;
-        curObj = obj;
-        curDesc = null;
         curPut = null;
 
         if (extendedDebugInfo) {
             debugInfoStack.push("writeExternal data");
         }
+        SerialCallbackContext oldContext = curContext;
         try {
+            curContext = null;
             if (protocol == PROTOCOL_VERSION_1) {
                 obj.writeExternal(this);
             } else {
@@ -1440,13 +1445,12 @@
                 bout.writeByte(TC_ENDBLOCKDATA);
             }
         } finally {
+            curContext = oldContext;
             if (extendedDebugInfo) {
                 debugInfoStack.pop();
             }
         }
 
-        curObj = oldObj;
-        curDesc = oldDesc;
         curPut = oldPut;
     }
 
@@ -1461,12 +1465,9 @@
         for (int i = 0; i < slots.length; i++) {
             ObjectStreamClass slotDesc = slots[i].desc;
             if (slotDesc.hasWriteObjectMethod()) {
-                Object oldObj = curObj;
-                ObjectStreamClass oldDesc = curDesc;
                 PutFieldImpl oldPut = curPut;
-                curObj = obj;
-                curDesc = slotDesc;
                 curPut = null;
+                SerialCallbackContext oldContext = curContext;
 
                 if (extendedDebugInfo) {
                     debugInfoStack.push(
@@ -1474,18 +1475,19 @@
                         slotDesc.getName() + "\")");
                 }
                 try {
+                    curContext = new SerialCallbackContext(obj, slotDesc);
                     bout.setBlockDataMode(true);
                     slotDesc.invokeWriteObject(obj, this);
                     bout.setBlockDataMode(false);
                     bout.writeByte(TC_ENDBLOCKDATA);
                 } finally {
+                    curContext.setUsed();
+                    curContext = oldContext;
                     if (extendedDebugInfo) {
                         debugInfoStack.pop();
                     }
                 }
 
-                curObj = oldObj;
-                curDesc = oldDesc;
                 curPut = oldPut;
             } else {
                 defaultWriteFields(obj, slotDesc);
--- a/jdk/src/share/classes/java/io/ObjectStreamClass.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/io/ObjectStreamClass.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, 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
@@ -1830,8 +1830,10 @@
         private final ObjectStreamField[] fields;
         /** number of primitive fields */
         private final int numPrimFields;
-        /** unsafe field keys */
-        private final long[] keys;
+        /** unsafe field keys for reading fields - may contain dupes */
+        private final long[] readKeys;
+        /** unsafe fields keys for writing fields - no dupes */
+        private final long[] writeKeys;
         /** field data offsets */
         private final int[] offsets;
         /** field type codes */
@@ -1849,16 +1851,22 @@
         FieldReflector(ObjectStreamField[] fields) {
             this.fields = fields;
             int nfields = fields.length;
-            keys = new long[nfields];
+            readKeys = new long[nfields];
+            writeKeys = new long[nfields];
             offsets = new int[nfields];
             typeCodes = new char[nfields];
             ArrayList<Class<?>> typeList = new ArrayList<Class<?>>();
+            Set<Long> usedKeys = new HashSet<Long>();
+
 
             for (int i = 0; i < nfields; i++) {
                 ObjectStreamField f = fields[i];
                 Field rf = f.getField();
-                keys[i] = (rf != null) ?
+                long key = (rf != null) ?
                     unsafe.objectFieldOffset(rf) : Unsafe.INVALID_FIELD_OFFSET;
+                readKeys[i] = key;
+                writeKeys[i] = usedKeys.add(key) ?
+                    key : Unsafe.INVALID_FIELD_OFFSET;
                 offsets[i] = f.getOffset();
                 typeCodes[i] = f.getTypeCode();
                 if (!f.isPrimitive()) {
@@ -1894,7 +1902,7 @@
              * in array should be equal to Unsafe.INVALID_FIELD_OFFSET.
              */
             for (int i = 0; i < numPrimFields; i++) {
-                long key = keys[i];
+                long key = readKeys[i];
                 int off = offsets[i];
                 switch (typeCodes[i]) {
                     case 'Z':
@@ -1945,7 +1953,7 @@
                 throw new NullPointerException();
             }
             for (int i = 0; i < numPrimFields; i++) {
-                long key = keys[i];
+                long key = writeKeys[i];
                 if (key == Unsafe.INVALID_FIELD_OFFSET) {
                     continue;           // discard value
                 }
@@ -2006,7 +2014,7 @@
                 switch (typeCodes[i]) {
                     case 'L':
                     case '[':
-                        vals[offsets[i]] = unsafe.getObject(obj, keys[i]);
+                        vals[offsets[i]] = unsafe.getObject(obj, readKeys[i]);
                         break;
 
                     default:
@@ -2027,7 +2035,7 @@
                 throw new NullPointerException();
             }
             for (int i = numPrimFields; i < fields.length; i++) {
-                long key = keys[i];
+                long key = writeKeys[i];
                 if (key == Unsafe.INVALID_FIELD_OFFSET) {
                     continue;           // discard value
                 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/io/SerialCallbackContext.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,58 @@
+  /*
+   * %W% %E%
+   *
+   * Copyright (c) 2006, 2010  Oracle and/or its affiliates. All rights reserved.
+   * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+   */
+
+  package java.io;
+
+  /**
+   * Context during upcalls from object stream to class-defined
+   * readObject/writeObject methods.
+   * Holds object currently being deserialized and descriptor for current class.
+   *
+   * This context keeps track of the thread it was constructed on, and allows
+   * only a single call of defaultReadObject, readFields, defaultWriteObject
+   * or writeFields which must be invoked on the same thread before the class's
+   * readObject/writeObject method has returned.
+   * If not set to the current thread, the getObj method throws NotActiveException.
+   */
+  final class SerialCallbackContext {
+      private final Object obj;
+      private final ObjectStreamClass desc;
+      /**
+       * Thread this context is in use by.
+       * As this only works in one thread, we do not need to worry about thread-safety.
+       */
+      private Thread thread;
+
+      public SerialCallbackContext(Object obj, ObjectStreamClass desc) {
+          this.obj = obj;
+          this.desc = desc;
+          this.thread = Thread.currentThread();
+      }
+
+      public Object getObj() throws NotActiveException {
+          checkAndSetUsed();
+          return obj;
+      }
+
+      public ObjectStreamClass getDesc() {
+          return desc;
+      }
+
+      private void checkAndSetUsed() throws NotActiveException {
+          if (thread != Thread.currentThread()) {
+               throw new NotActiveException(
+                "not in readObject invocation or fields already read");
+          }
+          thread = null;
+      }
+
+      public void setUsed() {
+          thread = null;
+      }
+  }
+
+
--- a/jdk/src/share/classes/java/lang/AbstractStringBuilder.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/lang/AbstractStringBuilder.java	Wed Jul 05 17:26:57 2017 +0200
@@ -100,7 +100,8 @@
      * @param   minimumCapacity   the minimum desired capacity.
      */
     public void ensureCapacity(int minimumCapacity) {
-        ensureCapacityInternal(minimumCapacity);
+        if (minimumCapacity > 0)
+            ensureCapacityInternal(minimumCapacity);
     }
 
     /**
@@ -108,6 +109,7 @@
      * never synchronized.
      */
     private void ensureCapacityInternal(int minimumCapacity) {
+        // overflow-conscious code
         if (minimumCapacity - value.length > 0)
             expandCapacity(minimumCapacity);
     }
--- a/jdk/src/share/classes/java/lang/ClassLoader.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/lang/ClassLoader.java	Wed Jul 05 17:26:57 2017 +0200
@@ -553,6 +553,13 @@
      *          If either <tt>off</tt> or <tt>len</tt> is negative, or if
      *          <tt>off+len</tt> is greater than <tt>b.length</tt>.
      *
+     * @throws  SecurityException
+     *          If an attempt is made to add this class to a package that
+     *          contains classes that were signed by a different set of
+     *          certificates than this class, or if an attempt is made
+     *          to define a class in a package with a fully-qualified name
+     *          that starts with "{@code java.}".
+     *
      * @see  #loadClass(String, boolean)
      * @see  #resolveClass(Class)
      *
--- a/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -28,9 +28,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.io.InterruptedIOException;
 import java.io.FileDescriptor;
-import java.io.ByteArrayOutputStream;
 
 import sun.net.ConnectionResetException;
 import sun.net.NetHooks;
@@ -58,7 +56,7 @@
     protected int fdUseCount = 0;
 
     /* lock when increment/decrementing fdUseCount */
-    protected Object fdLock = new Object();
+    protected final Object fdLock = new Object();
 
     /* indicates a close is pending on the file descriptor */
     protected boolean closePending = false;
@@ -68,7 +66,7 @@
     private int CONNECTION_RESET_PENDING = 1;
     private int CONNECTION_RESET = 2;
     private int resetState;
-    private Object resetLock = new Object();
+    private final Object resetLock = new Object();
 
     /**
      * Load net library into runtime.
@@ -100,25 +98,24 @@
     protected void connect(String host, int port)
         throws UnknownHostException, IOException
     {
-        IOException pending = null;
+        boolean connected = false;
         try {
             InetAddress address = InetAddress.getByName(host);
             this.port = port;
             this.address = address;
 
-            try {
-                connectToAddress(address, port, timeout);
-                return;
-            } catch (IOException e) {
-                pending = e;
+            connectToAddress(address, port, timeout);
+            connected = true;
+        } finally {
+            if (!connected) {
+                try {
+                    close();
+                } catch (IOException ioe) {
+                    /* Do nothing. If connect threw an exception then
+                       it will be passed up the call stack */
+                }
             }
-        } catch (UnknownHostException e) {
-            pending = e;
         }
-
-        // everything failed
-        close();
-        throw pending;
     }
 
     /**
@@ -151,22 +148,29 @@
      *          SocketAddress subclass not supported by this socket
      * @since 1.4
      */
-    protected void connect(SocketAddress address, int timeout) throws IOException {
-        if (address == null || !(address instanceof InetSocketAddress))
-            throw new IllegalArgumentException("unsupported address type");
-        InetSocketAddress addr = (InetSocketAddress) address;
-        if (addr.isUnresolved())
-            throw new UnknownHostException(addr.getHostName());
-        this.port = addr.getPort();
-        this.address = addr.getAddress();
+    protected void connect(SocketAddress address, int timeout)
+            throws IOException {
+        boolean connected = false;
+        try {
+            if (address == null || !(address instanceof InetSocketAddress))
+                throw new IllegalArgumentException("unsupported address type");
+            InetSocketAddress addr = (InetSocketAddress) address;
+            if (addr.isUnresolved())
+                throw new UnknownHostException(addr.getHostName());
+            this.port = addr.getPort();
+            this.address = addr.getAddress();
 
-        try {
             connectToAddress(this.address, port, timeout);
-            return;
-        } catch (IOException e) {
-            // everything failed
-            close();
-            throw e;
+            connected = true;
+        } finally {
+            if (!connected) {
+                try {
+                    close();
+                } catch (IOException ioe) {
+                    /* Do nothing. If connect threw an exception then
+                       it will be passed up the call stack */
+                }
+            }
         }
     }
 
@@ -311,7 +315,7 @@
             }
         }
         try {
-            FileDescriptor fd = acquireFD();
+            acquireFD();
             try {
                 socketConnect(address, port, timeout);
                 /* socket may have been closed during poll/select */
@@ -370,7 +374,7 @@
      * @param s the connection
      */
     protected void accept(SocketImpl s) throws IOException {
-        FileDescriptor fd = acquireFD();
+        acquireFD();
         try {
             socketAccept(s);
         } finally {
@@ -562,7 +566,6 @@
         close();
     }
 
-
     /*
      * "Acquires" and returns the FileDescriptor for this impl
      *
--- a/jdk/src/share/classes/java/nio/Direct-X-Buffer.java.template	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/nio/Direct-X-Buffer.java.template	Wed Jul 05 17:26:57 2017 +0200
@@ -27,6 +27,7 @@
 
 package java.nio;
 
+import java.io.FileDescriptor;
 import sun.misc.Cleaner;
 import sun.misc.Unsafe;
 import sun.misc.VM;
@@ -114,7 +115,7 @@
     //
     Direct$Type$Buffer$RW$(int cap) {                   // package-private
 #if[rw]
-        super(-1, 0, cap, cap, false);
+        super(-1, 0, cap, cap);
         boolean pa = VM.isDirectMemoryPageAligned();
         int ps = Bits.pageSize();
         long size = Math.max(1L, (long)cap + (pa ? ps : 0));
@@ -145,7 +146,7 @@
     // Invoked only by JNI: NewDirectByteBuffer(void*, long)
     //
     private Direct$Type$Buffer(long addr, int cap) {
-        super(-1, 0, cap, cap, false);
+        super(-1, 0, cap, cap);
         address = addr;
         cleaner = null;
     }
@@ -154,14 +155,17 @@
 
     // For memory-mapped buffers -- invoked by FileChannelImpl via reflection
     //
-    protected Direct$Type$Buffer$RW$(int cap, long addr, Runnable unmapper) {
+    protected Direct$Type$Buffer$RW$(int cap, long addr,
+                                     FileDescriptor fd,
+                                     Runnable unmapper)
+    {
 #if[rw]
-        super(-1, 0, cap, cap, true);
+        super(-1, 0, cap, cap, fd);
         address = addr;
         viewedBuffer = null;
         cleaner = Cleaner.create(this, unmapper);
 #else[rw]
-        super(cap, addr, unmapper);
+        super(cap, addr, fd, unmapper);
 #end[rw]
     }
 
--- a/jdk/src/share/classes/java/nio/MappedByteBuffer.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/nio/MappedByteBuffer.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,6 +25,7 @@
 
 package java.nio;
 
+import java.io.FileDescriptor;
 import sun.misc.Unsafe;
 
 
@@ -71,26 +72,26 @@
     // for optimization purposes, it's easier to do it the other way around.
     // This works because DirectByteBuffer is a package-private class.
 
-    // Volatile to make sure that the finalization thread sees the current
-    // value of this so that a region is not accidentally unmapped again later.
-    volatile boolean isAMappedBuffer;                   // package-private
+    // For mapped buffers, a FileDescriptor that may be used for mapping
+    // operations if valid; null if the buffer is not mapped.
+    private final FileDescriptor fd;
 
     // This should only be invoked by the DirectByteBuffer constructors
     //
     MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private
-                     boolean mapped)
+                     FileDescriptor fd)
     {
         super(mark, pos, lim, cap);
-        isAMappedBuffer = mapped;
+        this.fd = fd;
     }
 
     MappedByteBuffer(int mark, int pos, int lim, int cap) { // package-private
         super(mark, pos, lim, cap);
-        isAMappedBuffer = false;
+        this.fd = null;
     }
 
     private void checkMapped() {
-        if (!isAMappedBuffer)
+        if (fd == null)
             // Can only happen if a luser explicitly casts a direct byte buffer
             throw new UnsupportedOperationException();
     }
@@ -191,13 +192,12 @@
         checkMapped();
         if ((address != 0) && (capacity() != 0)) {
             long offset = mappingOffset();
-            force0(mappingAddress(offset), mappingLength(offset));
+            force0(fd, mappingAddress(offset), mappingLength(offset));
         }
         return this;
     }
 
     private native boolean isLoaded0(long address, long length, int pageCount);
     private native void load0(long address, long length);
-    private native void force0(long address, long length);
-
+    private native void force0(FileDescriptor fd, long address, long length);
 }
--- a/jdk/src/share/classes/java/nio/channels/AsynchronousDatagramChannel.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,572 +0,0 @@
-/*
- * Copyright (c) 2007, 2009, 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.
- */
-
-package java.nio.channels;
-
-import java.nio.channels.spi.*;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.Future;
-import java.io.IOException;
-import java.net.SocketOption;
-import java.net.SocketAddress;
-import java.net.ProtocolFamily;
-import java.nio.ByteBuffer;
-
-/**
- * An asynchronous channel for datagram-oriented sockets.
- *
- * <p> An asynchronous datagram channel is created by invoking one of the {@link
- * #open open} methods defined by this class. It is not possible to create a channel
- * for an arbitrary, pre-existing datagram socket. A newly-created asynchronous
- * datagram channel is open but not connected. It need not be connected in order
- * for the {@link #send send} and {@link #receive receive} methods to be used.
- * A datagram channel may be connected, by invoking its {@link #connect connect}
- * method, in order to avoid the overhead of the security checks that are otherwise
- * performed as part of every send and receive operation when a security manager
- * is set. The channel must be connected in order to use the {@link #read read}
- * and {@link #write write} methods, since those methods do not accept or return
- * socket addresses. Once connected, an asynchronous datagram channel remains
- * connected until it is disconnected or closed.
- *
- * <p> Socket options are configured using the {@link #setOption(SocketOption,Object)
- * setOption} method. An asynchronous datagram channel to an Internet Protocol
- * (IP) socket supports the following options:
- * <blockquote>
- * <table border>
- *   <tr>
- *     <th>Option Name</th>
- *     <th>Description</th>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#SO_SNDBUF SO_SNDBUF} </td>
- *     <td> The size of the socket send buffer </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#SO_RCVBUF SO_RCVBUF} </td>
- *     <td> The size of the socket receive buffer </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} </td>
- *     <td> Re-use address </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#SO_BROADCAST SO_BROADCAST} </td>
- *     <td> Allow transmission of broadcast datagrams </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#IP_TOS IP_TOS} </td>
- *     <td> The Type of Service (ToS) octet in the Internet Protocol (IP) header </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#IP_MULTICAST_IF IP_MULTICAST_IF} </td>
- *     <td> The network interface for Internet Protocol (IP) multicast datagrams </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#IP_MULTICAST_TTL
- *       IP_MULTICAST_TTL} </td>
- *     <td> The <em>time-to-live</em> for Internet Protocol (IP) multicast
- *       datagrams </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#IP_MULTICAST_LOOP
- *       IP_MULTICAST_LOOP} </td>
- *     <td> Loopback for Internet Protocol (IP) multicast datagrams </td>
- *   </tr>
- * </table>
- * </blockquote>
- * Additional (implementation specific) options may also be supported.
- *
- * <p> Asynchronous datagram channels allow more than one read/receive and
- * write/send to be oustanding at any given time.
- *
- * <p> <b>Usage Example:</b>
- * <pre>
- *  final AsynchronousDatagramChannel dc = AsynchronousDatagramChannel.open()
- *      .bind(new InetSocketAddress(4000));
- *
- *  // print the source address of all packets that we receive
- *  dc.receive(buffer, buffer, new CompletionHandler&lt;SocketAddress,ByteBuffer&gt;() {
- *      public void completed(SocketAddress sa, ByteBuffer buffer) {
- *          System.out.println(sa);
- *          buffer.clear();
- *          dc.receive(buffer, buffer, this);
- *      }
- *      public void failed(Throwable exc, ByteBuffer buffer) {
- *          ...
- *      }
- *  });
- * </pre>
- *
- * @since 1.7
- */
-
-public abstract class AsynchronousDatagramChannel
-    implements AsynchronousByteChannel, MulticastChannel
-{
-    private final AsynchronousChannelProvider provider;
-
-    /**
-     * Initializes a new instance of this class.
-     */
-    protected AsynchronousDatagramChannel(AsynchronousChannelProvider provider) {
-        this.provider = provider;
-    }
-
-    /**
-     * Returns the provider that created this channel.
-     */
-    public final AsynchronousChannelProvider provider() {
-        return provider;
-    }
-
-    /**
-     * Opens an asynchronous datagram channel.
-     *
-     * <p> The new channel is created by invoking the {@link
-     * java.nio.channels.spi.AsynchronousChannelProvider#openAsynchronousDatagramChannel
-     * openAsynchronousDatagramChannel} method on the {@link
-     * java.nio.channels.spi.AsynchronousChannelProvider} object that created
-     * the given group (or the default provider where {@code group} is {@code
-     * null}).
-     *
-     * <p> The {@code family} parameter is used to specify the {@link ProtocolFamily}.
-     * If the datagram channel is to be used for Internet Protocol {@link
-     * MulticastChannel multicasting} then this parameter should correspond to
-     * the address type of the multicast groups that this channel will join.
-     *
-     * @param   family
-     *          The protocol family, or {@code null} to use the default protocol
-     *          family
-     * @param   group
-     *          The group to which the newly constructed channel should be bound,
-     *          or {@code null} for the default group
-     *
-     * @return  A new asynchronous datagram channel
-     *
-     * @throws  UnsupportedOperationException
-     *          If the specified protocol family is not supported. For example,
-     *          suppose the parameter is specified as {@link
-     *          java.net.StandardProtocolFamily#INET6 INET6} but IPv6 is not
-     *          enabled on the platform.
-     * @throws  ShutdownChannelGroupException
-     *          The specified group is shutdown
-     * @throws  IOException
-     *          If an I/O error occurs
-     */
-    public static AsynchronousDatagramChannel open(ProtocolFamily family,
-                                                   AsynchronousChannelGroup group)
-        throws IOException
-    {
-        AsynchronousChannelProvider provider = (group == null) ?
-            AsynchronousChannelProvider.provider() : group.provider();
-        return provider.openAsynchronousDatagramChannel(family, group);
-    }
-
-    /**
-     * Opens an asynchronous datagram channel.
-     *
-     * <p> This method returns an asynchronous datagram channel that is
-     * bound to the <em>default group</em>. This method is equivalent to evaluating
-     * the expression:
-     * <blockquote><pre>
-     * open((ProtocolFamily)null,&nbsp;(AsynchronousChannelGroup)null);
-     * </pre></blockquote>
-     *
-     * @return  A new asynchronous datagram channel
-     *
-     * @throws  IOException
-     *          If an I/O error occurs
-     */
-    public static AsynchronousDatagramChannel open()
-        throws IOException
-    {
-        return open(null, null);
-    }
-
-    // -- Socket-specific operations --
-
-    /**
-     * @throws  AlreadyBoundException               {@inheritDoc}
-     * @throws  UnsupportedAddressTypeException     {@inheritDoc}
-     * @throws  ClosedChannelException              {@inheritDoc}
-     * @throws  IOException                         {@inheritDoc}
-     * @throws  SecurityException
-     *          If a security manager has been installed and its {@link
-     *          SecurityManager#checkListen checkListen} method denies the
-     *          operation
-     */
-    @Override
-    public abstract AsynchronousDatagramChannel bind(SocketAddress local)
-        throws IOException;
-
-    /**
-     * @throws  IllegalArgumentException                {@inheritDoc}
-     * @throws  ClosedChannelException                  {@inheritDoc}
-     * @throws  IOException                             {@inheritDoc}
-     */
-    @Override
-    public abstract <T> AsynchronousDatagramChannel setOption(SocketOption<T> name, T value)
-        throws IOException;
-
-    /**
-     * Returns the remote address to which this channel is connected.
-     *
-     * <p> Where the channel is connected to an Internet Protocol socket address
-     * then the return value from this method is of type {@link
-     * java.net.InetSocketAddress}.
-     *
-     * @return  The remote address; {@code null} if the channel's socket is not
-     *          connected
-     *
-     * @throws  ClosedChannelException
-     *          If the channel is closed
-     * @throws  IOException
-     *          If an I/O error occurs
-     */
-    public abstract SocketAddress getRemoteAddress() throws IOException;
-
-    /**
-     * Connects this channel's socket.
-     *
-     * <p> The channel's socket is configured so that it only receives
-     * datagrams from, and sends datagrams to, the given remote <i>peer</i>
-     * address.  Once connected, datagrams may not be received from or sent to
-     * any other address.  A datagram socket remains connected until it is
-     * explicitly disconnected or until it is closed.
-     *
-     * <p> This method performs exactly the same security checks as the {@link
-     * java.net.DatagramSocket#connect connect} method of the {@link
-     * java.net.DatagramSocket} class.  That is, if a security manager has been
-     * installed then this method verifies that its {@link
-     * java.lang.SecurityManager#checkAccept checkAccept} and {@link
-     * java.lang.SecurityManager#checkConnect checkConnect} methods permit
-     * datagrams to be received from and sent to, respectively, the given
-     * remote address.
-     *
-     * <p> This method may be invoked at any time. Whether it has any effect
-     * on outstanding read or write operations is implementation specific and
-     * therefore not specified.
-     *
-     * @param  remote
-     *         The remote address to which this channel is to be connected
-     *
-     * @return  This datagram channel
-     *
-     * @throws  ClosedChannelException
-     *          If this channel is closed
-     *
-     * @throws  SecurityException
-     *          If a security manager has been installed
-     *          and it does not permit access to the given remote address
-     *
-     * @throws  IOException
-     *          If some other I/O error occurs
-     */
-    public abstract AsynchronousDatagramChannel connect(SocketAddress remote)
-        throws IOException;
-
-    /**
-     * Disconnects this channel's socket.
-     *
-     * <p> The channel's socket is configured so that it can receive datagrams
-     * from, and sends datagrams to, any remote address so long as the security
-     * manager, if installed, permits it.
-     *
-     * <p> This method may be invoked at any time. Whether it has any effect
-     * on outstanding read or write operations is implementation specific and
-     * therefore not specified.
-     *
-     * @return  This datagram channel
-     *
-     * @throws  IOException
-     *          If some other I/O error occurs
-     */
-    public abstract AsynchronousDatagramChannel disconnect() throws IOException;
-
-    /**
-     * Receives a datagram via this channel.
-     *
-     * <p> This method initiates the receiving of a datagram into the given
-     * buffer. The {@code handler} parameter is a completion handler that is
-     * invoked when the receive operation completes (or fails). The result
-     * passed to the completion handler is the datagram's source address.
-     *
-     * <p> The datagram is transferred into the given byte buffer starting at
-     * its current position, as if by a regular {@link AsynchronousByteChannel#read
-     * read} operation. If there are fewer bytes remaining in the buffer
-     * than are required to hold the datagram then the remainder of the datagram
-     * is silently discarded.
-     *
-     * <p> If a timeout is specified and the timeout elapses before the operation
-     * completes then the operation completes with the exception {@link
-     * InterruptedByTimeoutException}. When a timeout elapses then the state of
-     * the {@link ByteBuffer} is not defined. The buffers should be discarded or
-     * at least care must be taken to ensure that the buffer is not accessed
-     * while the channel remains open.
-     *
-     * <p> When a security manager has been installed and the channel is not
-     * connected, then it verifies that the source's address and port number are
-     * permitted by the security manager's {@link SecurityManager#checkAccept
-     * checkAccept} method. The permission check is performed with privileges that
-     * are restricted by the calling context of this method. If the permission
-     * check fails then the operation completes with a {@link SecurityException}.
-     * The overhead of this security check can be avoided by first connecting the
-     * socket via the {@link #connect connect} method.
-     *
-     * @param   dst
-     *          The buffer into which the datagram is to be transferred
-     * @param   timeout
-     *          The timeout, or {@code 0L} for no timeout
-     * @param   unit
-     *          The time unit of the {@code timeout} argument
-     * @param   attachment
-     *          The object to attach to the I/O operation; can be {@code null}
-     * @param   handler
-     *          The handler for consuming the result
-     *
-     * @throws  IllegalArgumentException
-     *          If the timeout is negative or the buffer is read-only
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    public abstract <A> void receive(ByteBuffer dst,
-                                     long timeout,
-                                     TimeUnit unit,
-                                     A attachment,
-                                     CompletionHandler<SocketAddress,? super A> handler);
-
-    /**
-     * Receives a datagram via this channel.
-     *
-     * <p> This method initiates the receiving of a datagram into the given
-     * buffer. The {@code handler} parameter is a completion handler that is
-     * invoked when the receive operation completes (or fails). The result
-     * passed to the completion handler is the datagram's source address.
-     *
-     * <p> This method is equivalent to invoking {@link
-     * #receive(ByteBuffer,long,TimeUnit,Object,CompletionHandler)} with a
-     * timeout of {@code 0L}.
-     *
-     * @param   dst
-     *          The buffer into which the datagram is to be transferred
-     * @param   attachment
-     *          The object to attach to the I/O operation; can be {@code null}
-     * @param   handler
-     *          The handler for consuming the result
-     *
-     * @throws  IllegalArgumentException
-     *          If the buffer is read-only
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    public final <A> void receive(ByteBuffer dst,
-                                  A attachment,
-                                  CompletionHandler<SocketAddress,? super A> handler)
-    {
-        receive(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
-    }
-
-    /**
-     * Receives a datagram via this channel.
-     *
-     * <p> This method initiates the receiving of a datagram into the given
-     * buffer. The method behaves in exactly the same manner as the {@link
-     * #receive(ByteBuffer,Object,CompletionHandler)
-     * receive(ByteBuffer,Object,CompletionHandler)} method except that instead
-     * of specifying a completion handler, this method returns a {@code Future}
-     * representing the pending result. The {@code Future}'s {@link Future#get()
-     * get} method returns the datagram's source address.
-     *
-     * @param   dst
-     *          The buffer into which the datagram is to be transferred
-     *
-     * @return  a {@code Future} object representing the pending result
-     *
-     * @throws  IllegalArgumentException
-     *          If the buffer is read-only
-     */
-    public abstract Future<SocketAddress> receive(ByteBuffer dst);
-
-    /**
-     * Sends a datagram via this channel.
-     *
-     * <p> This method initiates sending of a datagram from the given buffer to
-     * the given address. The {@code handler} parameter is a completion handler
-     * that is invoked when the send completes (or fails). The result passed to
-     * the completion handler is the number of bytes sent.
-     *
-     * <p> Otherwise this method works in the same manner as the {@link
-     * AsynchronousByteChannel#write(ByteBuffer,Object,CompletionHandler)}
-     * method.
-     *
-     * @param   src
-     *          The buffer containing the datagram to be sent
-     * @param   target
-     *          The address to which the datagram is to be sent
-     * @param   attachment
-     *          The object to attach to the I/O operation; can be {@code null}
-     * @param   handler
-     *          The handler for consuming the result
-     *
-     * @throws  UnresolvedAddressException
-     *          If the given remote address is not fully resolved
-     * @throws  UnsupportedAddressTypeException
-     *          If the type of the given remote address is not supported
-     * @throws  IllegalArgumentException
-     *          If the channel's socket is connected and is connected to an
-     *          address that is not equal to {@code target}
-     * @throws  SecurityException
-     *          If a security manager has been installed and it does not permit
-     *          datagrams to be sent to the given address
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    public abstract <A> void send(ByteBuffer src,
-                                  SocketAddress target,
-                                  A attachment,
-                                  CompletionHandler<Integer,? super A> handler);
-
-    /**
-     * Sends a datagram via this channel.
-     *
-     * <p> This method initiates sending of a datagram from the given buffer to
-     * the given address. The method behaves in exactly the same manner as the
-     * {@link #send(ByteBuffer,SocketAddress,Object,CompletionHandler)
-     * send(ByteBuffer,SocketAddress,Object,CompletionHandler)} method except
-     * that instead of specifying a completion handler, this method returns a
-     * {@code Future} representing the pending result. The {@code Future}'s
-     * {@link Future#get() get} method returns the number of bytes sent.
-     *
-     * @param   src
-     *          The buffer containing the datagram to be sent
-     * @param   target
-     *          The address to which the datagram is to be sent
-     *
-     * @return  a {@code Future} object representing the pending result
-     *
-     * @throws  UnresolvedAddressException
-     *          If the given remote address is not fully resolved
-     * @throws  UnsupportedAddressTypeException
-     *          If the type of the given remote address is not supported
-     * @throws  IllegalArgumentException
-     *          If the channel's socket is connected and is connected to an
-     *          address that is not equal to {@code target}
-     * @throws  SecurityException
-     *          If a security manager has been installed and it does not permit
-     *          datagrams to be sent to the given address
-     */
-    public abstract Future<Integer> send(ByteBuffer src, SocketAddress target);
-
-    /**
-     * Receives a datagram via this channel.
-     *
-     * <p> This method initiates the receiving of a datagram into the given
-     * buffer. The {@code handler} parameter is a completion handler that is
-     * invoked when the receive operation completes (or fails). The result
-     * passed to the completion handler is number of bytes read.
-     *
-     * <p> This method may only be invoked if this channel is connected, and it
-     * only accepts datagrams from the peer that the channel is connected too.
-     * The datagram is transferred into the given byte buffer starting at
-     * its current position and exactly as specified in the {@link
-     * AsynchronousByteChannel} interface. If there are fewer bytes
-     * remaining in the buffer than are required to hold the datagram then the
-     * remainder of the datagram is silently discarded.
-     *
-     * <p> If a timeout is specified and the timeout elapses before the operation
-     * completes then the operation completes with the exception {@link
-     * InterruptedByTimeoutException}. When a timeout elapses then the state of
-     * the {@link ByteBuffer} is not defined. The buffers should be discarded or
-     * at least care must be taken to ensure that the buffer is not accessed
-     * while the channel remains open.
-     *
-     * @param   dst
-     *          The buffer into which the datagram is to be transferred
-     * @param   timeout
-     *          The timeout, or {@code 0L} for no timeout
-     * @param   unit
-     *          The time unit of the {@code timeout} argument
-     * @param   attachment
-     *          The object to attach to the I/O operation; can be {@code null}
-     * @param   handler
-     *          The handler for consuming the result
-     *
-     * @throws  IllegalArgumentException
-     *          If the timeout is negative or buffer is read-only
-     * @throws  NotYetConnectedException
-     *          If this channel is not connected
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    public abstract <A> void read(ByteBuffer dst,
-                                  long timeout,
-                                  TimeUnit unit,
-                                  A attachment,
-                                  CompletionHandler<Integer,? super A> handler);
-
-    /**
-     * @throws  NotYetConnectedException
-     *          If this channel is not connected
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    @Override
-    public final <A> void read(ByteBuffer dst,
-                               A attachment,
-                               CompletionHandler<Integer,? super A> handler)
-    {
-        read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
-    }
-
-    /**
-     * @throws  NotYetConnectedException
-     *          If this channel is not connected
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    @Override
-    public abstract Future<Integer> read(ByteBuffer dst);
-
-    /**
-     * @throws  NotYetConnectedException
-     *          If this channel is not connected
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    @Override
-    public abstract <A> void  write(ByteBuffer src,
-                                    A attachment,
-                                    CompletionHandler<Integer,? super A> handler);
-
-
-    /**
-     * @throws  NotYetConnectedException
-     *          If this channel is not connected
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    @Override
-    public abstract Future<Integer> write(ByteBuffer src);
-}
--- a/jdk/src/share/classes/java/nio/channels/package-info.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/nio/channels/package-info.java	Wed Jul 05 17:26:57 2017 +0200
@@ -232,8 +232,6 @@
  *     <td>An asynchronous channel to a stream-oriented connecting socket</td></tr>
  * <tr><td valign=top><tt>{@link java.nio.channels.AsynchronousServerSocketChannel}&nbsp;&nbsp;</tt></td>
  *     <td>An asynchronous channel to a stream-oriented listening socket</td></tr>
- * <tr><td valign=top><tt>{@link java.nio.channels.AsynchronousDatagramChannel}</tt></td>
- *     <td>An asynchronous channel to a datagram-oriented socket</td></tr>
  * <tr><td valign=top><tt>{@link java.nio.channels.CompletionHandler}</tt></td>
  *     <td>A handler for consuming the result of an asynchronous operation</td></tr>
  * <tr><td valign=top><tt>{@link java.nio.channels.AsynchronousChannelGroup}</tt></td>
--- a/jdk/src/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java	Wed Jul 05 17:26:57 2017 +0200
@@ -26,7 +26,6 @@
 package java.nio.channels.spi;
 
 import java.nio.channels.*;
-import java.net.ProtocolFamily;
 import java.io.IOException;
 import java.util.Iterator;
 import java.util.ServiceLoader;
@@ -239,26 +238,4 @@
      */
     public abstract AsynchronousSocketChannel openAsynchronousSocketChannel
         (AsynchronousChannelGroup group) throws IOException;
-
-    /**
-     * Opens an asynchronous datagram channel.
-     *
-     * @param   family
-     *          The protocol family, or {@code null} for the default protocol
-     *          family
-     * @param   group
-     *          The group to which the channel is bound, or {@code null} to
-     *          bind to the default group
-     *
-     * @return  The new channel
-     *
-     * @throws  IllegalChannelGroupException
-     *          If the provider that created the group differs from this provider
-     * @throws  ShutdownChannelGroupException
-     *          The group is shutdown
-     * @throws  IOException
-     *          If an I/O error occurs
-     */
-    public abstract AsynchronousDatagramChannel openAsynchronousDatagramChannel
-        (ProtocolFamily family, AsynchronousChannelGroup group) throws IOException;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/security/AlgorithmConstraints.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+package java.security;
+
+import java.util.Set;
+
+/**
+ * This interface specifies constraints for cryptographic algorithms,
+ * keys (key sizes), and other algorithm parameters.
+ * <p>
+ * {@code AlgorithmConstraints} objects are immutable.  An implementation
+ * of this interface should not provide methods that can change the state
+ * of an instance once it has been created.
+ * <p>
+ * Note that {@code AlgorithmConstraints} can be used to represent the
+ * restrictions described by the security properties
+ * {@code jdk.certpath.disabledAlgorithms} and
+ * {@code jdk.tls.disabledAlgorithms}, or could be used by a
+ * concrete {@code PKIXCertPathChecker} to check whether a specified
+ * certificate in the certification path contains the required algorithm
+ * constraints.
+ *
+ * @see javax.net.ssl.SSLParameters#getAlgorithmConstraints
+ * @see javax.net.ssl.SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
+ *
+ * @since 1.7
+ */
+
+public interface AlgorithmConstraints {
+
+    /**
+     * Determines whether an algorithm is granted permission for the
+     * specified cryptographic primitives.
+     *
+     * @param primitives a set of cryptographic primitives
+     * @param algorithm the algorithm name
+     * @param parameters the algorithm parameters, or null if no additional
+     *     parameters
+     *
+     * @return true if the algorithm is permitted and can be used for all
+     *     of the specified cryptographic primitives
+     *
+     * @throws IllegalArgumentException if primitives or algorithm is null
+     *     or empty
+     */
+    public boolean permits(Set<CryptoPrimitive> primitives,
+            String algorithm, AlgorithmParameters parameters);
+
+    /**
+     * Determines whether a key is granted permission for the specified
+     * cryptographic primitives.
+     * <p>
+     * This method is usually used to check key size and key usage.
+     *
+     * @param primitives a set of cryptographic primitives
+     * @param key the key
+     *
+     * @return true if the key can be used for all of the specified
+     *     cryptographic primitives
+     *
+     * @throws IllegalArgumentException if primitives is null or empty,
+     *     or the key is null
+     */
+    public boolean permits(Set<CryptoPrimitive> primitives, Key key);
+
+    /**
+     * Determines whether an algorithm and the corresponding key are granted
+     * permission for the specified cryptographic primitives.
+     *
+     * @param primitives a set of cryptographic primitives
+     * @param algorithm the algorithm name
+     * @param key the key
+     * @param parameters the algorithm parameters, or null if no additional
+     *     parameters
+     *
+     * @return true if the key and the algorithm can be used for all of the
+     *     specified cryptographic primitives
+     *
+     * @throws IllegalArgumentException if primitives or algorithm is null
+     *     or empty, or the key is null
+     */
+    public boolean permits(Set<CryptoPrimitive> primitives,
+                String algorithm, Key key, AlgorithmParameters parameters);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/security/CryptoPrimitive.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+package java.security;
+
+/**
+ * An enumeration of cryptographic primitives.
+ *
+ * @since 1.7
+ */
+public enum CryptoPrimitive {
+    /**
+     * Hash function
+     */
+    MESSAGE_DIGEST,
+
+    /**
+     * Cryptographic random number generator
+     */
+    SECURE_RANDOM,
+
+    /**
+     * Symmetric primitive: block cipher
+     */
+    BLOCK_CIPHER,
+
+    /**
+     * Symmetric primitive: stream cipher
+     */
+    STREAM_CIPHER,
+
+    /**
+     * Symmetric primitive: message authentication code
+     */
+    MAC,
+
+    /**
+     * Symmetric primitive: key wrap
+     */
+    KEY_WRAP,
+
+    /**
+     * Asymmetric primitive: public key encryption
+     */
+    PUBLIC_KEY_ENCRYPTION,
+
+    /**
+     * Asymmetric primitive: signature scheme
+     */
+    SIGNATURE,
+
+    /**
+     * Asymmetric primitive: key encapsulation mechanism
+     */
+    KEY_ENCAPSULATION,
+
+    /**
+     * Asymmetric primitive: key agreement and key distribution
+     */
+    KEY_AGREEMENT
+}
--- a/jdk/src/share/classes/java/text/DateFormatSymbols.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/text/DateFormatSymbols.java	Wed Jul 05 17:26:57 2017 +0200
@@ -44,11 +44,12 @@
 import java.lang.ref.SoftReference;
 import java.text.spi.DateFormatSymbolsProvider;
 import java.util.Arrays;
-import java.util.Hashtable;
 import java.util.List;
 import java.util.Locale;
 import java.util.ResourceBundle;
 import java.util.TimeZone;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.spi.LocaleServiceProvider;
 import sun.util.LocaleServiceProviderPool;
 import sun.util.TimeZoneNameUtility;
@@ -321,20 +322,64 @@
      * @since 1.6
      */
     public static final DateFormatSymbols getInstance(Locale locale) {
+        DateFormatSymbols dfs = getProviderInstance(locale);
+        if (dfs != null) {
+            return dfs;
+        }
+        return (DateFormatSymbols) getCachedInstance(locale).clone();
+    }
+
+    /**
+     * Returns a DateFormatSymbols provided by a provider or found in
+     * the cache. Note that this method returns a cached instance,
+     * not its clone. Therefore, the instance should never be given to
+     * an application.
+     */
+    static final DateFormatSymbols getInstanceRef(Locale locale) {
+        DateFormatSymbols dfs = getProviderInstance(locale);
+        if (dfs != null) {
+            return dfs;
+        }
+        return getCachedInstance(locale);
+    }
+
+    private static DateFormatSymbols getProviderInstance(Locale locale) {
+        DateFormatSymbols providersInstance = null;
 
         // Check whether a provider can provide an implementation that's closer
         // to the requested locale than what the Java runtime itself can provide.
         LocaleServiceProviderPool pool =
             LocaleServiceProviderPool.getPool(DateFormatSymbolsProvider.class);
         if (pool.hasProviders()) {
-            DateFormatSymbols providersInstance = pool.getLocalizedObject(
-                                DateFormatSymbolsGetter.INSTANCE, locale);
-            if (providersInstance != null) {
-                return providersInstance;
+            providersInstance = pool.getLocalizedObject(
+                                    DateFormatSymbolsGetter.INSTANCE, locale);
+        }
+        return providersInstance;
+    }
+
+    /**
+     * Returns a cached DateFormatSymbols if it's found in the
+     * cache. Otherwise, this method returns a newly cached instance
+     * for the given locale.
+     */
+    private static DateFormatSymbols getCachedInstance(Locale locale) {
+        SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
+        DateFormatSymbols dfs = null;
+        if (ref == null || (dfs = ref.get()) == null) {
+            dfs = new DateFormatSymbols(locale);
+            ref = new SoftReference<DateFormatSymbols>(dfs);
+            SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(locale, ref);
+            if (x != null) {
+                DateFormatSymbols y = x.get();
+                if (y != null) {
+                    dfs = y;
+                } else {
+                    // Replace the empty SoftReference with ref.
+                    cachedInstances.put(locale, ref);
+                }
             }
         }
-
-        return new DateFormatSymbols(locale);
+        return dfs;
     }
 
     /**
@@ -597,56 +642,44 @@
     static final int millisPerHour = 60*60*1000;
 
     /**
-     * Cache to hold the FormatData and TimeZoneNames ResourceBundles
-     * of a Locale.
-     */
-    private static Hashtable cachedLocaleData = new Hashtable(3);
-
-    /**
-     * Look up resource data for the desiredLocale in the cache; update the
-     * cache if necessary.
+     * Cache to hold DateFormatSymbols instances per Locale.
      */
-    private static ResourceBundle cacheLookup(Locale desiredLocale) {
-        ResourceBundle rb;
-        SoftReference data
-            = (SoftReference)cachedLocaleData.get(desiredLocale);
-        if (data == null) {
-            rb = LocaleData.getDateFormatData(desiredLocale);
-            data = new SoftReference(rb);
-            cachedLocaleData.put(desiredLocale, data);
-        } else {
-            if ((rb = (ResourceBundle)data.get()) == null) {
-                rb = LocaleData.getDateFormatData(desiredLocale);
-                data = new SoftReference(rb);
-            }
-        }
-        return rb;
-    }
+    private static final ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> cachedInstances
+        = new ConcurrentHashMap<Locale, SoftReference<DateFormatSymbols>>(3);
 
     private void initializeData(Locale desiredLocale) {
-        int i;
-        ResourceBundle resource = cacheLookup(desiredLocale);
+        locale = desiredLocale;
 
-        // FIXME: cache only ResourceBundle. Hence every time, will do
-        // getObject(). This won't be necessary if the Resource itself
-        // is cached.
-        eras = (String[])resource.getObject("Eras");
+        // Copy values of a cached instance if any.
+        SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
+        DateFormatSymbols dfs;
+        if (ref != null && (dfs = ref.get()) != null) {
+            copyMembers(dfs, this);
+            return;
+        }
+
+        // Initialize the fields from the ResourceBundle for locale.
+        ResourceBundle resource = LocaleData.getDateFormatData(locale);
+
+        eras = resource.getStringArray("Eras");
         months = resource.getStringArray("MonthNames");
         shortMonths = resource.getStringArray("MonthAbbreviations");
-        String[] lWeekdays = resource.getStringArray("DayNames");
-        weekdays = new String[8];
-        weekdays[0] = "";  // 1-based
-        for (i=0; i<lWeekdays.length; i++)
-            weekdays[i+1] = lWeekdays[i];
-        String[] sWeekdays = resource.getStringArray("DayAbbreviations");
-        shortWeekdays = new String[8];
-        shortWeekdays[0] = "";  // 1-based
-        for (i=0; i<sWeekdays.length; i++)
-            shortWeekdays[i+1] = sWeekdays[i];
         ampms = resource.getStringArray("AmPmMarkers");
         localPatternChars = resource.getString("DateTimePatternChars");
 
-        locale = desiredLocale;
+        // Day of week names are stored in a 1-based array.
+        weekdays = toOneBasedArray(resource.getStringArray("DayNames"));
+        shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations"));
+    }
+
+    private static String[] toOneBasedArray(String[] src) {
+        int len = src.length;
+        String[] dst = new String[len + 1];
+        dst[0] = "";
+        for (int i = 0; i < len; i++) {
+            dst[i + 1] = src[i];
+        }
+        return dst;
     }
 
     /**
--- a/jdk/src/share/classes/java/text/DecimalFormat.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/text/DecimalFormat.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, 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
@@ -46,9 +46,10 @@
 import java.math.RoundingMode;
 import java.util.ArrayList;
 import java.util.Currency;
-import java.util.Hashtable;
 import java.util.Locale;
 import java.util.ResourceBundle;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 import sun.util.resources.LocaleData;
@@ -394,14 +395,14 @@
     public DecimalFormat() {
         Locale def = Locale.getDefault(Locale.Category.FORMAT);
         // try to get the pattern from the cache
-        String pattern = (String) cachedLocaleData.get(def);
+        String pattern = cachedLocaleData.get(def);
         if (pattern == null) {  /* cache miss */
             // Get the pattern for the default locale.
             ResourceBundle rb = LocaleData.getNumberFormatData(def);
             String[] all = rb.getStringArray("NumberPatterns");
             pattern = all[0];
             /* update cache */
-            cachedLocaleData.put(def, pattern);
+            cachedLocaleData.putIfAbsent(def, pattern);
         }
 
         // Always applyPattern after the symbols are set
@@ -3272,5 +3273,6 @@
     /**
      * Cache to hold the NumberPattern of a Locale.
      */
-    private static Hashtable cachedLocaleData = new Hashtable(3);
+    private static final ConcurrentMap<Locale, String> cachedLocaleData
+        = new ConcurrentHashMap<Locale, String>(3);
 }
--- a/jdk/src/share/classes/java/text/SimpleDateFormat.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/text/SimpleDateFormat.java	Wed Jul 05 17:26:57 2017 +0200
@@ -44,13 +44,14 @@
 import java.util.Calendar;
 import java.util.Date;
 import java.util.GregorianCalendar;
-import java.util.Hashtable;
 import java.util.Locale;
 import java.util.Map;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
 import java.util.SimpleTimeZone;
 import java.util.TimeZone;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import sun.util.calendar.CalendarUtils;
 import sun.util.calendar.ZoneInfoFile;
 import sun.util.resources.LocaleData;
@@ -503,14 +504,14 @@
     /**
      * Cache to hold the DateTimePatterns of a Locale.
      */
-    private static Hashtable<String,String[]> cachedLocaleData
-        = new Hashtable<String,String[]>(3);
+    private static final ConcurrentMap<String, String[]> cachedLocaleData
+        = new ConcurrentHashMap<String, String[]>(3);
 
     /**
      * Cache NumberFormat instances with Locale key.
      */
-    private static Hashtable<Locale,NumberFormat> cachedNumberFormatData
-        = new Hashtable<Locale,NumberFormat>(3);
+    private static final ConcurrentMap<Locale, NumberFormat> cachedNumberFormatData
+        = new ConcurrentHashMap<Locale, NumberFormat>(3);
 
     /**
      * The Locale used to instantiate this
@@ -579,7 +580,7 @@
 
         initializeCalendar(locale);
         this.pattern = pattern;
-        this.formatData = DateFormatSymbols.getInstance(locale);
+        this.formatData = DateFormatSymbols.getInstanceRef(locale);
         this.locale = locale;
         initialize(locale);
     }
@@ -632,9 +633,9 @@
                 dateTimePatterns = r.getStringArray("DateTimePatterns");
             }
             /* update cache */
-            cachedLocaleData.put(key, dateTimePatterns);
+            cachedLocaleData.putIfAbsent(key, dateTimePatterns);
         }
-        formatData = DateFormatSymbols.getInstance(loc);
+        formatData = DateFormatSymbols.getInstanceRef(loc);
         if ((timeStyle >= 0) && (dateStyle >= 0)) {
             Object[] dateTimeArgs = {dateTimePatterns[timeStyle],
                                      dateTimePatterns[dateStyle + 4]};
@@ -665,7 +666,7 @@
             numberFormat.setGroupingUsed(false);
 
             /* update cache */
-            cachedNumberFormatData.put(loc, numberFormat);
+            cachedNumberFormatData.putIfAbsent(loc, numberFormat);
         }
         numberFormat = (NumberFormat) numberFormat.clone();
 
@@ -897,7 +898,7 @@
      * so we can call it from readObject().
      */
     private void initializeDefaultCentury() {
-        calendar.setTime( new Date() );
+        calendar.setTimeInMillis(System.currentTimeMillis());
         calendar.add( Calendar.YEAR, -80 );
         parseAmbiguousDatesAsAfter(calendar.getTime());
     }
@@ -921,7 +922,7 @@
      * @since 1.2
      */
     public void set2DigitYearStart(Date startDate) {
-        parseAmbiguousDatesAsAfter(startDate);
+        parseAmbiguousDatesAsAfter(new Date(startDate.getTime()));
     }
 
     /**
@@ -934,7 +935,7 @@
      * @since 1.2
      */
     public Date get2DigitYearStart() {
-        return defaultCenturyStart;
+        return (Date) defaultCenturyStart.clone();
     }
 
     /**
--- a/jdk/src/share/classes/java/util/ArrayList.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/util/ArrayList.java	Wed Jul 05 17:26:57 2017 +0200
@@ -176,6 +176,11 @@
      * @param minCapacity the desired minimum capacity
      */
     public void ensureCapacity(int minCapacity) {
+        if (minCapacity > 0)
+            ensureCapacityInternal(minCapacity);
+    }
+
+    private void ensureCapacityInternal(int minCapacity) {
         modCount++;
         // overflow-conscious code
         if (minCapacity - elementData.length > 0)
@@ -403,7 +408,7 @@
      * @return <tt>true</tt> (as specified by {@link Collection#add})
      */
     public boolean add(E e) {
-        ensureCapacity(size + 1);  // Increments modCount!!
+        ensureCapacityInternal(size + 1);  // Increments modCount!!
         elementData[size++] = e;
         return true;
     }
@@ -420,7 +425,7 @@
     public void add(int index, E element) {
         rangeCheckForAdd(index);
 
-        ensureCapacity(size + 1);  // Increments modCount!!
+        ensureCapacityInternal(size + 1);  // Increments modCount!!
         System.arraycopy(elementData, index, elementData, index + 1,
                          size - index);
         elementData[index] = element;
@@ -524,7 +529,7 @@
     public boolean addAll(Collection<? extends E> c) {
         Object[] a = c.toArray();
         int numNew = a.length;
-        ensureCapacity(size + numNew);  // Increments modCount
+        ensureCapacityInternal(size + numNew);  // Increments modCount
         System.arraycopy(a, 0, elementData, size, numNew);
         size += numNew;
         return numNew != 0;
@@ -550,7 +555,7 @@
 
         Object[] a = c.toArray();
         int numNew = a.length;
-        ensureCapacity(size + numNew);  // Increments modCount
+        ensureCapacityInternal(size + numNew);  // Increments modCount
 
         int numMoved = size - index;
         if (numMoved > 0)
--- a/jdk/src/share/classes/java/util/Calendar.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/util/Calendar.java	Wed Jul 05 17:26:57 2017 +0200
@@ -51,6 +51,8 @@
 import java.security.ProtectionDomain;
 import java.text.DateFormat;
 import java.text.DateFormatSymbols;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import sun.util.BuddhistCalendar;
 import sun.util.calendar.ZoneInfo;
 import sun.util.resources.LocaleData;
@@ -837,7 +839,8 @@
      * Cache to hold the firstDayOfWeek and minimalDaysInFirstWeek
      * of a Locale.
      */
-    private static Hashtable<Locale, int[]> cachedLocaleData = new Hashtable<Locale, int[]>(3);
+    private static final ConcurrentMap<Locale, int[]> cachedLocaleData
+        = new ConcurrentHashMap<Locale, int[]>(3);
 
     // Special values of stamp[]
     /**
@@ -1022,7 +1025,7 @@
             // returns a BuddhistCalendar instance.
             if ("th".equals(aLocale.getLanguage())
                     && ("TH".equals(aLocale.getCountry()))) {
-                    cal = new BuddhistCalendar(zone, aLocale);
+                cal = new BuddhistCalendar(zone, aLocale);
             } else {
                 cal = new GregorianCalendar(zone, aLocale);
             }
@@ -2588,7 +2591,7 @@
             data = new int[2];
             data[0] = Integer.parseInt(bundle.getString("firstDayOfWeek"));
             data[1] = Integer.parseInt(bundle.getString("minimalDaysInFirstWeek"));
-            cachedLocaleData.put(desiredLocale, data);
+            cachedLocaleData.putIfAbsent(desiredLocale, data);
         }
         firstDayOfWeek = data[0];
         minimalDaysInFirstWeek = data[1];
--- a/jdk/src/share/classes/java/util/Locale.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/util/Locale.java	Wed Jul 05 17:26:57 2017 +0200
@@ -758,7 +758,7 @@
     }
 
     private static void initDefault() {
-        String language, region, country, variant;
+        String language, region, script, country, variant;
         language = AccessController.doPrivileged(
             new GetPropertyAction("user.language", "en"));
         // for compatibility, check for old user.region property
@@ -774,43 +774,41 @@
                 country = region;
                 variant = "";
             }
+            script = "";
         } else {
+            script = AccessController.doPrivileged(
+                new GetPropertyAction("user.script", ""));
             country = AccessController.doPrivileged(
                 new GetPropertyAction("user.country", ""));
             variant = AccessController.doPrivileged(
                 new GetPropertyAction("user.variant", ""));
         }
-        defaultLocale = getInstance(language, country, variant);
+        defaultLocale = getInstance(language, script, country, variant, null);
     }
 
     private static void initDefault(Locale.Category category) {
-        String language, region, country, variant;
+        // make sure defaultLocale is initialized
+        if (defaultLocale == null) {
+            initDefault();
+        }
+
+        Locale defaultCategoryLocale = getInstance(
+            AccessController.doPrivileged(
+                new GetPropertyAction(category.languageKey, defaultLocale.getLanguage())),
+            AccessController.doPrivileged(
+                new GetPropertyAction(category.scriptKey, defaultLocale.getScript())),
+            AccessController.doPrivileged(
+                new GetPropertyAction(category.countryKey, defaultLocale.getCountry())),
+            AccessController.doPrivileged(
+                new GetPropertyAction(category.variantKey, defaultLocale.getVariant())),
+            null);
+
         switch (category) {
         case DISPLAY:
-            language = AccessController.doPrivileged(
-                new GetPropertyAction("user.language.display", ""));
-            if ("".equals(language)) {
-                defaultDisplayLocale = getDefault();
-            } else {
-                country = AccessController.doPrivileged(
-                    new GetPropertyAction("user.country.display", ""));
-                variant = AccessController.doPrivileged(
-                    new GetPropertyAction("user.variant.display", ""));
-                defaultDisplayLocale = getInstance(language, country, variant);
-            }
+            defaultDisplayLocale = defaultCategoryLocale;
             break;
         case FORMAT:
-            language = AccessController.doPrivileged(
-                new GetPropertyAction("user.language.format", ""));
-            if ("".equals(language)) {
-                defaultFormatLocale = getDefault();
-            } else {
-                country = AccessController.doPrivileged(
-                    new GetPropertyAction("user.country.format", ""));
-                variant = AccessController.doPrivileged(
-                    new GetPropertyAction("user.variant.format", ""));
-                defaultFormatLocale = getInstance(language, country, variant);
-            }
+            defaultFormatLocale = defaultCategoryLocale;
             break;
         }
     }
@@ -2124,13 +2122,31 @@
          * Category used to represent the default locale for
          * displaying user interfaces.
          */
-        DISPLAY,
+        DISPLAY("user.language.display",
+                "user.script.display",
+                "user.country.display",
+                "user.variant.display"),
 
         /**
          * Category used to represent the default locale for
          * formatting dates, numbers, and/or currencies.
          */
-        FORMAT,
+        FORMAT("user.language.format",
+               "user.script.format",
+               "user.country.format",
+               "user.variant.format");
+
+        Category(String languageKey, String scriptKey, String countryKey, String variantKey) {
+            this.languageKey = languageKey;
+            this.scriptKey = scriptKey;
+            this.countryKey = countryKey;
+            this.variantKey = variantKey;
+        }
+
+        final String languageKey;
+        final String scriptKey;
+        final String countryKey;
+        final String variantKey;
     }
 
     /**
--- a/jdk/src/share/classes/java/util/TimeZone.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/util/TimeZone.java	Wed Jul 05 17:26:57 2017 +0200
@@ -160,11 +160,6 @@
     private static final int ONE_HOUR   = 60*ONE_MINUTE;
     private static final int ONE_DAY    = 24*ONE_HOUR;
 
-    /**
-     * Cache to hold the SimpleDateFormat objects for a Locale.
-     */
-    private static Hashtable cachedLocaleData = new Hashtable(3);
-
     // Proclaim serialization compatibility with JDK 1.1
     static final long serialVersionUID = 3581463369166924961L;
 
--- a/jdk/src/share/classes/java/util/Vector.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/util/Vector.java	Wed Jul 05 17:26:57 2017 +0200
@@ -222,8 +222,10 @@
      * @param minCapacity the desired minimum capacity
      */
     public synchronized void ensureCapacity(int minCapacity) {
-        modCount++;
-        ensureCapacityHelper(minCapacity);
+        if (minCapacity > 0) {
+            modCount++;
+            ensureCapacityHelper(minCapacity);
+        }
     }
 
     /**
--- a/jdk/src/share/classes/java/util/logging/LogRecord.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/java/util/logging/LogRecord.java	Wed Jul 05 17:26:57 2017 +0200
@@ -529,8 +529,6 @@
         Throwable throwable = new Throwable();
         int depth = access.getStackTraceDepth(throwable);
 
-        String logClassName = "java.util.logging.Logger";
-        String plogClassName = "sun.util.logging.PlatformLogger";
         boolean lookingForLogger = true;
         for (int ix = 0; ix < depth; ix++) {
             // Calling getStackTraceElement directly prevents the VM
@@ -538,13 +536,14 @@
             StackTraceElement frame =
                 access.getStackTraceElement(throwable, ix);
             String cname = frame.getClassName();
+            boolean isLoggerImpl = isLoggerImplFrame(cname);
             if (lookingForLogger) {
                 // Skip all frames until we have found the first logger frame.
-                if (cname.equals(logClassName) || cname.startsWith(plogClassName)) {
+                if (isLoggerImpl) {
                     lookingForLogger = false;
                 }
             } else {
-                if (!cname.equals(logClassName) && !cname.startsWith(plogClassName)) {
+                if (!isLoggerImpl) {
                     // skip reflection call
                     if (!cname.startsWith("java.lang.reflect.") && !cname.startsWith("sun.reflect.")) {
                        // We've found the relevant frame.
@@ -558,4 +557,11 @@
         // We haven't found a suitable frame, so just punt.  This is
         // OK as we are only committed to making a "best effort" here.
     }
+
+    private boolean isLoggerImplFrame(String cname) {
+        // the log record could be created for a platform logger
+        return (cname.equals("java.util.logging.Logger") ||
+                cname.startsWith("java.util.logging.LoggingProxyImpl") ||
+                cname.startsWith("sun.util.logging."));
+    }
 }
--- a/jdk/src/share/classes/javax/management/ObjectName.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/management/ObjectName.java	Wed Jul 05 17:26:57 2017 +0200
@@ -211,8 +211,8 @@
  * reverse DNS name of the organization that specifies the MBeans,
  * followed by a period and a string whose interpretation is
  * determined by that organization.  For example, MBeans specified by
- * Sun Microsystems Inc., DNS name <code>sun.com</code>, would have
- * domains such as <code>com.sun.MyDomain</code>.  This is essentially
+ * <code>example.com</code>  would have
+ * domains such as <code>com.example.MyDomain</code>.  This is essentially
  * the same convention as for Java-language package names.</p>
  *
  * <p>The <b>serialVersionUID</b> of this class is <code>1081892073854801359L</code>.
--- a/jdk/src/share/classes/javax/management/build.xml	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/management/build.xml	Wed Jul 05 17:26:57 2017 +0200
@@ -35,18 +35,18 @@
      . Please also read the important comment on basedir definition below.
  -->
 
-<project name="JMX API Version 1.4 - Java SE 6 implementation" 
-	 default="jar" 
-	 basedir="../../../../.." 
+<project name="JMX API Version 1.4 - Java SE 6 implementation"
+	 default="jar"
+	 basedir="../../../../.."
 	 >
 
-    <!-- IMPORTANT: BASEDIR DEFINITION  
-         This file is assumed to be in: 
-         <src_bundle_dir>/j2se/src/share/classes/javax/management 
-         Thus the basedir for this project is defined above as: 
-         basedir="../../../../.."  
+    <!-- IMPORTANT: BASEDIR DEFINITION
+         This file is assumed to be in:
+         <src_bundle_dir>/j2se/src/share/classes/javax/management
+         Thus the basedir for this project is defined above as:
+         basedir="../../../../.."
          in order to be the parent dir of src subdir.
-	 Result of the build will be placed in ${basedir}/build_jmx 
+	 Result of the build will be placed in ${basedir}/build_jmx
 	 as defined by ${dir.build} property below.
      -->
 
@@ -163,14 +163,14 @@
         <echo message="   BUILD_DATE                  = ${BUILD_DATE}" />
 
     </target>
-    
+
 
 
     <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
     <!-- Call classes subtargets and rmic stubs generation -->
 
-    <target name="classes" depends="init,classes-javac,classes-rmic" 
-	    description="Call classes subtargets and rmic stubs generation" 
+    <target name="classes" depends="init,classes-javac,classes-rmic"
+	    description="Call classes subtargets and rmic stubs generation"
     />
 
 
@@ -183,13 +183,13 @@
         <mkdir dir="${dir.build.classes}" />
 
 	<javac 	srcdir="${dir.src}"
-		destdir="${dir.build.classes}" 
+		destdir="${dir.build.classes}"
 		source="${flag.javac.source}"
 		debug="${flag.debug}"
 		debuglevel="${flag.debug.level}"
 		optimize="${flag.optimize}"
 		includeAntRuntime="no"
-		includeJavaRuntime="no"	
+		includeJavaRuntime="no"
 	        >
 	    <include name="javax/management/**"/>
 	    <include name="com/sun/jmx/**"/>
@@ -253,7 +253,7 @@
 
        <mkdir dir="${dir.build.lib}" />
 
-       <jar jarfile="${dir.build.lib}/jmx.jar" 
+       <jar jarfile="${dir.build.lib}/jmx.jar"
 	    update="true"
 	    >
 
@@ -269,10 +269,10 @@
 		    <attribute name="Sealed"                 value="true" />
 		    <attribute name="Specification-Title"    value="JMX(TM) API" />
 		    <attribute name="Specification-Version"  value="1.4" />
-		    <attribute name="Specification-Vendor"   value="Sun Microsystems, Inc." />
+		    <attribute name="Specification-Vendor"   value="Oracle Corporation" />
 		    <attribute name="Implementation-Title"   value="JMX(TM) API, Java SE 6 implementation" />
-		    <attribute name="Implementation-Version" value="${BUILD_DATE} rebuild of Mustang JMX sources" /> 
-		    <attribute name="Implementation-Vendor"  value="Source bundle from Sun Microsystems, Inc. - Customer rebuilt" />
+		    <attribute name="Implementation-Version" value="${BUILD_DATE} rebuild of Java SE JMX sources" />
+		    <attribute name="Implementation-Vendor"  value="Source bundle from Oracle Corporation - Customer rebuilt" />
 		</section>
 	    </manifest>
        </jar>
@@ -295,16 +295,16 @@
     <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
     <!-- Delete build directory and all its contents -->
 
-    <target name="clean-all" 
+    <target name="clean-all"
             description="Delete build directory and all its contents" >
         <delete dir="${dir.build}" />
-    </target>               
-        
-  
+    </target>
+
+
     <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
     <!-- Clean all and build everything -->
 
-    <target name="all" depends="clean-all,jar" 
+    <target name="all" depends="clean-all,jar"
 	    description="Clean all and build everything" />
 
 
--- a/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java	Wed Jul 05 17:26:57 2017 +0200
@@ -92,8 +92,6 @@
  * @since 1.5
  */
 
-// Sun Microsystems, Sept. 2002: Revisited for JMX 1.2 (DF)
-//
 @SuppressWarnings("serial")  // serialVersionUID is not constant
 public class ModelMBeanNotificationInfo
     extends MBeanNotificationInfo
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/javax/net/ssl/ExtendedSSLSession.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+package javax.net.ssl;
+
+/**
+ * Extends the <code>SSLSession</code> interface to support additional
+ * session attributes.
+ *
+ * @since 1.7
+ */
+public abstract class ExtendedSSLSession implements SSLSession {
+    /**
+     * Obtains an array of supported signature algorithms that the local side
+     * is willing to use.
+     * <p>
+     * Note: this method is used to indicate to the peer which signature
+     * algorithms may be used for digital signatures in TLS 1.2. It is
+     * not meaningful for TLS versions prior to 1.2.
+     * <p>
+     * The signature algorithm name must be a standard Java Security
+     * name (such as "SHA1withRSA", "SHA256withECDSA", and so on).
+     * See Appendix A in the <a href=
+     * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+     * Java Cryptography Architecture API Specification &amp; Reference </a>
+     * for information about standard algorithm names.
+     * <p>
+     * Note: the local supported signature algorithms should conform to
+     * the algorithm constraints specified by
+     * {@link SSLParameters#getAlgorithmConstraints getAlgorithmConstraints()}
+     * method in <code>SSLParameters</code>.
+     *
+     * @return An array of supported signature algorithms, in descending
+     *     order of preference.  The return value is an empty array if
+     *     no signature algorithm is supported.
+     *
+     * @see SSLParameters#getAlgorithmConstraints
+     */
+    public abstract String[] getLocalSupportedSignatureAlgorithms();
+
+    /**
+     * Obtains an array of supported signature algorithms that the peer is
+     * able to use.
+     * <p>
+     * Note: this method is used to indicate to the local side which signature
+     * algorithms may be used for digital signatures in TLS 1.2. It is
+     * not meaningful for TLS versions prior to 1.2.
+     * <p>
+     * The signature algorithm name must be a standard Java Security
+     * name (such as "SHA1withRSA", "SHA256withECDSA", and so on).
+     * See Appendix A in the <a href=
+     * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+     * Java Cryptography Architecture API Specification &amp; Reference </a>
+     * for information about standard algorithm names.
+     *
+     * @return An array of supported signature algorithms, in descending
+     *     order of preference.  The return value is an empty array if
+     *     the peer has not sent the supported signature algorithms.
+     *
+     * @see X509KeyManager
+     * @see X509ExtendedKeyManager
+     */
+    public abstract String[] getPeerSupportedSignatureAlgorithms();
+}
--- a/jdk/src/share/classes/javax/net/ssl/HttpsURLConnection.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/net/ssl/HttpsURLConnection.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, 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
@@ -188,19 +188,8 @@
      * <p>
      * The default implementation will deny such connections.
      */
-    private static HostnameVerifier defaultHostnameVerifier;
-
-    /**
-     * Initialize the default <code>HostnameVerifier</code>.
-     */
-    static {
-        try {
-            defaultHostnameVerifier =
-                new sun.net.www.protocol.https.DefaultHostnameVerifier();
-        } catch (NoClassDefFoundError e) {
-            defaultHostnameVerifier = new DefaultHostnameVerifier();
-        }
-    }
+    private static HostnameVerifier defaultHostnameVerifier =
+                                        new DefaultHostnameVerifier();
 
     /*
      * The initial default <code>HostnameVerifier</code>.  Should be
--- a/jdk/src/share/classes/javax/net/ssl/SSLEngine.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/net/ssl/SSLEngine.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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
@@ -968,6 +968,47 @@
 
 
     /**
+     * Returns the {@code SSLSession} being constructed during a SSL/TLS
+     * handshake.
+     * <p>
+     * TLS protocols may negotiate parameters that are needed when using
+     * an instance of this class, but before the {@code SSLSession} has
+     * been completely initialized and made available via {@code getSession}.
+     * For example, the list of valid signature algorithms may restrict
+     * the type of certificates that can used during TrustManager
+     * decisions, or the maximum TLS fragment packet sizes can be
+     * resized to better support the network environment.
+     * <p>
+     * This method provides early access to the {@code SSLSession} being
+     * constructed.  Depending on how far the handshake has progressed,
+     * some data may not yet be available for use.  For example, if a
+     * remote server will be sending a Certificate chain, but that chain
+     * has yet not been processed, the {@code getPeerCertificates}
+     * method of {@code SSLSession} will throw a
+     * SSLPeerUnverifiedException.  Once that chain has been processed,
+     * {@code getPeerCertificates} will return the proper value.
+     *
+     * @see SSLSocket
+     * @see SSLSession
+     * @see ExtendedSSLSession
+     * @see X509ExtendedKeyManager
+     * @see X509ExtendedTrustManager
+     *
+     * @return null if this instance is not currently handshaking, or
+     *         if the current handshake has not progressed far enough to
+     *         create a basic SSLSession.  Otherwise, this method returns the
+     *         {@code SSLSession} currently being negotiated.
+     * @throws UnsupportedOperationException if the underlying provider
+     *         does not implement the operation.
+     *
+     * @since 1.7
+     */
+    public SSLSession getHandshakeSession() {
+        throw new UnsupportedOperationException();
+    }
+
+
+    /**
      * Initiates handshaking (initial or renegotiation) on this SSLEngine.
      * <P>
      * This method is not needed for the initial handshake, as the
--- a/jdk/src/share/classes/javax/net/ssl/SSLParameters.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/net/ssl/SSLParameters.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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,24 +25,29 @@
 
 package javax.net.ssl;
 
+import java.security.AlgorithmConstraints;
+
 /**
  * Encapsulates parameters for an SSL/TLS connection. The parameters
  * are the list of ciphersuites to be accepted in an SSL/TLS handshake,
- * the list of protocols to be allowed, and whether SSL/TLS servers should
- * request or require client authentication.
- *
- * <p>SSLParameters can be created via the constructors in this class.
+ * the list of protocols to be allowed, the endpoint identification
+ * algorithm during SSL/TLS handshaking, the algorithm constraints and
+ * whether SSL/TLS servers should request or require client authentication.
+ * <p>
+ * SSLParameters can be created via the constructors in this class.
  * Objects can also be obtained using the <code>getSSLParameters()</code>
  * methods in
  * {@link SSLSocket#getSSLParameters SSLSocket} and
+ * {@link SSLServerSocket#getSSLParameters SSLServerSocket} and
  * {@link SSLEngine#getSSLParameters SSLEngine} or the
  * {@link SSLContext#getDefaultSSLParameters getDefaultSSLParameters()} and
  * {@link SSLContext#getSupportedSSLParameters getSupportedSSLParameters()}
  * methods in <code>SSLContext</code>.
- *
- * <P>SSLParameters can be applied to a connection via the methods
+ * <p>
+ * SSLParameters can be applied to a connection via the methods
  * {@link SSLSocket#setSSLParameters SSLSocket.setSSLParameters()} and
- * {@link SSLEngine#setSSLParameters SSLEngine.getSSLParameters()}.
+ * {@link SSLServerSocket#setSSLParameters SSLServerSocket.setSSLParameters()}
+ * and {@link SSLEngine#setSSLParameters SSLEngine.getSSLParameters()}.
  *
  * @see SSLSocket
  * @see SSLEngine
@@ -56,11 +61,13 @@
     private String[] protocols;
     private boolean wantClientAuth;
     private boolean needClientAuth;
+    private String identificationAlgorithm;
+    private AlgorithmConstraints algorithmConstraints;
 
     /**
      * Constructs SSLParameters.
-     *
-     * <p>The cipherSuites and protocols values are set to <code>null</code>,
+     * <p>
+     * The cipherSuites and protocols values are set to <code>null</code>,
      * wantClientAuth and needClientAuth are set to <code>false</code>.
      */
     public SSLParameters() {
@@ -69,6 +76,7 @@
 
     /**
      * Constructs SSLParameters from the specified array of ciphersuites.
+     * <p>
      * Calling this constructor is equivalent to calling the no-args
      * constructor followed by
      * <code>setCipherSuites(cipherSuites);</code>.
@@ -82,6 +90,7 @@
     /**
      * Constructs SSLParameters from the specified array of ciphersuites
      * and protocols.
+     * <p>
      * Calling this constructor is equivalent to calling the no-args
      * constructor followed by
      * <code>setCipherSuites(cipherSuites); setProtocols(protocols);</code>.
@@ -178,4 +187,71 @@
         this.needClientAuth = needClientAuth;
     }
 
+    /**
+     * Returns the cryptographic algorithm constraints.
+     *
+     * @return the cryptographic algorithm constraints, or null if the
+     *     constraints have not been set
+     *
+     * @see #setAlgorithmConstraints(AlgorithmConstraints)
+     *
+     * @since 1.7
+     */
+    public AlgorithmConstraints getAlgorithmConstraints() {
+        return algorithmConstraints;
+    }
+
+    /**
+     * Sets the cryptographic algorithm constraints, which will be used
+     * in addition to any configured by the runtime environment.
+     * <p>
+     * If the <code>constraints</code> parameter is non-null, every
+     * cryptographic algorithm, key and algorithm parameters used in the
+     * SSL/TLS handshake must be permitted by the constraints.
+     *
+     * @param constraints the algorithm constraints (or null)
+     *
+     * @since 1.7
+     */
+    public void setAlgorithmConstraints(AlgorithmConstraints constraints) {
+        // the constraints object is immutable
+        this.algorithmConstraints = constraints;
+    }
+
+    /**
+     * Gets the endpoint identification algorithm.
+     *
+     * @return the endpoint identification algorithm, or null if none
+     * has been set.
+     *
+     * @see X509ExtendedTrustManager
+     * @see #setEndpointIdentificationAlgorithm(String)
+     *
+     * @since 1.7
+     */
+    public String getEndpointIdentificationAlgorithm() {
+        return identificationAlgorithm;
+    }
+
+    /**
+     * Sets the endpoint identification algorithm.
+     * <p>
+     * If the <code>algorithm</code> parameter is non-null or non-empty, the
+     * endpoint identification/verification procedures must be handled during
+     * SSL/TLS handshaking.  This is to prevent man-in-the-middle attacks.
+     *
+     * @param algorithm The standard string name of the endpoint
+     *     identification algorithm (or null).  See Appendix A in the <a href=
+     *     "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+     *     Java Cryptography Architecture API Specification &amp; Reference </a>
+     *     for information about standard algorithm names.
+     *
+     * @see X509ExtendedTrustManager
+     *
+     * @since 1.7
+     */
+    public void setEndpointIdentificationAlgorithm(String algorithm) {
+        this.identificationAlgorithm = algorithm;
+    }
+
 }
--- a/jdk/src/share/classes/javax/net/ssl/SSLServerSocket.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/net/ssl/SSLServerSocket.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,8 +56,8 @@
  * @since 1.4
  * @author David Brownell
  */
-public abstract class SSLServerSocket extends ServerSocket
-{
+public abstract class SSLServerSocket extends ServerSocket {
+
     /**
      * Used only by subclasses.
      * <P>
@@ -449,8 +449,79 @@
      *
      * @return true indicates that sessions may be created; this
      *          is the default.  false indicates that an existing
-     *          session must be resumed.
+     *          session must be resumed
      * @see #setEnableSessionCreation(boolean)
      */
     public abstract boolean getEnableSessionCreation();
+
+    /**
+     * Returns the SSLParameters in effect for newly accepted connections.
+     * The ciphersuites and protocols of the returned SSLParameters
+     * are always non-null.
+     *
+     * @return the SSLParameters in effect for newly accepted connections
+     *
+     * @see #setSSLParameters(SSLParameters)
+     *
+     * @since 1.7
+     */
+    public SSLParameters getSSLParameters() {
+        SSLParameters parameters = new SSLParameters();
+
+        parameters.setCipherSuites(getEnabledCipherSuites());
+        parameters.setProtocols(getEnabledProtocols());
+        if (getNeedClientAuth()) {
+            parameters.setNeedClientAuth(true);
+        } else if (getWantClientAuth()) {
+            parameters.setWantClientAuth(true);
+        }
+
+        return parameters;
+    }
+
+    /**
+     * Applies SSLParameters to newly accepted connections.
+     *
+     * <p>This means:
+     * <ul>
+     * <li>if <code>params.getCipherSuites()</code> is non-null,
+     *   <code>setEnabledCipherSuites()</code> is called with that value
+     * <li>if <code>params.getProtocols()</code> is non-null,
+     *   <code>setEnabledProtocols()</code> is called with that value
+     * <li>if <code>params.getNeedClientAuth()</code> or
+     *   <code>params.getWantClientAuth()</code> return <code>true</code>,
+     *   <code>setNeedClientAuth(true)</code> and
+     *   <code>setWantClientAuth(true)</code> are called, respectively;
+     *   otherwise <code>setWantClientAuth(false)</code> is called.
+     * </ul>
+     *
+     * @param params the parameters
+     * @throws IllegalArgumentException if the setEnabledCipherSuites() or
+     *    the setEnabledProtocols() call fails
+     *
+     * @see #getSSLParameters()
+     *
+     * @since 1.7
+     */
+    public void setSSLParameters(SSLParameters params) {
+        String[] s;
+        s = params.getCipherSuites();
+        if (s != null) {
+            setEnabledCipherSuites(s);
+        }
+
+        s = params.getProtocols();
+        if (s != null) {
+            setEnabledProtocols(s);
+        }
+
+        if (params.getNeedClientAuth()) {
+            setNeedClientAuth(true);
+        } else if (params.getWantClientAuth()) {
+            setWantClientAuth(true);
+        } else {
+            setWantClientAuth(false);
+        }
+    }
+
 }
--- a/jdk/src/share/classes/javax/net/ssl/SSLSocket.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/net/ssl/SSLSocket.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -371,6 +371,51 @@
 
 
     /**
+     * Returns the {@code SSLSession} being constructed during a SSL/TLS
+     * handshake.
+     * <p>
+     * TLS protocols may negotiate parameters that are needed when using
+     * an instance of this class, but before the {@code SSLSession} has
+     * been completely initialized and made available via {@code getSession}.
+     * For example, the list of valid signature algorithms may restrict
+     * the type of certificates that can used during TrustManager
+     * decisions, or the maximum TLS fragment packet sizes can be
+     * resized to better support the network environment.
+     * <p>
+     * This method provides early access to the {@code SSLSession} being
+     * constructed.  Depending on how far the handshake has progressed,
+     * some data may not yet be available for use.  For example, if a
+     * remote server will be sending a Certificate chain, but that chain
+     * has yet not been processed, the {@code getPeerCertificates}
+     * method of {@code SSLSession} will throw a
+     * SSLPeerUnverifiedException.  Once that chain has been processed,
+     * {@code getPeerCertificates} will return the proper value.
+     * <p>
+     * Unlike {@link #getSession()}, this method does not initiate the
+     * initial handshake and does not block until handshaking is
+     * complete.
+     *
+     * @see SSLEngine
+     * @see SSLSession
+     * @see ExtendedSSLSession
+     * @see X509ExtendedKeyManager
+     * @see X509ExtendedTrustManager
+     *
+     * @return null if this instance is not currently handshaking, or
+     *         if the current handshake has not progressed far enough to
+     *         create a basic SSLSession.  Otherwise, this method returns the
+     *         {@code SSLSession} currently being negotiated.
+     * @throws UnsupportedOperationException if the underlying provider
+     *         does not implement the operation.
+     *
+     * @since 1.7
+     */
+    public SSLSession getHandshakeSession() {
+        throw new UnsupportedOperationException();
+    }
+
+
+    /**
      * Registers an event listener to receive notifications that an
      * SSL handshake has completed on this connection.
      *
--- a/jdk/src/share/classes/javax/net/ssl/SSLSocketFactory.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/net/ssl/SSLSocketFactory.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -30,6 +30,7 @@
 import javax.net.SocketFactory;
 import java.io.IOException;
 import java.security.*;
+import java.util.Locale;
 
 import sun.security.action.GetPropertyAction;
 
@@ -50,7 +51,8 @@
 
     static {
         String s = java.security.AccessController.doPrivileged(
-            new GetPropertyAction("javax.net.debug", "")).toLowerCase();
+            new GetPropertyAction("javax.net.debug", "")).toLowerCase(
+                                                            Locale.ENGLISH);
         DEBUG = s.contains("all") || s.contains("ssl");
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/javax/net/ssl/X509ExtendedTrustManager.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+package javax.net.ssl;
+
+import java.net.Socket;
+import javax.net.ssl.X509TrustManager;
+
+import java.security.cert.X509Certificate;
+import java.security.cert.CertificateException;
+
+/**
+ * Extensions to the <code>X509TrustManager</code> interface to support
+ * SSL/TLS connection sensitive trust management.
+ * <p>
+ * To prevent man-in-the-middle attacks, hostname checks can be done
+ * to verify that the hostname in an end-entity certificate matches the
+ * targeted hostname.  TLS does not require such checks, but some protocols
+ * over TLS (such as HTTPS) do.  In earlier versions of the JDK, the
+ * certificate chain checks were done at the SSL/TLS layer, and the hostname
+ * verification checks were done at the layer over TLS.  This class allows
+ * for the checking to be done during a single call to this class.
+ * <p>
+ * RFC 2830 defines the server identification specification for the "LDAPS"
+ * algorithm. RFC 2818 defines both the server identification and the
+ * client identification specification for the "HTTPS" algorithm.
+ *
+ * @see X509TrustManager
+ * @see HostnameVerifier
+ *
+ * @since 1.7
+ */
+public abstract class X509ExtendedTrustManager implements X509TrustManager {
+    /**
+     * Given the partial or complete certificate chain provided by the
+     * peer, build and validate the certificate path based on the
+     * authentication type and ssl parameters.
+     * <p>
+     * The authentication type is determined by the actual certificate
+     * used. For instance, if RSAPublicKey is used, the authType
+     * should be "RSA". Checking is case-sensitive.
+     * <p>
+     * If the <code>socket</code> parameter is an instance of
+     * {@link javax.net.SSLSocket}, and the endpoint identification
+     * algorithm of the <code>SSLParameters</code> is non-empty, to prevent
+     * man-in-the-middle attacks, the address that the <code>socket</code>
+     * connected to should be checked against the peer's identity presented
+     * in the end-entity X509 certificate, as specified in the endpoint
+     * identification algorithm.
+     * <p>
+     * If the <code>socket</code> parameter is an instance of
+     * {@link javax.net.SSLSocket}, and the algorithm constraints of the
+     * <code>SSLParameters</code> is non-null, for every certificate in the
+     * certification path, fields such as subject public key, the signature
+     * algorithm, key usage, extended key usage, etc. need to conform to the
+     * algorithm constraints in place on this socket.
+     *
+     * @param chain the peer certificate chain
+     * @param authType the key exchange algorithm used
+     * @param socket the socket used for this connection. This parameter
+     *        can be null, which indicates that implementations need not check
+     *        the ssl parameters
+     * @throws IllegalArgumentException if null or zero-length array is passed
+     *        in for the <code>chain</code> parameter or if null or zero-length
+     *        string is passed in for the <code>authType</code> parameter
+     * @throws CertificateException if the certificate chain is not trusted
+     *        by this TrustManager
+     *
+     * @see SSLParameters#getEndpointIdentificationProtocol
+     * @see SSLParameters#setEndpointIdentificationProtocol(String)
+     * @see SSLParameters#getAlgorithmConstraints
+     * @see SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
+     */
+    public abstract void checkClientTrusted(X509Certificate[] chain,
+            String authType, Socket socket) throws CertificateException;
+
+    /**
+     * Given the partial or complete certificate chain provided by the
+     * peer, build and validate the certificate path based on the
+     * authentication type and ssl parameters.
+     * <p>
+     * The authentication type is the key exchange algorithm portion
+     * of the cipher suites represented as a String, such as "RSA",
+     * "DHE_DSS". Note: for some exportable cipher suites, the key
+     * exchange algorithm is determined at run time during the
+     * handshake. For instance, for TLS_RSA_EXPORT_WITH_RC4_40_MD5,
+     * the authType should be RSA_EXPORT when an ephemeral RSA key is
+     * used for the key exchange, and RSA when the key from the server
+     * certificate is used. Checking is case-sensitive.
+     * <p>
+     * If the <code>socket</code> parameter is an instance of
+     * {@link javax.net.SSLSocket}, and the endpoint identification
+     * algorithm of the <code>SSLParameters</code> is non-empty, to prevent
+     * man-in-the-middle attacks, the address that the <code>socket</code>
+     * connected to should be checked against the peer's identity presented
+     * in the end-entity X509 certificate, as specified in the endpoint
+     * identification algorithm.
+     * <p>
+     * If the <code>socket</code> parameter is an instance of
+     * {@link javax.net.SSLSocket}, and the algorithm constraints of the
+     *  <code>SSLParameters</code> is non-null, for every certificate in the
+     * certification path, fields such as subject public key, the signature
+     * algorithm, key usage, extended key usage, etc. need to conform to the
+     * algorithm constraints in place on this socket.
+     *
+     * @param chain the peer certificate chain
+     * @param authType the key exchange algorithm used
+     * @param socket the socket used for this connection. This parameter
+     *        can be null, which indicates that implementations need not check
+     *        the ssl parameters
+     * @throws IllegalArgumentException if null or zero-length array is passed
+     *        in for the <code>chain</code> parameter or if null or zero-length
+     *        string is passed in for the <code>authType</code> parameter
+     * @throws CertificateException if the certificate chain is not trusted
+     *        by this TrustManager
+     *
+     * @see SSLParameters#getEndpointIdentificationProtocol
+     * @see SSLParameters#setEndpointIdentificationProtocol(String)
+     * @see SSLParameters#getAlgorithmConstraints
+     * @see SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
+     */
+    public abstract void checkServerTrusted(X509Certificate[] chain,
+        String authType, Socket socket) throws CertificateException;
+
+    /**
+     * Given the partial or complete certificate chain provided by the
+     * peer, build and validate the certificate path based on the
+     * authentication type and ssl parameters.
+     * <p>
+     * The authentication type is determined by the actual certificate
+     * used. For instance, if RSAPublicKey is used, the authType
+     * should be "RSA". Checking is case-sensitive.
+     * <p>
+     * If the <code>engine</code> parameter is available, and the endpoint
+     * identification algorithm of the <code>SSLParameters</code> is
+     * non-empty, to prevent man-in-the-middle attacks, the address that
+     * the <code>engine</code> connected to should be checked against
+     * the peer's identity presented in the end-entity X509 certificate,
+     * as specified in the endpoint identification algorithm.
+     * <p>
+     * If the <code>engine</code> parameter is available, and the algorithm
+     * constraints of the <code>SSLParameters</code> is non-null, for every
+     * certificate in the certification path, fields such as subject public
+     * key, the signature algorithm, key usage, extended key usage, etc.
+     * need to conform to the algorithm constraints in place on this engine.
+     *
+     * @param chain the peer certificate chain
+     * @param authType the key exchange algorithm used
+     * @param engine the engine used for this connection. This parameter
+     *        can be null, which indicates that implementations need not check
+     *        the ssl parameters
+     * @throws IllegalArgumentException if null or zero-length array is passed
+     *        in for the <code>chain</code> parameter or if null or zero-length
+     *        string is passed in for the <code>authType</code> parameter
+     * @throws CertificateException if the certificate chain is not trusted
+     *        by this TrustManager
+     *
+     * @see SSLParameters#getEndpointIdentificationProtocol
+     * @see SSLParameters#setEndpointIdentificationProtocol(String)
+     * @see SSLParameters#getAlgorithmConstraints
+     * @see SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
+     */
+    public abstract void checkClientTrusted(X509Certificate[] chain,
+        String authType, SSLEngine engine) throws CertificateException;
+
+    /**
+     * Given the partial or complete certificate chain provided by the
+     * peer, build and validate the certificate path based on the
+     * authentication type and ssl parameters.
+     * <p>
+     * The authentication type is the key exchange algorithm portion
+     * of the cipher suites represented as a String, such as "RSA",
+     * "DHE_DSS". Note: for some exportable cipher suites, the key
+     * exchange algorithm is determined at run time during the
+     * handshake. For instance, for TLS_RSA_EXPORT_WITH_RC4_40_MD5,
+     * the authType should be RSA_EXPORT when an ephemeral RSA key is
+     * used for the key exchange, and RSA when the key from the server
+     * certificate is used. Checking is case-sensitive.
+     * <p>
+     * If the <code>engine</code> parameter is available, and the endpoint
+     * identification algorithm of the <code>SSLParameters</code> is
+     * non-empty, to prevent man-in-the-middle attacks, the address that
+     * the <code>engine</code> connected to should be checked against
+     * the peer's identity presented in the end-entity X509 certificate,
+     * as specified in the endpoint identification algorithm.
+     * <p>
+     * If the <code>engine</code> parameter is available, and the algorithm
+     * constraints of the <code>SSLParameters</code> is non-null, for every
+     * certificate in the certification path, fields such as subject public
+     * key, the signature algorithm, key usage, extended key usage, etc.
+     * need to conform to the algorithm constraints in place on this engine.
+     *
+     * @param chain the peer certificate chain
+     * @param authType the key exchange algorithm used
+     * @param engine the engine used for this connection. This parameter
+     *        can be null, which indicates that implementations need not check
+     *        the ssl parameters
+     * @throws IllegalArgumentException if null or zero-length array is passed
+     *        in for the <code>chain</code> parameter or if null or zero-length
+     *        string is passed in for the <code>authType</code> parameter
+     * @throws CertificateException if the certificate chain is not trusted
+     *        by this TrustManager
+     *
+     * @see SSLParameters#getEndpointIdentificationProtocol
+     * @see SSLParameters#setEndpointIdentificationProtocol(String)
+     * @see SSLParameters#getAlgorithmConstraints
+     * @see SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
+     */
+    public abstract void checkServerTrusted(X509Certificate[] chain,
+        String authType, SSLEngine engine) throws CertificateException;
+
+}
--- a/jdk/src/share/classes/javax/swing/BorderFactory.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/BorderFactory.java	Wed Jul 05 17:26:57 2017 +0200
@@ -24,8 +24,10 @@
  */
 package javax.swing;
 
+import java.awt.BasicStroke;
 import java.awt.Color;
 import java.awt.Font;
+import java.awt.Paint;
 import javax.swing.border.*;
 
 /**
@@ -636,4 +638,125 @@
                                                 Icon tileIcon) {
         return new MatteBorder(top, left, bottom, right, tileIcon);
     }
+
+//// StrokeBorder //////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Creates a border of the specified {@code stroke}.
+     * The component's foreground color will be used to render the border.
+     *
+     * @param stroke  the {@link BasicStroke} object used to stroke a shape
+     * @return the {@code Border} object
+     *
+     * @throws NullPointerException if the specified {@code stroke} is {@code null}
+     *
+     * @since 1.7
+     */
+    public static Border createStrokeBorder(BasicStroke stroke) {
+        return new StrokeBorder(stroke);
+    }
+
+    /**
+     * Creates a border of the specified {@code stroke} and {@code paint}.
+     * If the specified {@code paint} is {@code null},
+     * the component's foreground color will be used to render the border.
+     *
+     * @param stroke  the {@link BasicStroke} object used to stroke a shape
+     * @param paint   the {@link Paint} object used to generate a color
+     * @return the {@code Border} object
+     *
+     * @throws NullPointerException if the specified {@code stroke} is {@code null}
+     *
+     * @since 1.7
+     */
+    public static Border createStrokeBorder(BasicStroke stroke, Paint paint) {
+        return new StrokeBorder(stroke, paint);
+    }
+
+//// DashedBorder //////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+    private static Border sharedDashedBorder;
+
+    /**
+     * Creates a dashed border of the specified {@code paint}.
+     * If the specified {@code paint} is {@code null},
+     * the component's foreground color will be used to render the border.
+     * The width of a dash line is equal to {@code 1}.
+     * The relative length of a dash line and
+     * the relative spacing between dash lines are equal to {@code 1}.
+     * A dash line is not rounded.
+     *
+     * @param paint  the {@link Paint} object used to generate a color
+     * @return the {@code Border} object
+     *
+     * @since 1.7
+     */
+    public static Border createDashedBorder(Paint paint) {
+        return createDashedBorder(paint, 1.0f, 1.0f, 1.0f, false);
+    }
+
+    /**
+     * Creates a dashed border of the specified {@code paint},
+     * relative {@code length}, and relative {@code spacing}.
+     * If the specified {@code paint} is {@code null},
+     * the component's foreground color will be used to render the border.
+     * The width of a dash line is equal to {@code 1}.
+     * A dash line is not rounded.
+     *
+     * @param paint    the {@link Paint} object used to generate a color
+     * @param length   the relative length of a dash line
+     * @param spacing  the relative spacing between dash lines
+     * @return the {@code Border} object
+     *
+     * @throws IllegalArgumentException if the specified {@code length} is less than {@code 1}, or
+     *                                  if the specified {@code spacing} is less than {@code 0}
+     * @since 1.7
+     */
+    public static Border createDashedBorder(Paint paint, float length, float spacing) {
+        return createDashedBorder(paint, 1.0f, length, spacing, false);
+    }
+
+    /**
+     * Creates a dashed border of the specified {@code paint}, {@code thickness},
+     * line shape, relative {@code length}, and relative {@code spacing}.
+     * If the specified {@code paint} is {@code null},
+     * the component's foreground color will be used to render the border.
+     *
+     * @param paint      the {@link Paint} object used to generate a color
+     * @param thickness  the width of a dash line
+     * @param length     the relative length of a dash line
+     * @param spacing    the relative spacing between dash lines
+     * @param rounded    whether or not line ends should be round
+     * @return the {@code Border} object
+     *
+     * @throws IllegalArgumentException if the specified {@code thickness} is less than {@code 1}, or
+     *                                  if the specified {@code length} is less than {@code 1}, or
+     *                                  if the specified {@code spacing} is less than {@code 0}
+     * @since 1.7
+     */
+    public static Border createDashedBorder(Paint paint, float thickness, float length, float spacing, boolean rounded) {
+        boolean shared = !rounded && (paint == null) && (thickness == 1.0f) && (length == 1.0f) && (spacing == 1.0f);
+        if (shared && (sharedDashedBorder != null)) {
+            return sharedDashedBorder;
+        }
+        if (thickness < 1.0f) {
+            throw new IllegalArgumentException("thickness is less than 1");
+        }
+        if (length < 1.0f) {
+            throw new IllegalArgumentException("length is less than 1");
+        }
+        if (spacing < 0.0f) {
+            throw new IllegalArgumentException("spacing is less than 0");
+        }
+        int cap = rounded ? BasicStroke.CAP_ROUND : BasicStroke.CAP_SQUARE;
+        int join = rounded ? BasicStroke.JOIN_ROUND : BasicStroke.JOIN_MITER;
+        float[] array = { thickness * (length - 1.0f), thickness * (spacing + 1.0f) };
+        Border border = createStrokeBorder(new BasicStroke(thickness, cap, join, thickness * 2.0f, array, 0.0f), paint);
+        if (shared) {
+            sharedDashedBorder = border;
+        }
+        return border;
+    }
 }
--- a/jdk/src/share/classes/javax/swing/DebugGraphics.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/DebugGraphics.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1322,13 +1322,11 @@
     }
 
     String toShortString() {
-        StringBuffer buffer = new StringBuffer("Graphics" + (isDrawingBuffer() ? "<B>" : "") + "(" + graphicsID + "-" + debugOptions + ")");
-        return buffer.toString();
+        return "Graphics" + (isDrawingBuffer() ? "<B>" : "") + "(" + graphicsID + "-" + debugOptions + ")";
     }
 
     String pointToString(int x, int y) {
-        StringBuffer buffer = new StringBuffer("(" + x + ", " + y + ")");
-        return buffer.toString();
+        return "(" + x + ", " + y + ")";
     }
 
     /** Enables/disables diagnostic information about every graphics
--- a/jdk/src/share/classes/javax/swing/JComponent.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/JComponent.java	Wed Jul 05 17:26:57 2017 +0200
@@ -4783,21 +4783,11 @@
      * @param y  the y value of the dirty region
      * @param width  the width of the dirty region
      * @param height  the height of the dirty region
+     * @see #isPaintingOrigin()
      * @see java.awt.Component#isShowing
      * @see RepaintManager#addDirtyRegion
      */
     public void repaint(long tm, int x, int y, int width, int height) {
-        Container p = this;
-        while ((p = p.getParent()) instanceof JComponent) {
-            JComponent jp = (JComponent) p;
-            if (jp.isPaintingOrigin()) {
-                Rectangle rectangle = SwingUtilities.convertRectangle(
-                        this, new Rectangle(x, y, width, height), jp);
-                jp.repaint(tm,
-                        rectangle.x, rectangle.y, rectangle.width, rectangle.height);
-                return;
-            }
-        }
         RepaintManager.currentManager(this).addDirtyRegion(this, x, y, width, height);
     }
 
@@ -4808,6 +4798,7 @@
      * currently pending events have been dispatched.
      *
      * @param  r a <code>Rectangle</code> containing the dirty region
+     * @see #isPaintingOrigin()
      * @see java.awt.Component#isShowing
      * @see RepaintManager#addDirtyRegion
      */
@@ -4912,13 +4903,19 @@
     }
 
     /**
-     * Returns true if a paint triggered on a child component should cause
+     * Returns {@code true} if a paint triggered on a child component should cause
      * painting to originate from this Component, or one of its ancestors.
+     * <p/>
+     * Calling {@link JComponent#repaint} on a Swing component will be delegated to
+     * the first ancestor which {@code isPaintingOrigin()} returns {@true},
+     * if there are any.
+     * <p/>
+     * {@code JComponent} subclasses that need to be repainted when any of their
+     * children are repainted should override this method to return {@code true}.
      *
-     * @return true if painting should originate from this Component or
-     *         one of its ancestors.
-     */
-    boolean isPaintingOrigin() {
+     * @return always returns {@code false}
+     */
+    protected boolean isPaintingOrigin() {
         return false;
     }
 
--- a/jdk/src/share/classes/javax/swing/JDialog.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/JDialog.java	Wed Jul 05 17:26:57 2017 +0200
@@ -303,10 +303,9 @@
      * @param modal specifies whether dialog blocks user input to other top-level
      *     windows when shown. If {@code true}, the modality type property is set to
      *     {@code DEFAULT_MODALITY_TYPE}, otherwise the dialog is modeless.
-     * @param gc the {@code GraphicsConfiguration}
-     *     of the target screen device.  If {@code gc} is
-     *     {@code null}, the same
-     *     {@code GraphicsConfiguration} as the owning Frame is used.
+     * @param gc the {@code GraphicsConfiguration} of the target screen device;
+     *     if {@code null}, the default system {@code GraphicsConfiguration}
+     *     is assumed
      * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()}
      *     returns {@code true}.
      * @see java.awt.Dialog.ModalityType
@@ -441,10 +440,9 @@
      * @param modal specifies whether dialog blocks user input to other top-level
      *     windows when shown. If {@code true}, the modality type property is set to
      *     {@code DEFAULT_MODALITY_TYPE}, otherwise the dialog is modeless
-     * @param gc the {@code GraphicsConfiguration}
-     *     of the target screen device.  If {@code gc} is
-     *     {@code null}, the same
-     *     {@code GraphicsConfiguration} as the owning Dialog is used.
+     * @param gc the {@code GraphicsConfiguration} of the target screen device;
+     *     if {@code null}, the default system {@code GraphicsConfiguration}
+     *     is assumed
      * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()}
      *     returns {@code true}.
      * @see java.awt.Dialog.ModalityType
@@ -612,10 +610,8 @@
      *     windows when shown. {@code null} value and unsupported modality
      *     types are equivalent to {@code MODELESS}
      * @param gc the {@code GraphicsConfiguration} of the target screen device;
-     *     if {@code null}, the {@code GraphicsConfiguration} from the owning
-     *     window is used; if {@code owner} is also {@code null}, the
-     *     system default {@code GraphicsConfiguration} is assumed
-     *
+     *     if {@code null}, the default system {@code GraphicsConfiguration}
+     *     is assumed
      * @throws IllegalArgumentException
      *     if the {@code owner} is not an instance of {@link java.awt.Dialog Dialog}
      *     or {@link java.awt.Frame Frame}
--- a/jdk/src/share/classes/javax/swing/JLayer.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/JLayer.java	Wed Jul 05 17:26:57 2017 +0200
@@ -384,7 +384,7 @@
      * @return true
      * @see JComponent#isPaintingOrigin()
      */
-    boolean isPaintingOrigin() {
+    protected boolean isPaintingOrigin() {
         return true;
     }
 
--- a/jdk/src/share/classes/javax/swing/JViewport.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/JViewport.java	Wed Jul 05 17:26:57 2017 +0200
@@ -637,14 +637,14 @@
     }
 
     /**
-     * Returns true if scroll mode is a BACKINGSTORE_SCROLL_MODE to cause
-     * painting to originate from <code>JViewport</code>, or one of its
-     * ancestors. Otherwise returns false.
+     * Returns true if scroll mode is a {@code BACKINGSTORE_SCROLL_MODE} to cause
+     * painting to originate from {@code JViewport}, or one of its
+     * ancestors. Otherwise returns {@code false}.
      *
-     * @return true if if scroll mode is a BACKINGSTORE_SCROLL_MODE.
+     * @return true if if scroll mode is a {@code BACKINGSTORE_SCROLL_MODE}.
      * @see JComponent#isPaintingOrigin()
      */
-    boolean isPaintingOrigin() {
+    protected boolean isPaintingOrigin() {
         return scrollMode == BACKINGSTORE_SCROLL_MODE;
     }
 
--- a/jdk/src/share/classes/javax/swing/RepaintManager.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/RepaintManager.java	Wed Jul 05 17:26:57 2017 +0200
@@ -438,6 +438,7 @@
      * @param y Y coordinate of the region to repaint
      * @param w Width of the region to repaint
      * @param h Height of the region to repaint
+     * @see JComponent#isPaintingOrigin()
      * @see JComponent#repaint
      */
     public void addDirtyRegion(JComponent c, int x, int y, int w, int h)
@@ -447,6 +448,16 @@
             delegate.addDirtyRegion(c, x, y, w, h);
             return;
         }
+        Container p = c;
+        while ((p = p.getParent()) instanceof JComponent) {
+            JComponent jp = (JComponent) p;
+            if (jp.isPaintingOrigin()) {
+                Rectangle rectangle = SwingUtilities.convertRectangle(
+                        c, new Rectangle(x, y, w, h), jp);
+                jp.repaint(0, rectangle.x, rectangle.y, rectangle.width, rectangle.height);
+                return;
+            }
+        }
         addDirtyRegion0(c, x, y, w, h);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/javax/swing/border/StrokeBorder.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+package javax.swing.border;
+
+import java.awt.BasicStroke;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Insets;
+import java.awt.Paint;
+import java.awt.RenderingHints;
+import java.awt.geom.Rectangle2D;
+import java.beans.ConstructorProperties;
+
+/**
+ * A class which implements a border of an arbitrary stroke.
+ * <p>
+ * <strong>Warning:</strong>
+ * Serialized objects of this class will not be compatible with
+ * future Swing releases. The current serialization support is
+ * appropriate for short term storage or RMI
+ * between applications running the same version of Swing.
+ * As of 1.4, support for long term storage of all JavaBeans&trade;
+ * has been added to the <code>java.beans</code> package.
+ * Please see {@link java.beans.XMLEncoder}.
+ *
+ * @author Sergey A. Malenkov
+ *
+ * @since 1.7
+ */
+public class StrokeBorder extends AbstractBorder {
+    private final BasicStroke stroke;
+    private final Paint paint;
+
+    /**
+     * Creates a border of the specified {@code stroke}.
+     * The component's foreground color will be used to render the border.
+     *
+     * @param stroke  the {@link BasicStroke} object used to stroke a shape
+     *
+     * @throws NullPointerException if the specified {@code stroke} is {@code null}
+     */
+    public StrokeBorder(BasicStroke stroke) {
+        this(stroke, null);
+    }
+
+    /**
+     * Creates a border of the specified {@code stroke} and {@code paint}.
+     * If the specified {@code paint} is {@code null},
+     * the component's foreground color will be used to render the border.
+     *
+     * @param stroke  the {@link BasicStroke} object used to stroke a shape
+     * @param paint   the {@link Paint} object used to generate a color
+     *
+     * @throws NullPointerException if the specified {@code stroke} is {@code null}
+     */
+    @ConstructorProperties({ "stroke", "paint" })
+    public StrokeBorder(BasicStroke stroke, Paint paint) {
+        if (stroke == null) {
+            throw new NullPointerException("border's stroke");
+        }
+        this.stroke = stroke;
+        this.paint = paint;
+    }
+
+    /**
+     * Paints the border for the specified component
+     * with the specified position and size.
+     *
+     * @param c       the component for which this border is being painted
+     * @param g       the paint graphics
+     * @param x       the x position of the painted border
+     * @param y       the y position of the painted border
+     * @param width   the width of the painted border
+     * @param height  the height of the painted border
+     *
+     * @throws NullPointerException if the specified {@code c} or {@code g} are {@code null}
+     */
+    @Override
+    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
+        float size = this.stroke.getLineWidth();
+        if (size > 0.0f) {
+            g = g.create();
+            if (g instanceof Graphics2D) {
+                Graphics2D g2d = (Graphics2D) g;
+                g2d.setStroke(this.stroke);
+                g2d.setPaint(this.paint != null ? this.paint : c.getForeground());
+                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                                     RenderingHints.VALUE_ANTIALIAS_ON);
+                g2d.draw(new Rectangle2D.Float(x + size / 2, y + size / 2, width - size, height - size));
+            }
+            g.dispose();
+        }
+    }
+
+    /**
+     * Reinitializes the {@code insets} parameter
+     * with this border's current insets.
+     * All insets are equal to the line width of the stroke.
+     *
+     * @param c       the component for which this border insets value applies
+     * @param insets  the {@code Insets} object to be reinitialized
+     * @return the reinitialized {@code insets} parameter
+     *
+     * @throws NullPointerException if the specified {@code insets} is {@code null}
+     */
+    @Override
+    public Insets getBorderInsets(Component c, Insets insets) {
+        int size = (int) Math.ceil(this.stroke.getLineWidth());
+        insets.set(size, size, size, size);
+        return insets;
+    }
+
+    /**
+     * Returns the {@link BasicStroke} object used to stroke a shape
+     * during the border rendering.
+     *
+     * @return the {@link BasicStroke} object
+     */
+    public BasicStroke getStroke() {
+        return this.stroke;
+    }
+
+    /**
+     * Returns the {@link Paint} object used to generate a color
+     * during the border rendering.
+     *
+     * @return the {@link Paint} object or {@code null}
+     *         if the {@code paint} parameter is not set
+     */
+    public Paint getPaint() {
+        return this.paint;
+    }
+}
--- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java	Wed Jul 05 17:26:57 2017 +0200
@@ -362,6 +362,14 @@
      * @since 1.6
      */
     public int getBaseline(JComponent c, int width, int height) {
+        if (c == null) {
+            throw new NullPointerException("Component must be non-null");
+        }
+
+        if (width < 0 || height < 0) {
+            throw new IllegalArgumentException("Width and height must be >= 0");
+        }
+
         JViewport viewport = scrollpane.getViewport();
         Insets spInsets = scrollpane.getInsets();
         int y = spInsets.top;
--- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java	Wed Jul 05 17:26:57 2017 +0200
@@ -115,10 +115,7 @@
         return new SynthTabbedPaneUI();
     }
 
-    private SynthTabbedPaneUI() {
-    }
-
-    private boolean scrollableTabLayoutEnabled() {
+     private boolean scrollableTabLayoutEnabled() {
         return (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT);
     }
 
--- a/jdk/src/share/classes/javax/swing/table/DefaultTableCellRenderer.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/table/DefaultTableCellRenderer.java	Wed Jul 05 17:26:57 2017 +0200
@@ -186,6 +186,9 @@
      */
     public Component getTableCellRendererComponent(JTable table, Object value,
                           boolean isSelected, boolean hasFocus, int row, int column) {
+        if (table == null) {
+            return this;
+        }
 
         Color fg = null;
         Color bg = null;
--- a/jdk/src/share/classes/javax/swing/text/DefaultCaret.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/text/DefaultCaret.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1334,13 +1334,13 @@
                     && component.getClientProperty("JPasswordField.cutCopyAllowed") !=
                     Boolean.TRUE) {
                     //fix for 4793761
-                    StringBuffer txt = null;
+                    StringBuilder txt = null;
                     char echoChar = ((JPasswordField)component).getEchoChar();
                     int p0 = Math.min(getDot(), getMark());
                     int p1 = Math.max(getDot(), getMark());
                     for (int i = p0; i < p1; i++) {
                         if (txt == null) {
-                            txt = new StringBuffer();
+                            txt = new StringBuilder();
                         }
                         txt.append(echoChar);
                     }
@@ -1675,7 +1675,6 @@
                 }
                 return;
             }
-            int adjust = 0;
             int offset = e.getOffset();
             int length = e.getLength();
             int newDot = dot;
@@ -1759,7 +1758,6 @@
             }
             int offs0 = e.getOffset();
             int offs1 = offs0 + e.getLength();
-            int adjust = 0;
             int newDot = dot;
             boolean adjustDotBias = false;
             int newMark = mark;
--- a/jdk/src/share/classes/javax/swing/text/DefaultStyledDocument.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/text/DefaultStyledDocument.java	Wed Jul 05 17:26:57 2017 +0200
@@ -132,7 +132,7 @@
             // install the content
             Content c = getContent();
             int n = data.length;
-            StringBuffer sb = new StringBuffer();
+            StringBuilder sb = new StringBuilder();
             for (int i = 0; i < n; i++) {
                 ElementSpec es = data[i];
                 if (es.getLength() > 0) {
@@ -191,7 +191,7 @@
             // install the content
             Content c = getContent();
             int n = data.length;
-            StringBuffer sb = new StringBuffer();
+            StringBuilder sb = new StringBuilder();
             for (int i = 0; i < n; i++) {
                 ElementSpec es = data[i];
                 if (es.getLength() > 0) {
--- a/jdk/src/share/classes/javax/swing/text/InternationalFormatter.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/text/InternationalFormatter.java	Wed Jul 05 17:26:57 2017 +0200
@@ -30,7 +30,6 @@
 import java.text.AttributedCharacterIterator.Attribute;
 import java.util.*;
 import javax.swing.*;
-import javax.swing.text.*;
 
 /**
  * <code>InternationalFormatter</code> extends <code>DefaultFormatter</code>,
@@ -875,7 +874,6 @@
                     (f instanceof AttributedCharacterIterator.Attribute)) {
             AttributedCharacterIterator.Attribute field =
                                    (AttributedCharacterIterator.Attribute)f;
-            int index = 0;
 
             iterator.first();
             while (iterator.getIndex() < start) {
--- a/jdk/src/share/classes/javax/swing/text/JTextComponent.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/text/JTextComponent.java	Wed Jul 05 17:26:57 2017 +0200
@@ -35,10 +35,7 @@
 import java.util.Hashtable;
 import java.util.Enumeration;
 import java.util.Vector;
-import java.util.Iterator;
 import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
 
 import java.util.concurrent.*;
 
@@ -4058,7 +4055,7 @@
 
     private static final Object KEYMAP_TABLE =
         new StringBuilder("JTextComponent_KeymapTable");
-    private JTextComponent editor;
+
     //
     // member variables used for on-the-spot input method
     // editing style support
@@ -4748,14 +4745,14 @@
                         processKeyEvent(ke);
                     }
                 } else {
-                    StringBuffer strBuf = new StringBuffer();
+                    StringBuilder strBuf = new StringBuilder();
                     for (char c = text.current(); commitCount > 0;
                          c = text.next(), commitCount--) {
                         strBuf.append(c);
                     }
 
                     // map it to an ActionEvent
-                    mapCommittedTextToAction(new String(strBuf));
+                    mapCommittedTextToAction(strBuf.toString());
                 }
 
                 // Remember latest committed text end index
@@ -4801,7 +4798,7 @@
     private void createComposedTextAttribute(int composedIndex,
                                         AttributedCharacterIterator text) {
         Document doc = getDocument();
-        StringBuffer strBuf = new StringBuffer();
+        StringBuilder strBuf = new StringBuilder();
 
         // create attributed string with no attributes
         for (char c = text.setIndex(composedIndex);
@@ -4809,7 +4806,7 @@
             strBuf.append(c);
         }
 
-        composedTextContent = new String(strBuf);
+        composedTextContent = strBuf.toString();
         composedTextAttribute = new SimpleAttributeSet();
         composedTextAttribute.addAttribute(StyleConstants.ComposedTextAttribute,
                 new AttributedString(text, composedIndex, text.getEndIndex()));
--- a/jdk/src/share/classes/javax/swing/text/MaskFormatter.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/text/MaskFormatter.java	Wed Jul 05 17:26:57 2017 +0200
@@ -29,7 +29,6 @@
 import java.text.*;
 import java.util.*;
 import javax.swing.*;
-import javax.swing.text.*;
 
 /**
  * <code>MaskFormatter</code> is used to format and edit strings. The behavior
@@ -385,7 +384,7 @@
      */
     public String valueToString(Object value) throws ParseException {
         String sValue = (value == null) ? "" : value.toString();
-        StringBuffer result = new StringBuffer();
+        StringBuilder result = new StringBuilder();
         String placeholder = getPlaceholder();
         int[] valueCounter = { 0 };
 
@@ -484,7 +483,7 @@
      * Invokes <code>append</code> on the mask characters in
      * <code>mask</code>.
      */
-    private void append(StringBuffer result, String value, int[] index,
+    private void append(StringBuilder result, String value, int[] index,
                         String placeholder, MaskCharacter[] mask)
                           throws ParseException {
         for (int counter = 0, maxCounter = mask.length;
@@ -611,13 +610,13 @@
      * Removes the literal characters from the passed in string.
      */
     private String stripLiteralChars(String string) {
-        StringBuffer sb = null;
+        StringBuilder sb = null;
         int last = 0;
 
         for (int counter = 0, max = string.length(); counter < max; counter++){
             if (isLiteral(counter)) {
                 if (sb == null) {
-                    sb = new StringBuffer();
+                    sb = new StringBuilder();
                     if (counter > 0) {
                         sb.append(string.substring(0, counter));
                     }
@@ -715,10 +714,10 @@
      */
     boolean canReplace(ReplaceHolder rh) {
         // This method is rather long, but much of the burden is in
-        // maintaining a String and swapping to a StringBuffer only if
+        // maintaining a String and swapping to a StringBuilder only if
         // absolutely necessary.
         if (!getAllowsInvalid()) {
-            StringBuffer replace = null;
+            StringBuilder replace = null;
             String text = rh.text;
             int tl = (text != null) ? text.length() : 0;
 
@@ -737,7 +736,7 @@
                     char aChar = text.charAt(textIndex);
                     if (aChar != getCharacter(rh.offset + counter, aChar)) {
                         if (replace == null) {
-                            replace = new StringBuffer();
+                            replace = new StringBuilder();
                             if (textIndex > 0) {
                                 replace.append(text.substring(0, textIndex));
                             }
@@ -758,7 +757,7 @@
                         }
                     }
                     else if (textIndex > 0) {
-                        replace = new StringBuffer(max);
+                        replace = new StringBuilder(max);
                         replace.append(text.substring(0, textIndex));
                         replace.append(getLiteral(rh.offset + counter));
                         if (textIndex < tl) {
@@ -780,7 +779,7 @@
                 else if (textIndex >= tl) {
                     // placeholder
                     if (replace == null) {
-                        replace = new StringBuffer();
+                        replace = new StringBuilder();
                         if (text != null) {
                             replace.append(text);
                         }
@@ -863,7 +862,7 @@
          * Appends the necessary character in <code>formatting</code> at
          * <code>index</code> to <code>buff</code>.
          */
-        public void append(StringBuffer buff, String formatting, int[] index,
+        public void append(StringBuilder buff, String formatting, int[] index,
                            String placeholder)
                           throws ParseException {
             boolean inString = index[0] < formatting.length();
--- a/jdk/src/share/classes/javax/swing/text/NumberFormatter.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/text/NumberFormatter.java	Wed Jul 05 17:26:57 2017 +0200
@@ -27,7 +27,6 @@
 import java.lang.reflect.*;
 import java.text.*;
 import java.util.*;
-import javax.swing.text.*;
 
 /**
  * <code>NumberFormatter</code> subclasses <code>InternationalFormatter</code>
@@ -132,7 +131,7 @@
         DecimalFormatSymbols dfs = getDecimalFormatSymbols();
 
         if (dfs != null) {
-            StringBuffer sb = new StringBuffer();
+            StringBuilder sb = new StringBuilder();
 
             sb.append(dfs.getCurrencySymbol());
             sb.append(dfs.getDecimalSeparator());
@@ -240,13 +239,6 @@
     }
 
     /**
-     */
-    private boolean isValidInsertionCharacter(char aChar) {
-        return (Character.isDigit(aChar) || specialChars.indexOf(aChar) != -1);
-    }
-
-
-    /**
      * Subclassed to return false if <code>text</code> contains in an invalid
      * character to insert, that is, it is not a digit
      * (<code>Character.isDigit()</code>) and
@@ -403,28 +395,6 @@
     }
 
     /**
-     * Returns true if the range offset to length identifies the only
-     * integer field.
-     */
-    private boolean isOnlyIntegerField(int offset, int length) {
-        if (isValidMask()) {
-            int start = getAttributeStart(NumberFormat.Field.INTEGER);
-
-            if (start != -1) {
-                AttributedCharacterIterator iterator = getIterator();
-
-                iterator.setIndex(start);
-                if (offset > start || iterator.getRunLimit(
-                    NumberFormat.Field.INTEGER) > (offset + length)) {
-                    return false;
-                }
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
      * Invoked to toggle the sign. For this to work the value class
      * must have a single arg constructor that takes a String.
      */
--- a/jdk/src/share/classes/javax/swing/text/PlainDocument.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/text/PlainDocument.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,7 +25,6 @@
 package javax.swing.text;
 
 import java.util.Vector;
-import javax.swing.event.*;
 
 /**
  * A plain document that maintains no character attributes.  The
@@ -118,7 +117,7 @@
         Object filterNewlines = getProperty("filterNewlines");
         if ((filterNewlines instanceof Boolean) && filterNewlines.equals(Boolean.TRUE)) {
             if ((str != null) && (str.indexOf('\n') >= 0)) {
-                StringBuffer filtered = new StringBuffer(str);
+                StringBuilder filtered = new StringBuilder(str);
                 int n = filtered.length();
                 for (int i = 0; i < n; i++) {
                     if (filtered.charAt(i) == '\n') {
@@ -204,11 +203,9 @@
                 }
             }
             if (hasBreaks) {
-                int rmCount = 1;
                 removed.addElement(rmCandidate);
                 if ((offset + length == rmOffs1) && (lastOffset != rmOffs1) &&
                     ((index+1) < lineMap.getElementCount())) {
-                    rmCount += 1;
                     Element e = lineMap.getElement(index+1);
                     removed.addElement(e);
                     rmOffs1 = e.getEndOffset();
--- a/jdk/src/share/classes/javax/swing/text/TabSet.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/text/TabSet.java	Wed Jul 05 17:26:57 2017 +0200
@@ -199,7 +199,7 @@
      */
     public String toString() {
         int            tabCount = getTabCount();
-        StringBuffer   buffer = new StringBuffer("[ ");
+        StringBuilder buffer = new StringBuilder("[ ");
 
         for(int counter = 0; counter < tabCount; counter++) {
             if(counter > 0)
--- a/jdk/src/share/classes/javax/swing/text/html/FormView.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/text/html/FormView.java	Wed Jul 05 17:26:57 2017 +0200
@@ -362,7 +362,7 @@
      */
     public void actionPerformed(ActionEvent evt) {
         Element element = getElement();
-        StringBuffer dataBuffer = new StringBuffer();
+        StringBuilder dataBuffer = new StringBuilder();
         HTMLDocument doc = (HTMLDocument)getDocument();
         AttributeSet attr = element.getAttributes();
 
@@ -508,7 +508,7 @@
      */
     protected void imageSubmit(String imageData) {
 
-        StringBuffer dataBuffer = new StringBuffer();
+        StringBuilder dataBuffer = new StringBuilder();
         Element elem = getElement();
         HTMLDocument hdoc = (HTMLDocument)elem.getDocument();
         getFormData(dataBuffer);
@@ -589,7 +589,7 @@
      * @param targetElement the element that triggered the
      *                      form submission
      */
-    void getFormData(StringBuffer buffer) {
+    private void getFormData(StringBuilder buffer) {
         Element formE = getFormElement();
         if (formE != null) {
             ElementIterator it = new ElementIterator(formE);
@@ -623,7 +623,7 @@
      * data is loaded in name/value pairs.
      *
      */
-    private void loadElementDataIntoBuffer(Element elem, StringBuffer buffer) {
+    private void loadElementDataIntoBuffer(Element elem, StringBuilder buffer) {
 
         AttributeSet attr = elem.getAttributes();
         String name = (String)attr.getAttribute(HTML.Attribute.NAME);
@@ -692,29 +692,6 @@
             }
             if (path != null && path.length() > 0) {
                 value = path;
-/*
-
-                try {
-                    Reader reader = new BufferedReader(new FileReader(path));
-                    StringBuffer buffer = new StringBuffer();
-                    char[] cBuff = new char[1024];
-                    int read;
-
-                    try {
-                        while ((read = reader.read(cBuff)) != -1) {
-                            buffer.append(cBuff, 0, read);
-                        }
-                    } catch (IOException ioe) {
-                        buffer = null;
-                    }
-                    try {
-                        reader.close();
-                    } catch (IOException ioe) {}
-                    if (buffer != null) {
-                        value = buffer.toString();
-                    }
-                } catch (IOException ioe) {}
-*/
             }
         }
         return value;
@@ -740,7 +717,7 @@
      * form element.  Basically, only items that are selected
      * and have their name attribute set are added to the buffer.
      */
-    private void loadSelectData(AttributeSet attr, StringBuffer buffer) {
+    private void loadSelectData(AttributeSet attr, StringBuilder buffer) {
 
         String name = (String)attr.getAttribute(HTML.Attribute.NAME);
         if (name == null) {
@@ -771,7 +748,7 @@
      * URLEncoder.encode() method before being added to the
      * buffer.
      */
-    private void appendBuffer(StringBuffer buffer, String name, String value) {
+    private void appendBuffer(StringBuilder buffer, String name, String value) {
         if (buffer.length() > 0) {
             buffer.append('&');
         }
--- a/jdk/src/share/classes/javax/swing/text/html/MinimalHTMLWriter.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/text/html/MinimalHTMLWriter.java	Wed Jul 05 17:26:57 2017 +0200
@@ -691,11 +691,11 @@
         if (styleNameMapping == null) {
             return style;
         }
-        StringBuffer sb = null;
+        StringBuilder sb = null;
         for (int counter = style.length() - 1; counter >= 0; counter--) {
             if (!isValidCharacter(style.charAt(counter))) {
                 if (sb == null) {
-                    sb = new StringBuffer(style);
+                    sb = new StringBuilder(style);
                 }
                 sb.setCharAt(counter, 'a');
             }
--- a/jdk/src/share/classes/javax/swing/text/html/StyleSheet.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/text/html/StyleSheet.java	Wed Jul 05 17:26:57 2017 +0200
@@ -998,7 +998,7 @@
     void addRule(String[] selector, AttributeSet declaration,
                  boolean isLinked) {
         int n = selector.length;
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append(selector[0]);
         for (int counter = 1; counter < n; counter++) {
             sb.append(' ');
--- a/jdk/src/share/classes/javax/swing/text/html/parser/Parser.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/text/html/parser/Parser.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1470,7 +1470,7 @@
      */
     public String parseDTDMarkup() throws IOException {
 
-        StringBuffer strBuff = new StringBuffer();
+        StringBuilder strBuff = new StringBuilder();
         ch = readCh();
         while(true) {
             switch (ch) {
--- a/jdk/src/share/classes/javax/swing/text/rtf/AbstractFilter.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/text/rtf/AbstractFilter.java	Wed Jul 05 17:26:57 2017 +0200
@@ -160,7 +160,7 @@
     public void write(byte[] buf, int off, int len)
       throws IOException
     {
-      StringBuffer accumulator = null;
+      StringBuilder accumulator = null;
       while (len > 0) {
         short b = (short)buf[off];
 
@@ -178,7 +178,7 @@
           char ch = translationTable[b];
           if (ch != (char)0) {
             if (accumulator == null)
-              accumulator = new StringBuffer();
+              accumulator = new StringBuilder();
             accumulator.append(ch);
           }
         }
--- a/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java	Wed Jul 05 17:26:57 2017 +0200
@@ -48,8 +48,6 @@
     private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(IMPL_TOKEN);
 
     // Constructors in this class *must* be package scoped or private.
-    // Exception:  JavaMethodHandle constructors are protected.
-    // (The link between JMH and BMH is temporary.)
 
     /** Bind a direct MH to its receiver (or first ref. argument).
      *  The JVM will pre-dispatch the MH if it is not already static.
@@ -122,55 +120,6 @@
         assert(this instanceof JavaMethodHandle);
     }
 
-    /** Initialize the current object as a Java method handle.
-     */
-    protected BoundMethodHandle(String entryPointName, MethodType type, boolean matchArity) {
-        super(Access.TOKEN, null);
-        MethodHandle entryPoint
-                = findJavaMethodHandleEntryPoint(this.getClass(),
-                                        entryPointName, type, matchArity);
-        MethodHandleImpl.initType(this, entryPoint.type().dropParameterTypes(0, 1));
-        this.argument = this; // kludge; get rid of
-        this.vmargslot = this.type().parameterSlotDepth(0);
-        initTarget(entryPoint, 0);
-        assert(this instanceof JavaMethodHandle);
-    }
-
-    private static
-    MethodHandle findJavaMethodHandleEntryPoint(Class<?> caller,
-                                                String name,
-                                                MethodType type,
-                                                boolean matchArity) {
-        if (matchArity)  type.getClass();  // elicit NPE
-        List<MemberName> methods = IMPL_NAMES.getMethods(caller, true, name, null, caller);
-        MethodType foundType = null;
-        MemberName foundMethod = null;
-        for (MemberName method : methods) {
-            if (method.getDeclaringClass() == MethodHandle.class)
-                continue;  // ignore methods inherited from MH class itself
-            MethodType mtype = method.getMethodType();
-            if (type != null && type.parameterCount() != mtype.parameterCount())
-                continue;
-            else if (foundType == null)
-                foundType = mtype;
-            else if (foundType != mtype)
-                throw newIllegalArgumentException("more than one method named "+name+" in "+caller.getName());
-            // discard overrides
-            if (foundMethod == null)
-                foundMethod = method;
-            else if (foundMethod.getDeclaringClass().isAssignableFrom(method.getDeclaringClass()))
-                foundMethod = method;
-        }
-        if (foundMethod == null)
-            throw newIllegalArgumentException("no method named "+name+" in "+caller.getName());
-        MethodHandle entryPoint = MethodHandleImpl.findMethod(IMPL_TOKEN, foundMethod, true, caller);
-        if (type != null) {
-            MethodType epType = type.insertParameterTypes(0, entryPoint.type().parameterType(0));
-            entryPoint = MethodHandles.convertArguments(entryPoint, epType);
-        }
-        return entryPoint;
-    }
-
     /** Make sure the given {@code argument} can be used as {@code argnum}-th
      *  parameter of the given method handle {@code mh}, which must be a reference.
      *  <p>
--- a/jdk/src/share/classes/sun/dyn/CallSiteImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/dyn/CallSiteImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -26,6 +26,7 @@
 package sun.dyn;
 
 import java.dyn.*;
+import static sun.dyn.MemberName.uncaughtException;
 
 /**
  * Parts of CallSite known to the JVM.
@@ -49,18 +50,21 @@
         }
         CallSite site;
         try {
-            if (bootstrapMethod.type().parameterCount() == 3)
-                site = bootstrapMethod.<CallSite>invokeExact(caller, name, type);
-            else if (bootstrapMethod.type().parameterCount() == 4)
-                site = bootstrapMethod.<CallSite>invokeExact(caller, name, type,
-                                                             !(info instanceof java.lang.annotation.Annotation[]) ? null
-                                                             : (java.lang.annotation.Annotation[]) info);
+            Object binding;
+            if (false)  // switch when invokeGeneric works
+                binding = bootstrapMethod.invokeGeneric(caller, name, type);
             else
-                throw new InternalError("bad BSM: "+bootstrapMethod);
-            if (!(site instanceof CallSite))
-                throw new InvokeDynamicBootstrapError("class bootstrap method failed to create a call site: "+caller);
-            PRIVATE_INITIALIZE_CALL_SITE.<void>invokeExact(site,
-                                                           name, type,
+                binding = bootstrapMethod.invokeVarargs(new Object[]{ caller, name, type });
+            //System.out.println("BSM for "+name+type+" => "+binding);
+            if (binding instanceof CallSite) {
+                site = (CallSite) binding;
+            } else if (binding instanceof MethodHandleProvider) {
+                MethodHandle target = ((MethodHandleProvider) binding).asMethodHandle();
+                site = new ConstantCallSite(target);
+            } else {
+                throw new ClassCastException("bootstrap method failed to produce a MethodHandle or CallSite");
+            }
+            PRIVATE_INITIALIZE_CALL_SITE.<void>invokeExact(site, name, type,
                                                            callerMethod, callerBCI);
             assert(site.getTarget() != null);
             assert(site.getTarget().type().equals(type));
@@ -77,11 +81,18 @@
 
     // This method is private in CallSite because it touches private fields in CallSite.
     // These private fields (vmmethod, vmindex) are specific to the JVM.
-    private static final MethodHandle PRIVATE_INITIALIZE_CALL_SITE =
+    private static final MethodHandle PRIVATE_INITIALIZE_CALL_SITE;
+    static {
+        try {
+            PRIVATE_INITIALIZE_CALL_SITE =
             MethodHandleImpl.IMPL_LOOKUP.findVirtual(CallSite.class, "initializeFromJVM",
                 MethodType.methodType(void.class,
                                       String.class, MethodType.class,
                                       MemberName.class, int.class));
+        } catch (NoAccessException ex) {
+            throw uncaughtException(ex);
+        }
+    }
 
     public static void setCallSiteTarget(Access token, CallSite site, MethodHandle target) {
         Access.check(token);
--- a/jdk/src/share/classes/sun/dyn/FilterGeneric.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/dyn/FilterGeneric.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,12 +25,8 @@
 
 package sun.dyn;
 
-import java.dyn.JavaMethodHandle;
-import java.dyn.MethodHandle;
-import java.dyn.MethodType;
-import java.dyn.NoAccessException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
+import java.dyn.*;
+import java.lang.reflect.*;
 import static sun.dyn.MemberName.newIllegalArgumentException;
 
 /**
@@ -119,7 +115,7 @@
 
     static MethodHandle make(Kind kind, int pos, MethodHandle filter, MethodHandle target) {
         FilterGeneric fgen = of(kind, pos, filter.type(), target.type());
-        return fgen.makeInstance(kind, pos, filter, target);
+        return fgen.makeInstance(kind, pos, filter, target).asMethodHandle();
     }
 
     /** Return the adapter information for this target and filter type. */
--- a/jdk/src/share/classes/sun/dyn/FilterOneArgument.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/dyn/FilterOneArgument.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,9 +25,8 @@
 
 package sun.dyn;
 
-import java.dyn.JavaMethodHandle;
-import java.dyn.MethodHandle;
-import java.dyn.MethodType;
+import java.dyn.*;
+import static sun.dyn.MemberName.uncaughtException;
 
 /**
  * Unary function composition, useful for many small plumbing jobs.
@@ -51,8 +50,16 @@
         return target.invokeExact(filteredArgument);
     }
 
-    private static final MethodHandle INVOKE =
-        MethodHandleImpl.IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "invoke", MethodType.genericMethodType(1));
+    private static final MethodHandle INVOKE;
+    static {
+        try {
+            INVOKE =
+                MethodHandleImpl.IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "invoke",
+                                                         MethodType.genericMethodType(1));
+        } catch (NoAccessException ex) {
+            throw uncaughtException(ex);
+        }
+    }
 
     protected FilterOneArgument(MethodHandle filter, MethodHandle target) {
         super(INVOKE);
--- a/jdk/src/share/classes/sun/dyn/FromGeneric.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/dyn/FromGeneric.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,15 +25,9 @@
 
 package sun.dyn;
 
-import java.dyn.JavaMethodHandle;
-import java.dyn.MethodHandle;
-import java.dyn.MethodHandles;
-import java.dyn.MethodType;
-import java.dyn.NoAccessException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import sun.dyn.util.ValueConversions;
-import sun.dyn.util.Wrapper;
+import java.dyn.*;
+import java.lang.reflect.*;
+import sun.dyn.util.*;
 
 /**
  * Adapters which mediate between incoming calls which are generic
--- a/jdk/src/share/classes/sun/dyn/Invokers.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/dyn/Invokers.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,10 +25,7 @@
 
 package sun.dyn;
 
-import java.dyn.MethodHandle;
-import java.dyn.MethodHandles;
-import java.dyn.MethodType;
-
+import java.dyn.*;
 
 /**
  * Construction and caching of often-used invokers.
@@ -63,8 +60,11 @@
     public MethodHandle exactInvoker() {
         MethodHandle invoker = exactInvoker;
         if (invoker != null)  return invoker;
-        invoker = MethodHandleImpl.IMPL_LOOKUP.findVirtual(MethodHandle.class, "invoke", targetType);
-        if (invoker == null)  throw new InternalError("JVM cannot find invoker for "+targetType);
+        try {
+            invoker = MethodHandleImpl.IMPL_LOOKUP.findVirtual(MethodHandle.class, "invoke", targetType);
+        } catch (NoAccessException ex) {
+            throw new InternalError("JVM cannot find invoker for "+targetType);
+        }
         assert(invokerType(targetType) == invoker.type());
         exactInvoker = invoker;
         return invoker;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/dyn/JavaMethodHandle.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2008, 2009, 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.
+ */
+
+package sun.dyn;
+
+import java.dyn.*;
+import sun.dyn.Access;
+
+/**
+ * A Java method handle is a deprecated proposal for extending
+ * the basic method handle type with additional
+ * programmer defined methods and fields.
+ * Its behavior as a method handle is determined at instance creation time,
+ * by providing the new instance with an "entry point" method handle
+ * to handle calls.  This entry point must accept a leading argument
+ * whose type is the Java method handle itself or a supertype, and the
+ * entry point is always called with the Java method handle itself as
+ * the first argument.  This is similar to ordinary virtual methods, which also
+ * accept the receiver object {@code this} as an implicit leading argument.
+ * The {@code MethodType} of the Java method handle is the same as that
+ * of the entry point method handle, with the leading parameter type
+ * omitted.
+ * <p>
+ * Here is an example of usage, creating a hybrid object/functional datum:
+ * <p><blockquote><pre>
+ * class Greeter extends JavaMethodHandle {
+ *     private String greeting = "hello";
+ *     public void setGreeting(String s) { greeting = s; }
+ *     public void run() { System.out.println(greeting+", "+greetee); }
+ *     private final String greetee;
+ *     Greeter(String greetee) {
+ *         super(RUN); // alternatively, super("run")
+ *         this.greetee = greetee;
+ *     }
+ *     // the entry point function is computed once:
+ *     private static final MethodHandle RUN
+ *         = MethodHandles.lookup().findVirtual(Greeter.class, "run",
+ *               MethodType.make(void.class));
+ * }
+ * // class Main { public static void main(String... av) { ...
+ * Greeter greeter = new Greeter("world");
+ * greeter.run();  // prints "hello, world"
+ * // Statically typed method handle invocation (most direct):
+ * MethodHandle mh = greeter;
+ * mh.&lt;void&gt;invokeExact();  // also prints "hello, world"
+ * // Dynamically typed method handle invocation:
+ * MethodHandles.invokeExact(greeter);  // also prints "hello, world"
+ * greeter.setGreeting("howdy");
+ * mh.invokeExact();  // prints "howdy, world" (object-like mutable behavior)
+ * </pre></blockquote>
+ * <p>
+ * In the example of {@code Greeter}, the method {@code run} provides the entry point.
+ * The entry point need not be a constant value; it may be independently
+ * computed in each call to the constructor.  The entry point does not
+ * even need to be a method on the {@code Greeter} class, though
+ * that is the typical case.
+ * <p>
+ * The entry point may also be provided symbolically, in which case the the
+ * {@code JavaMethodHandle} constructor performs the lookup of the entry point.
+ * This makes it possible to use {@code JavaMethodHandle} to create an anonymous
+ * inner class:
+ * <p><blockquote><pre>
+ * // We can also do this with symbolic names and/or inner classes:
+ * MethodHandles.invokeExact(new JavaMethodHandle("yow") {
+ *     void yow() { System.out.println("yow, world"); }
+ * });
+ * </pre></blockquote>
+ * <p>
+ * Here is similar lower-level code which works in terms of a bound method handle.
+ * <p><blockquote><pre>
+ *     class Greeter {
+ *         public void run() { System.out.println("hello, "+greetee); }
+ *         private final String greetee;
+ *         Greeter(String greetee) { this.greetee = greetee; }
+ *         // the entry point function is computed once:
+ *         private static final MethodHandle RUN
+ *             = MethodHandles.findVirtual(Greeter.class, "run",
+ *                   MethodType.make(void.class));
+ *     }
+ *     // class Main { public static void main(String... av) { ...
+ *     Greeter greeter = new Greeter("world");
+ *     greeter.run();  // prints "hello, world"
+ *     MethodHandle mh = MethodHanndles.insertArgument(Greeter.RUN, 0, greeter);
+ *     mh.invokeExact();  // also prints "hello, world"
+ * </pre></blockquote>
+ * Note that the method handle must be separately created as a view on the base object.
+ * This increases footprint, complexity, and dynamic indirections.
+ * <p>
+ * Here is a pure functional value expressed most concisely as an anonymous inner class:
+ * <p><blockquote><pre>
+ *     // class Main { public static void main(String... av) { ...
+ *     final String greetee = "world";
+ *     MethodHandle greeter = new JavaMethodHandle("run") {
+ *         private void run() { System.out.println("hello, "+greetee); }
+ *     }
+ *     greeter.invokeExact();  // prints "hello, world"
+ * </pre></blockquote>
+ * <p>
+ * Here is an abstract parameterized lvalue, efficiently expressed as a subtype of MethodHandle,
+ * and instantiated as an anonymous class.  The data structure is a handle to 1-D array,
+ * with a specialized index type (long).  It is created by inner class, and uses
+ * signature-polymorphic APIs throughout.
+ * <p><blockquote><pre>
+ *     abstract class AssignableMethodHandle extends JavaMethodHandle {
+ *       private final MethodHandle setter;
+ *       public MethodHandle setter() { return setter; }
+ *       public AssignableMethodHandle(String get, String set) {
+ *         super(get);
+ *         MethodType getType = this.type();
+ *         MethodType setType = getType.insertParameterType(getType.parameterCount(), getType.returnType()).changeReturnType(void.class);
+ *         this.setter = MethodHandles.publicLookup().bind(this, set, setType);
+ *       }
+ *     }
+ *     // class Main { public static void main(String... av) { ...
+ *     final Number[] stuff = { 123, 456 };
+ *     AssignableMethodHandle stuffPtr = new AssignableMethodHandle("get", "set") {
+ *         public Number get(long i)           { return stuff[(int)i]; }
+ *         public void   set(long i, Object x) {        stuff[(int)i] = x; }
+ *     }
+ *     int x = (Integer) stuffPtr.&lt;Number&gt;invokeExact(1L);  // 456
+ *     stuffPtr.setter().&lt;void&gt;invokeExact(0L, (Number) 789);  // replaces 123 with 789
+ * </pre></blockquote>
+ * @see MethodHandle
+ * @deprecated The JSR 292 EG intends to replace {@code JavaMethodHandle} with
+ * an interface-based API for mixing method handle behavior with other classes.
+ * @author John Rose, JSR 292 EG
+ */
+public abstract class JavaMethodHandle
+        // Note: This is an implementation inheritance hack, and will be removed
+        // with a JVM change which moves the required hidden behavior onto this class.
+        extends sun.dyn.BoundMethodHandle
+{
+    private static final Access IMPL_TOKEN = Access.getToken();
+
+    /**
+     * When creating a {@code JavaMethodHandle}, the actual method handle
+     * invocation behavior will be delegated to the specified {@code entryPoint}.
+     * This may be any method handle which can take the newly constructed object
+     * as a leading parameter.
+     * <p>
+     * The method handle type of {@code this} (i.e, the fully constructed object)
+     * will be {@code entryPoint}, minus the leading argument.
+     * The leading argument will be bound to {@code this} on every method
+     * handle invocation.
+     * @param entryPoint the method handle to handle calls
+     */
+    protected JavaMethodHandle(MethodHandle entryPoint) {
+        super(entryPoint);
+    }
+}
--- a/jdk/src/share/classes/sun/dyn/MemberName.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/dyn/MemberName.java	Wed Jul 05 17:26:57 2017 +0200
@@ -521,6 +521,11 @@
         if (lookupClass != null)  message += ", from " + lookupClass.getName();
         return new NoAccessException(message);
     }
+    public static Error uncaughtException(Exception ex) {
+        Error err = new InternalError("uncaught exception");
+        err.initCause(ex);
+        return err;
+    }
 
     /** Actually making a query requires an access check. */
     public static Factory getFactory(Access token) {
@@ -641,7 +646,7 @@
          *  If lookup fails or access is not permitted, a {@linkplain NoAccessException} is thrown.
          *  Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
          */
-        public MemberName resolveOrFail(MemberName m, boolean searchSupers, Class<?> lookupClass) {
+        public MemberName resolveOrFail(MemberName m, boolean searchSupers, Class<?> lookupClass) throws NoAccessException {
             MemberName result = resolveOrNull(m, searchSupers, lookupClass);
             if (result != null)
                 return result;
--- a/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,11 +25,8 @@
 
 package sun.dyn;
 
-import java.dyn.JavaMethodHandle;
-import java.dyn.MethodHandle;
-import java.dyn.MethodHandles;
+import java.dyn.*;
 import java.dyn.MethodHandles.Lookup;
-import java.dyn.MethodType;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import sun.dyn.util.VerifyType;
@@ -46,6 +43,7 @@
 import sun.misc.Unsafe;
 import static sun.dyn.MemberName.newIllegalArgumentException;
 import static sun.dyn.MemberName.newNoAccessException;
+import static sun.dyn.MemberName.uncaughtException;
 
 /**
  * Base class for method handles, containing JVM-specific fields and logic.
@@ -173,7 +171,7 @@
      */
     public static
     MethodHandle findMethod(Access token, MemberName method,
-            boolean doDispatch, Class<?> lookupClass) {
+            boolean doDispatch, Class<?> lookupClass) throws NoAccessException {
         Access.check(token);  // only trusted calls
         MethodType mtype = method.getMethodType();
         if (!method.isStatic()) {
@@ -320,7 +318,7 @@
             try {
                 VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "invoke_V", MethodType.genericMethodType(0, true));
             } catch (NoAccessException ex) {
-                throw new InternalError("");
+                throw uncaughtException(ex);
             }
         }
         // Corresponding generic constructor types:
@@ -416,9 +414,7 @@
                 f = c.getDeclaredField(field.getName());
                 return unsafe.staticFieldBase(f);
             } catch (Exception ee) {
-                Error e = new InternalError();
-                e.initCause(ee);
-                throw e;
+                throw uncaughtException(ee);
             }
         }
 
@@ -473,10 +469,8 @@
             MethodHandle mh;
             try {
                 mh = IMPL_LOOKUP.findVirtual(FieldAccessor.class, name, type);
-            } catch (NoAccessException ee) {
-                Error e = new InternalError("name,type="+name+type);
-                e.initCause(ee);
-                throw e;
+            } catch (NoAccessException ex) {
+                throw uncaughtException(ex);
             }
             if (evclass != vclass || (!isStatic && ecclass != cclass)) {
                 MethodType strongType = FieldAccessor.ftype(cclass, vclass, isSetter, isStatic);
@@ -543,10 +537,8 @@
             MethodHandle mh;
             try {
                 mh = IMPL_LOOKUP.findStatic(FieldAccessor.class, name, type);
-            } catch (NoAccessException ee) {
-                Error e = new InternalError("name,type="+name+type);
-                e.initCause(ee);
-                throw e;
+            } catch (NoAccessException ex) {
+                throw uncaughtException(ex);
             }
             if (caclass != null) {
                 MethodType strongType = FieldAccessor.atype(caclass, isSetter);
@@ -1031,7 +1023,7 @@
             try {
                 VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithTest.class, "invoke_V", MethodType.genericMethodType(0, true));
             } catch (NoAccessException ex) {
-                throw new InternalError("");
+                throw uncaughtException(ex);
             }
         }
     }
@@ -1167,7 +1159,7 @@
             try {
                 VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true));
             } catch (NoAccessException ex) {
-                throw new InternalError("");
+                throw uncaughtException(ex);
             }
         }
     }
@@ -1207,9 +1199,16 @@
         return AdapterMethodHandle.makeRetypeRaw(token, type, THROW_EXCEPTION);
     }
 
-    static final MethodHandle THROW_EXCEPTION
+    static final MethodHandle THROW_EXCEPTION;
+    static {
+        try {
+            THROW_EXCEPTION
             = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException",
                     MethodType.methodType(Empty.class, Throwable.class));
+        } catch (NoAccessException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
     static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
 
     public static String getNameString(Access token, MethodHandle target) {
--- a/jdk/src/share/classes/sun/dyn/MethodHandleNatives.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/dyn/MethodHandleNatives.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,9 +25,7 @@
 
 package sun.dyn;
 
-import java.dyn.CallSite;
-import java.dyn.MethodHandle;
-import java.dyn.MethodType;
+import java.dyn.*;
 import java.dyn.MethodHandles.Lookup;
 import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.Field;
@@ -324,18 +322,24 @@
      */
     static MethodHandle linkMethodHandleConstant(Class<?> callerClass, int refKind,
                                                  Class<?> defc, String name, Object type) {
-        Lookup lookup = IMPL_LOOKUP.in(callerClass);
-        switch (refKind) {
-        case REF_getField:          return lookup.findGetter(       defc, name, (Class<?>)   type );
-        case REF_getStatic:         return lookup.findStaticGetter( defc, name, (Class<?>)   type );
-        case REF_putField:          return lookup.findSetter(       defc, name, (Class<?>)   type );
-        case REF_putStatic:         return lookup.findStaticSetter( defc, name, (Class<?>)   type );
-        case REF_invokeVirtual:     return lookup.findVirtual(      defc, name, (MethodType) type );
-        case REF_invokeStatic:      return lookup.findStatic(       defc, name, (MethodType) type );
-        case REF_invokeSpecial:     return lookup.findSpecial(      defc, name, (MethodType) type, callerClass );
-        case REF_newInvokeSpecial:  return lookup.findConstructor(  defc,       (MethodType) type );
-        case REF_invokeInterface:   return lookup.findVirtual(      defc, name, (MethodType) type );
+        try {
+            Lookup lookup = IMPL_LOOKUP.in(callerClass);
+            switch (refKind) {
+            case REF_getField:          return lookup.findGetter(       defc, name, (Class<?>)   type );
+            case REF_getStatic:         return lookup.findStaticGetter( defc, name, (Class<?>)   type );
+            case REF_putField:          return lookup.findSetter(       defc, name, (Class<?>)   type );
+            case REF_putStatic:         return lookup.findStaticSetter( defc, name, (Class<?>)   type );
+            case REF_invokeVirtual:     return lookup.findVirtual(      defc, name, (MethodType) type );
+            case REF_invokeStatic:      return lookup.findStatic(       defc, name, (MethodType) type );
+            case REF_invokeSpecial:     return lookup.findSpecial(      defc, name, (MethodType) type, callerClass );
+            case REF_newInvokeSpecial:  return lookup.findConstructor(  defc,       (MethodType) type );
+            case REF_invokeInterface:   return lookup.findVirtual(      defc, name, (MethodType) type );
+            }
+            throw new IllegalArgumentException("bad MethodHandle constant "+name+" : "+type);
+        } catch (NoAccessException ex) {
+            Error err = new IncompatibleClassChangeError();
+            err.initCause(ex);
+            throw err;
         }
-        throw new IllegalArgumentException("bad MethodHandle constant "+name+" : "+type);
     }
 }
--- a/jdk/src/share/classes/sun/dyn/SpreadGeneric.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/dyn/SpreadGeneric.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,11 +25,7 @@
 
 package sun.dyn;
 
-import java.dyn.JavaMethodHandle;
-import java.dyn.MethodHandle;
-import java.dyn.MethodHandles;
-import java.dyn.MethodType;
-import java.dyn.NoAccessException;
+import java.dyn.*;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
--- a/jdk/src/share/classes/sun/dyn/ToGeneric.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/dyn/ToGeneric.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,11 +25,7 @@
 
 package sun.dyn;
 
-import java.dyn.JavaMethodHandle;
-import java.dyn.MethodHandle;
-import java.dyn.MethodHandles;
-import java.dyn.MethodType;
-import java.dyn.NoAccessException;
+import java.dyn.*;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import sun.dyn.util.ValueConversions;
--- a/jdk/src/share/classes/sun/dyn/util/ValueConversions.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/dyn/util/ValueConversions.java	Wed Jul 05 17:26:57 2017 +0200
@@ -34,6 +34,7 @@
 import sun.dyn.Access;
 import sun.dyn.AdapterMethodHandle;
 import sun.dyn.MethodHandleImpl;
+import static sun.dyn.MemberName.uncaughtException;
 
 public class ValueConversions {
     private static final Access IMPL_TOKEN = Access.getToken();
@@ -148,11 +149,16 @@
         // look up the method
         String name = "unbox" + wrap.simpleName() + (raw ? "Raw" : "");
         MethodType type = unboxType(wrap, raw);
-        if (!exact)
-            // actually, type is wrong; the Java method takes Object
-            mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type.erase());
-        else
+        if (!exact) {
+            try {
+                // actually, type is wrong; the Java method takes Object
+                mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type.erase());
+            } catch (NoAccessException ex) {
+                mh = null;
+            }
+        } else {
             mh = retype(type, unbox(wrap, !exact, raw));
+        }
         if (mh != null) {
             cache.put(wrap, mh);
             return mh;
@@ -280,10 +286,15 @@
         // look up the method
         String name = "box" + wrap.simpleName() + (raw ? "Raw" : "");
         MethodType type = boxType(wrap, raw);
-        if (exact)
-            mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type);
-        else
+        if (exact) {
+            try {
+                mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type);
+            } catch (NoAccessException ex) {
+                mh = null;
+            }
+        } else {
             mh = retype(type.erase(), box(wrap, !exact, raw));
+        }
         if (mh != null) {
             cache.put(wrap, mh);
             return mh;
@@ -394,10 +405,15 @@
         // look up the method
         String name = "reboxRaw" + wrap.simpleName();
         MethodType type = reboxType(wrap);
-        if (exact)
-            mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type);
-        else
+        if (exact) {
+            try {
+                mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type);
+            } catch (NoAccessException ex) {
+                mh = null;
+            }
+        } else {
             mh = retype(IDENTITY.type(), rebox(wrap, !exact));
+        }
         if (mh != null) {
             cache.put(wrap, mh);
             return mh;
@@ -474,7 +490,11 @@
                 mh = EMPTY;
                 break;
             case INT: case LONG: case FLOAT: case DOUBLE:
-                mh = IMPL_LOOKUP.findStatic(ValueConversions.class, "zero"+wrap.simpleName(), type);
+                try {
+                    mh = IMPL_LOOKUP.findStatic(ValueConversions.class, "zero"+wrap.simpleName(), type);
+                } catch (NoAccessException ex) {
+                    mh = null;
+                }
                 break;
         }
         if (mh != null) {
@@ -549,8 +569,8 @@
             ZERO_OBJECT = IMPL_LOOKUP.findStatic(ValueConversions.class, "zeroObject", zeroObjectType);
             IGNORE = IMPL_LOOKUP.findStatic(ValueConversions.class, "ignore", ignoreType);
             EMPTY = IMPL_LOOKUP.findStatic(ValueConversions.class, "empty", ignoreType.dropParameterTypes(0, 1));
-        } catch (RuntimeException ex) {
-            throw ex;
+        } catch (Exception ex) {
+            throw uncaughtException(ex);
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/java2d/pisces/Curve.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2007, 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.
+ */
+
+package sun.java2d.pisces;
+
+import java.util.Iterator;
+
+class Curve {
+
+    float ax, ay, bx, by, cx, cy, dx, dy;
+    float dax, day, dbx, dby;
+
+    Curve() {
+    }
+
+    void set(float[] points, int type) {
+        switch(type) {
+        case 8:
+            set(points[0], points[1],
+                points[2], points[3],
+                points[4], points[5],
+                points[6], points[7]);
+            break;
+        case 6:
+            set(points[0], points[1],
+                points[2], points[3],
+                points[4], points[5]);
+            break;
+        default:
+            throw new InternalError("Curves can only be cubic or quadratic");
+        }
+    }
+
+    void set(float x1, float y1,
+             float x2, float y2,
+             float x3, float y3,
+             float x4, float y4)
+    {
+        ax = 3 * (x2 - x3) + x4 - x1;
+        ay = 3 * (y2 - y3) + y4 - y1;
+        bx = 3 * (x1 - 2 * x2 + x3);
+        by = 3 * (y1 - 2 * y2 + y3);
+        cx = 3 * (x2 - x1);
+        cy = 3 * (y2 - y1);
+        dx = x1;
+        dy = y1;
+        dax = 3 * ax; day = 3 * ay;
+        dbx = 2 * bx; dby = 2 * by;
+    }
+
+    void set(float x1, float y1,
+             float x2, float y2,
+             float x3, float y3)
+    {
+        ax = ay = 0f;
+
+        bx = x1 - 2 * x2 + x3;
+        by = y1 - 2 * y2 + y3;
+        cx = 2 * (x2 - x1);
+        cy = 2 * (y2 - y1);
+        dx = x1;
+        dy = y1;
+        dax = 0; day = 0;
+        dbx = 2 * bx; dby = 2 * by;
+    }
+
+    float xat(float t) {
+        return t * (t * (t * ax + bx) + cx) + dx;
+    }
+    float yat(float t) {
+        return t * (t * (t * ay + by) + cy) + dy;
+    }
+
+    float dxat(float t) {
+        return t * (t * dax + dbx) + cx;
+    }
+
+    float dyat(float t) {
+        return t * (t * day + dby) + cy;
+    }
+
+    private float ddxat(float t) {
+        return 2 * dax * t + dbx;
+    }
+
+    private float ddyat(float t) {
+        return 2 * day * t + dby;
+    }
+
+    int dxRoots(float[] roots, int off) {
+        return Helpers.quadraticRoots(dax, dbx, cx, roots, off);
+    }
+
+    int dyRoots(float[] roots, int off) {
+        return Helpers.quadraticRoots(day, dby, cy, roots, off);
+    }
+
+    int infPoints(float[] pts, int off) {
+        // inflection point at t if -f'(t)x*f''(t)y + f'(t)y*f''(t)x == 0
+        // Fortunately, this turns out to be quadratic, so there are at
+        // most 2 inflection points.
+        final float a = dax * dby - dbx * day;
+        final float b = 2 * (cy * dax - day * cx);
+        final float c = cy * dbx - cx * dby;
+
+        return Helpers.quadraticRoots(a, b, c, pts, off);
+    }
+
+    // finds points where the first and second derivative are
+    // perpendicular. This happens when g(t) = f'(t)*f''(t) == 0 (where
+    // * is a dot product). Unfortunately, we have to solve a cubic.
+    private int perpendiculardfddf(float[] pts, int off, final float err) {
+        assert pts.length >= off + 4;
+
+        // these are the coefficients of g(t):
+        final float a = 2*(dax*dax + day*day);
+        final float b = 3*(dax*dbx + day*dby);
+        final float c = 2*(dax*cx + day*cy) + dbx*dbx + dby*dby;
+        final float d = dbx*cx + dby*cy;
+        // TODO: We might want to divide the polynomial by a to make the
+        // coefficients smaller. This won't change the roots.
+        return Helpers.cubicRootsInAB(a, b, c, d, pts, off, err, 0f, 1f);
+    }
+
+    // Tries to find the roots of the function ROC(t)-w in [0, 1). It uses
+    // a variant of the false position algorithm to find the roots. False
+    // position requires that 2 initial values x0,x1 be given, and that the
+    // function must have opposite signs at those values. To find such
+    // values, we need the local extrema of the ROC function, for which we
+    // need the roots of its derivative; however, it's harder to find the
+    // roots of the derivative in this case than it is to find the roots
+    // of the original function. So, we find all points where this curve's
+    // first and second derivative are perpendicular, and we pretend these
+    // are our local extrema. There are at most 3 of these, so we will check
+    // at most 4 sub-intervals of (0,1). ROC has asymptotes at inflection
+    // points, so roc-w can have at least 6 roots. This shouldn't be a
+    // problem for what we're trying to do (draw a nice looking curve).
+    int rootsOfROCMinusW(float[] roots, int off, final float w, final float err) {
+        // no OOB exception, because by now off<=6, and roots.length >= 10
+        assert off <= 6 && roots.length >= 10;
+        int ret = off;
+        int numPerpdfddf = perpendiculardfddf(roots, off, err);
+        float t0 = 0, ft0 = ROCsq(t0) - w*w;
+        roots[off + numPerpdfddf] = 1f; // always check interval end points
+        numPerpdfddf++;
+        for (int i = off; i < off + numPerpdfddf; i++) {
+            float t1 = roots[i], ft1 = ROCsq(t1) - w*w;
+            if (ft0 == 0f) {
+                roots[ret++] = t0;
+            } else if (ft1 * ft0 < 0f) { // have opposite signs
+                // (ROC(t)^2 == w^2) == (ROC(t) == w) is true because
+                // ROC(t) >= 0 for all t.
+                roots[ret++] = falsePositionROCsqMinusX(t0, t1, w*w, err);
+            }
+            t0 = t1;
+            ft0 = ft1;
+        }
+
+        return ret - off;
+    }
+
+    private static float eliminateInf(float x) {
+        return (x == Float.POSITIVE_INFINITY ? Float.MAX_VALUE :
+            (x == Float.NEGATIVE_INFINITY ? Float.MIN_VALUE : x));
+    }
+
+    // A slight modification of the false position algorithm on wikipedia.
+    // This only works for the ROCsq-x functions. It might be nice to have
+    // the function as an argument, but that would be awkward in java6.
+    // It is something to consider for java7, depending on how closures
+    // and function objects turn out. Same goes for the newton's method
+    // algorithm in Helpers.java
+    private float falsePositionROCsqMinusX(float x0, float x1,
+                                           final float x, final float err)
+    {
+        final int iterLimit = 100;
+        int side = 0;
+        float t = x1, ft = eliminateInf(ROCsq(t) - x);
+        float s = x0, fs = eliminateInf(ROCsq(s) - x);
+        float r = s, fr;
+        for (int i = 0; i < iterLimit && Math.abs(t - s) > err * Math.abs(t + s); i++) {
+            r = (fs * t - ft * s) / (fs - ft);
+            fr = ROCsq(r) - x;
+            if (fr * ft > 0) {// have the same sign
+                ft = fr; t = r;
+                if (side < 0) {
+                    fs /= (1 << (-side));
+                    side--;
+                } else {
+                    side = -1;
+                }
+            } else if (fr * fs > 0) {
+                fs = fr; s = r;
+                if (side > 0) {
+                    ft /= (1 << side);
+                    side++;
+                } else {
+                    side = 1;
+                }
+            } else {
+                break;
+            }
+        }
+        return r;
+    }
+
+    // returns the radius of curvature squared at t of this curve
+    // see http://en.wikipedia.org/wiki/Radius_of_curvature_(applications)
+    private float ROCsq(final float t) {
+        final float dx = dxat(t);
+        final float dy = dyat(t);
+        final float ddx = ddxat(t);
+        final float ddy = ddyat(t);
+        final float dx2dy2 = dx*dx + dy*dy;
+        final float ddx2ddy2 = ddx*ddx + ddy*ddy;
+        final float ddxdxddydy = ddx*dx + ddy*dy;
+        float ret = ((dx2dy2*dx2dy2) / (dx2dy2 * ddx2ddy2 - ddxdxddydy*ddxdxddydy))*dx2dy2;
+        return ret;
+    }
+
+    // curve to be broken should be in pts[0]
+    // this will change the contents of both pts and Ts
+    // TODO: There's no reason for Ts to be an array. All we need is a sequence
+    // of t values at which to subdivide. An array statisfies this condition,
+    // but is unnecessarily restrictive. Ts should be an Iterator<Float> instead.
+    // Doing this will also make dashing easier, since we could easily make
+    // LengthIterator an Iterator<Float> and feed it to this function to simplify
+    // the loop in Dasher.somethingTo.
+    static Iterator<float[]> breakPtsAtTs(final float[][] pts, final int type,
+                                          final float[] Ts, final int numTs)
+    {
+        assert pts.length >= 2 && pts[0].length >= 8 && numTs <= Ts.length;
+        return new Iterator<float[]>() {
+            int nextIdx = 0;
+            int nextCurveIdx = 0;
+            float prevT = 0;
+
+            @Override public boolean hasNext() {
+                return nextCurveIdx < numTs + 1;
+            }
+
+            @Override public float[] next() {
+                float[] ret;
+                if (nextCurveIdx < numTs) {
+                    float curT = Ts[nextCurveIdx];
+                    float splitT = (curT - prevT) / (1 - prevT);
+                    Helpers.subdivideAt(splitT,
+                                        pts[nextIdx], 0,
+                                        pts[nextIdx], 0,
+                                        pts[1-nextIdx], 0, type);
+                    updateTs(Ts, Ts[nextCurveIdx], nextCurveIdx + 1, numTs - nextCurveIdx - 1);
+                    ret = pts[nextIdx];
+                    nextIdx = 1 - nextIdx;
+                } else {
+                    ret = pts[nextIdx];
+                }
+                nextCurveIdx++;
+                return ret;
+            }
+
+            @Override public void remove() {}
+        };
+    }
+
+    // precondition: ts[off]...ts[off+len-1] must all be greater than t.
+    private static void updateTs(float[] ts, final float t, final int off, final int len) {
+        for (int i = off; i < off + len; i++) {
+            ts[i] = (ts[i] - t) / (1 - t);
+        }
+    }
+}
+
--- a/jdk/src/share/classes/sun/java2d/pisces/Dasher.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/java2d/pisces/Dasher.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,6 +25,8 @@
 
 package sun.java2d.pisces;
 
+import sun.awt.geom.PathConsumer2D;
+
 /**
  * The <code>Dasher</code> class takes a series of linear commands
  * (<code>moveTo</code>, <code>lineTo</code>, <code>close</code> and
@@ -36,18 +38,16 @@
  * semantics are unclear.
  *
  */
-public class Dasher implements LineSink {
-    private final LineSink output;
+public class Dasher implements sun.awt.geom.PathConsumer2D {
+
+    private final PathConsumer2D out;
     private final float[] dash;
     private final float startPhase;
     private final boolean startDashOn;
     private final int startIdx;
 
-    private final float m00, m10, m01, m11;
-    private final float det;
-
-    private boolean firstDashOn;
     private boolean starting;
+    private boolean needsMoveTo;
 
     private int idx;
     private boolean dashOn;
@@ -55,28 +55,23 @@
 
     private float sx, sy;
     private float x0, y0;
-    private float sx1, sy1;
 
+    // temporary storage for the current curve
+    private float[] curCurvepts;
 
     /**
      * Constructs a <code>Dasher</code>.
      *
-     * @param output an output <code>LineSink</code>.
-     * @param dash an array of <code>int</code>s containing the dash pattern
-     * @param phase an <code>int</code> containing the dash phase
-     * @param transform a <code>Transform4</code> object indicating
-     * the transform that has been previously applied to all incoming
-     * coordinates.  This is required in order to compute dash lengths
-     * properly.
+     * @param out an output <code>PathConsumer2D</code>.
+     * @param dash an array of <code>float</code>s containing the dash pattern
+     * @param phase a <code>float</code> containing the dash phase
      */
-    public Dasher(LineSink output,
-                  float[] dash, float phase,
-                  float a00, float a01, float a10, float a11) {
+    public Dasher(PathConsumer2D out, float[] dash, float phase) {
         if (phase < 0) {
             throw new IllegalArgumentException("phase < 0 !");
         }
 
-        this.output = output;
+        this.out = out;
 
         // Normalize so 0 <= phase < dash[0]
         int idx = 0;
@@ -92,16 +87,19 @@
         this.startPhase = this.phase = phase;
         this.startDashOn = dashOn;
         this.startIdx = idx;
+        this.starting = true;
 
-        m00 = a00;
-        m01 = a01;
-        m10 = a10;
-        m11 = a11;
-        det = m00 * m11 - m01 * m10;
+        // we need curCurvepts to be able to contain 2 curves because when
+        // dashing curves, we need to subdivide it
+        curCurvepts = new float[8 * 2];
     }
 
     public void moveTo(float x0, float y0) {
-        output.moveTo(x0, y0);
+        if (firstSegidx > 0) {
+            out.moveTo(sx, sy);
+            emitFirstSegments();
+        }
+        needsMoveTo = true;
         this.idx = startIdx;
         this.dashOn = this.startDashOn;
         this.phase = this.startPhase;
@@ -110,88 +108,108 @@
         this.starting = true;
     }
 
-    public void lineJoin() {
-        output.lineJoin();
+    private void emitSeg(float[] buf, int off, int type) {
+        switch (type) {
+        case 8:
+            out.curveTo(buf[off+0], buf[off+1],
+                        buf[off+2], buf[off+3],
+                        buf[off+4], buf[off+5]);
+            break;
+        case 6:
+            out.quadTo(buf[off+0], buf[off+1],
+                       buf[off+2], buf[off+3]);
+            break;
+        case 4:
+            out.lineTo(buf[off], buf[off+1]);
+        }
     }
 
-    private void goTo(float x1, float y1) {
+    private void emitFirstSegments() {
+        for (int i = 0; i < firstSegidx; ) {
+            emitSeg(firstSegmentsBuffer, i+1, (int)firstSegmentsBuffer[i]);
+            i += (((int)firstSegmentsBuffer[i]) - 1);
+        }
+        firstSegidx = 0;
+    }
+
+    // We don't emit the first dash right away. If we did, caps would be
+    // drawn on it, but we need joins to be drawn if there's a closePath()
+    // So, we store the path elements that make up the first dash in the
+    // buffer below.
+    private float[] firstSegmentsBuffer = new float[7];
+    private int firstSegidx = 0;
+    // precondition: pts must be in relative coordinates (relative to x0,y0)
+    // fullCurve is true iff the curve in pts has not been split.
+    private void goTo(float[] pts, int off, final int type) {
+        float x = pts[off + type - 4];
+        float y = pts[off + type - 3];
         if (dashOn) {
             if (starting) {
-                this.sx1 = x1;
-                this.sy1 = y1;
-                firstDashOn = true;
-                starting = false;
+                firstSegmentsBuffer = Helpers.widenArray(firstSegmentsBuffer,
+                                      firstSegidx, type - 2);
+                firstSegmentsBuffer[firstSegidx++] = type;
+                System.arraycopy(pts, off, firstSegmentsBuffer, firstSegidx, type - 2);
+                firstSegidx += type - 2;
+            } else {
+                if (needsMoveTo) {
+                    out.moveTo(x0, y0);
+                    needsMoveTo = false;
+                }
+                emitSeg(pts, off, type);
             }
-            output.lineTo(x1, y1);
         } else {
-            if (starting) {
-                firstDashOn = false;
-                starting = false;
-            }
-            output.moveTo(x1, y1);
+            starting = false;
+            needsMoveTo = true;
         }
-        this.x0 = x1;
-        this.y0 = y1;
+        this.x0 = x;
+        this.y0 = y;
     }
 
     public void lineTo(float x1, float y1) {
-        // The widened line is squished to a 0 width one, so no drawing is done
-        if (det == 0) {
-            goTo(x1, y1);
-            return;
-        }
         float dx = x1 - x0;
         float dy = y1 - y0;
 
-
-        // Compute segment length in the untransformed
-        // coordinate system
+        float len = (float) Math.hypot(dx, dy);
 
-        float la = (dy*m00 - dx*m10)/det;
-        float lb = (dy*m01 - dx*m11)/det;
-        float origLen = (float) Math.hypot(la, lb);
-
-        if (origLen == 0) {
-            // Let the output LineSink deal with cases where dx, dy are 0.
-            goTo(x1, y1);
+        if (len == 0) {
             return;
         }
 
         // The scaling factors needed to get the dx and dy of the
         // transformed dash segments.
-        float cx = dx / origLen;
-        float cy = dy / origLen;
+        float cx = dx / len;
+        float cy = dy / len;
 
         while (true) {
             float leftInThisDashSegment = dash[idx] - phase;
-            if (origLen < leftInThisDashSegment) {
-                goTo(x1, y1);
+            if (len <= leftInThisDashSegment) {
+                curCurvepts[0] = x1;
+                curCurvepts[1] = y1;
+                goTo(curCurvepts, 0, 4);
                 // Advance phase within current dash segment
-                phase += origLen;
-                return;
-            } else if (origLen == leftInThisDashSegment) {
-                goTo(x1, y1);
-                phase = 0f;
-                idx = (idx + 1) % dash.length;
-                dashOn = !dashOn;
+                phase += len;
+                if (len == leftInThisDashSegment) {
+                    phase = 0f;
+                    idx = (idx + 1) % dash.length;
+                    dashOn = !dashOn;
+                }
                 return;
             }
 
-            float dashx, dashy;
             float dashdx = dash[idx] * cx;
             float dashdy = dash[idx] * cy;
             if (phase == 0) {
-                dashx = x0 + dashdx;
-                dashy = y0 + dashdy;
+                curCurvepts[0] = x0 + dashdx;
+                curCurvepts[1] = y0 + dashdy;
             } else {
-                float p = (leftInThisDashSegment) / dash[idx];
-                dashx = x0 + p * dashdx;
-                dashy = y0 + p * dashdy;
+                float p = leftInThisDashSegment / dash[idx];
+                curCurvepts[0] = x0 + p * dashdx;
+                curCurvepts[1] = y0 + p * dashdy;
             }
 
-            goTo(dashx, dashy);
+            goTo(curCurvepts, 0, 4);
 
-            origLen -= (dash[idx] - phase);
+            len -= leftInThisDashSegment;
             // Advance to next dash segment
             idx = (idx + 1) % dash.length;
             dashOn = !dashOn;
@@ -199,15 +217,289 @@
         }
     }
 
+    private LengthIterator li = null;
 
-    public void close() {
-        lineTo(sx, sy);
-        if (firstDashOn) {
-            output.lineTo(sx1, sy1);
+    // preconditions: curCurvepts must be an array of length at least 2 * type,
+    // that contains the curve we want to dash in the first type elements
+    private void somethingTo(int type) {
+        if (pointCurve(curCurvepts, type)) {
+            return;
+        }
+        if (li == null) {
+            li = new LengthIterator(4, 0.0001f);
+        }
+        li.initializeIterationOnCurve(curCurvepts, type);
+
+        int curCurveoff = 0; // initially the current curve is at curCurvepts[0...type]
+        float lastSplitT = 0;
+        float t = 0;
+        float leftInThisDashSegment = dash[idx] - phase;
+        while ((t = li.next(leftInThisDashSegment)) < 1) {
+            if (t != 0) {
+                Helpers.subdivideAt((t - lastSplitT) / (1 - lastSplitT),
+                        curCurvepts, curCurveoff,
+                        curCurvepts, 0,
+                        curCurvepts, type, type);
+                lastSplitT = t;
+                goTo(curCurvepts, 2, type);
+                curCurveoff = type;
+            }
+            // Advance to next dash segment
+            idx = (idx + 1) % dash.length;
+            dashOn = !dashOn;
+            phase = 0;
+            leftInThisDashSegment = dash[idx];
+        }
+        goTo(curCurvepts, curCurveoff+2, type);
+        phase += li.lastSegLen();
+        if (phase >= dash[idx]) {
+            phase = 0f;
+            idx = (idx + 1) % dash.length;
+            dashOn = !dashOn;
         }
     }
 
-    public void end() {
-        output.end();
+    private static boolean pointCurve(float[] curve, int type) {
+        for (int i = 2; i < type; i++) {
+            if (curve[i] != curve[i-2]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    // Objects of this class are used to iterate through curves. They return
+    // t values where the left side of the curve has a specified length.
+    // It does this by subdividing the input curve until a certain error
+    // condition has been met. A recursive subdivision procedure would
+    // return as many as 1<<limit curves, but this is an iterator and we
+    // don't need all the curves all at once, so what we carry out a
+    // lazy inorder traversal of the recursion tree (meaning we only move
+    // through the tree when we need the next subdivided curve). This saves
+    // us a lot of memory because at any one time we only need to store
+    // limit+1 curves - one for each level of the tree + 1.
+    // NOTE: the way we do things here is not enough to traverse a general
+    // tree; however, the trees we are interested in have the property that
+    // every non leaf node has exactly 2 children
+    private static class LengthIterator {
+        private enum Side {LEFT, RIGHT};
+        // Holds the curves at various levels of the recursion. The root
+        // (i.e. the original curve) is at recCurveStack[0] (but then it
+        // gets subdivided, the left half is put at 1, so most of the time
+        // only the right half of the original curve is at 0)
+        private float[][] recCurveStack;
+        // sides[i] indicates whether the node at level i+1 in the path from
+        // the root to the current leaf is a left or right child of its parent.
+        private Side[] sides;
+        private int curveType;
+        private final int limit;
+        private final float ERR;
+        private final float minTincrement;
+        // lastT and nextT delimit the current leaf.
+        private float nextT;
+        private float lenAtNextT;
+        private float lastT;
+        private float lenAtLastT;
+        private float lenAtLastSplit;
+        private float lastSegLen;
+        // the current level in the recursion tree. 0 is the root. limit
+        // is the deepest possible leaf.
+        private int recLevel;
+        private boolean done;
+
+        public LengthIterator(int reclimit, float err) {
+            this.limit = reclimit;
+            this.minTincrement = 1f / (1 << limit);
+            this.ERR = err;
+            this.recCurveStack = new float[reclimit+1][8];
+            this.sides = new Side[reclimit];
+            // if any methods are called without first initializing this object on
+            // a curve, we want it to fail ASAP.
+            this.nextT = Float.MAX_VALUE;
+            this.lenAtNextT = Float.MAX_VALUE;
+            this.lenAtLastSplit = Float.MIN_VALUE;
+            this.recLevel = Integer.MIN_VALUE;
+            this.lastSegLen = Float.MAX_VALUE;
+            this.done = true;
+        }
+
+        public void initializeIterationOnCurve(float[] pts, int type) {
+            System.arraycopy(pts, 0, recCurveStack[0], 0, type);
+            this.curveType = type;
+            this.recLevel = 0;
+            this.lastT = 0;
+            this.lenAtLastT = 0;
+            this.nextT = 0;
+            this.lenAtNextT = 0;
+            goLeft(); // initializes nextT and lenAtNextT properly
+            this.lenAtLastSplit = 0;
+            if (recLevel > 0) {
+                this.sides[0] = Side.LEFT;
+                this.done = false;
+            } else {
+                // the root of the tree is a leaf so we're done.
+                this.sides[0] = Side.RIGHT;
+                this.done = true;
+            }
+            this.lastSegLen = 0;
+        }
+
+        // returns the t value where the remaining curve should be split in
+        // order for the left subdivided curve to have length len. If len
+        // is >= than the length of the uniterated curve, it returns 1.
+        public float next(float len) {
+            float targetLength = lenAtLastSplit + len;
+            while(lenAtNextT < targetLength) {
+                if (done) {
+                    lastSegLen = lenAtNextT - lenAtLastSplit;
+                    return 1;
+                }
+                goToNextLeaf();
+            }
+            lenAtLastSplit = targetLength;
+            float t = binSearchForLen(lenAtLastSplit - lenAtLastT,
+                    recCurveStack[recLevel], curveType, lenAtNextT - lenAtLastT, ERR);
+            // t is relative to the current leaf, so we must make it a valid parameter
+            // of the original curve.
+            t = t * (nextT - lastT) + lastT;
+            if (t >= 1) {
+                t = 1;
+                done = true;
+            }
+            // even if done = true, if we're here, that means targetLength
+            // is equal to, or very, very close to the total length of the
+            // curve, so lastSegLen won't be too high. In cases where len
+            // overshoots the curve, this method will exit in the while
+            // loop, and lastSegLen will still be set to the right value.
+            lastSegLen = len;
+            return t;
+        }
+
+        public float lastSegLen() {
+            return lastSegLen;
+        }
+
+        // Returns t such that if leaf is subdivided at t the left
+        // curve will have length len. leafLen must be the length of leaf.
+        private static Curve bsc = new Curve();
+        private static float binSearchForLen(float len, float[] leaf, int type,
+                                             float leafLen, float err)
+        {
+            assert len <= leafLen;
+            bsc.set(leaf, type);
+            float errBound = err*len;
+            float left = 0, right = 1;
+            while (left < right) {
+                float m = (left + right) / 2;
+                if (m == left || m == right) {
+                    return m;
+                }
+                float x = bsc.xat(m);
+                float y = bsc.yat(m);
+                float leftLen = Helpers.linelen(leaf[0], leaf[1], x, y);
+                if (Math.abs(leftLen - len) < errBound) {
+                    return m;
+                }
+                if (leftLen < len) {
+                    left = m;
+                } else {
+                    right = m;
+                }
+            }
+            return left;
+        }
+
+        // go to the next leaf (in an inorder traversal) in the recursion tree
+        // preconditions: must be on a leaf, and that leaf must not be the root.
+        private void goToNextLeaf() {
+            // We must go to the first ancestor node that has an unvisited
+            // right child.
+            recLevel--;
+            while(sides[recLevel] == Side.RIGHT) {
+                if (recLevel == 0) {
+                    done = true;
+                    return;
+                }
+                recLevel--;
+            }
+
+            sides[recLevel] = Side.RIGHT;
+            System.arraycopy(recCurveStack[recLevel], 0, recCurveStack[recLevel+1], 0, curveType);
+            recLevel++;
+            goLeft();
+        }
+
+        // go to the leftmost node from the current node. Return its length.
+        private void goLeft() {
+            float len = onLeaf();
+            if (len >= 0) {
+                lastT = nextT;
+                lenAtLastT = lenAtNextT;
+                nextT += (1 << (limit - recLevel)) * minTincrement;
+                lenAtNextT += len;
+            } else {
+                Helpers.subdivide(recCurveStack[recLevel], 0,
+                                  recCurveStack[recLevel+1], 0,
+                                  recCurveStack[recLevel], 0, curveType);
+                sides[recLevel] = Side.LEFT;
+                recLevel++;
+                goLeft();
+            }
+        }
+
+        // this is a bit of a hack. It returns -1 if we're not on a leaf, and
+        // the length of the leaf if we are on a leaf.
+        private float onLeaf() {
+            float polylen = Helpers.polyLineLength(recCurveStack[recLevel], 0, curveType);
+            float linelen = Helpers.linelen(recCurveStack[recLevel][0], recCurveStack[recLevel][1],
+                    recCurveStack[recLevel][curveType - 2], recCurveStack[recLevel][curveType - 1]);
+            return (polylen - linelen < ERR || recLevel == limit) ?
+                   (polylen + linelen)/2 : -1;
+        }
+    }
+
+    @Override
+    public void curveTo(float x1, float y1,
+                        float x2, float y2,
+                        float x3, float y3)
+    {
+        curCurvepts[0] = x0;        curCurvepts[1] = y0;
+        curCurvepts[2] = x1;        curCurvepts[3] = y1;
+        curCurvepts[4] = x2;        curCurvepts[5] = y2;
+        curCurvepts[6] = x3;        curCurvepts[7] = y3;
+        somethingTo(8);
+    }
+
+    @Override
+    public void quadTo(float x1, float y1, float x2, float y2) {
+        curCurvepts[0] = x0;        curCurvepts[1] = y0;
+        curCurvepts[2] = x1;        curCurvepts[3] = y1;
+        curCurvepts[4] = x2;        curCurvepts[5] = y2;
+        somethingTo(6);
+    }
+
+    public void closePath() {
+        lineTo(sx, sy);
+        if (firstSegidx > 0) {
+            if (!dashOn || needsMoveTo) {
+                out.moveTo(sx, sy);
+            }
+            emitFirstSegments();
+        }
+        moveTo(sx, sy);
+    }
+
+    public void pathDone() {
+        if (firstSegidx > 0) {
+            out.moveTo(sx, sy);
+            emitFirstSegments();
+        }
+        out.pathDone();
+    }
+
+    @Override
+    public long getNativeConsumer() {
+        throw new InternalError("Dasher does not use a native consumer");
     }
 }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/java2d/pisces/Helpers.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 2007, 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.
+ */
+
+package sun.java2d.pisces;
+
+import java.util.Arrays;
+
+final class Helpers {
+    private Helpers() {
+        throw new Error("This is a non instantiable class");
+    }
+
+    static boolean within(final float x, final float y, final float err) {
+        final float d = y - x;
+        return (d <= err && d >= -err);
+    }
+
+    static boolean within(final double x, final double y, final double err) {
+        final double d = y - x;
+        return (d <= err && d >= -err);
+    }
+
+    static int quadraticRoots(final float a, final float b,
+                              final float c, float[] zeroes, final int off)
+    {
+        int ret = off;
+        float t;
+        if (a != 0f) {
+            final float dis = b*b - 4*a*c;
+            if (dis > 0) {
+                final float sqrtDis = (float)Math.sqrt(dis);
+                // depending on the sign of b we use a slightly different
+                // algorithm than the traditional one to find one of the roots
+                // so we can avoid adding numbers of different signs (which
+                // might result in loss of precision).
+                if (b >= 0) {
+                    zeroes[ret++] = (2 * c) / (-b - sqrtDis);
+                    zeroes[ret++] = (-b - sqrtDis) / (2 * a);
+                } else {
+                    zeroes[ret++] = (-b + sqrtDis) / (2 * a);
+                    zeroes[ret++] = (2 * c) / (-b + sqrtDis);
+                }
+            } else if (dis == 0f) {
+                t = (-b) / (2 * a);
+                zeroes[ret++] = t;
+            }
+        } else {
+            if (b != 0f) {
+                t = (-c) / b;
+                zeroes[ret++] = t;
+            }
+        }
+        return ret - off;
+    }
+
+    // find the roots of g(t) = a*t^3 + b*t^2 + c*t + d in [A,B)
+    // We will not use Cardano's method, since it is complicated and
+    // involves too many square and cubic roots. We will use Newton's method.
+    // TODO: this should probably return ALL roots. Then the user can do
+    // his own filtering of roots outside [A,B).
+    static int cubicRootsInAB(final float a, final float b,
+                              final float c, final float d,
+                              float[] pts, final int off, final float E,
+                              final float A, final float B)
+    {
+        if (a == 0) {
+            return quadraticRoots(b, c, d, pts, off);
+        }
+        // the coefficients of g'(t). no dc variable because dc=c
+        // we use these to get the critical points of g(t), which
+        // we then use to chose starting points for Newton's method. These
+        // should be very close to the actual roots.
+        final float da = 3 * a;
+        final float db = 2 * b;
+        int numCritPts = quadraticRoots(da, db, c, pts, off+1);
+        numCritPts = filterOutNotInAB(pts, off+1, numCritPts, A, B) - off - 1;
+        // need them sorted.
+        if (numCritPts == 2 && pts[off+1] > pts[off+2]) {
+            float tmp = pts[off+1];
+            pts[off+1] = pts[off+2];
+            pts[off+2] = tmp;
+        }
+
+        int ret = off;
+
+        // we don't actually care much about the extrema themselves. We
+        // only use them to ensure that g(t) is monotonic in each
+        // interval [pts[i],pts[i+1] (for i in off...off+numCritPts+1).
+        // This will allow us to determine intervals containing exactly
+        // one root.
+        // The end points of the interval are always local extrema.
+        pts[off] = A;
+        pts[off + numCritPts + 1] = B;
+        numCritPts += 2;
+
+        float x0 = pts[off], fx0 = evalCubic(a, b, c, d, x0);
+        for (int i = off; i < off + numCritPts - 1; i++) {
+            float x1 = pts[i+1], fx1 = evalCubic(a, b, c, d, x1);
+            if (fx0 == 0f) {
+                pts[ret++] = x0;
+            } else if (fx1 * fx0 < 0f) { // have opposite signs
+                pts[ret++] = CubicNewton(a, b, c, d,
+                        x0 + fx0 * (x1 - x0) / (fx0 - fx1), E);
+            }
+            x0 = x1;
+            fx0 = fx1;
+        }
+        return ret - off;
+    }
+
+    // precondition: the polynomial to be evaluated must not be 0 at x0.
+    static float CubicNewton(final float a, final float b,
+                             final float c, final float d,
+                             float x0, final float err)
+    {
+        // considering how this function is used, 10 should be more than enough
+        final int itlimit = 10;
+        float fx0 = evalCubic(a, b, c, d, x0);
+        float x1;
+        int count = 0;
+        while(true) {
+            x1 = x0 - (fx0 / evalCubic(0, 3 * a, 2 * b, c, x0));
+            if (Math.abs(x1 - x0) < err * Math.abs(x1 + x0) || count == itlimit) {
+                break;
+            }
+            x0 = x1;
+            fx0 = evalCubic(a, b, c, d, x0);
+            count++;
+        }
+        return x1;
+    }
+
+    // fills the input array with numbers 0, INC, 2*INC, ...
+    static void fillWithIdxes(final float[] data, final int[] idxes) {
+        if (idxes.length > 0) {
+            idxes[0] = 0;
+            for (int i = 1; i < idxes.length; i++) {
+                idxes[i] = idxes[i-1] + (int)data[idxes[i-1]];
+            }
+        }
+    }
+
+    static void fillWithIdxes(final int[] idxes, final int inc) {
+        if (idxes.length > 0) {
+            idxes[0] = 0;
+            for (int i = 1; i < idxes.length; i++) {
+                idxes[i] = idxes[i-1] + inc;
+            }
+        }
+    }
+
+    // These use a hardcoded factor of 2 for increasing sizes. Perhaps this
+    // should be provided as an argument.
+    static float[] widenArray(float[] in, final int cursize, final int numToAdd) {
+        if (in == null) {
+            return new float[5 * numToAdd];
+        }
+        if (in.length >= cursize + numToAdd) {
+            return in;
+        }
+        return Arrays.copyOf(in, 2 * (cursize + numToAdd));
+    }
+    static int[] widenArray(int[] in, final int cursize, final int numToAdd) {
+        if (in.length >= cursize + numToAdd) {
+            return in;
+        }
+        return Arrays.copyOf(in, 2 * (cursize + numToAdd));
+    }
+
+    static float evalCubic(final float a, final float b,
+                           final float c, final float d,
+                           final float t)
+    {
+        return t * (t * (t * a + b) + c) + d;
+    }
+
+    static float evalQuad(final float a, final float b,
+                          final float c, final float t)
+    {
+        return t * (t * a + b) + c;
+    }
+
+    // returns the index 1 past the last valid element remaining after filtering
+    static int filterOutNotInAB(float[] nums, final int off, final int len,
+                                final float a, final float b)
+    {
+        int ret = off;
+        for (int i = off; i < off + len; i++) {
+            if (nums[i] > a && nums[i] < b) {
+                nums[ret++] = nums[i];
+            }
+        }
+        return ret;
+    }
+
+    static float polyLineLength(float[] poly, final int off, final int nCoords) {
+        assert nCoords % 2 == 0 && poly.length >= off + nCoords : "";
+        float acc = 0;
+        for (int i = off + 2; i < off + nCoords; i += 2) {
+            acc += linelen(poly[i], poly[i+1], poly[i-2], poly[i-1]);
+        }
+        return acc;
+    }
+
+    static float linelen(float x1, float y1, float x2, float y2) {
+        return (float)Math.hypot(x2 - x1, y2 - y1);
+    }
+
+    static void subdivide(float[] src, int srcoff, float[] left, int leftoff,
+                          float[] right, int rightoff, int type)
+    {
+        switch(type) {
+        case 6:
+            Helpers.subdivideQuad(src, srcoff, left, leftoff, right, rightoff);
+            break;
+        case 8:
+            Helpers.subdivideCubic(src, srcoff, left, leftoff, right, rightoff);
+            break;
+        default:
+            throw new InternalError("Unsupported curve type");
+        }
+    }
+
+    static void isort(float[] a, int off, int len) {
+        for (int i = off + 1; i < off + len; i++) {
+            float ai = a[i];
+            int j = i - 1;
+            for (; j >= off && a[j] > ai; j--) {
+                a[j+1] = a[j];
+            }
+            a[j+1] = ai;
+        }
+    }
+
+    // Most of these are copied from classes in java.awt.geom because we need
+    // float versions of these functions, and Line2D, CubicCurve2D,
+    // QuadCurve2D don't provide them.
+    /**
+     * Subdivides the cubic curve specified by the coordinates
+     * stored in the <code>src</code> array at indices <code>srcoff</code>
+     * through (<code>srcoff</code>&nbsp;+&nbsp;7) and stores the
+     * resulting two subdivided curves into the two result arrays at the
+     * corresponding indices.
+     * Either or both of the <code>left</code> and <code>right</code>
+     * arrays may be <code>null</code> or a reference to the same array
+     * as the <code>src</code> array.
+     * Note that the last point in the first subdivided curve is the
+     * same as the first point in the second subdivided curve. Thus,
+     * it is possible to pass the same array for <code>left</code>
+     * and <code>right</code> and to use offsets, such as <code>rightoff</code>
+     * equals (<code>leftoff</code> + 6), in order
+     * to avoid allocating extra storage for this common point.
+     * @param src the array holding the coordinates for the source curve
+     * @param srcoff the offset into the array of the beginning of the
+     * the 6 source coordinates
+     * @param left the array for storing the coordinates for the first
+     * half of the subdivided curve
+     * @param leftoff the offset into the array of the beginning of the
+     * the 6 left coordinates
+     * @param right the array for storing the coordinates for the second
+     * half of the subdivided curve
+     * @param rightoff the offset into the array of the beginning of the
+     * the 6 right coordinates
+     * @since 1.7
+     */
+    static void subdivideCubic(float src[], int srcoff,
+                               float left[], int leftoff,
+                               float right[], int rightoff)
+    {
+        float x1 = src[srcoff + 0];
+        float y1 = src[srcoff + 1];
+        float ctrlx1 = src[srcoff + 2];
+        float ctrly1 = src[srcoff + 3];
+        float ctrlx2 = src[srcoff + 4];
+        float ctrly2 = src[srcoff + 5];
+        float x2 = src[srcoff + 6];
+        float y2 = src[srcoff + 7];
+        if (left != null) {
+            left[leftoff + 0] = x1;
+            left[leftoff + 1] = y1;
+        }
+        if (right != null) {
+            right[rightoff + 6] = x2;
+            right[rightoff + 7] = y2;
+        }
+        x1 = (x1 + ctrlx1) / 2.0f;
+        y1 = (y1 + ctrly1) / 2.0f;
+        x2 = (x2 + ctrlx2) / 2.0f;
+        y2 = (y2 + ctrly2) / 2.0f;
+        float centerx = (ctrlx1 + ctrlx2) / 2.0f;
+        float centery = (ctrly1 + ctrly2) / 2.0f;
+        ctrlx1 = (x1 + centerx) / 2.0f;
+        ctrly1 = (y1 + centery) / 2.0f;
+        ctrlx2 = (x2 + centerx) / 2.0f;
+        ctrly2 = (y2 + centery) / 2.0f;
+        centerx = (ctrlx1 + ctrlx2) / 2.0f;
+        centery = (ctrly1 + ctrly2) / 2.0f;
+        if (left != null) {
+            left[leftoff + 2] = x1;
+            left[leftoff + 3] = y1;
+            left[leftoff + 4] = ctrlx1;
+            left[leftoff + 5] = ctrly1;
+            left[leftoff + 6] = centerx;
+            left[leftoff + 7] = centery;
+        }
+        if (right != null) {
+            right[rightoff + 0] = centerx;
+            right[rightoff + 1] = centery;
+            right[rightoff + 2] = ctrlx2;
+            right[rightoff + 3] = ctrly2;
+            right[rightoff + 4] = x2;
+            right[rightoff + 5] = y2;
+        }
+    }
+
+
+    static void subdivideCubicAt(float t, float src[], int srcoff,
+                                 float left[], int leftoff,
+                                 float right[], int rightoff)
+    {
+        float x1 = src[srcoff + 0];
+        float y1 = src[srcoff + 1];
+        float ctrlx1 = src[srcoff + 2];
+        float ctrly1 = src[srcoff + 3];
+        float ctrlx2 = src[srcoff + 4];
+        float ctrly2 = src[srcoff + 5];
+        float x2 = src[srcoff + 6];
+        float y2 = src[srcoff + 7];
+        if (left != null) {
+            left[leftoff + 0] = x1;
+            left[leftoff + 1] = y1;
+        }
+        if (right != null) {
+            right[rightoff + 6] = x2;
+            right[rightoff + 7] = y2;
+        }
+        x1 = x1 + t * (ctrlx1 - x1);
+        y1 = y1 + t * (ctrly1 - y1);
+        x2 = ctrlx2 + t * (x2 - ctrlx2);
+        y2 = ctrly2 + t * (y2 - ctrly2);
+        float centerx = ctrlx1 + t * (ctrlx2 - ctrlx1);
+        float centery = ctrly1 + t * (ctrly2 - ctrly1);
+        ctrlx1 = x1 + t * (centerx - x1);
+        ctrly1 = y1 + t * (centery - y1);
+        ctrlx2 = centerx + t * (x2 - centerx);
+        ctrly2 = centery + t * (y2 - centery);
+        centerx = ctrlx1 + t * (ctrlx2 - ctrlx1);
+        centery = ctrly1 + t * (ctrly2 - ctrly1);
+        if (left != null) {
+            left[leftoff + 2] = x1;
+            left[leftoff + 3] = y1;
+            left[leftoff + 4] = ctrlx1;
+            left[leftoff + 5] = ctrly1;
+            left[leftoff + 6] = centerx;
+            left[leftoff + 7] = centery;
+        }
+        if (right != null) {
+            right[rightoff + 0] = centerx;
+            right[rightoff + 1] = centery;
+            right[rightoff + 2] = ctrlx2;
+            right[rightoff + 3] = ctrly2;
+            right[rightoff + 4] = x2;
+            right[rightoff + 5] = y2;
+        }
+    }
+
+    static void subdivideQuad(float src[], int srcoff,
+                              float left[], int leftoff,
+                              float right[], int rightoff)
+    {
+        float x1 = src[srcoff + 0];
+        float y1 = src[srcoff + 1];
+        float ctrlx = src[srcoff + 2];
+        float ctrly = src[srcoff + 3];
+        float x2 = src[srcoff + 4];
+        float y2 = src[srcoff + 5];
+        if (left != null) {
+            left[leftoff + 0] = x1;
+            left[leftoff + 1] = y1;
+        }
+        if (right != null) {
+            right[rightoff + 4] = x2;
+            right[rightoff + 5] = y2;
+        }
+        x1 = (x1 + ctrlx) / 2.0f;
+        y1 = (y1 + ctrly) / 2.0f;
+        x2 = (x2 + ctrlx) / 2.0f;
+        y2 = (y2 + ctrly) / 2.0f;
+        ctrlx = (x1 + x2) / 2.0f;
+        ctrly = (y1 + y2) / 2.0f;
+        if (left != null) {
+            left[leftoff + 2] = x1;
+            left[leftoff + 3] = y1;
+            left[leftoff + 4] = ctrlx;
+            left[leftoff + 5] = ctrly;
+        }
+        if (right != null) {
+            right[rightoff + 0] = ctrlx;
+            right[rightoff + 1] = ctrly;
+            right[rightoff + 2] = x2;
+            right[rightoff + 3] = y2;
+        }
+    }
+
+    static void subdivideQuadAt(float t, float src[], int srcoff,
+                                float left[], int leftoff,
+                                float right[], int rightoff)
+    {
+        float x1 = src[srcoff + 0];
+        float y1 = src[srcoff + 1];
+        float ctrlx = src[srcoff + 2];
+        float ctrly = src[srcoff + 3];
+        float x2 = src[srcoff + 4];
+        float y2 = src[srcoff + 5];
+        if (left != null) {
+            left[leftoff + 0] = x1;
+            left[leftoff + 1] = y1;
+        }
+        if (right != null) {
+            right[rightoff + 4] = x2;
+            right[rightoff + 5] = y2;
+        }
+        x1 = x1 + t * (ctrlx - x1);
+        y1 = y1 + t * (ctrly - y1);
+        x2 = ctrlx + t * (x2 - ctrlx);
+        y2 = ctrly + t * (y2 - ctrly);
+        ctrlx = x1 + t * (x2 - x1);
+        ctrly = y1 + t * (y2 - y1);
+        if (left != null) {
+            left[leftoff + 2] = x1;
+            left[leftoff + 3] = y1;
+            left[leftoff + 4] = ctrlx;
+            left[leftoff + 5] = ctrly;
+        }
+        if (right != null) {
+            right[rightoff + 0] = ctrlx;
+            right[rightoff + 1] = ctrly;
+            right[rightoff + 2] = x2;
+            right[rightoff + 3] = y2;
+        }
+    }
+
+    static void subdivideAt(float t, float src[], int srcoff,
+                            float left[], int leftoff,
+                            float right[], int rightoff, int size)
+    {
+        switch(size) {
+        case 8:
+            subdivideCubicAt(t, src, srcoff, left, leftoff, right, rightoff);
+            break;
+        case 6:
+            subdivideQuadAt(t, src, srcoff, left, leftoff, right, rightoff);
+            break;
+        }
+    }
+}
--- a/jdk/src/share/classes/sun/java2d/pisces/LineSink.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2007, 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.
- */
-
-package sun.java2d.pisces;
-
-/**
- * The <code>LineSink</code> interface accepts a series of line
- * drawing commands: <code>moveTo</code>, <code>lineTo</code>,
- * <code>close</code> (equivalent to a <code>lineTo</code> command
- * with an argument equal to the argument of the last
- * <code>moveTo</code> command), and <code>end</code>.
- *
- * <p> A <code>Flattener</code> may be used to connect a general path
- * source to a <code>LineSink</code>.
- *
- * <p> The <code>Renderer</code> class implements the
- * <code>LineSink</code> interface.
- *
- */
-public interface LineSink {
-
-    /**
-     * Moves the current drawing position to the point <code>(x0,
-     * y0)</code>.
-     *
-     * @param x0 the X coordinate
-     * @param y0 the Y coordinate
-     */
-    public void moveTo(float x0, float y0);
-
-    /**
-     * Provides a hint that the current segment should be joined to
-     * the following segment using an explicit miter or round join if
-     * required.
-     *
-     * <p> An application-generated path will generally have no need
-     * to contain calls to this method; they are typically introduced
-     * by a <code>Flattener</code> to mark segment divisions that
-     * appear in its input, and consumed by a <code>Stroker</code>
-     * that is responsible for emitting the miter or round join
-     * segments.
-     *
-     * <p> Other <code>LineSink</code> classes should simply pass this
-     * hint to their output sink as needed.
-     */
-    public void lineJoin();
-
-    /**
-     * Draws a line from the current drawing position to the point
-     * <code>(x1, y1)</code> and sets the current drawing position to
-     * <code>(x1, y1)</code>.
-     *
-     * @param x1 the X coordinate
-     * @param y1 the Y coordinate
-     */
-    public void lineTo(float x1, float y1);
-
-    /**
-     * Closes the current path by drawing a line from the current
-     * drawing position to the point specified by the moset recent
-     * <code>moveTo</code> command.
-     */
-    public void close();
-
-    /**
-     * Ends the current path.  It may be necessary to end a path in
-     * order to allow end caps to be drawn.
-     */
-    public void end();
-
-}
--- a/jdk/src/share/classes/sun/java2d/pisces/PiscesCache.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/java2d/pisces/PiscesCache.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,6 +25,8 @@
 
 package sun.java2d.pisces;
 
+import java.util.Arrays;
+
 /**
  * An object used to cache pre-rendered complex paths.
  *
@@ -32,115 +34,153 @@
  */
 public final class PiscesCache {
 
-    int bboxX0, bboxY0, bboxX1, bboxY1;
+    final int bboxX0, bboxY0, bboxX1, bboxY1;
+
+    // rowAARLE[i] holds the encoding of the pixel row with y = bboxY0+i.
+    // The format of each of the inner arrays is: rowAARLE[i][0,1] = (x0, n)
+    // where x0 is the first x in row i with nonzero alpha, and n is the
+    // number of RLE entries in this row. rowAARLE[i][j,j+1] for j>1 is
+    // (val,runlen)
+    final int[][] rowAARLE;
 
-    byte[] rowAARLE;
-    int alphaRLELength;
+    // RLE encodings are added in increasing y rows and then in increasing
+    // x inside those rows. Therefore, at any one time there is a well
+    // defined position (x,y) where a run length is about to be added (or
+    // the row terminated). x0,y0 is this (x,y)-(bboxX0,bboxY0). They
+    // are used to get indices into the current tile.
+    private int x0 = Integer.MIN_VALUE, y0 = Integer.MIN_VALUE;
+
+    // touchedTile[i][j] is the sum of all the alphas in the tile with
+    // y=i*TILE_SIZE+bboxY0 and x=j*TILE_SIZE+bboxX0.
+    private final int[][] touchedTile;
 
-    int[] rowOffsetsRLE;
-    int[] minTouched;
-    int alphaRows;
+    static final int TILE_SIZE_LG = 5;
+    static final int TILE_SIZE = 1 << TILE_SIZE_LG; // 32
+    private static final int INIT_ROW_SIZE = 8; // enough for 3 run lengths
 
-    private PiscesCache() {}
+    PiscesCache(int minx, int miny, int maxx, int maxy) {
+        assert maxy >= miny && maxx >= minx;
+        bboxX0 = minx;
+        bboxY0 = miny;
+        bboxX1 = maxx + 1;
+        bboxY1 = maxy + 1;
+        // we could just leave the inner arrays as null and allocate them
+        // lazily (which would be beneficial for shapes with gaps), but we
+        // assume there won't be too many of those so we allocate everything
+        // up front (which is better for other cases)
+        rowAARLE = new int[bboxY1 - bboxY0 + 1][INIT_ROW_SIZE];
+        x0 = 0;
+        y0 = -1; // -1 makes the first assert in startRow succeed
+        // the ceiling of (maxy - miny + 1) / TILE_SIZE;
+        int nyTiles = (maxy - miny + TILE_SIZE) >> TILE_SIZE_LG;
+        int nxTiles = (maxx - minx + TILE_SIZE) >> TILE_SIZE_LG;
 
-    public static PiscesCache createInstance() {
-        return new PiscesCache();
+        touchedTile = new int[nyTiles][nxTiles];
     }
 
-    private static final float ROWAA_RLE_FACTOR = 1.5f;
-    private static final float TOUCHED_FACTOR = 1.5f;
-    private static final int MIN_TOUCHED_LEN = 64;
-
-    private void reallocRowAARLE(int newLength) {
-        if (rowAARLE == null) {
-            rowAARLE = new byte[newLength];
-        } else if (rowAARLE.length < newLength) {
-            int len = Math.max(newLength,
-                               (int)(rowAARLE.length*ROWAA_RLE_FACTOR));
-            byte[] newRowAARLE = new byte[len];
-            System.arraycopy(rowAARLE, 0, newRowAARLE, 0, rowAARLE.length);
-            rowAARLE = newRowAARLE;
-        }
-    }
-
-    private void reallocRowInfo(int newHeight) {
-        if (minTouched == null) {
-            int len = Math.max(newHeight, MIN_TOUCHED_LEN);
-            minTouched = new int[len];
-            rowOffsetsRLE = new int[len];
-        } else if (minTouched.length < newHeight) {
-            int len = Math.max(newHeight,
-                               (int)(minTouched.length*TOUCHED_FACTOR));
-            int[] newMinTouched = new int[len];
-            int[] newRowOffsetsRLE = new int[len];
-            System.arraycopy(minTouched, 0, newMinTouched, 0,
-                             alphaRows);
-            System.arraycopy(rowOffsetsRLE, 0, newRowOffsetsRLE, 0,
-                             alphaRows);
-            minTouched = newMinTouched;
-            rowOffsetsRLE = newRowOffsetsRLE;
+    void addRLERun(int val, int runLen) {
+        if (runLen > 0) {
+            addTupleToRow(y0, val, runLen);
+            if (val != 0) {
+                // the x and y of the current row, minus bboxX0, bboxY0
+                int tx = x0 >> TILE_SIZE_LG;
+                int ty = y0 >> TILE_SIZE_LG;
+                int tx1 = (x0 + runLen - 1) >> TILE_SIZE_LG;
+                // while we forbid rows from starting before bboxx0, our users
+                // can still store rows that go beyond bboxx1 (although this
+                // shouldn't happen), so it's a good idea to check that i
+                // is not going out of bounds in touchedTile[ty]
+                if (tx1 >= touchedTile[ty].length) {
+                    tx1 = touchedTile[ty].length - 1;
+                }
+                if (tx <= tx1) {
+                    int nextTileXCoord = (tx + 1) << TILE_SIZE_LG;
+                    if (nextTileXCoord > x0+runLen) {
+                        touchedTile[ty][tx] += val * runLen;
+                    } else {
+                        touchedTile[ty][tx] += val * (nextTileXCoord - x0);
+                    }
+                    tx++;
+                }
+                // don't go all the way to tx1 - we need to handle the last
+                // tile as a special case (just like we did with the first
+                for (; tx < tx1; tx++) {
+//                    try {
+                    touchedTile[ty][tx] += (val << TILE_SIZE_LG);
+//                    } catch (RuntimeException e) {
+//                        System.out.println("x0, y0: " + x0 + ", " + y0);
+//                        System.out.printf("tx, ty, tx1: %d, %d, %d %n", tx, ty, tx1);
+//                        System.out.printf("bboxX/Y0/1: %d, %d, %d, %d %n",
+//                                bboxX0, bboxY0, bboxX1, bboxY1);
+//                        throw e;
+//                    }
+                }
+                // they will be equal unless x0>>TILE_SIZE_LG == tx1
+                if (tx == tx1) {
+                    int lastXCoord = Math.min(x0 + runLen, (tx + 1) << TILE_SIZE_LG);
+                    int txXCoord = tx << TILE_SIZE_LG;
+                    touchedTile[ty][tx] += val * (lastXCoord - txXCoord);
+                }
+            }
+            x0 += runLen;
         }
     }
 
-    void addRLERun(byte val, int runLen) {
-        reallocRowAARLE(alphaRLELength + 2);
-        rowAARLE[alphaRLELength++] = val;
-        rowAARLE[alphaRLELength++] = (byte)runLen;
+    void startRow(int y, int x) {
+        // rows are supposed to be added by increasing y.
+        assert y - bboxY0 > y0;
+        assert y <= bboxY1; // perhaps this should be < instead of <=
+
+        y0 = y - bboxY0;
+        // this should be a new, uninitialized row.
+        assert rowAARLE[y0][1] == 0;
+
+        x0 = x - bboxX0;
+        assert x0 >= 0 : "Input must not be to the left of bbox bounds";
+
+        // the way addTupleToRow is implemented it would work for this but it's
+        // not a good idea to use it because it is meant for adding
+        // RLE tuples, not the first tuple (which is special).
+        rowAARLE[y0][0] = x;
+        rowAARLE[y0][1] = 2;
     }
 
-    void startRow(int y, int x0, int x1) {
-        if (alphaRows == 0) {
-            bboxY0 = y;
-            bboxY1 = y+1;
-            bboxX0 = x0;
-            bboxX1 = x1+1;
-        } else {
-            if (bboxX0 > x0) bboxX0 = x0;
-            if (bboxX1 < x1 + 1) bboxX1 = x1 + 1;
-            while (bboxY1++ < y) {
-                reallocRowInfo(alphaRows+1);
-                minTouched[alphaRows] = 0;
-                // Assuming last 2 entries in rowAARLE are 0,0
-                rowOffsetsRLE[alphaRows] = alphaRLELength-2;
-                alphaRows++;
-            }
-        }
-        reallocRowInfo(alphaRows+1);
-        minTouched[alphaRows] = x0;
-        rowOffsetsRLE[alphaRows] = alphaRLELength;
-        alphaRows++;
+    int alphaSumInTile(int x, int y) {
+        x -= bboxX0;
+        y -= bboxY0;
+        return touchedTile[y>>TILE_SIZE_LG][x>>TILE_SIZE_LG];
+    }
+
+    int minTouched(int rowidx) {
+        return rowAARLE[rowidx][0];
     }
 
-    public synchronized void dispose() {
-        rowAARLE = null;
-        alphaRLELength = 0;
+    int rowLength(int rowidx) {
+        return rowAARLE[rowidx][1];
+    }
 
-        minTouched = null;
-        rowOffsetsRLE = null;
-        alphaRows = 0;
-
-        bboxX0 = bboxY0 = bboxX1 = bboxY1 = 0;
+    private void addTupleToRow(int row, int a, int b) {
+        int end = rowAARLE[row][1];
+        rowAARLE[row] = Helpers.widenArray(rowAARLE[row], end, 2);
+        rowAARLE[row][end++] = a;
+        rowAARLE[row][end++] = b;
+        rowAARLE[row][1] = end;
     }
 
-    public void print(java.io.PrintStream out) {
-        synchronized (out) {
-        out.println("bbox = ["+
-                    bboxX0+", "+bboxY0+" => "+
-                    bboxX1+", "+bboxY1+"]");
-
-        out.println("alphRLELength = "+alphaRLELength);
-
-        for (int y = bboxY0; y < bboxY1; y++) {
-            int i = y-bboxY0;
-            out.println("row["+i+"] == {"+
-                        "minX = "+minTouched[i]+
-                        ", off = "+rowOffsetsRLE[i]+"}");
+    @Override
+    public String toString() {
+        String ret = "bbox = ["+
+                      bboxX0+", "+bboxY0+" => "+
+                      bboxX1+", "+bboxY1+"]\n";
+        for (int[] row : rowAARLE) {
+            if (row != null) {
+                ret += ("minTouchedX=" + row[0] +
+                        "\tRLE Entries: " + Arrays.toString(
+                                Arrays.copyOfRange(row, 2, row[1])) + "\n");
+            } else {
+                ret += "[]\n";
+            }
         }
-
-        for (int i = 0; i < alphaRLELength; i += 2) {
-            out.println("rle["+i+"] = "+
-                        (rowAARLE[i+1]&0xff)+" of "+(rowAARLE[i]&0xff));
-        }
-    }
+        return ret;
     }
 }
--- a/jdk/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java	Wed Jul 05 17:26:57 2017 +0200
@@ -27,7 +27,7 @@
 
 import java.awt.Shape;
 import java.awt.BasicStroke;
-import java.awt.geom.FlatteningPathIterator;
+import java.awt.geom.NoninvertibleTransformException;
 import java.awt.geom.Path2D;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.PathIterator;
@@ -38,8 +38,6 @@
 import sun.java2d.pipe.AATileGenerator;
 
 public class PiscesRenderingEngine extends RenderingEngine {
-    public static double defaultFlat = 0.1;
-
     private static enum NormMode {OFF, ON_NO_AA, ON_WITH_AA}
 
     /**
@@ -78,20 +76,29 @@
                  miterlimit,
                  dashes,
                  dashphase,
-                 new LineSink() {
+                 new PathConsumer2D() {
                      public void moveTo(float x0, float y0) {
                          p2d.moveTo(x0, y0);
                      }
-                     public void lineJoin() {}
                      public void lineTo(float x1, float y1) {
                          p2d.lineTo(x1, y1);
                      }
-                     public void close() {
+                     public void closePath() {
                          p2d.closePath();
                      }
-                     public void end() {}
+                     public void pathDone() {}
+                     public void curveTo(float x1, float y1,
+                                         float x2, float y2,
+                                         float x3, float y3) {
+                         p2d.curveTo(x1, y1, x2, y2, x3, y3);
+                     }
+                     public void quadTo(float x1, float y1, float x2, float y2) {
+                         p2d.quadTo(x1, y1, x2, y2);
+                     }
+                     public long getNativeConsumer() {
+                         throw new InternalError("Not using a native peer");
+                     }
                  });
-
         return p2d;
     }
 
@@ -133,22 +140,7 @@
         NormMode norm = (normalize) ?
                 ((antialias) ? NormMode.ON_WITH_AA : NormMode.ON_NO_AA)
                 : NormMode.OFF;
-        strokeTo(src, at, bs, thin, norm, antialias,
-                 new LineSink() {
-                     public void moveTo(float x0, float y0) {
-                         consumer.moveTo(x0, y0);
-                     }
-                     public void lineJoin() {}
-                     public void lineTo(float x1, float y1) {
-                         consumer.lineTo(x1, y1);
-                     }
-                     public void close() {
-                         consumer.closePath();
-                     }
-                     public void end() {
-                         consumer.pathDone();
-                     }
-                 });
+        strokeTo(src, at, bs, thin, norm, antialias, consumer);
     }
 
     void strokeTo(Shape src,
@@ -157,7 +149,7 @@
                   boolean thin,
                   NormMode normalize,
                   boolean antialias,
-                  LineSink lsink)
+                  PathConsumer2D pc2d)
     {
         float lw;
         if (thin) {
@@ -178,7 +170,7 @@
                  bs.getMiterLimit(),
                  bs.getDashArray(),
                  bs.getDashPhase(),
-                 lsink);
+                 pc2d);
     }
 
     private float userSpaceLineWidth(AffineTransform at, float lw) {
@@ -256,28 +248,113 @@
                   float miterlimit,
                   float dashes[],
                   float dashphase,
-                  LineSink lsink)
+                  PathConsumer2D pc2d)
     {
-        float a00 = 1f, a01 = 0f, a10 = 0f, a11 = 1f;
+        // We use inat and outat so that in Stroker and Dasher we can work only
+        // with the pre-transformation coordinates. This will repeat a lot of
+        // computations done in the path iterator, but the alternative is to
+        // work with transformed paths and compute untransformed coordinates
+        // as needed. This would be faster but I do not think the complexity
+        // of working with both untransformed and transformed coordinates in
+        // the same code is worth it.
+        // However, if a path's width is constant after a transformation,
+        // we can skip all this untransforming.
+
+        // If normalization is off we save some transformations by not
+        // transforming the input to pisces. Instead, we apply the
+        // transformation after the path processing has been done.
+        // We can't do this if normalization is on, because it isn't a good
+        // idea to normalize before the transformation is applied.
+        AffineTransform inat = null;
+        AffineTransform outat = null;
+
+        PathIterator pi = null;
+
         if (at != null && !at.isIdentity()) {
-            a00 = (float)at.getScaleX();
-            a01 = (float)at.getShearX();
-            a10 = (float)at.getShearY();
-            a11 = (float)at.getScaleY();
+            final double a = at.getScaleX();
+            final double b = at.getShearX();
+            final double c = at.getShearY();
+            final double d = at.getScaleY();
+            final double det = a * d - c * b;
+            if (Math.abs(det) <= 2 * Float.MIN_VALUE) {
+                // this rendering engine takes one dimensional curves and turns
+                // them into 2D shapes by giving them width.
+                // However, if everything is to be passed through a singular
+                // transformation, these 2D shapes will be squashed down to 1D
+                // again so, nothing can be drawn.
+
+                // Every path needs an initial moveTo and a pathDone. If these
+                // aren't there this causes a SIGSEV in libawt.so (at the time
+                // of writing of this comment (September 16, 2010)). Actually,
+                // I'm not sure if the moveTo is necessary to avoid the SIGSEV
+                // but the pathDone is definitely needed.
+                pc2d.moveTo(0, 0);
+                pc2d.pathDone();
+                return;
+            }
+
+            // If the transform is a constant multiple of an orthogonal transformation
+            // then every length is just multiplied by a constant, so we just
+            // need to transform input paths to stroker and tell stroker
+            // the scaled width. This condition is satisfied if
+            // a*b == -c*d && a*a+c*c == b*b+d*d. In the actual check below, we
+            // leave a bit of room for error.
+            if (nearZero(a*b + c*d, 2) && nearZero(a*a+c*c - (b*b+d*d), 2)) {
+                double scale = Math.sqrt(a*a + c*c);
+                if (dashes != null) {
+                    dashes = java.util.Arrays.copyOf(dashes, dashes.length);
+                    for (int i = 0; i < dashes.length; i++) {
+                        dashes[i] = (float)(scale * dashes[i]);
+                    }
+                    dashphase = (float)(scale * dashphase);
+                }
+                width = (float)(scale * width);
+                pi = src.getPathIterator(at);
+                if (normalize != NormMode.OFF) {
+                    pi = new NormalizingPathIterator(pi, normalize);
+                }
+                // leave inat and outat null.
+            } else {
+                // We only need the inverse if normalization is on. Otherwise
+                // we just don't transform the input paths, do all the stroking
+                // and then transform out output (instead of making PathIterator
+                // apply the transformation, us applying the inverse, and then
+                // us applying the transform again to our output).
+                outat = at;
+                if (normalize != NormMode.OFF) {
+                    try {
+                        inat = outat.createInverse();
+                    } catch (NoninvertibleTransformException e) {
+                        // we made sure this can't happen
+                        e.printStackTrace();
+                    }
+                    pi = src.getPathIterator(at);
+                    pi = new NormalizingPathIterator(pi, normalize);
+                } else {
+                    pi = src.getPathIterator(null);
+                }
+            }
+        } else {
+            // either at is null or it's the identity. In either case
+            // we don't transform the path.
+            pi = src.getPathIterator(null);
+            if (normalize != NormMode.OFF) {
+                pi = new NormalizingPathIterator(pi, normalize);
+            }
         }
-        lsink = new Stroker(lsink, width, caps, join, miterlimit, a00, a01, a10, a11);
+
+        pc2d = TransformingPathConsumer2D.transformConsumer(pc2d, outat);
+        pc2d = new Stroker(pc2d, width, caps, join, miterlimit);
         if (dashes != null) {
-            lsink = new Dasher(lsink, dashes, dashphase, a00, a01, a10, a11);
+            pc2d = new Dasher(pc2d, dashes, dashphase);
         }
-        PathIterator pi;
-        if (normalize != NormMode.OFF) {
-            pi = new FlatteningPathIterator(
-                    new NormalizingPathIterator(src.getPathIterator(at), normalize),
-                    defaultFlat);
-        } else {
-            pi = src.getPathIterator(at, defaultFlat);
-        }
-        pathTo(pi, lsink);
+        pc2d = TransformingPathConsumer2D.transformConsumer(pc2d, inat);
+
+        pathTo(pi, pc2d);
+    }
+
+    private static boolean nearZero(double num, int nulps) {
+        return Math.abs(num) < nulps * Math.ulp(num);
     }
 
     private static class NormalizingPathIterator implements PathIterator {
@@ -337,10 +414,10 @@
             }
 
             // normalize endpoint
-            float x_adjust = (float)Math.floor(coords[lastCoord] + lval) + rval -
-                         coords[lastCoord];
-            float y_adjust = (float)Math.floor(coords[lastCoord+1] + lval) + rval -
-                         coords[lastCoord + 1];
+            float x_adjust = (float)Math.floor(coords[lastCoord] + lval) +
+                         rval - coords[lastCoord];
+            float y_adjust = (float)Math.floor(coords[lastCoord+1] + lval) +
+                         rval - coords[lastCoord + 1];
 
             coords[lastCoord    ] += x_adjust;
             coords[lastCoord + 1] += y_adjust;
@@ -393,27 +470,9 @@
         }
     }
 
-    void pathTo(PathIterator pi, LineSink lsink) {
-        float coords[] = new float[2];
-        while (!pi.isDone()) {
-            switch (pi.currentSegment(coords)) {
-            case PathIterator.SEG_MOVETO:
-                lsink.moveTo(coords[0], coords[1]);
-                break;
-            case PathIterator.SEG_LINETO:
-                lsink.lineJoin();
-                lsink.lineTo(coords[0], coords[1]);
-                break;
-            case PathIterator.SEG_CLOSE:
-                lsink.lineJoin();
-                lsink.close();
-                break;
-            default:
-                throw new InternalError("unknown flattened segment type");
-            }
-            pi.next();
-        }
-        lsink.end();
+    static void pathTo(PathIterator pi, PathConsumer2D pc2d) {
+        RenderingEngine.feedConsumer(pi, pc2d);
+        pc2d.pathDone();
     }
 
     /**
@@ -471,32 +530,29 @@
                                               boolean normalize,
                                               int bbox[])
     {
-        PiscesCache pc = PiscesCache.createInstance();
         Renderer r;
         NormMode norm = (normalize) ? NormMode.ON_WITH_AA : NormMode.OFF;
         if (bs == null) {
             PathIterator pi;
             if (normalize) {
-                pi = new FlatteningPathIterator(
-                        new NormalizingPathIterator(s.getPathIterator(at), norm),
-                        defaultFlat);
+                pi = new NormalizingPathIterator(s.getPathIterator(at), norm);
             } else {
-                pi = s.getPathIterator(at, defaultFlat);
+                pi = s.getPathIterator(at);
             }
             r = new Renderer(3, 3,
                              clip.getLoX(), clip.getLoY(),
                              clip.getWidth(), clip.getHeight(),
-                             pi.getWindingRule(), pc);
+                             pi.getWindingRule());
             pathTo(pi, r);
         } else {
             r = new Renderer(3, 3,
                              clip.getLoX(), clip.getLoY(),
                              clip.getWidth(), clip.getHeight(),
-                             PathIterator.WIND_NON_ZERO, pc);
+                             PathIterator.WIND_NON_ZERO);
             strokeTo(s, at, bs, thin, norm, true, r);
         }
         r.endRendering();
-        PiscesTileGenerator ptg = new PiscesTileGenerator(pc, r.MAX_AA_ALPHA);
+        PiscesTileGenerator ptg = new PiscesTileGenerator(r, r.MAX_AA_ALPHA);
         ptg.getBbox(bbox);
         return ptg;
     }
--- a/jdk/src/share/classes/sun/java2d/pisces/PiscesTileGenerator.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/java2d/pisces/PiscesTileGenerator.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,40 +25,54 @@
 
 package sun.java2d.pisces;
 
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
 import sun.java2d.pipe.AATileGenerator;
 
-public class PiscesTileGenerator implements AATileGenerator {
-    public static final int TILE_SIZE = 32;
+public final class PiscesTileGenerator implements AATileGenerator {
+    public static final int TILE_SIZE = PiscesCache.TILE_SIZE;
+
+    // perhaps we should be using weak references here, but right now
+    // that's not necessary. The way the renderer is, this map will
+    // never contain more than one element - the one with key 64, since
+    // we only do 8x8 supersampling.
+    private static final Map<Integer, byte[]> alphaMapsCache = new
+                   ConcurrentHashMap<Integer, byte[]>();
 
     PiscesCache cache;
     int x, y;
-    int maxalpha;
+    final int maxalpha;
+    private final int maxTileAlphaSum;
+
+    // The alpha map used by this object (taken out of our map cache) to convert
+    // pixel coverage counts gotten from PiscesCache (which are in the range
+    // [0, maxalpha]) into alpha values, which are in [0,256).
     byte alphaMap[];
 
-    public PiscesTileGenerator(PiscesCache cache, int maxalpha) {
-        this.cache = cache;
+    public PiscesTileGenerator(Renderer r, int maxalpha) {
+        this.cache = r.getCache();
         this.x = cache.bboxX0;
         this.y = cache.bboxY0;
         this.alphaMap = getAlphaMap(maxalpha);
         this.maxalpha = maxalpha;
+        this.maxTileAlphaSum = TILE_SIZE*TILE_SIZE*maxalpha;
     }
 
-    static int prevMaxAlpha;
-    static byte prevAlphaMap[];
+    private static byte[] buildAlphaMap(int maxalpha) {
+        byte[] alMap = new byte[maxalpha+1];
+        int halfmaxalpha = maxalpha>>2;
+        for (int i = 0; i <= maxalpha; i++) {
+            alMap[i] = (byte) ((i * 255 + halfmaxalpha) / maxalpha);
+        }
+        return alMap;
+    }
 
-    public synchronized static byte[] getAlphaMap(int maxalpha) {
-        if (maxalpha != prevMaxAlpha) {
-            prevAlphaMap = new byte[maxalpha+300];
-            int halfmaxalpha = maxalpha>>2;
-            for (int i = 0; i <= maxalpha; i++) {
-                prevAlphaMap[i] = (byte) ((i * 255 + halfmaxalpha) / maxalpha);
-            }
-            for (int i = maxalpha; i < prevAlphaMap.length; i++) {
-                prevAlphaMap[i] = (byte) 255;
-            }
-            prevMaxAlpha = maxalpha;
+    public static byte[] getAlphaMap(int maxalpha) {
+        if (!alphaMapsCache.containsKey(maxalpha)) {
+            alphaMapsCache.put(maxalpha, buildAlphaMap(maxalpha));
         }
-        return prevAlphaMap;
+        return alphaMapsCache.get(maxalpha);
     }
 
     public void getBbox(int bbox[]) {
@@ -96,53 +110,24 @@
      *         value for partial coverage of the tile
      */
     public int getTypicalAlpha() {
-        if (true) return 0x80;
-        // Decode run-length encoded alpha mask data
-        // The data for row j begins at cache.rowOffsetsRLE[j]
-        // and is encoded as a set of 2-byte pairs (val, runLen)
-        // terminated by a (0, 0) pair.
-
-        int x0 = this.x;
-        int x1 = x0 + TILE_SIZE;
-        int y0 = this.y;
-        int y1 = y0 + TILE_SIZE;
-        if (x1 > cache.bboxX1) x1 = cache.bboxX1;
-        if (y1 > cache.bboxY1) y1 = cache.bboxY1;
-        y0 -= cache.bboxY0;
-        y1 -= cache.bboxY0;
-
-        int ret = -1;
-        for (int cy = y0; cy < y1; cy++) {
-            int pos = cache.rowOffsetsRLE[cy];
-            int cx = cache.minTouched[cy];
-
-            if (cx > x0) {
-                if (ret > 0) return 0x80;
-                ret = 0x00;
-            }
-            while (cx < x1) {
-                int runLen = cache.rowAARLE[pos + 1] & 0xff;
-                if (runLen == 0) {
-                    if (ret > 0) return 0x80;
-                    ret = 0x00;
-                    break;
-                }
-                cx += runLen;
-                if (cx > x0) {
-                    int val = cache.rowAARLE[pos] & 0xff;
-                    if (ret != val) {
-                        if (ret < 0) {
-                            if (val != 0x00 && val != maxalpha) return 0x80;
-                            ret = val;
-                        } else {
-                            return 0x80;
-                        }
-                    }
-                }
-                pos += 2;
-            }
-        }
-        return ret;
+        int al = cache.alphaSumInTile(x, y);
+        // Note: if we have a filled rectangle that doesn't end on a tile
+        // border, we could still return 0xff, even though al!=maxTileAlphaSum
+        // This is because if we return 0xff, our users will fill a rectangle
+        // starting at x,y that has width = Math.min(TILE_SIZE, bboxX1-x),
+        // and height min(TILE_SIZE,bboxY1-y), which is what should happen.
+        // However, to support this, we would have to use 2 Math.min's
+        // and 2 multiplications per tile, instead of just 2 multiplications
+        // to compute maxTileAlphaSum. The savings offered would probably
+        // not be worth it, considering how rare this case is.
+        // Note: I have not tested this, so in the future if it is determined
+        // that it is worth it, it should be implemented. Perhaps this method's
+        // interface should be changed to take arguments the width and height
+        // of the current tile. This would eliminate the 2 Math.min calls that
+        // would be needed here, since our caller needs to compute these 2
+        // values anyway.
+        return (al == 0x00 ? 0x00 :
+            (al == maxTileAlphaSum ? 0xff : 0x80));
     }
 
     /**
@@ -179,22 +164,24 @@
 
         int idx = offset;
         for (int cy = y0; cy < y1; cy++) {
-            int pos = cache.rowOffsetsRLE[cy];
-            int cx = cache.minTouched[cy];
+            int[] row = cache.rowAARLE[cy];
+            assert row != null;
+            int cx = cache.minTouched(cy);
             if (cx > x1) cx = x1;
 
-            if (cx > x0) {
-                //System.out.println("L["+(cx-x0)+"]");
-                for (int i = x0; i < cx; i++) {
-                    tile[idx++] = 0x00;
-                }
+            for (int i = x0; i < cx; i++) {
+                tile[idx++] = 0x00;
             }
-            while (cx < x1) {
+
+            int pos = 2;
+            while (cx < x1 && pos < row[1]) {
                 byte val;
                 int runLen = 0;
+                assert row[1] > 2;
                 try {
-                    val = alphaMap[cache.rowAARLE[pos] & 0xff];
-                    runLen = cache.rowAARLE[pos + 1] & 0xff;
+                    val = alphaMap[row[pos]];
+                    runLen = row[pos + 1];
+                    assert runLen > 0;
                 } catch (RuntimeException e0) {
                     System.out.println("maxalpha = "+maxalpha);
                     System.out.println("tile["+x0+", "+y0+
@@ -202,14 +189,12 @@
                     System.out.println("cx = "+cx+", cy = "+cy);
                     System.out.println("idx = "+idx+", pos = "+pos);
                     System.out.println("len = "+runLen);
-                    cache.print(System.out);
+                    System.out.print(cache.toString());
                     e0.printStackTrace();
                     System.exit(1);
                     return;
                 }
-                if (runLen == 0) {
-                    break;
-                }
+
                 int rx0 = cx;
                 cx += runLen;
                 int rx1 = cx;
@@ -228,7 +213,7 @@
                         System.out.println("idx = "+idx+", pos = "+pos);
                         System.out.println("rx0 = "+rx0+", rx1 = "+rx1);
                         System.out.println("len = "+runLen);
-                        cache.print(System.out);
+                        System.out.print(cache.toString());
                         e.printStackTrace();
                         System.exit(1);
                         return;
@@ -265,4 +250,4 @@
      * No further calls will be made on this instance.
      */
     public void dispose() {}
-}
+}
\ No newline at end of file
--- a/jdk/src/share/classes/sun/java2d/pisces/Renderer.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/java2d/pisces/Renderer.java	Wed Jul 05 17:26:57 2017 +0200
@@ -26,250 +26,552 @@
 package sun.java2d.pisces;
 
 import java.util.Arrays;
+import java.util.Iterator;
 
-public class Renderer implements LineSink {
+import sun.awt.geom.PathConsumer2D;
 
-///////////////////////////////////////////////////////////////////////////////
-// Scan line iterator and edge crossing data.
-//////////////////////////////////////////////////////////////////////////////
+public class Renderer implements PathConsumer2D {
 
-    private int[] crossings;
+    private class ScanlineIterator {
+
+        private int[] crossings;
 
-    // This is an array of indices into the edge array. It is initialized to
-    // [i * SIZEOF_STRUCT_EDGE for i in range(0, edgesSize/SIZEOF_STRUCT_EDGE)]
-    // (where range(i, j) is i,i+1,...,j-1 -- just like in python).
-    // The reason for keeping this is because we need the edges array sorted
-    // by y0, but we don't want to move all that data around, so instead we
-    // sort the indices into the edge array, and use edgeIndices to access
-    // the edges array. This is meant to simulate a pointer array (hence the name)
-    private int[] edgePtrs;
+        // crossing bounds. The bounds are not necessarily tight (the scan line
+        // at minY, for example, might have no crossings). The x bounds will
+        // be accumulated as crossings are computed.
+        private int minY, maxY;
+        private int nextY;
 
-    // crossing bounds. The bounds are not necessarily tight (the scan line
-    // at minY, for example, might have no crossings). The x bounds will
-    // be accumulated as crossings are computed.
-    private int minY, maxY;
-    private int minX, maxX;
-    private int nextY;
+        // indices into the segment pointer lists. They indicate the "active"
+        // sublist in the segment lists (the portion of the list that contains
+        // all the segments that cross the next scan line).
+        private int elo, ehi;
+        private final int[] edgePtrs;
+        private int qlo, qhi;
+        private final int[] quadPtrs;
+        private int clo, chi;
+        private final int[] curvePtrs;
+
+        private static final int INIT_CROSSINGS_SIZE = 10;
+
+        private ScanlineIterator() {
+            crossings = new int[INIT_CROSSINGS_SIZE];
 
-    // indices into the edge pointer list. They indicate the "active" sublist in
-    // the edge list (the portion of the list that contains all the edges that
-    // cross the next scan line).
-    private int lo, hi;
+            edgePtrs = new int[numEdges];
+            Helpers.fillWithIdxes(edgePtrs, SIZEOF_EDGE);
+            qsort(edges, edgePtrs, YMIN, 0, numEdges - 1);
 
-    private static final int INIT_CROSSINGS_SIZE = 50;
-    private void ScanLineItInitialize() {
-        crossings = new int[INIT_CROSSINGS_SIZE];
-        edgePtrs = new int[edgesSize / SIZEOF_STRUCT_EDGE];
-        for (int i = 0; i < edgePtrs.length; i++) {
-            edgePtrs[i] = i * SIZEOF_STRUCT_EDGE;
-        }
+            quadPtrs = new int[numQuads];
+            Helpers.fillWithIdxes(quadPtrs, SIZEOF_QUAD);
+            qsort(quads, quadPtrs, YMIN, 0, numQuads - 1);
+
+            curvePtrs = new int[numCurves];
+            Helpers.fillWithIdxes(curvePtrs, SIZEOF_CURVE);
+            qsort(curves, curvePtrs, YMIN, 0, numCurves - 1);
 
-        qsort(0, edgePtrs.length - 1);
+            // We don't care if we clip some of the line off with ceil, since
+            // no scan line crossings will be eliminated (in fact, the ceil is
+            // the y of the first scan line crossing).
+            nextY = minY = Math.max(boundsMinY, (int)Math.ceil(edgeMinY));
+            maxY = Math.min(boundsMaxY, (int)Math.ceil(edgeMaxY));
 
-        // We don't care if we clip some of the line off with ceil, since
-        // no scan line crossings will be eliminated (in fact, the ceil is
-        // the y of the first scan line crossing).
-        nextY = minY = Math.max(boundsMinY, (int)Math.ceil(edgeMinY));
-        maxY = Math.min(boundsMaxY, (int)Math.ceil(edgeMaxY));
+            for (elo = 0; elo < numEdges && edges[edgePtrs[elo]+YMAX] <= minY; elo++)
+                ;
+            // the active list is *edgePtrs[lo] (inclusive) *edgePtrs[hi] (exclusive)
+            for (ehi = elo; ehi < numEdges && edges[edgePtrs[ehi]+YMIN] <= minY; ehi++)
+                edgeSetCurY(edgePtrs[ehi], minY);// TODO: make minY a float to avoid casts
 
-        for (lo = 0; lo < edgePtrs.length && edges[edgePtrs[lo]+Y1] <= nextY; lo++)
-            ;
-        for (hi = lo; hi < edgePtrs.length && edges[edgePtrs[hi]+CURY] <= nextY; hi++)
-            ; // the active list is *edgePtrs[lo] (inclusive) *edgePtrs[hi] (exclusive)
-        for (int i = lo; i < hi; i++) {
-            setCurY(edgePtrs[i], nextY);
+            for (qlo = 0; qlo < numQuads && quads[quadPtrs[qlo]+YMAX] <= minY; qlo++)
+                ;
+            for (qhi = qlo; qhi < numQuads && quads[quadPtrs[qhi]+YMIN] <= minY; qhi++)
+                quadSetCurY(quadPtrs[qhi], minY);
+
+            for (clo = 0; clo < numCurves && curves[curvePtrs[clo]+YMAX] <= minY; clo++)
+                ;
+            for (chi = clo; chi < numCurves && curves[curvePtrs[chi]+YMIN] <= minY; chi++)
+                curveSetCurY(curvePtrs[chi], minY);
         }
 
-        // We accumulate X in the iterator because accumulating it in addEdge
-        // like we do with Y does not do much good: if there's an edge
-        // (0,0)->(1000,10000), and if y gets clipped to 1000, then the x
-        // bound should be 100, but the accumulator from addEdge would say 1000,
-        // so we'd still have to accumulate the X bounds as we add crossings.
-        minX = boundsMinX;
-        maxX = boundsMaxX;
-    }
+        private int next() {
+            // we go through the active lists and remove segments that don't cross
+            // the nextY scanline.
+            int crossingIdx = 0;
+            for (int i = elo; i < ehi; i++) {
+                if (edges[edgePtrs[i]+YMAX] <= nextY) {
+                    edgePtrs[i] = edgePtrs[elo++];
+                }
+            }
+            for (int i = qlo; i < qhi; i++) {
+                if (quads[quadPtrs[i]+YMAX] <= nextY) {
+                    quadPtrs[i] = quadPtrs[qlo++];
+                }
+            }
+            for (int i = clo; i < chi; i++) {
+                if (curves[curvePtrs[i]+YMAX] <= nextY) {
+                    curvePtrs[i] = curvePtrs[clo++];
+                }
+            }
 
-    private int ScanLineItCurrentY() {
-        return nextY - 1;
-    }
+            crossings = Helpers.widenArray(crossings, 0, ehi-elo+qhi-qlo+chi-clo);
 
-    private int ScanLineItGoToNextYAndComputeCrossings() {
-        // we go through the active list and remove the ones that don't cross
-        // the nextY scanline.
-        int crossingIdx = 0;
-        for (int i = lo; i < hi; i++) {
-            if (edges[edgePtrs[i]+Y1] <= nextY) {
-                edgePtrs[i] = edgePtrs[lo++];
+            // Now every edge between lo and hi crosses nextY. Compute it's
+            // crossing and put it in the crossings array.
+            for (int i = elo; i < ehi; i++) {
+                int ptr = edgePtrs[i];
+                addCrossing(nextY, (int)edges[ptr+CURX], edges[ptr+OR], crossingIdx);
+                edgeGoToNextY(ptr);
+                crossingIdx++;
+            }
+            for (int i = qlo; i < qhi; i++) {
+                int ptr = quadPtrs[i];
+                addCrossing(nextY, (int)quads[ptr+CURX], quads[ptr+OR], crossingIdx);
+                quadGoToNextY(ptr);
+                crossingIdx++;
             }
-        }
-        if (hi - lo > crossings.length) {
-            int newSize = Math.max(hi - lo, crossings.length * 2);
-            crossings = Arrays.copyOf(crossings, newSize);
-        }
-        // Now every edge between lo and hi crosses nextY. Compute it's
-        // crossing and put it in the crossings array.
-        for (int i = lo; i < hi; i++) {
-            addCrossing(nextY, getCurCrossing(edgePtrs[i]), (int)edges[edgePtrs[i]+OR], crossingIdx);
-            gotoNextY(edgePtrs[i]);
-            crossingIdx++;
+            for (int i = clo; i < chi; i++) {
+                int ptr = curvePtrs[i];
+                addCrossing(nextY, (int)curves[ptr+CURX], curves[ptr+OR], crossingIdx);
+                curveGoToNextY(ptr);
+                crossingIdx++;
+            }
+
+            nextY++;
+            // Expand active lists to include new edges.
+            for (; ehi < numEdges && edges[edgePtrs[ehi]+YMIN] <= nextY; ehi++) {
+                edgeSetCurY(edgePtrs[ehi], nextY);
+            }
+            for (; qhi < numQuads && quads[quadPtrs[qhi]+YMIN] <= nextY; qhi++) {
+                quadSetCurY(quadPtrs[qhi], nextY);
+            }
+            for (; chi < numCurves && curves[curvePtrs[chi]+YMIN] <= nextY; chi++) {
+                curveSetCurY(curvePtrs[chi], nextY);
+            }
+            Arrays.sort(crossings, 0, crossingIdx);
+            return crossingIdx;
         }
 
-        nextY++;
-        // Expand active list to include new edges.
-        for (; hi < edgePtrs.length && edges[edgePtrs[hi]+CURY] <= nextY; hi++) {
-            setCurY(edgePtrs[hi], nextY);
+        private boolean hasNext() {
+            return nextY < maxY;
         }
 
-        Arrays.sort(crossings, 0, crossingIdx);
-        return crossingIdx;
-    }
-
-    private boolean ScanLineItHasNext() {
-        return nextY < maxY;
-    }
+        private int curY() {
+            return nextY - 1;
+        }
 
-    private void addCrossing(int y, int x, int or, int idx) {
-        if (x < minX) {
-            minX = x;
+        private void addCrossing(int y, int x, float or, int idx) {
+            x <<= 1;
+            crossings[idx] = ((or > 0) ? (x | 0x1) : x);
         }
-        if (x > maxX) {
-            maxX = x;
-        }
-        x <<= 1;
-        crossings[idx] = ((or == 1) ? (x | 0x1) : x);
     }
-
-
     // quicksort implementation for sorting the edge indices ("pointers")
     // by increasing y0. first, last are indices into the "pointer" array
     // It sorts the pointer array from first (inclusive) to last (inclusive)
-    private void qsort(int first, int last) {
+    private static void qsort(final float[] data, final int[] ptrs,
+                              final int fieldForCmp, int first, int last)
+    {
         if (last > first) {
-            int p = partition(first, last);
+            int p = partition(data, ptrs, fieldForCmp, first, last);
             if (first < p - 1) {
-                qsort(first, p - 1);
+                qsort(data, ptrs, fieldForCmp, first, p - 1);
             }
             if (p < last) {
-                qsort(p, last);
+                qsort(data, ptrs, fieldForCmp, p, last);
             }
         }
     }
 
     // i, j are indices into edgePtrs.
-    private int partition(int i, int j) {
-        int pivotVal = edgePtrs[i];
+    private static int partition(final float[] data, final int[] ptrs,
+                                 final int fieldForCmp, int i, int j)
+    {
+        int pivotValFieldForCmp = ptrs[i]+fieldForCmp;
         while (i <= j) {
             // edges[edgePtrs[i]+1] is equivalent to (*(edgePtrs[i])).y0 in C
-            while (edges[edgePtrs[i]+CURY] < edges[pivotVal+CURY]) { i++; }
-            while (edges[edgePtrs[j]+CURY] > edges[pivotVal+CURY]) { j--; }
+            while (data[ptrs[i]+fieldForCmp] < data[pivotValFieldForCmp])
+                i++;
+            while (data[ptrs[j]+fieldForCmp] > data[pivotValFieldForCmp])
+                j--;
             if (i <= j) {
-                int tmp = edgePtrs[i];
-                edgePtrs[i] = edgePtrs[j];
-                edgePtrs[j] = tmp;
+                int tmp = ptrs[i];
+                ptrs[i] = ptrs[j];
+                ptrs[j] = tmp;
                 i++;
                 j--;
             }
         }
         return i;
     }
-
 //============================================================================
 
 
 //////////////////////////////////////////////////////////////////////////////
 //  EDGE LIST
 //////////////////////////////////////////////////////////////////////////////
+// TODO(maybe): very tempting to use fixed point here. A lot of opportunities
+// for shifts and just removing certain operations altogether.
+// TODO: it might be worth it to make an EdgeList class. It would probably
+// clean things up a bit and not impact performance much.
 
-    private static final int INIT_NUM_EDGES = 1000;
-    private static final int SIZEOF_STRUCT_EDGE = 5;
+    // common to all types of input path segments.
+    private static final int YMIN = 0;
+    private static final int YMAX = 1;
+    private static final int CURX = 2;
+    // this and OR are meant to be indeces into "int" fields, but arrays must
+    // be homogenous, so every field is a float. However floats can represent
+    // exactly up to 26 bit ints, so we're ok.
+    private static final int CURY = 3;
+    private static final int OR   = 4;
+
+    // for straight lines only:
+    private static final int SLOPE = 5;
+
+    // for quads and cubics:
+    private static final int X0 = 5;
+    private static final int Y0 = 6;
+    private static final int XL = 7;
+    private static final int COUNT = 8;
+    private static final int CURSLOPE = 9;
+    private static final int DX = 10;
+    private static final int DY = 11;
+    private static final int DDX = 12;
+    private static final int DDY = 13;
+
+    // for cubics only
+    private static final int DDDX = 14;
+    private static final int DDDY = 15;
+
+    private float edgeMinY = Float.POSITIVE_INFINITY;
+    private float edgeMaxY = Float.NEGATIVE_INFINITY;
+    private float edgeMinX = Float.POSITIVE_INFINITY;
+    private float edgeMaxX = Float.NEGATIVE_INFINITY;
+
+    private static final int SIZEOF_EDGE = 6;
+    private float[] edges = null;
+    private int numEdges;
+    // these are static because we need them to be usable from ScanlineIterator
+    private void edgeSetCurY(final int idx, int y) {
+        edges[idx+CURX] += (y - edges[idx+CURY]) * edges[idx+SLOPE];
+        edges[idx+CURY] = y;
+    }
+    private void edgeGoToNextY(final int idx) {
+        edges[idx+CURY] += 1;
+        edges[idx+CURX] += edges[idx+SLOPE];
+    }
+
+
+    private static final int SIZEOF_QUAD = 14;
+    private float[] quads = null;
+    private int numQuads;
+    // This function should be called exactly once, to set the first scanline
+    // of the curve. Before it is called, the curve should think its first
+    // scanline is CEIL(YMIN).
+    private void quadSetCurY(final int idx, final int y) {
+        assert y < quads[idx+YMAX];
+        assert (quads[idx+CURY] > y);
+        assert (quads[idx+CURY] == Math.ceil(quads[idx+CURY]));
 
-    // The following array is a poor man's struct array:
-    // it simulates a struct array by having
-    // edges[SIZEOF_STRUCT_EDGE * i + j] be the jth field in the ith element
-    // of an array of edge structs.
-    private float[] edges;
-    private int edgesSize; // size of the edge list.
-    private static final int Y1    = 0;
-    private static final int SLOPE = 1;
-    private static final int OR    = 2; // the orientation. This can be -1 or 1.
-                                     // -1 means up, 1 means down.
-    private static final int CURY  = 3; // j = 5 corresponds to the "current Y".
-                             // Each edge keeps track of the last scanline
-                             // crossing it computed, and this is the y coord of
-                             // that scanline.
-    private static final int CURX = 4; //the x coord of the current crossing.
+        while (quads[idx+CURY] < ((float)y)) {
+            quadGoToNextY(idx);
+        }
+    }
+    private void quadGoToNextY(final int idx) {
+        quads[idx+CURY] += 1;
+        // this will get overriden if the while executes.
+        quads[idx+CURX] += quads[idx+CURSLOPE];
+        int count = (int)quads[idx+COUNT];
+        // this loop should never execute more than once because our
+        // curve is monotonic in Y. Still we put it in because you can
+        // never be too sure when dealing with floating point.
+        while(quads[idx+CURY] >= quads[idx+Y0] && count > 0) {
+            float x0 = quads[idx+X0], y0 = quads[idx+Y0];
+            count = executeQuadAFDIteration(idx);
+            float x1 = quads[idx+X0], y1 = quads[idx+Y0];
+            // our quads are monotonic, so this shouldn't happen, but
+            // it is conceivable that for very flat quads with different
+            // y values at their endpoints AFD might give us a horizontal
+            // segment.
+            if (y1 == y0) {
+                continue;
+            }
+            quads[idx+CURSLOPE] = (x1 - x0) / (y1 - y0);
+            quads[idx+CURX] = x0 + (quads[idx+CURY] - y0) * quads[idx+CURSLOPE];
+        }
+    }
+
 
-    // Note that while the array is declared as a float[] not all of it's
-    // elements should be floats. currentY and Orientation should be ints (or int and
-    // byte respectively), but they all need to be the same type. This isn't
-    // really a problem because floats can represent exactly all 23 bit integers,
-    // which should be more than enough.
-    // Note, also, that we only need x1 for slope computation, so we don't need
-    // to store it. x0, y0 don't need to be stored either. They can be put into
-    // curx, cury, and it's ok if they're lost when curx and cury are changed.
-    // We take this undeniably ugly and error prone approach (instead of simply
-    // making an Edge class) for performance reasons. Also, it would probably be nicer
-    // to have one array for each field, but that would defeat the purpose because
-    // it would make poor use of the processor cache, since we tend to access
-    // all the fields for one edge at a time.
+    private static final int SIZEOF_CURVE = 16;
+    private float[] curves = null;
+    private int numCurves;
+    private void curveSetCurY(final int idx, final int y) {
+        assert y < curves[idx+YMAX];
+        assert (curves[idx+CURY] > y);
+        assert (curves[idx+CURY] == Math.ceil(curves[idx+CURY]));
 
-    private float edgeMinY;
-    private float edgeMaxY;
+        while (curves[idx+CURY] < ((float)y)) {
+            curveGoToNextY(idx);
+        }
+    }
+    private void curveGoToNextY(final int idx) {
+        curves[idx+CURY] += 1;
+        // this will get overriden if the while executes.
+        curves[idx+CURX] += curves[idx+CURSLOPE];
+        int count = (int)curves[idx+COUNT];
+        // this loop should never execute more than once because our
+        // curve is monotonic in Y. Still we put it in because you can
+        // never be too sure when dealing with floating point.
+        while(curves[idx+CURY] >= curves[idx+Y0] && count > 0) {
+            float x0 = curves[idx+X0], y0 = curves[idx+Y0];
+            count = executeCurveAFDIteration(idx);
+            float x1 = curves[idx+X0], y1 = curves[idx+Y0];
+            // our curves are monotonic, so this shouldn't happen, but
+            // it is conceivable that for very flat curves with different
+            // y values at their endpoints AFD might give us a horizontal
+            // segment.
+            if (y1 == y0) {
+                continue;
+            }
+            curves[idx+CURSLOPE] = (x1 - x0) / (y1 - y0);
+            curves[idx+CURX] = x0 + (curves[idx+CURY] - y0) * curves[idx+CURSLOPE];
+        }
+    }
 
 
-    private void addEdge(float x0, float y0, float x1, float y1) {
-        float or = (y0 < y1) ? 1f : -1f; // orientation: 1 = UP; -1 = DOWN
-        if (or == -1) {
-            float tmp = y0;
-            y0 = y1;
-            y1 = tmp;
-            tmp = x0;
-            x0 = x1;
-            x1 = tmp;
+    private static final float DEC_BND = 20f;
+    private static final float INC_BND = 8f;
+    // Flattens using adaptive forward differencing. This only carries out
+    // one iteration of the AFD loop. All it does is update AFD variables (i.e.
+    // X0, Y0, D*[X|Y], COUNT; not variables used for computing scanline crossings).
+    private int executeQuadAFDIteration(int idx) {
+        int count = (int)quads[idx+COUNT];
+        float ddx = quads[idx+DDX];
+        float ddy = quads[idx+DDY];
+        float dx = quads[idx+DX];
+        float dy = quads[idx+DY];
+
+        while (Math.abs(ddx) > DEC_BND || Math.abs(ddy) > DEC_BND) {
+            ddx = ddx / 4;
+            ddy = ddy / 4;
+            dx = (dx - ddx) / 2;
+            dy = (dy - ddy) / 2;
+            count <<= 1;
+        }
+        // can only do this on even "count" values, because we must divide count by 2
+        while (count % 2 == 0 && Math.abs(dx) <= INC_BND && Math.abs(dy) <= INC_BND) {
+            dx = 2 * dx + ddx;
+            dy = 2 * dy + ddy;
+            ddx = 4 * ddx;
+            ddy = 4 * ddy;
+            count >>= 1;
+        }
+        count--;
+        if (count > 0) {
+            quads[idx+X0] += dx;
+            dx += ddx;
+            quads[idx+Y0] += dy;
+            dy += ddy;
+        } else {
+            quads[idx+X0] = quads[idx+XL];
+            quads[idx+Y0] = quads[idx+YMAX];
+        }
+        quads[idx+COUNT] = count;
+        quads[idx+DDX] = ddx;
+        quads[idx+DDY] = ddy;
+        quads[idx+DX] = dx;
+        quads[idx+DY] = dy;
+        return count;
+    }
+    private int executeCurveAFDIteration(int idx) {
+        int count = (int)curves[idx+COUNT];
+        float ddx = curves[idx+DDX];
+        float ddy = curves[idx+DDY];
+        float dx = curves[idx+DX];
+        float dy = curves[idx+DY];
+        float dddx = curves[idx+DDDX];
+        float dddy = curves[idx+DDDY];
+
+        while (Math.abs(ddx) > DEC_BND || Math.abs(ddy) > DEC_BND) {
+            dddx /= 8;
+            dddy /= 8;
+            ddx = ddx/4 - dddx;
+            ddy = ddy/4 - dddy;
+            dx = (dx - ddx) / 2;
+            dy = (dy - ddy) / 2;
+            count <<= 1;
+        }
+        // can only do this on even "count" values, because we must divide count by 2
+        while (count % 2 == 0 && Math.abs(dx) <= INC_BND && Math.abs(dy) <= INC_BND) {
+            dx = 2 * dx + ddx;
+            dy = 2 * dy + ddy;
+            ddx = 4 * (ddx + dddx);
+            ddy = 4 * (ddy + dddy);
+            dddx = 8 * dddx;
+            dddy = 8 * dddy;
+            count >>= 1;
+        }
+        count--;
+        if (count > 0) {
+            curves[idx+X0] += dx;
+            dx += ddx;
+            ddx += dddx;
+            curves[idx+Y0] += dy;
+            dy += ddy;
+            ddy += dddy;
+        } else {
+            curves[idx+X0] = curves[idx+XL];
+            curves[idx+Y0] = curves[idx+YMAX];
         }
-        // skip edges that don't cross a scanline
-        if (Math.ceil(y0) >= Math.ceil(y1)) {
+        curves[idx+COUNT] = count;
+        curves[idx+DDDX] = dddx;
+        curves[idx+DDDY] = dddy;
+        curves[idx+DDX] = ddx;
+        curves[idx+DDY] = ddy;
+        curves[idx+DX] = dx;
+        curves[idx+DY] = dy;
+        return count;
+    }
+
+
+    private void initLine(final int idx, float[] pts, int or) {
+        edges[idx+SLOPE] = (pts[2] - pts[0]) / (pts[3] - pts[1]);
+        edges[idx+CURX] = pts[0] + (edges[idx+CURY] - pts[1]) * edges[idx+SLOPE];
+    }
+
+    private void initQuad(final int idx, float[] points, int or) {
+        final int countlg = 3;
+        final int count = 1 << countlg;
+
+        // the dx and dy refer to forward differencing variables, not the last
+        // coefficients of the "points" polynomial
+        final float ddx, ddy, dx, dy;
+        c.set(points, 6);
+
+        ddx = c.dbx / (1 << (2 * countlg));
+        ddy = c.dby / (1 << (2 * countlg));
+        dx = c.bx / (1 << (2 * countlg)) + c.cx / (1 << countlg);
+        dy = c.by / (1 << (2 * countlg)) + c.cy / (1 << countlg);
+
+        quads[idx+DDX] = ddx;
+        quads[idx+DDY] = ddy;
+        quads[idx+DX] = dx;
+        quads[idx+DY] = dy;
+        quads[idx+COUNT] = count;
+        quads[idx+XL] = points[4];
+        quads[idx+X0] = points[0];
+        quads[idx+Y0] = points[1];
+        executeQuadAFDIteration(idx);
+        float x1 = quads[idx+X0], y1 = quads[idx+Y0];
+        quads[idx+CURSLOPE] = (x1 - points[0]) / (y1 - points[1]);
+        quads[idx+CURX] = points[0] + (quads[idx+CURY] - points[1])*quads[idx+CURSLOPE];
+    }
+
+    private void initCurve(final int idx, float[] points, int or) {
+        final int countlg = 3;
+        final int count = 1 << countlg;
+
+        // the dx and dy refer to forward differencing variables, not the last
+        // coefficients of the "points" polynomial
+        final float dddx, dddy, ddx, ddy, dx, dy;
+        c.set(points, 8);
+        dddx = 2f * c.dax / (1 << (3 * countlg));
+        dddy = 2f * c.day / (1 << (3 * countlg));
+
+        ddx = dddx + c.dbx / (1 << (2 * countlg));
+        ddy = dddy + c.dby / (1 << (2 * countlg));
+        dx = c.ax / (1 << (3 * countlg)) + c.bx / (1 << (2 * countlg)) + c.cx / (1 << countlg);
+        dy = c.ay / (1 << (3 * countlg)) + c.by / (1 << (2 * countlg)) + c.cy / (1 << countlg);
+
+        curves[idx+DDDX] = dddx;
+        curves[idx+DDDY] = dddy;
+        curves[idx+DDX] = ddx;
+        curves[idx+DDY] = ddy;
+        curves[idx+DX] = dx;
+        curves[idx+DY] = dy;
+        curves[idx+COUNT] = count;
+        curves[idx+XL] = points[6];
+        curves[idx+X0] = points[0];
+        curves[idx+Y0] = points[1];
+        executeCurveAFDIteration(idx);
+        float x1 = curves[idx+X0], y1 = curves[idx+Y0];
+        curves[idx+CURSLOPE] = (x1 - points[0]) / (y1 - points[1]);
+        curves[idx+CURX] = points[0] + (curves[idx+CURY] - points[1])*curves[idx+CURSLOPE];
+    }
+
+    private void addPathSegment(float[] pts, final int type, final int or) {
+        int idx;
+        float[] addTo;
+        switch (type) {
+        case 4:
+            idx = numEdges * SIZEOF_EDGE;
+            addTo = edges = Helpers.widenArray(edges, numEdges*SIZEOF_EDGE, SIZEOF_EDGE);
+            numEdges++;
+            break;
+        case 6:
+            idx = numQuads * SIZEOF_QUAD;
+            addTo = quads = Helpers.widenArray(quads, numQuads*SIZEOF_QUAD, SIZEOF_QUAD);
+            numQuads++;
+            break;
+        case 8:
+            idx = numCurves * SIZEOF_CURVE;
+            addTo = curves = Helpers.widenArray(curves, numCurves*SIZEOF_CURVE, SIZEOF_CURVE);
+            numCurves++;
+            break;
+        default:
+            throw new InternalError();
+        }
+        // set the common fields, except CURX, for which we must know the kind
+        // of curve. NOTE: this must be done before the type specific fields
+        // are initialized, because those depend on the common ones.
+        addTo[idx+YMIN] = pts[1];
+        addTo[idx+YMAX] = pts[type-1];
+        addTo[idx+OR] = or;
+        addTo[idx+CURY] = (float)Math.ceil(pts[1]);
+        switch (type) {
+        case 4:
+            initLine(idx, pts, or);
+            break;
+        case 6:
+            initQuad(idx, pts, or);
+            break;
+        case 8:
+            initCurve(idx, pts, or);
+            break;
+        default:
+            throw new InternalError();
+        }
+    }
+
+    // precondition: the curve in pts must be monotonic and increasing in y.
+    private void somethingTo(float[] pts, final int type, final int or) {
+        // NOTE: it's very important that we check for or >= 0 below (as
+        // opposed to or == 1, or or > 0, or anything else). That's
+        // because if we check for or==1, when the curve being added
+        // is a horizontal line, or will be 0 so or==1 will be false and
+        // x0 and y0 will be updated to pts[0] and pts[1] instead of pts[type-2]
+        // and pts[type-1], which is the correct thing to do.
+        this.x0 = or >= 0 ? pts[type - 2] : pts[0];
+        this.y0 = or >= 0 ? pts[type - 1] : pts[1];
+
+        float minY = pts[1], maxY = pts[type - 1];
+        if (Math.ceil(minY) >= Math.ceil(maxY) ||
+            Math.ceil(minY) >= boundsMaxY || maxY < boundsMinY)
+        {
             return;
         }
 
-        int newSize = edgesSize + SIZEOF_STRUCT_EDGE;
-        if (edges.length < newSize) {
-            edges = Arrays.copyOf(edges, newSize * 2);
-        }
-        edges[edgesSize+CURX] = x0;
-        edges[edgesSize+CURY] = y0;
-        edges[edgesSize+Y1] = y1;
-        edges[edgesSize+SLOPE] = (x1 - x0) / (y1 - y0);
-        edges[edgesSize+OR] = or;
-        // the crossing values can't be initialized meaningfully yet. This
-        // will have to wait until setCurY is called
-        edgesSize += SIZEOF_STRUCT_EDGE;
+        if (minY < edgeMinY) { edgeMinY = minY; }
+        if (maxY > edgeMaxY) { edgeMaxY = maxY; }
 
-        // Accumulate edgeMinY and edgeMaxY
-        if (y0 < edgeMinY) { edgeMinY = y0; }
-        if (y1 > edgeMaxY) { edgeMaxY = y1; }
+        int minXidx = (pts[0] < pts[type-2] ? 0 : type - 2);
+        float minX = pts[minXidx];
+        float maxX = pts[type - 2 - minXidx];
+        if (minX < edgeMinX) { edgeMinX = minX; }
+        if (maxX > edgeMaxX) { edgeMaxX = maxX; }
+        addPathSegment(pts, type, or);
     }
 
-    // As far as the following methods care, this edges extends to infinity.
-    // They can compute the x intersect of any horizontal line.
-    // precondition: idx is the index to the start of the desired edge.
-    // So, if the ith edge is wanted, idx should be SIZEOF_STRUCT_EDGE * i
-    private void setCurY(int idx, int y) {
-        // compute the x crossing of edge at idx and horizontal line y
-        // currentXCrossing = (y - y0)*slope + x0
-        edges[idx + CURX] = (y - edges[idx + CURY]) * edges[idx + SLOPE] + edges[idx+CURX];
-        edges[idx + CURY] = (float)y;
-    }
+// END EDGE LIST
+//////////////////////////////////////////////////////////////////////////////
 
-    private void gotoNextY(int idx) {
-        edges[idx + CURY] += 1f; // i.e. curY += 1
-        edges[idx + CURX] += edges[idx + SLOPE]; // i.e. curXCrossing += slope
-    }
-
-    private int getCurCrossing(int idx) {
-        return (int)edges[idx + CURX];
-    }
-//====================================================================================
 
     public static final int WIND_EVEN_ODD = 0;
     public static final int WIND_NON_ZERO = 1;
@@ -284,16 +586,13 @@
     final int MAX_AA_ALPHA;
 
     // Cache to store RLE-encoded coverage mask of the current primitive
-    final PiscesCache cache;
+    PiscesCache cache;
 
     // Bounds of the drawing region, at subpixel precision.
-    final private int boundsMinX, boundsMinY, boundsMaxX, boundsMaxY;
-
-    // Pixel bounding box for current primitive
-    private int pix_bboxX0, pix_bboxY0, pix_bboxX1, pix_bboxY1;
+    private final int boundsMinX, boundsMinY, boundsMaxX, boundsMaxY;
 
     // Current winding rule
-    final private int windingRule;
+    private final int windingRule;
 
     // Current drawing position, i.e., final point of last segment
     private float x0, y0;
@@ -304,8 +603,8 @@
     public Renderer(int subpixelLgPositionsX, int subpixelLgPositionsY,
                     int pix_boundsX, int pix_boundsY,
                     int pix_boundsWidth, int pix_boundsHeight,
-                    int windingRule,
-                    PiscesCache cache) {
+                    int windingRule)
+    {
         this.SUBPIXEL_LG_POSITIONS_X = subpixelLgPositionsX;
         this.SUBPIXEL_LG_POSITIONS_Y = subpixelLgPositionsY;
         this.SUBPIXEL_MASK_X = (1 << (SUBPIXEL_LG_POSITIONS_X)) - 1;
@@ -314,23 +613,12 @@
         this.SUBPIXEL_POSITIONS_Y = 1 << (SUBPIXEL_LG_POSITIONS_Y);
         this.MAX_AA_ALPHA = (SUBPIXEL_POSITIONS_X * SUBPIXEL_POSITIONS_Y);
 
-        this.edges = new float[SIZEOF_STRUCT_EDGE * INIT_NUM_EDGES];
-        edgeMinY = Float.POSITIVE_INFINITY;
-        edgeMaxY = Float.NEGATIVE_INFINITY;
-        edgesSize = 0;
-
         this.windingRule = windingRule;
-        this.cache = cache;
 
         this.boundsMinX = pix_boundsX * SUBPIXEL_POSITIONS_X;
         this.boundsMinY = pix_boundsY * SUBPIXEL_POSITIONS_Y;
         this.boundsMaxX = (pix_boundsX + pix_boundsWidth) * SUBPIXEL_POSITIONS_X;
         this.boundsMaxY = (pix_boundsY + pix_boundsHeight) * SUBPIXEL_POSITIONS_Y;
-
-        this.pix_bboxX0 = pix_boundsX;
-        this.pix_bboxY0 = pix_boundsY;
-        this.pix_bboxX1 = pix_boundsX + pix_boundsWidth;
-        this.pix_bboxY1 = pix_boundsY + pix_boundsHeight;
     }
 
     private float tosubpixx(float pix_x) {
@@ -341,7 +629,7 @@
     }
 
     public void moveTo(float pix_x0, float pix_y0) {
-        close();
+        closePath();
         this.pix_sx0 = pix_x0;
         this.pix_sy0 = pix_y0;
         this.y0 = tosubpixy(pix_y0);
@@ -350,39 +638,102 @@
 
     public void lineJoin() { /* do nothing */ }
 
-    public void lineTo(float pix_x1, float pix_y1) {
-        float x1 = tosubpixx(pix_x1);
-        float y1 = tosubpixy(pix_y1);
+    private final float[][] pts = new float[2][8];
+    private final float[] ts = new float[4];
+
+    private static void invertPolyPoints(float[] pts, int off, int type) {
+        for (int i = off, j = off + type - 2; i < j; i += 2, j -= 2) {
+            float tmp = pts[i];
+            pts[i] = pts[j];
+            pts[j] = tmp;
+            tmp = pts[i+1];
+            pts[i+1] = pts[j+1];
+            pts[j+1] = tmp;
+        }
+    }
 
-        // Ignore horizontal lines
-        if (y0 == y1) {
-            this.x0 = x1;
-            return;
+    // return orientation before making the curve upright.
+    private static int makeMonotonicCurveUpright(float[] pts, int off, int type) {
+        float y0 = pts[off + 1];
+        float y1 = pts[off + type - 1];
+        if (y0 > y1) {
+            invertPolyPoints(pts, off, type);
+            return -1;
+        } else if (y0 < y1) {
+            return 1;
         }
-
-        addEdge(x0, y0, x1, y1);
+        return 0;
+    }
 
-        this.x0 = x1;
-        this.y0 = y1;
+    public void lineTo(float pix_x1, float pix_y1) {
+        pts[0][0] = x0; pts[0][1] = y0;
+        pts[0][2] = tosubpixx(pix_x1); pts[0][3] = tosubpixy(pix_y1);
+        int or = makeMonotonicCurveUpright(pts[0], 0, 4);
+        somethingTo(pts[0], 4, or);
     }
 
-    public void close() {
+    Curve c = new Curve();
+    private void curveOrQuadTo(int type) {
+        c.set(pts[0], type);
+        int numTs = c.dxRoots(ts, 0);
+        numTs += c.dyRoots(ts, numTs);
+        numTs = Helpers.filterOutNotInAB(ts, 0, numTs, 0, 1);
+        Helpers.isort(ts, 0, numTs);
+
+        Iterator<float[]> it = Curve.breakPtsAtTs(pts, type, ts, numTs);
+        while(it.hasNext()) {
+            float[] curCurve = it.next();
+            int or = makeMonotonicCurveUpright(curCurve, 0, type);
+            somethingTo(curCurve, type, or);
+        }
+    }
+
+    @Override public void curveTo(float x1, float y1,
+                                  float x2, float y2,
+                                  float x3, float y3)
+    {
+        pts[0][0] = x0; pts[0][1] = y0;
+        pts[0][2] = tosubpixx(x1); pts[0][3] = tosubpixy(y1);
+        pts[0][4] = tosubpixx(x2); pts[0][5] = tosubpixy(y2);
+        pts[0][6] = tosubpixx(x3); pts[0][7] = tosubpixy(y3);
+        curveOrQuadTo(8);
+    }
+
+    @Override public void quadTo(float x1, float y1, float x2, float y2) {
+        pts[0][0] = x0; pts[0][1] = y0;
+        pts[0][2] = tosubpixx(x1); pts[0][3] = tosubpixy(y1);
+        pts[0][4] = tosubpixx(x2); pts[0][5] = tosubpixy(y2);
+        curveOrQuadTo(6);
+    }
+
+    public void closePath() {
         // lineTo expects its input in pixel coordinates.
         lineTo(pix_sx0, pix_sy0);
     }
 
-    public void end() {
-        close();
+    public void pathDone() {
+        closePath();
     }
 
-    private void _endRendering() {
+
+    @Override
+    public long getNativeConsumer() {
+        throw new InternalError("Renderer does not use a native consumer.");
+    }
+
+    private void _endRendering(final int pix_bboxx0, final int pix_bboxy0,
+                               final int pix_bboxx1, final int pix_bboxy1)
+    {
         // Mask to determine the relevant bit of the crossing sum
         // 0x1 if EVEN_ODD, all bits if NON_ZERO
         int mask = (windingRule == WIND_EVEN_ODD) ? 0x1 : ~0x0;
 
         // add 1 to better deal with the last pixel in a pixel row.
-        int width = ((boundsMaxX - boundsMinX) >> SUBPIXEL_LG_POSITIONS_X) + 1;
-        byte[] alpha = new byte[width+1];
+        int width = pix_bboxx1 - pix_bboxx0 + 1;
+        int[] alpha = new int[width+1];
+
+        int bboxx0 = pix_bboxx0 << SUBPIXEL_LG_POSITIONS_X;
+        int bboxx1 = pix_bboxx1 << SUBPIXEL_LG_POSITIONS_X;
 
         // Now we iterate through the scanlines. We must tell emitRow the coord
         // of the first non-transparent pixel, so we must keep accumulators for
@@ -394,33 +745,34 @@
         int pix_minX = Integer.MAX_VALUE;
 
         int y = boundsMinY; // needs to be declared here so we emit the last row properly.
-        ScanLineItInitialize();
-        for ( ; ScanLineItHasNext(); ) {
-            int numCrossings = ScanLineItGoToNextYAndComputeCrossings();
-            y = ScanLineItCurrentY();
+        ScanlineIterator it = this.new ScanlineIterator();
+        for ( ; it.hasNext(); ) {
+            int numCrossings = it.next();
+            int[] crossings = it.crossings;
+            y = it.curY();
 
             if (numCrossings > 0) {
                 int lowx = crossings[0] >> 1;
                 int highx = crossings[numCrossings - 1] >> 1;
-                int x0 = Math.max(lowx, boundsMinX);
-                int x1 = Math.min(highx, boundsMaxX);
+                int x0 = Math.max(lowx, bboxx0);
+                int x1 = Math.min(highx, bboxx1);
 
                 pix_minX = Math.min(pix_minX, x0 >> SUBPIXEL_LG_POSITIONS_X);
                 pix_maxX = Math.max(pix_maxX, x1 >> SUBPIXEL_LG_POSITIONS_X);
             }
 
             int sum = 0;
-            int prev = boundsMinX;
+            int prev = bboxx0;
             for (int i = 0; i < numCrossings; i++) {
                 int curxo = crossings[i];
                 int curx = curxo >> 1;
                 int crorientation = ((curxo & 0x1) == 0x1) ? 1 : -1;
                 if ((sum & mask) != 0) {
-                    int x0 = Math.max(prev, boundsMinX);
-                    int x1 = Math.min(curx, boundsMaxX);
+                    int x0 = Math.max(prev, bboxx0);
+                    int x1 = Math.min(curx, bboxx1);
                     if (x0 < x1) {
-                        x0 -= boundsMinX; // turn x0, x1 from coords to indeces
-                        x1 -= boundsMinX; // in the alpha array.
+                        x0 -= bboxx0; // turn x0, x1 from coords to indeces
+                        x1 -= bboxx0; // in the alpha array.
 
                         int pix_x = x0 >> SUBPIXEL_LG_POSITIONS_X;
                         int pix_xmaxm1 = (x1 - 1) >> SUBPIXEL_LG_POSITIONS_X;
@@ -442,6 +794,9 @@
                 prev = curx;
             }
 
+            // even if this last row had no crossings, alpha will be zeroed
+            // from the last emitRow call. But this doesn't matter because
+            // maxX < minX, so no row will be emitted to the cache.
             if ((y & SUBPIXEL_MASK_Y) == SUBPIXEL_MASK_Y) {
                 emitRow(alpha, y >> SUBPIXEL_LG_POSITIONS_Y, pix_minX, pix_maxX);
                 pix_minX = Integer.MAX_VALUE;
@@ -453,47 +808,53 @@
         if (pix_maxX >= pix_minX) {
             emitRow(alpha, y >> SUBPIXEL_LG_POSITIONS_Y, pix_minX, pix_maxX);
         }
-        pix_bboxX0 = minX >> SUBPIXEL_LG_POSITIONS_X;
-        pix_bboxX1 = maxX >> SUBPIXEL_LG_POSITIONS_X;
-        pix_bboxY0 = minY >> SUBPIXEL_LG_POSITIONS_Y;
-        pix_bboxY1 = maxY >> SUBPIXEL_LG_POSITIONS_Y;
     }
 
-
     public void endRendering() {
-        // Set up the cache to accumulate the bounding box
-        if (cache != null) {
-            cache.bboxX0 = Integer.MAX_VALUE;
-            cache.bboxY0 = Integer.MAX_VALUE;
-            cache.bboxX1 = Integer.MIN_VALUE;
-            cache.bboxY1 = Integer.MIN_VALUE;
+        final int bminx = boundsMinX >> SUBPIXEL_LG_POSITIONS_X;
+        final int bmaxx = boundsMaxX >> SUBPIXEL_LG_POSITIONS_X;
+        final int bminy = boundsMinY >> SUBPIXEL_LG_POSITIONS_Y;
+        final int bmaxy = boundsMaxY >> SUBPIXEL_LG_POSITIONS_Y;
+        final int eminx = ((int)Math.floor(edgeMinX)) >> SUBPIXEL_LG_POSITIONS_X;
+        final int emaxx = ((int)Math.ceil(edgeMaxX)) >> SUBPIXEL_LG_POSITIONS_X;
+        final int eminy = ((int)Math.floor(edgeMinY)) >> SUBPIXEL_LG_POSITIONS_Y;
+        final int emaxy = ((int)Math.ceil(edgeMaxY)) >> SUBPIXEL_LG_POSITIONS_Y;
+
+        final int minX = Math.max(bminx, eminx);
+        final int maxX = Math.min(bmaxx, emaxx);
+        final int minY = Math.max(bminy, eminy);
+        final int maxY = Math.min(bmaxy, emaxy);
+        if (minX > maxX || minY > maxY) {
+            this.cache = new PiscesCache(bminx, bminy, bmaxx, bmaxy);
+            return;
         }
 
-        _endRendering();
+        this.cache = new PiscesCache(minX, minY, maxX, maxY);
+        _endRendering(minX, minY, maxX, maxY);
     }
 
-    public void getBoundingBox(int[] pix_bbox) {
-        pix_bbox[0] = pix_bboxX0;
-        pix_bbox[1] = pix_bboxY0;
-        pix_bbox[2] = pix_bboxX1 - pix_bboxX0;
-        pix_bbox[3] = pix_bboxY1 - pix_bboxY0;
+    public PiscesCache getCache() {
+        if (cache == null) {
+            throw new InternalError("cache not yet initialized");
+        }
+        return cache;
     }
 
-    private void emitRow(byte[] alphaRow, int pix_y, int pix_from, int pix_to) {
+    private void emitRow(int[] alphaRow, int pix_y, int pix_from, int pix_to) {
         // Copy rowAA data into the cache if one is present
         if (cache != null) {
             if (pix_to >= pix_from) {
-                cache.startRow(pix_y, pix_from, pix_to);
+                cache.startRow(pix_y, pix_from);
 
                 // Perform run-length encoding and store results in the cache
-                int from = pix_from - (boundsMinX >> SUBPIXEL_LG_POSITIONS_X);
-                int to = pix_to - (boundsMinX >> SUBPIXEL_LG_POSITIONS_X);
+                int from = pix_from - cache.bboxX0;
+                int to = pix_to - cache.bboxX0;
 
                 int runLen = 1;
-                byte startVal = alphaRow[from];
+                int startVal = alphaRow[from];
                 for (int i = from + 1; i <= to; i++) {
-                    byte nextVal = (byte)(startVal + alphaRow[i]);
-                    if (nextVal == startVal && runLen < 255) {
+                    int nextVal = startVal + alphaRow[i];
+                    if (nextVal == startVal) {
                         runLen++;
                     } else {
                         cache.addRLERun(startVal, runLen);
@@ -502,9 +863,8 @@
                     }
                 }
                 cache.addRLERun(startVal, runLen);
-                cache.addRLERun((byte)0, 0);
             }
         }
-        java.util.Arrays.fill(alphaRow, (byte)0);
+        java.util.Arrays.fill(alphaRow, 0);
     }
 }
--- a/jdk/src/share/classes/sun/java2d/pisces/Stroker.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/java2d/pisces/Stroker.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,10 +25,18 @@
 
 package sun.java2d.pisces;
 
-public class Stroker implements LineSink {
+import java.util.Arrays;
+import java.util.Iterator;
+
+import sun.awt.geom.PathConsumer2D;
+
+// TODO: some of the arithmetic here is too verbose and prone to hard to
+// debug typos. We should consider making a small Point/Vector class that
+// has methods like plus(Point), minus(Point), dot(Point), cross(Point)and such
+public class Stroker implements PathConsumer2D {
 
     private static final int MOVE_TO = 0;
-    private static final int LINE_TO = 1;
+    private static final int DRAWING_OP_TO = 1; // ie. curve, line, or quad
     private static final int CLOSE = 2;
 
     /**
@@ -61,57 +69,37 @@
      */
     public static final int CAP_SQUARE = 2;
 
-    private final LineSink output;
+    private final PathConsumer2D out;
 
     private final int capStyle;
     private final int joinStyle;
 
-    private final float m00, m01, m10, m11, det;
-
     private final float lineWidth2;
-    private final float scaledLineWidth2;
 
-    // For any pen offset (pen_dx, pen_dy) that does not depend on
-    // the line orientation, the pen should be transformed so that:
-    //
-    // pen_dx' = m00*pen_dx + m01*pen_dy
-    // pen_dy' = m10*pen_dx + m11*pen_dy
-    //
-    // For a round pen, this means:
-    //
-    // pen_dx(r, theta) = r*cos(theta)
-    // pen_dy(r, theta) = r*sin(theta)
-    //
-    // pen_dx'(r, theta) = r*(m00*cos(theta) + m01*sin(theta))
-    // pen_dy'(r, theta) = r*(m10*cos(theta) + m11*sin(theta))
-    private int numPenSegments;
-    private final float[] pen_dx;
-    private final float[] pen_dy;
-    private boolean[] penIncluded;
-    private final float[] join;
-
-    private final float[] offset = new float[2];
-    private float[] reverse = new float[100];
+    private final float[][] offset = new float[3][2];
     private final float[] miter = new float[2];
     private final float miterLimitSq;
 
     private int prev;
-    private int rindex;
-    private boolean started;
-    private boolean lineToOrigin;
-    private boolean joinToOrigin;
 
-    private float sx0, sy0, sx1, sy1, x0, y0, px0, py0;
-    private float mx0, my0, omx, omy;
+    // The starting point of the path, and the slope there.
+    private float sx0, sy0, sdx, sdy;
+    // the current point and the slope there.
+    private float cx0, cy0, cdx, cdy; // c stands for current
+    // vectors that when added to (sx0,sy0) and (cx0,cy0) respectively yield the
+    // first and last points on the left parallel path. Since this path is
+    // parallel, it's slope at any point is parallel to the slope of the
+    // original path (thought they may have different directions), so these
+    // could be computed from sdx,sdy and cdx,cdy (and vice versa), but that
+    // would be error prone and hard to read, so we keep these anyway.
+    private float smx, smy, cmx, cmy;
 
-    private float m00_2_m01_2;
-    private float m10_2_m11_2;
-    private float m00_m10_m01_m11;
+    private final PolyStack reverse = new PolyStack();
 
     /**
      * Constructs a <code>Stroker</code>.
      *
-     * @param output an output <code>LineSink</code>.
+     * @param pc2d an output <code>PathConsumer2D</code>.
      * @param lineWidth the desired line width in pixels
      * @param capStyle the desired end cap style, one of
      * <code>CAP_BUTT</code>, <code>CAP_ROUND</code> or
@@ -120,183 +108,61 @@
      * <code>JOIN_MITER</code>, <code>JOIN_ROUND</code> or
      * <code>JOIN_BEVEL</code>.
      * @param miterLimit the desired miter limit
-     * @param transform a <code>Transform4</code> object indicating
-     * the transform that has been previously applied to all incoming
-     * coordinates.  This is required in order to produce consistently
-     * shaped end caps and joins.
      */
-    public Stroker(LineSink output,
+    public Stroker(PathConsumer2D pc2d,
                    float lineWidth,
                    int capStyle,
                    int joinStyle,
-                   float miterLimit,
-                   float m00, float m01, float m10, float m11) {
-        this.output = output;
+                   float miterLimit)
+    {
+        this.out = pc2d;
 
         this.lineWidth2 = lineWidth / 2;
-        this.scaledLineWidth2 = m00 * lineWidth2;
         this.capStyle = capStyle;
         this.joinStyle = joinStyle;
 
-        m00_2_m01_2 = m00*m00 + m01*m01;
-        m10_2_m11_2 = m10*m10 + m11*m11;
-        m00_m10_m01_m11 = m00*m10 + m01*m11;
-
-        this.m00 = m00;
-        this.m01 = m01;
-        this.m10 = m10;
-        this.m11 = m11;
-        det = m00*m11 - m01*m10;
-
-        float limit = miterLimit * lineWidth2 * det;
+        float limit = miterLimit * lineWidth2;
         this.miterLimitSq = limit*limit;
 
-        this.numPenSegments = (int)(3.14159f * lineWidth);
-        this.pen_dx = new float[numPenSegments];
-        this.pen_dy = new float[numPenSegments];
-        this.penIncluded = new boolean[numPenSegments];
-        this.join = new float[2*numPenSegments];
-
-        for (int i = 0; i < numPenSegments; i++) {
-            double theta = (i * 2.0 * Math.PI)/numPenSegments;
-
-            double cos = Math.cos(theta);
-            double sin = Math.sin(theta);
-            pen_dx[i] = (float)(lineWidth2 * (m00*cos + m01*sin));
-            pen_dy[i] = (float)(lineWidth2 * (m10*cos + m11*sin));
-        }
-
-        prev = CLOSE;
-        rindex = 0;
-        started = false;
-        lineToOrigin = false;
+        this.prev = CLOSE;
     }
 
-    private void computeOffset(float x0, float y0,
-                               float x1, float y1, float[] m) {
-        float lx = x1 - x0;
-        float ly = y1 - y0;
-
-        float dx, dy;
-        if (m00 > 0 && m00 == m11 && m01 == 0 & m10 == 0) {
-            float ilen = (float)Math.hypot(lx, ly);
-            if (ilen == 0) {
-                dx = dy = 0;
-            } else {
-                dx = (ly * scaledLineWidth2)/ilen;
-                dy = -(lx * scaledLineWidth2)/ilen;
-            }
+    private static void computeOffset(final float lx, final float ly,
+                                      final float w, final float[] m)
+    {
+        final float len = (float)Math.hypot(lx, ly);
+        if (len == 0) {
+            m[0] = m[1] = 0;
         } else {
-            int sdet = (det > 0) ? 1 : -1;
-            float a = ly * m00 - lx * m10;
-            float b = ly * m01 - lx * m11;
-            float dh = (float)Math.hypot(a, b);
-            float div = sdet * lineWidth2/dh;
-
-            float ddx = ly * m00_2_m01_2 - lx * m00_m10_m01_m11;
-            float ddy = ly * m00_m10_m01_m11 - lx * m10_2_m11_2;
-            dx = ddx*div;
-            dy = ddy*div;
-        }
-
-        m[0] = dx;
-        m[1] = dy;
-    }
-
-    private void ensureCapacity(int newrindex) {
-        if (reverse.length < newrindex) {
-            reverse = java.util.Arrays.copyOf(reverse, 6*reverse.length/5);
+            m[0] = (ly * w)/len;
+            m[1] = -(lx * w)/len;
         }
     }
 
-    private boolean isCCW(float x0, float y0,
-                          float x1, float y1,
-                          float x2, float y2) {
-        return (x1 - x0) * (y2 - y1) < (y1 - y0) * (x2 - x1);
-    }
-
-    private boolean side(float x,  float y,
-                         float x0, float y0,
-                         float x1, float y1) {
-        return (y0 - y1)*x + (x1 - x0)*y + (x0*y1 - x1*y0) > 0;
-    }
-
-    private int computeRoundJoin(float cx, float cy,
-                                 float xa, float ya,
-                                 float xb, float yb,
-                                 int side,
-                                 boolean flip,
-                                 float[] join) {
-        float px, py;
-        int ncoords = 0;
-
-        boolean centerSide;
-        if (side == 0) {
-            centerSide = side(cx, cy, xa, ya, xb, yb);
-        } else {
-            centerSide = (side == 1);
-        }
-        for (int i = 0; i < numPenSegments; i++) {
-            px = cx + pen_dx[i];
-            py = cy + pen_dy[i];
-
-            boolean penSide = side(px, py, xa, ya, xb, yb);
-            penIncluded[i] = (penSide != centerSide);
-        }
-
-        int start = -1, end = -1;
-        for (int i = 0; i < numPenSegments; i++) {
-            if (penIncluded[i] &&
-                !penIncluded[(i + numPenSegments - 1) % numPenSegments]) {
-                start = i;
-            }
-            if (penIncluded[i] &&
-                !penIncluded[(i + 1) % numPenSegments]) {
-                end = i;
-            }
-        }
-
-        if (end < start) {
-            end += numPenSegments;
-        }
-
-        if (start != -1 && end != -1) {
-            float dxa = cx + pen_dx[start] - xa;
-            float dya = cy + pen_dy[start] - ya;
-            float dxb = cx + pen_dx[start] - xb;
-            float dyb = cy + pen_dy[start] - yb;
-
-            boolean rev = (dxa*dxa + dya*dya > dxb*dxb + dyb*dyb);
-            int i = rev ? end : start;
-            int incr = rev ? -1 : 1;
-            while (true) {
-                int idx = i % numPenSegments;
-                px = cx + pen_dx[idx];
-                py = cy + pen_dy[idx];
-                join[ncoords++] = px;
-                join[ncoords++] = py;
-                if (i == (rev ? start : end)) {
-                    break;
-                }
-                i += incr;
-            }
-        }
-
-        return ncoords/2;
+    // Returns true if the vectors (dx1, dy1) and (dx2, dy2) are
+    // clockwise (if dx1,dy1 needs to be rotated clockwise to close
+    // the smallest angle between it and dx2,dy2).
+    // This is equivalent to detecting whether a point q is on the right side
+    // of a line passing through points p1, p2 where p2 = p1+(dx1,dy1) and
+    // q = p2+(dx2,dy2), which is the same as saying p1, p2, q are in a
+    // clockwise order.
+    // NOTE: "clockwise" here assumes coordinates with 0,0 at the bottom left.
+    private static boolean isCW(final float dx1, final float dy1,
+                                final float dx2, final float dy2)
+    {
+        return dx1 * dy2 <= dy1 * dx2;
     }
 
     // pisces used to use fixed point arithmetic with 16 decimal digits. I
-    // didn't want to change the values of the constants below when I converted
+    // didn't want to change the values of the constant below when I converted
     // it to floating point, so that's why the divisions by 2^16 are there.
     private static final float ROUND_JOIN_THRESHOLD = 1000/65536f;
-    private static final float ROUND_JOIN_INTERNAL_THRESHOLD = 1000000000/65536f;
 
     private void drawRoundJoin(float x, float y,
                                float omx, float omy, float mx, float my,
-                               int side,
-                               boolean flip,
                                boolean rev,
-                               float threshold) {
+                               float threshold)
+    {
         if ((omx == 0 && omy == 0) || (mx == 0 && my == 0)) {
             return;
         }
@@ -314,54 +180,148 @@
             mx = -mx;
             my = -my;
         }
+        drawRoundJoin(x, y, omx, omy, mx, my, rev);
+    }
 
-        float bx0 = x + omx;
-        float by0 = y + omy;
-        float bx1 = x + mx;
-        float by1 = y + my;
+    private void drawRoundJoin(float cx, float cy,
+                               float omx, float omy,
+                               float mx, float my,
+                               boolean rev)
+    {
+        // The sign of the dot product of mx,my and omx,omy is equal to the
+        // the sign of the cosine of ext
+        // (ext is the angle between omx,omy and mx,my).
+        double cosext = omx * mx + omy * my;
+        // If it is >=0, we know that abs(ext) is <= 90 degrees, so we only
+        // need 1 curve to approximate the circle section that joins omx,omy
+        // and mx,my.
+        final int numCurves = cosext >= 0 ? 1 : 2;
 
-        int npoints = computeRoundJoin(x, y,
-                                       bx0, by0, bx1, by1, side, flip,
-                                       join);
-        for (int i = 0; i < npoints; i++) {
-            emitLineTo(join[2*i], join[2*i + 1], rev);
+        switch (numCurves) {
+        case 1:
+            drawBezApproxForArc(cx, cy, omx, omy, mx, my, rev);
+            break;
+        case 2:
+            // we need to split the arc into 2 arcs spanning the same angle.
+            // The point we want will be one of the 2 intersections of the
+            // perpendicular bisector of the chord (omx,omy)->(mx,my) and the
+            // circle. We could find this by scaling the vector
+            // (omx+mx, omy+my)/2 so that it has length=lineWidth2 (and thus lies
+            // on the circle), but that can have numerical problems when the angle
+            // between omx,omy and mx,my is close to 180 degrees. So we compute a
+            // normal of (omx,omy)-(mx,my). This will be the direction of the
+            // perpendicular bisector. To get one of the intersections, we just scale
+            // this vector that its length is lineWidth2 (this works because the
+            // perpendicular bisector goes through the origin). This scaling doesn't
+            // have numerical problems because we know that lineWidth2 divided by
+            // this normal's length is at least 0.5 and at most sqrt(2)/2 (because
+            // we know the angle of the arc is > 90 degrees).
+            float nx = my - omy, ny = omx - mx;
+            float nlen = (float)Math.sqrt(nx*nx + ny*ny);
+            float scale = lineWidth2/nlen;
+            float mmx = nx * scale, mmy = ny * scale;
+
+            // if (isCW(omx, omy, mx, my) != isCW(mmx, mmy, mx, my)) then we've
+            // computed the wrong intersection so we get the other one.
+            // The test above is equivalent to if (rev).
+            if (rev) {
+                mmx = -mmx;
+                mmy = -mmy;
+            }
+            drawBezApproxForArc(cx, cy, omx, omy, mmx, mmy, rev);
+            drawBezApproxForArc(cx, cy, mmx, mmy, mx, my, rev);
+            break;
         }
     }
 
-    // Return the intersection point of the lines (ix0, iy0) -> (ix1, iy1)
-    // and (ix0p, iy0p) -> (ix1p, iy1p) in m[0] and m[1]
-    private void computeMiter(float x0, float y0, float x1, float y1,
-                              float x0p, float y0p, float x1p, float y1p,
-                              float[] m) {
+    // the input arc defined by omx,omy and mx,my must span <= 90 degrees.
+    private void drawBezApproxForArc(final float cx, final float cy,
+                                     final float omx, final float omy,
+                                     final float mx, final float my,
+                                     boolean rev)
+    {
+        float cosext2 = (omx * mx + omy * my) / (2 * lineWidth2 * lineWidth2);
+        // cv is the length of P1-P0 and P2-P3 divided by the radius of the arc
+        // (so, cv assumes the arc has radius 1). P0, P1, P2, P3 are the points that
+        // define the bezier curve we're computing.
+        // It is computed using the constraints that P1-P0 and P3-P2 are parallel
+        // to the arc tangents at the endpoints, and that |P1-P0|=|P3-P2|.
+        float cv = (float)((4.0 / 3.0) * Math.sqrt(0.5-cosext2) /
+                           (1.0 + Math.sqrt(cosext2+0.5)));
+        // if clockwise, we need to negate cv.
+        if (rev) { // rev is equivalent to isCW(omx, omy, mx, my)
+            cv = -cv;
+        }
+        final float x1 = cx + omx;
+        final float y1 = cy + omy;
+        final float x2 = x1 - cv * omy;
+        final float y2 = y1 + cv * omx;
+
+        final float x4 = cx + mx;
+        final float y4 = cy + my;
+        final float x3 = x4 + cv * my;
+        final float y3 = y4 - cv * mx;
+
+        emitCurveTo(x1, y1, x2, y2, x3, y3, x4, y4, rev);
+    }
+
+    private void drawRoundCap(float cx, float cy, float mx, float my) {
+        final float C = 0.5522847498307933f;
+        // the first and second arguments of the following two calls
+        // are really will be ignored by emitCurveTo (because of the false),
+        // but we put them in anyway, as opposed to just giving it 4 zeroes,
+        // because it's just 4 additions and it's not good to rely on this
+        // sort of assumption (right now it's true, but that may change).
+        emitCurveTo(cx+mx,      cy+my,
+                    cx+mx-C*my, cy+my+C*mx,
+                    cx-my+C*mx, cy+mx+C*my,
+                    cx-my,      cy+mx,
+                    false);
+        emitCurveTo(cx-my,      cy+mx,
+                    cx-my-C*mx, cy+mx-C*my,
+                    cx-mx-C*my, cy-my+C*mx,
+                    cx-mx,      cy-my,
+                    false);
+    }
+
+    // Return the intersection point of the lines (x0, y0) -> (x1, y1)
+    // and (x0p, y0p) -> (x1p, y1p) in m[0] and m[1]
+    private void computeMiter(final float x0, final float y0,
+                              final float x1, final float y1,
+                              final float x0p, final float y0p,
+                              final float x1p, final float y1p,
+                              final float[] m, int off)
+    {
         float x10 = x1 - x0;
         float y10 = y1 - y0;
         float x10p = x1p - x0p;
         float y10p = y1p - y0p;
 
+        // if this is 0, the lines are parallel. If they go in the
+        // same direction, there is no intersection so m[off] and
+        // m[off+1] will contain infinity, so no miter will be drawn.
+        // If they go in the same direction that means that the start of the
+        // current segment and the end of the previous segment have the same
+        // tangent, in which case this method won't even be involved in
+        // miter drawing because it won't be called by drawMiter (because
+        // (mx == omx && my == omy) will be true, and drawMiter will return
+        // immediately).
         float den = x10*y10p - x10p*y10;
-        if (den == 0) {
-            m[0] = x0;
-            m[1] = y0;
-            return;
-        }
-
-        float t = x1p*(y0 - y0p) - x0*y10p + x0p*(y1p - y0);
-        m[0] = x0 + (t*x10)/den;
-        m[1] = y0 + (t*y10)/den;
+        float t = x10p*(y0-y0p) - y10p*(x0-x0p);
+        t /= den;
+        m[off++] = x0 + t*x10;
+        m[off] = y0 + t*y10;
     }
 
-    private void drawMiter(float px0, float py0,
-                           float x0, float y0,
-                           float x1, float y1,
+    private void drawMiter(final float pdx, final float pdy,
+                           final float x0, final float y0,
+                           final float dx, final float dy,
                            float omx, float omy, float mx, float my,
-                           boolean rev) {
-        if (mx == omx && my == omy) {
-            return;
-        }
-        if (px0 == x0 && py0 == y0) {
-            return;
-        }
-        if (x0 == x1 && y0 == y1) {
+                           boolean rev)
+    {
+        if ((mx == omx && my == omy) ||
+            (pdx == 0 && pdy == 0) ||
+            (dx == 0 && dy == 0)) {
             return;
         }
 
@@ -372,297 +332,734 @@
             my = -my;
         }
 
-        computeMiter(px0 + omx, py0 + omy, x0 + omx, y0 + omy,
-                     x0 + mx, y0 + my, x1 + mx, y1 + my,
-                     miter);
+        computeMiter((x0 - pdx) + omx, (y0 - pdy) + omy, x0 + omx, y0 + omy,
+                     (dx + x0) + mx, (dy + y0) + my, x0 + mx, y0 + my,
+                     miter, 0);
 
-        // Compute miter length in untransformed coordinates
-        float dx = miter[0] - x0;
-        float dy = miter[1] - y0;
-        float a = dy*m00 - dx*m10;
-        float b = dy*m01 - dx*m11;
-        float lenSq = a*a + b*b;
+        float lenSq = (miter[0]-x0)*(miter[0]-x0) + (miter[1]-y0)*(miter[1]-y0);
 
         if (lenSq < miterLimitSq) {
             emitLineTo(miter[0], miter[1], rev);
         }
     }
 
-
     public void moveTo(float x0, float y0) {
-        // System.out.println("Stroker.moveTo(" + x0/65536.0 + ", " + y0/65536.0 + ")");
-
-        if (lineToOrigin) {
-            // not closing the path, do the previous lineTo
-            lineToImpl(sx0, sy0, joinToOrigin);
-            lineToOrigin = false;
-        }
-
-        if (prev == LINE_TO) {
+        if (prev == DRAWING_OP_TO) {
             finish();
         }
-
-        this.sx0 = this.x0 = x0;
-        this.sy0 = this.y0 = y0;
-        this.rindex = 0;
-        this.started = false;
-        this.joinSegment = false;
+        this.sx0 = this.cx0 = x0;
+        this.sy0 = this.cy0 = y0;
+        this.cdx = this.sdx = 1;
+        this.cdy = this.sdy = 0;
         this.prev = MOVE_TO;
     }
 
-    boolean joinSegment = false;
-
-    public void lineJoin() {
-        // System.out.println("Stroker.lineJoin()");
-        this.joinSegment = true;
-    }
-
     public void lineTo(float x1, float y1) {
-        // System.out.println("Stroker.lineTo(" + x1/65536.0 + ", " + y1/65536.0 + ")");
+        float dx = x1 - cx0;
+        float dy = y1 - cy0;
+        if (dx == 0f && dy == 0f) {
+            dx = 1;
+        }
+        computeOffset(dx, dy, lineWidth2, offset[0]);
+        float mx = offset[0][0];
+        float my = offset[0][1];
 
-        if (lineToOrigin) {
-            if (x1 == sx0 && y1 == sy0) {
-                // staying in the starting point
-                return;
-            }
+        drawJoin(cdx, cdy, cx0, cy0, dx, dy, cmx, cmy, mx, my);
 
-            // not closing the path, do the previous lineTo
-            lineToImpl(sx0, sy0, joinToOrigin);
-            lineToOrigin = false;
-        } else if (x1 == x0 && y1 == y0) {
-            return;
-        } else if (x1 == sx0 && y1 == sy0) {
-            lineToOrigin = true;
-            joinToOrigin = joinSegment;
-            joinSegment = false;
-            return;
-        }
+        emitLineTo(cx0 + mx, cy0 + my);
+        emitLineTo(x1 + mx, y1 + my);
+
+        emitLineTo(cx0 - mx, cy0 - my, true);
+        emitLineTo(x1 - mx, y1 - my, true);
 
-        lineToImpl(x1, y1, joinSegment);
-        joinSegment = false;
+        this.cmx = mx;
+        this.cmy = my;
+        this.cdx = dx;
+        this.cdy = dy;
+        this.cx0 = x1;
+        this.cy0 = y1;
+        this.prev = DRAWING_OP_TO;
     }
 
-    private void lineToImpl(float x1, float y1, boolean joinSegment) {
-        computeOffset(x0, y0, x1, y1, offset);
-        float mx = offset[0];
-        float my = offset[1];
-
-        if (!started) {
-            emitMoveTo(x0 + mx, y0 + my);
-            this.sx1 = x1;
-            this.sy1 = y1;
-            this.mx0 = mx;
-            this.my0 = my;
-            started = true;
-        } else {
-            boolean ccw = isCCW(px0, py0, x0, y0, x1, y1);
-            if (joinSegment) {
-                if (joinStyle == JOIN_MITER) {
-                    drawMiter(px0, py0, x0, y0, x1, y1, omx, omy, mx, my,
-                              ccw);
-                } else if (joinStyle == JOIN_ROUND) {
-                    drawRoundJoin(x0, y0,
-                                  omx, omy,
-                                  mx, my, 0, false, ccw,
-                                  ROUND_JOIN_THRESHOLD);
-                }
-            } else {
-                // Draw internal joins as round
-                drawRoundJoin(x0, y0,
-                              omx, omy,
-                              mx, my, 0, false, ccw,
-                              ROUND_JOIN_INTERNAL_THRESHOLD);
+    public void closePath() {
+        if (prev != DRAWING_OP_TO) {
+            if (prev == CLOSE) {
+                return;
             }
-
-            emitLineTo(x0, y0, !ccw);
-        }
-
-        emitLineTo(x0 + mx, y0 + my, false);
-        emitLineTo(x1 + mx, y1 + my, false);
-
-        emitLineTo(x0 - mx, y0 - my, true);
-        emitLineTo(x1 - mx, y1 - my, true);
-
-        this.omx = mx;
-        this.omy = my;
-        this.px0 = x0;
-        this.py0 = y0;
-        this.x0 = x1;
-        this.y0 = y1;
-        this.prev = LINE_TO;
-    }
-
-    public void close() {
-        // System.out.println("Stroker.close()");
-
-        if (lineToOrigin) {
-            // ignore the previous lineTo
-            lineToOrigin = false;
-        }
-
-        if (!started) {
+            emitMoveTo(cx0, cy0 - lineWidth2);
+            this.cmx = this.smx = 0;
+            this.cmy = this.smy = -lineWidth2;
+            this.cdx = this.sdx = 1;
+            this.cdy = this.sdy = 0;
             finish();
             return;
         }
 
-        computeOffset(x0, y0, sx0, sy0, offset);
-        float mx = offset[0];
-        float my = offset[1];
-
-        // Draw penultimate join
-        boolean ccw = isCCW(px0, py0, x0, y0, sx0, sy0);
-        if (joinSegment) {
-            if (joinStyle == JOIN_MITER) {
-                drawMiter(px0, py0, x0, y0, sx0, sy0, omx, omy, mx, my, ccw);
-            } else if (joinStyle == JOIN_ROUND) {
-                drawRoundJoin(x0, y0, omx, omy, mx, my, 0, false, ccw,
-                              ROUND_JOIN_THRESHOLD);
-            }
-        } else {
-            // Draw internal joins as round
-            drawRoundJoin(x0, y0,
-                          omx, omy,
-                          mx, my, 0, false, ccw,
-                          ROUND_JOIN_INTERNAL_THRESHOLD);
+        if (cx0 != sx0 || cy0 != sy0) {
+            lineTo(sx0, sy0);
         }
 
-        emitLineTo(x0 + mx, y0 + my);
-        emitLineTo(sx0 + mx, sy0 + my);
-
-        ccw = isCCW(x0, y0, sx0, sy0, sx1, sy1);
+        drawJoin(cdx, cdy, cx0, cy0, sdx, sdy, cmx, cmy, smx, smy);
 
-        // Draw final join on the outside
-        if (!ccw) {
-            if (joinStyle == JOIN_MITER) {
-                drawMiter(x0, y0, sx0, sy0, sx1, sy1,
-                          mx, my, mx0, my0, false);
-            } else if (joinStyle == JOIN_ROUND) {
-                drawRoundJoin(sx0, sy0, mx, my, mx0, my0, 0, false, false,
-                              ROUND_JOIN_THRESHOLD);
-            }
-        }
-
-        emitLineTo(sx0 + mx0, sy0 + my0);
-        emitLineTo(sx0 - mx0, sy0 - my0);  // same as reverse[0], reverse[1]
+        emitLineTo(sx0 + smx, sy0 + smy);
 
-        // Draw final join on the inside
-        if (ccw) {
-            if (joinStyle == JOIN_MITER) {
-                drawMiter(x0, y0, sx0, sy0, sx1, sy1,
-                          -mx, -my, -mx0, -my0, false);
-            } else if (joinStyle == JOIN_ROUND) {
-                drawRoundJoin(sx0, sy0, -mx, -my, -mx0, -my0, 0,
-                              true, false,
-                              ROUND_JOIN_THRESHOLD);
-            }
-        }
+        emitMoveTo(sx0 - smx, sy0 - smy);
+        emitReverse();
 
-        emitLineTo(sx0 - mx, sy0 - my);
-        emitLineTo(x0 - mx, y0 - my);
-        for (int i = rindex - 2; i >= 0; i -= 2) {
-            emitLineTo(reverse[i], reverse[i + 1]);
-        }
-
-        this.x0 = this.sx0;
-        this.y0 = this.sy0;
-        this.rindex = 0;
-        this.started = false;
-        this.joinSegment = false;
         this.prev = CLOSE;
         emitClose();
     }
 
-    public void end() {
-        // System.out.println("Stroker.end()");
+    private void emitReverse() {
+        while(!reverse.isEmpty()) {
+            reverse.pop(out);
+        }
+    }
 
-        if (lineToOrigin) {
-            // not closing the path, do the previous lineTo
-            lineToImpl(sx0, sy0, joinToOrigin);
-            lineToOrigin = false;
-        }
-
-        if (prev == LINE_TO) {
+    public void pathDone() {
+        if (prev == DRAWING_OP_TO) {
             finish();
         }
 
-        output.end();
-        this.joinSegment = false;
-        this.prev = MOVE_TO;
-    }
-
-    double userSpaceLineLength(double dx, double dy) {
-        double a = (dy*m00 - dx*m10)/det;
-        double b = (dy*m01 - dx*m11)/det;
-        return Math.hypot(a, b);
+        out.pathDone();
+        // this shouldn't matter since this object won't be used
+        // after the call to this method.
+        this.prev = CLOSE;
     }
 
     private void finish() {
         if (capStyle == CAP_ROUND) {
-            drawRoundJoin(x0, y0,
-                          omx, omy, -omx, -omy, 1, false, false,
-                          ROUND_JOIN_THRESHOLD);
+            drawRoundCap(cx0, cy0, cmx, cmy);
         } else if (capStyle == CAP_SQUARE) {
-            float dx = px0 - x0;
-            float dy = py0 - y0;
-            float len = (float)userSpaceLineLength(dx, dy);
-            float s = lineWidth2/len;
-
-            float capx = x0 - dx*s;
-            float capy = y0 - dy*s;
-
-            emitLineTo(capx + omx, capy + omy);
-            emitLineTo(capx - omx, capy - omy);
+            emitLineTo(cx0 - cmy + cmx, cy0 + cmx + cmy);
+            emitLineTo(cx0 - cmy - cmx, cy0 + cmx - cmy);
         }
 
-        for (int i = rindex - 2; i >= 0; i -= 2) {
-            emitLineTo(reverse[i], reverse[i + 1]);
-        }
-        this.rindex = 0;
+        emitReverse();
 
         if (capStyle == CAP_ROUND) {
-            drawRoundJoin(sx0, sy0,
-                          -mx0, -my0, mx0, my0, 1, false, false,
-                          ROUND_JOIN_THRESHOLD);
+            drawRoundCap(sx0, sy0, -smx, -smy);
         } else if (capStyle == CAP_SQUARE) {
-            float dx = sx1 - sx0;
-            float dy = sy1 - sy0;
-            float len = (float)userSpaceLineLength(dx, dy);
-            float s = lineWidth2/len;
-
-            float capx = sx0 - dx*s;
-            float capy = sy0 - dy*s;
-
-            emitLineTo(capx - mx0, capy - my0);
-            emitLineTo(capx + mx0, capy + my0);
+            emitLineTo(sx0 + smy - smx, sy0 - smx - smy);
+            emitLineTo(sx0 + smy + smx, sy0 - smx + smy);
         }
 
         emitClose();
-        this.joinSegment = false;
     }
 
-    private void emitMoveTo(float x0, float y0) {
-        // System.out.println("Stroker.emitMoveTo(" + x0/65536.0 + ", " + y0/65536.0 + ")");
-        output.moveTo(x0, y0);
+    private void emitMoveTo(final float x0, final float y0) {
+        out.moveTo(x0, y0);
     }
 
-    private void emitLineTo(float x1, float y1) {
-        // System.out.println("Stroker.emitLineTo(" + x0/65536.0 + ", " + y0/65536.0 + ")");
-        output.lineTo(x1, y1);
+    private void emitLineTo(final float x1, final float y1) {
+        out.lineTo(x1, y1);
     }
 
-    private void emitLineTo(float x1, float y1, boolean rev) {
+    private void emitLineTo(final float x1, final float y1,
+                            final boolean rev)
+    {
         if (rev) {
-            ensureCapacity(rindex + 2);
-            reverse[rindex++] = x1;
-            reverse[rindex++] = y1;
+            reverse.pushLine(x1, y1);
         } else {
             emitLineTo(x1, y1);
         }
     }
 
+    private void emitQuadTo(final float x0, final float y0,
+                            final float x1, final float y1,
+                            final float x2, final float y2, final boolean rev)
+    {
+        if (rev) {
+            reverse.pushQuad(x0, y0, x1, y1);
+        } else {
+            out.quadTo(x1, y1, x2, y2);
+        }
+    }
+
+    private void emitCurveTo(final float x0, final float y0,
+                             final float x1, final float y1,
+                             final float x2, final float y2,
+                             final float x3, final float y3, final boolean rev)
+    {
+        if (rev) {
+            reverse.pushCubic(x0, y0, x1, y1, x2, y2);
+        } else {
+            out.curveTo(x1, y1, x2, y2, x3, y3);
+        }
+    }
+
     private void emitClose() {
-        // System.out.println("Stroker.emitClose()");
-        output.close();
+        out.closePath();
+    }
+
+    private void drawJoin(float pdx, float pdy,
+                          float x0, float y0,
+                          float dx, float dy,
+                          float omx, float omy,
+                          float mx, float my)
+    {
+        if (prev != DRAWING_OP_TO) {
+            emitMoveTo(x0 + mx, y0 + my);
+            this.sdx = dx;
+            this.sdy = dy;
+            this.smx = mx;
+            this.smy = my;
+        } else {
+            boolean cw = isCW(pdx, pdy, dx, dy);
+            if (joinStyle == JOIN_MITER) {
+                drawMiter(pdx, pdy, x0, y0, dx, dy, omx, omy, mx, my, cw);
+            } else if (joinStyle == JOIN_ROUND) {
+                drawRoundJoin(x0, y0,
+                              omx, omy,
+                              mx, my, cw,
+                              ROUND_JOIN_THRESHOLD);
+            }
+            emitLineTo(x0, y0, !cw);
+        }
+        prev = DRAWING_OP_TO;
+    }
+
+    private static boolean within(final float x1, final float y1,
+                                  final float x2, final float y2,
+                                  final float ERR)
+    {
+        assert ERR > 0 : "";
+        // compare taxicab distance. ERR will always be small, so using
+        // true distance won't give much benefit
+        return (Helpers.within(x1, x2, ERR) &&  // we want to avoid calling Math.abs
+                Helpers.within(y1, y2, ERR)); // this is just as good.
+    }
+
+    private void getLineOffsets(float x1, float y1,
+                                float x2, float y2,
+                                float[] left, float[] right) {
+        computeOffset(x2 - x1, y2 - y1, lineWidth2, offset[0]);
+        left[0] = x1 + offset[0][0];
+        left[1] = y1 + offset[0][1];
+        left[2] = x2 + offset[0][0];
+        left[3] = y2 + offset[0][1];
+        right[0] = x1 - offset[0][0];
+        right[1] = y1 - offset[0][1];
+        right[2] = x2 - offset[0][0];
+        right[3] = y2 - offset[0][1];
+    }
+
+    private int computeOffsetCubic(float[] pts, final int off,
+                                   float[] leftOff, float[] rightOff)
+    {
+        // if p1=p2 or p3=p4 it means that the derivative at the endpoint
+        // vanishes, which creates problems with computeOffset. Usually
+        // this happens when this stroker object is trying to winden
+        // a curve with a cusp. What happens is that curveTo splits
+        // the input curve at the cusp, and passes it to this function.
+        // because of inaccuracies in the splitting, we consider points
+        // equal if they're very close to each other.
+        final float x1 = pts[off + 0], y1 = pts[off + 1];
+        final float x2 = pts[off + 2], y2 = pts[off + 3];
+        final float x3 = pts[off + 4], y3 = pts[off + 5];
+        final float x4 = pts[off + 6], y4 = pts[off + 7];
+
+        float dx4 = x4 - x3;
+        float dy4 = y4 - y3;
+        float dx1 = x2 - x1;
+        float dy1 = y2 - y1;
+
+        // if p1 == p2 && p3 == p4: draw line from p1->p4, unless p1 == p4,
+        // in which case ignore if p1 == p2
+        final boolean p1eqp2 = within(x1,y1,x2,y2, 6 * Math.ulp(y2));
+        final boolean p3eqp4 = within(x3,y3,x4,y4, 6 * Math.ulp(y4));
+        if (p1eqp2 && p3eqp4) {
+            getLineOffsets(x1, y1, x4, y4, leftOff, rightOff);
+            return 4;
+        } else if (p1eqp2) {
+            dx1 = x3 - x1;
+            dy1 = y3 - y1;
+        } else if (p3eqp4) {
+            dx4 = x4 - x2;
+            dy4 = y4 - y2;
+        }
+
+        // if p2-p1 and p4-p3 are parallel, that must mean this curve is a line
+        float dotsq = (dx1 * dx4 + dy1 * dy4);
+        dotsq = dotsq * dotsq;
+        float l1sq = dx1 * dx1 + dy1 * dy1, l4sq = dx4 * dx4 + dy4 * dy4;
+        if (Helpers.within(dotsq, l1sq * l4sq, 4 * Math.ulp(dotsq))) {
+            getLineOffsets(x1, y1, x4, y4, leftOff, rightOff);
+            return 4;
+        }
+
+//      What we're trying to do in this function is to approximate an ideal
+//      offset curve (call it I) of the input curve B using a bezier curve Bp.
+//      The constraints I use to get the equations are:
+//
+//      1. The computed curve Bp should go through I(0) and I(1). These are
+//      x1p, y1p, x4p, y4p, which are p1p and p4p. We still need to find
+//      4 variables: the x and y components of p2p and p3p (i.e. x2p, y2p, x3p, y3p).
+//
+//      2. Bp should have slope equal in absolute value to I at the endpoints. So,
+//      (by the way, the operator || in the comments below means "aligned with".
+//      It is defined on vectors, so when we say I'(0) || Bp'(0) we mean that
+//      vectors I'(0) and Bp'(0) are aligned, which is the same as saying
+//      that the tangent lines of I and Bp at 0 are parallel. Mathematically
+//      this means (I'(t) || Bp'(t)) <==> (I'(t) = c * Bp'(t)) where c is some
+//      nonzero constant.)
+//      I'(0) || Bp'(0) and I'(1) || Bp'(1). Obviously, I'(0) || B'(0) and
+//      I'(1) || B'(1); therefore, Bp'(0) || B'(0) and Bp'(1) || B'(1).
+//      We know that Bp'(0) || (p2p-p1p) and Bp'(1) || (p4p-p3p) and the same
+//      is true for any bezier curve; therefore, we get the equations
+//          (1) p2p = c1 * (p2-p1) + p1p
+//          (2) p3p = c2 * (p4-p3) + p4p
+//      We know p1p, p4p, p2, p1, p3, and p4; therefore, this reduces the number
+//      of unknowns from 4 to 2 (i.e. just c1 and c2).
+//      To eliminate these 2 unknowns we use the following constraint:
+//
+//      3. Bp(0.5) == I(0.5). Bp(0.5)=(x,y) and I(0.5)=(xi,yi), and I should note
+//      that I(0.5) is *the only* reason for computing dxm,dym. This gives us
+//          (3) Bp(0.5) = (p1p + 3 * (p2p + p3p) + p4p)/8, which is equivalent to
+//          (4) p2p + p3p = (Bp(0.5)*8 - p1p - p4p) / 3
+//      We can substitute (1) and (2) from above into (4) and we get:
+//          (5) c1*(p2-p1) + c2*(p4-p3) = (Bp(0.5)*8 - p1p - p4p)/3 - p1p - p4p
+//      which is equivalent to
+//          (6) c1*(p2-p1) + c2*(p4-p3) = (4/3) * (Bp(0.5) * 2 - p1p - p4p)
+//
+//      The right side of this is a 2D vector, and we know I(0.5), which gives us
+//      Bp(0.5), which gives us the value of the right side.
+//      The left side is just a matrix vector multiplication in disguise. It is
+//
+//      [x2-x1, x4-x3][c1]
+//      [y2-y1, y4-y3][c2]
+//      which, is equal to
+//      [dx1, dx4][c1]
+//      [dy1, dy4][c2]
+//      At this point we are left with a simple linear system and we solve it by
+//      getting the inverse of the matrix above. Then we use [c1,c2] to compute
+//      p2p and p3p.
+
+        float x = 0.125f * (x1 + 3 * (x2 + x3) + x4);
+        float y = 0.125f * (y1 + 3 * (y2 + y3) + y4);
+        // (dxm,dym) is some tangent of B at t=0.5. This means it's equal to
+        // c*B'(0.5) for some constant c.
+        float dxm = x3 + x4 - x1 - x2, dym = y3 + y4 - y1 - y2;
+
+        // this computes the offsets at t=0, 0.5, 1, using the property that
+        // for any bezier curve the vectors p2-p1 and p4-p3 are parallel to
+        // the (dx/dt, dy/dt) vectors at the endpoints.
+        computeOffset(dx1, dy1, lineWidth2, offset[0]);
+        computeOffset(dxm, dym, lineWidth2, offset[1]);
+        computeOffset(dx4, dy4, lineWidth2, offset[2]);
+        float x1p = x1 + offset[0][0]; // start
+        float y1p = y1 + offset[0][1]; // point
+        float xi  = x + offset[1][0]; // interpolation
+        float yi  = y + offset[1][1]; // point
+        float x4p = x4 + offset[2][0]; // end
+        float y4p = y4 + offset[2][1]; // point
+
+        float invdet43 = 4f / (3f * (dx1 * dy4 - dy1 * dx4));
+
+        float two_pi_m_p1_m_p4x = 2*xi - x1p - x4p;
+        float two_pi_m_p1_m_p4y = 2*yi - y1p - y4p;
+        float c1 = invdet43 * (dy4 * two_pi_m_p1_m_p4x - dx4 * two_pi_m_p1_m_p4y);
+        float c2 = invdet43 * (dx1 * two_pi_m_p1_m_p4y - dy1 * two_pi_m_p1_m_p4x);
+
+        float x2p, y2p, x3p, y3p;
+        x2p = x1p + c1*dx1;
+        y2p = y1p + c1*dy1;
+        x3p = x4p + c2*dx4;
+        y3p = y4p + c2*dy4;
+
+        leftOff[0] = x1p; leftOff[1] = y1p;
+        leftOff[2] = x2p; leftOff[3] = y2p;
+        leftOff[4] = x3p; leftOff[5] = y3p;
+        leftOff[6] = x4p; leftOff[7] = y4p;
+
+        x1p = x1 - offset[0][0]; y1p = y1 - offset[0][1];
+        xi = xi - 2 * offset[1][0]; yi = yi - 2 * offset[1][1];
+        x4p = x4 - offset[2][0]; y4p = y4 - offset[2][1];
+
+        two_pi_m_p1_m_p4x = 2*xi - x1p - x4p;
+        two_pi_m_p1_m_p4y = 2*yi - y1p - y4p;
+        c1 = invdet43 * (dy4 * two_pi_m_p1_m_p4x - dx4 * two_pi_m_p1_m_p4y);
+        c2 = invdet43 * (dx1 * two_pi_m_p1_m_p4y - dy1 * two_pi_m_p1_m_p4x);
+
+        x2p = x1p + c1*dx1;
+        y2p = y1p + c1*dy1;
+        x3p = x4p + c2*dx4;
+        y3p = y4p + c2*dy4;
+
+        rightOff[0] = x1p; rightOff[1] = y1p;
+        rightOff[2] = x2p; rightOff[3] = y2p;
+        rightOff[4] = x3p; rightOff[5] = y3p;
+        rightOff[6] = x4p; rightOff[7] = y4p;
+        return 8;
+    }
+
+    // compute offset curves using bezier spline through t=0.5 (i.e.
+    // ComputedCurve(0.5) == IdealParallelCurve(0.5))
+    // return the kind of curve in the right and left arrays.
+    private int computeOffsetQuad(float[] pts, final int off,
+                                  float[] leftOff, float[] rightOff)
+    {
+        final float x1 = pts[off + 0], y1 = pts[off + 1];
+        final float x2 = pts[off + 2], y2 = pts[off + 3];
+        final float x3 = pts[off + 4], y3 = pts[off + 5];
+
+        float dx3 = x3 - x2;
+        float dy3 = y3 - y2;
+        float dx1 = x2 - x1;
+        float dy1 = y2 - y1;
+
+        // if p1=p2 or p3=p4 it means that the derivative at the endpoint
+        // vanishes, which creates problems with computeOffset. Usually
+        // this happens when this stroker object is trying to winden
+        // a curve with a cusp. What happens is that curveTo splits
+        // the input curve at the cusp, and passes it to this function.
+        // because of inaccuracies in the splitting, we consider points
+        // equal if they're very close to each other.
+
+        // if p1 == p2 && p3 == p4: draw line from p1->p4, unless p1 == p4,
+        // in which case ignore.
+        final boolean p1eqp2 = within(x1,y1,x2,y2, 6 * Math.ulp(y2));
+        final boolean p2eqp3 = within(x2,y2,x3,y3, 6 * Math.ulp(y3));
+        if (p1eqp2 || p2eqp3) {
+            getLineOffsets(x1, y1, x3, y3, leftOff, rightOff);
+            return 4;
+        }
+
+        // if p2-p1 and p4-p3 are parallel, that must mean this curve is a line
+        float dotsq = (dx1 * dx3 + dy1 * dy3);
+        dotsq = dotsq * dotsq;
+        float l1sq = dx1 * dx1 + dy1 * dy1, l3sq = dx3 * dx3 + dy3 * dy3;
+        if (Helpers.within(dotsq, l1sq * l3sq, 4 * Math.ulp(dotsq))) {
+            getLineOffsets(x1, y1, x3, y3, leftOff, rightOff);
+            return 4;
+        }
+
+        // this computes the offsets at t=0, 0.5, 1, using the property that
+        // for any bezier curve the vectors p2-p1 and p4-p3 are parallel to
+        // the (dx/dt, dy/dt) vectors at the endpoints.
+        computeOffset(dx1, dy1, lineWidth2, offset[0]);
+        computeOffset(dx3, dy3, lineWidth2, offset[1]);
+        float x1p = x1 + offset[0][0]; // start
+        float y1p = y1 + offset[0][1]; // point
+        float x3p = x3 + offset[1][0]; // end
+        float y3p = y3 + offset[1][1]; // point
+
+        computeMiter(x1p, y1p, x1p+dx1, y1p+dy1, x3p, y3p, x3p-dx3, y3p-dy3, leftOff, 2);
+        leftOff[0] = x1p; leftOff[1] = y1p;
+        leftOff[4] = x3p; leftOff[5] = y3p;
+        x1p = x1 - offset[0][0]; y1p = y1 - offset[0][1];
+        x3p = x3 - offset[1][0]; y3p = y3 - offset[1][1];
+        computeMiter(x1p, y1p, x1p+dx1, y1p+dy1, x3p, y3p, x3p-dx3, y3p-dy3, rightOff, 2);
+        rightOff[0] = x1p; rightOff[1] = y1p;
+        rightOff[4] = x3p; rightOff[5] = y3p;
+        return 6;
+    }
+
+    // This is where the curve to be processed is put. We give it
+    // enough room to store 2 curves: one for the current subdivision, the
+    // other for the rest of the curve.
+    private float[][] middle = new float[2][8];
+    private float[] lp = new float[8];
+    private float[] rp = new float[8];
+    private static final int MAX_N_CURVES = 11;
+    private float[] subdivTs = new float[MAX_N_CURVES - 1];
+
+    private void somethingTo(final int type) {
+        // need these so we can update the state at the end of this method
+        final float xf = middle[0][type-2], yf = middle[0][type-1];
+        float dxs = middle[0][2] - middle[0][0];
+        float dys = middle[0][3] - middle[0][1];
+        float dxf = middle[0][type - 2] - middle[0][type - 4];
+        float dyf = middle[0][type - 1] - middle[0][type - 3];
+        switch(type) {
+        case 6:
+            if ((dxs == 0f && dys == 0f) ||
+                (dxf == 0f && dyf == 0f)) {
+               dxs = dxf = middle[0][4] - middle[0][0];
+               dys = dyf = middle[0][5] - middle[0][1];
+            }
+            break;
+        case 8:
+            boolean p1eqp2 = (dxs == 0f && dys == 0f);
+            boolean p3eqp4 = (dxf == 0f && dyf == 0f);
+            if (p1eqp2) {
+                dxs = middle[0][4] - middle[0][0];
+                dys = middle[0][5] - middle[0][1];
+                if (dxs == 0f && dys == 0f) {
+                    dxs = middle[0][6] - middle[0][0];
+                    dys = middle[0][7] - middle[0][1];
+                }
+            }
+            if (p3eqp4) {
+                dxf = middle[0][6] - middle[0][2];
+                dyf = middle[0][7] - middle[0][3];
+                if (dxf == 0f && dyf == 0f) {
+                    dxf = middle[0][6] - middle[0][0];
+                    dyf = middle[0][7] - middle[0][1];
+                }
+            }
+        }
+        if (dxs == 0f && dys == 0f) {
+            // this happens iff the "curve" is just a point
+            lineTo(middle[0][0], middle[0][1]);
+            return;
+        }
+        // if these vectors are too small, normalize them, to avoid future
+        // precision problems.
+        if (Math.abs(dxs) < 0.1f && Math.abs(dys) < 0.1f) {
+            double len = Math.hypot(dxs, dys);
+            dxs = (float)(dxs / len);
+            dys = (float)(dys / len);
+        }
+        if (Math.abs(dxf) < 0.1f && Math.abs(dyf) < 0.1f) {
+            double len = Math.hypot(dxf, dyf);
+            dxf = (float)(dxf / len);
+            dyf = (float)(dyf / len);
+        }
+
+        computeOffset(dxs, dys, lineWidth2, offset[0]);
+        final float mx = offset[0][0];
+        final float my = offset[0][1];
+        drawJoin(cdx, cdy, cx0, cy0, dxs, dys, cmx, cmy, mx, my);
+
+        int nSplits = findSubdivPoints(middle[0], subdivTs, type,lineWidth2);
+
+        int kind = 0;
+        Iterator<float[]> it = Curve.breakPtsAtTs(middle, type, subdivTs, nSplits);
+        while(it.hasNext()) {
+            float[] curCurve = it.next();
+
+            kind = 0;
+            switch (type) {
+            case 8:
+                kind = computeOffsetCubic(curCurve, 0, lp, rp);
+                break;
+            case 6:
+                kind = computeOffsetQuad(curCurve, 0, lp, rp);
+                break;
+            }
+            if (kind != 0) {
+                emitLineTo(lp[0], lp[1]);
+                switch(kind) {
+                case 8:
+                    emitCurveTo(lp[0], lp[1], lp[2], lp[3], lp[4], lp[5], lp[6], lp[7], false);
+                    emitCurveTo(rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7], true);
+                    break;
+                case 6:
+                    emitQuadTo(lp[0], lp[1], lp[2], lp[3], lp[4], lp[5], false);
+                    emitQuadTo(rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], true);
+                    break;
+                case 4:
+                    emitLineTo(lp[2], lp[3]);
+                    emitLineTo(rp[0], rp[1], true);
+                    break;
+                }
+                emitLineTo(rp[kind - 2], rp[kind - 1], true);
+            }
+        }
+
+        this.cmx = (lp[kind - 2] - rp[kind - 2]) / 2;
+        this.cmy = (lp[kind - 1] - rp[kind - 1]) / 2;
+        this.cdx = dxf;
+        this.cdy = dyf;
+        this.cx0 = xf;
+        this.cy0 = yf;
+        this.prev = DRAWING_OP_TO;
+    }
+
+    // finds values of t where the curve in pts should be subdivided in order
+    // to get good offset curves a distance of w away from the middle curve.
+    // Stores the points in ts, and returns how many of them there were.
+    private static Curve c = new Curve();
+    private static int findSubdivPoints(float[] pts, float[] ts,
+                                        final int type, final float w)
+    {
+        final float x12 = pts[2] - pts[0];
+        final float y12 = pts[3] - pts[1];
+        // if the curve is already parallel to either axis we gain nothing
+        // from rotating it.
+        if (y12 != 0f && x12 != 0f) {
+            // we rotate it so that the first vector in the control polygon is
+            // parallel to the x-axis. This will ensure that rotated quarter
+            // circles won't be subdivided.
+            final float hypot = (float)Math.sqrt(x12 * x12 + y12 * y12);
+            final float cos = x12 / hypot;
+            final float sin = y12 / hypot;
+            final float x1 = cos * pts[0] + sin * pts[1];
+            final float y1 = cos * pts[1] - sin * pts[0];
+            final float x2 = cos * pts[2] + sin * pts[3];
+            final float y2 = cos * pts[3] - sin * pts[2];
+            final float x3 = cos * pts[4] + sin * pts[5];
+            final float y3 = cos * pts[5] - sin * pts[4];
+            switch(type) {
+            case 8:
+                final float x4 = cos * pts[6] + sin * pts[7];
+                final float y4 = cos * pts[7] - sin * pts[6];
+                c.set(x1, y1, x2, y2, x3, y3, x4, y4);
+                break;
+            case 6:
+                c.set(x1, y1, x2, y2, x3, y3);
+                break;
+            }
+        } else {
+            c.set(pts, type);
+        }
+
+        int ret = 0;
+        // we subdivide at values of t such that the remaining rotated
+        // curves are monotonic in x and y.
+        ret += c.dxRoots(ts, ret);
+        ret += c.dyRoots(ts, ret);
+        // subdivide at inflection points.
+        if (type == 8) {
+            // quadratic curves can't have inflection points
+            ret += c.infPoints(ts, ret);
+        }
+
+        // now we must subdivide at points where one of the offset curves will have
+        // a cusp. This happens at ts where the radius of curvature is equal to w.
+        ret += c.rootsOfROCMinusW(ts, ret, w, 0.0001f);
+        ret = Helpers.filterOutNotInAB(ts, 0, ret, 0.0001f, 0.9999f);
+        Helpers.isort(ts, 0, ret);
+        return ret;
+    }
+
+    @Override public void curveTo(float x1, float y1,
+                                  float x2, float y2,
+                                  float x3, float y3)
+    {
+        middle[0][0] = cx0; middle[0][1] = cy0;
+        middle[0][2] = x1; middle[0][3] = y1;
+        middle[0][4] = x2; middle[0][5] = y2;
+        middle[0][6] = x3; middle[0][7] = y3;
+        somethingTo(8);
+    }
+
+    @Override public long getNativeConsumer() {
+        throw new InternalError("Stroker doesn't use a native consumer");
+    }
+
+    @Override public void quadTo(float x1, float y1, float x2, float y2) {
+        middle[0][0] = cx0; middle[0][1] = cy0;
+        middle[0][2] = x1; middle[0][3] = y1;
+        middle[0][4] = x2; middle[0][5] = y2;
+        somethingTo(6);
+    }
+
+    // a stack of polynomial curves where each curve shares endpoints with
+    // adjacent ones.
+    private static final class PolyStack {
+        float[] curves;
+        int end;
+        int[] curveTypes;
+        int numCurves;
+
+        private static final int INIT_SIZE = 50;
+
+        PolyStack() {
+            curves = new float[8 * INIT_SIZE];
+            curveTypes = new int[INIT_SIZE];
+            end = 0;
+            numCurves = 0;
+        }
+
+        public boolean isEmpty() {
+            return numCurves == 0;
+        }
+
+        private void ensureSpace(int n) {
+            if (end + n >= curves.length) {
+                int newSize = (end + n) * 2;
+                curves = Arrays.copyOf(curves, newSize);
+            }
+            if (numCurves >= curveTypes.length) {
+                int newSize = numCurves * 2;
+                curveTypes = Arrays.copyOf(curveTypes, newSize);
+            }
+        }
+
+        public void pushCubic(float x0, float y0,
+                              float x1, float y1,
+                              float x2, float y2)
+        {
+            ensureSpace(6);
+            curveTypes[numCurves++] = 8;
+            // assert(x0 == lastX && y0 == lastY)
+
+            // we reverse the coordinate order to make popping easier
+            curves[end++] = x2;    curves[end++] = y2;
+            curves[end++] = x1;    curves[end++] = y1;
+            curves[end++] = x0;    curves[end++] = y0;
+        }
+
+        public void pushQuad(float x0, float y0,
+                             float x1, float y1)
+        {
+            ensureSpace(4);
+            curveTypes[numCurves++] = 6;
+            // assert(x0 == lastX && y0 == lastY)
+            curves[end++] = x1;    curves[end++] = y1;
+            curves[end++] = x0;    curves[end++] = y0;
+        }
+
+        public void pushLine(float x, float y) {
+            ensureSpace(2);
+            curveTypes[numCurves++] = 4;
+            // assert(x0 == lastX && y0 == lastY)
+            curves[end++] = x;    curves[end++] = y;
+        }
+
+        @SuppressWarnings("unused")
+        public int pop(float[] pts) {
+            int ret = curveTypes[numCurves - 1];
+            numCurves--;
+            end -= (ret - 2);
+            System.arraycopy(curves, end, pts, 0, ret - 2);
+            return ret;
+        }
+
+        public void pop(PathConsumer2D io) {
+            numCurves--;
+            int type = curveTypes[numCurves];
+            end -= (type - 2);
+            switch(type) {
+            case 8:
+                io.curveTo(curves[end+0], curves[end+1],
+                           curves[end+2], curves[end+3],
+                           curves[end+4], curves[end+5]);
+                break;
+            case 6:
+                io.quadTo(curves[end+0], curves[end+1],
+                           curves[end+2], curves[end+3]);
+                 break;
+            case 4:
+                io.lineTo(curves[end], curves[end+1]);
+            }
+        }
+
+        @Override
+        public String toString() {
+            String ret = "";
+            int nc = numCurves;
+            int end = this.end;
+            while (nc > 0) {
+                nc--;
+                int type = curveTypes[numCurves];
+                end -= (type - 2);
+                switch(type) {
+                case 8:
+                    ret += "cubic: ";
+                    break;
+                case 6:
+                    ret += "quad: ";
+                    break;
+                case 4:
+                    ret += "line: ";
+                    break;
+                }
+                ret += Arrays.toString(Arrays.copyOfRange(curves, end, end+type-2)) + "\n";
+            }
+            return ret;
+        }
     }
 }
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/java2d/pisces/TransformingPathConsumer2D.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2007, 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.
+ */
+
+package sun.java2d.pisces;
+
+import sun.awt.geom.PathConsumer2D;
+import java.awt.geom.AffineTransform;
+
+public class TransformingPathConsumer2D {
+    public static PathConsumer2D
+        transformConsumer(PathConsumer2D out,
+                          AffineTransform at)
+    {
+        if (at == null) {
+            return out;
+        }
+        float Mxx = (float) at.getScaleX();
+        float Mxy = (float) at.getShearX();
+        float Mxt = (float) at.getTranslateX();
+        float Myx = (float) at.getShearY();
+        float Myy = (float) at.getScaleY();
+        float Myt = (float) at.getTranslateY();
+        if (Mxy == 0f && Myx == 0f) {
+            if (Mxx == 1f && Myy == 1f) {
+                if (Mxt == 0f && Myt == 0f) {
+                    return out;
+                } else {
+                    return new TranslateFilter(out, Mxt, Myt);
+                }
+            } else {
+                return new ScaleFilter(out, Mxx, Myy, Mxt, Myt);
+            }
+        } else {
+            return new TransformFilter(out, Mxx, Mxy, Mxt, Myx, Myy, Myt);
+        }
+    }
+
+    static class TranslateFilter implements PathConsumer2D {
+        PathConsumer2D out;
+        float tx;
+        float ty;
+
+        TranslateFilter(PathConsumer2D out,
+                        float tx, float ty)
+        {
+            this.out = out;
+            this.tx = tx;
+            this.ty = ty;
+        }
+
+        public void moveTo(float x0, float y0) {
+            out.moveTo(x0 + tx, y0 + ty);
+        }
+
+        public void lineTo(float x1, float y1) {
+            out.lineTo(x1 + tx, y1 + ty);
+        }
+
+        public void quadTo(float x1, float y1,
+                           float x2, float y2)
+        {
+            out.quadTo(x1 + tx, y1 + ty,
+                       x2 + tx, y2 + ty);
+        }
+
+        public void curveTo(float x1, float y1,
+                            float x2, float y2,
+                            float x3, float y3)
+        {
+            out.curveTo(x1 + tx, y1 + ty,
+                        x2 + tx, y2 + ty,
+                        x3 + tx, y3 + ty);
+        }
+
+        public void closePath() {
+            out.closePath();
+        }
+
+        public void pathDone() {
+            out.pathDone();
+        }
+
+        public long getNativeConsumer() {
+            return 0;
+        }
+    }
+
+    static class ScaleFilter implements PathConsumer2D {
+        PathConsumer2D out;
+        float sx;
+        float sy;
+        float tx;
+        float ty;
+
+        ScaleFilter(PathConsumer2D out,
+                    float sx, float sy, float tx, float ty)
+        {
+            this.out = out;
+            this.sx = sx;
+            this.sy = sy;
+            this.tx = tx;
+            this.ty = ty;
+        }
+
+        public void moveTo(float x0, float y0) {
+            out.moveTo(x0 * sx + tx, y0 * sy + ty);
+        }
+
+        public void lineTo(float x1, float y1) {
+            out.lineTo(x1 * sx + tx, y1 * sy + ty);
+        }
+
+        public void quadTo(float x1, float y1,
+                           float x2, float y2)
+        {
+            out.quadTo(x1 * sx + tx, y1 * sy + ty,
+                       x2 * sx + tx, y2 * sy + ty);
+        }
+
+        public void curveTo(float x1, float y1,
+                            float x2, float y2,
+                            float x3, float y3)
+        {
+            out.curveTo(x1 * sx + tx, y1 * sy + ty,
+                        x2 * sx + tx, y2 * sy + ty,
+                        x3 * sx + tx, y3 * sy + ty);
+        }
+
+        public void closePath() {
+            out.closePath();
+        }
+
+        public void pathDone() {
+            out.pathDone();
+        }
+
+        public long getNativeConsumer() {
+            return 0;
+        }
+    }
+
+    static class TransformFilter implements PathConsumer2D {
+        PathConsumer2D out;
+        float Mxx;
+        float Mxy;
+        float Mxt;
+        float Myx;
+        float Myy;
+        float Myt;
+
+        TransformFilter(PathConsumer2D out,
+                        float Mxx, float Mxy, float Mxt,
+                        float Myx, float Myy, float Myt)
+        {
+            this.out = out;
+            this.Mxx = Mxx;
+            this.Mxy = Mxy;
+            this.Mxt = Mxt;
+            this.Myx = Myx;
+            this.Myy = Myy;
+            this.Myt = Myt;
+        }
+
+        public void moveTo(float x0, float y0) {
+            out.moveTo(x0 * Mxx + y0 * Mxy + Mxt,
+                       x0 * Myx + y0 * Myy + Myt);
+        }
+
+        public void lineTo(float x1, float y1) {
+            out.lineTo(x1 * Mxx + y1 * Mxy + Mxt,
+                       x1 * Myx + y1 * Myy + Myt);
+        }
+
+        public void quadTo(float x1, float y1,
+                           float x2, float y2)
+        {
+            out.quadTo(x1 * Mxx + y1 * Mxy + Mxt,
+                       x1 * Myx + y1 * Myy + Myt,
+                       x2 * Mxx + y2 * Mxy + Mxt,
+                       x2 * Myx + y2 * Myy + Myt);
+        }
+
+        public void curveTo(float x1, float y1,
+                            float x2, float y2,
+                            float x3, float y3)
+        {
+            out.curveTo(x1 * Mxx + y1 * Mxy + Mxt,
+                        x1 * Myx + y1 * Myy + Myt,
+                        x2 * Mxx + y2 * Mxy + Mxt,
+                        x2 * Myx + y2 * Myy + Myt,
+                        x3 * Mxx + y3 * Mxy + Mxt,
+                        x3 * Myx + y3 * Myy + Myt);
+        }
+
+        public void closePath() {
+            out.closePath();
+        }
+
+        public void pathDone() {
+            out.pathDone();
+        }
+
+        public long getNativeConsumer() {
+            return 0;
+        }
+    }
+}
--- a/jdk/src/share/classes/sun/net/InetAddressCachePolicy.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/net/InetAddressCachePolicy.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,7 +25,6 @@
 
 package sun.net;
 
-import java.net.InetAddress;
 import java.security.PrivilegedAction;
 import java.security.Security;
 
@@ -57,7 +56,7 @@
      * caching. For security reasons, this caching is made forever when
      * a security manager is set.
      */
-    private static int cachePolicy;
+    private static int cachePolicy = FOREVER;
 
     /* The Java-level namelookup cache policy for negative lookups:
      *
@@ -67,31 +66,24 @@
      * default value is 0. It can be set to some other value for
      * performance reasons.
      */
-    private static int negativeCachePolicy;
+    private static int negativeCachePolicy = NEVER;
 
     /*
      * Whether or not the cache policy for successful lookups was set
      * using a property (cmd line).
      */
-    private static boolean set = false;
+    private static boolean propertySet;
 
     /*
      * Whether or not the cache policy for negative lookups was set
      * using a property (cmd line).
      */
-    private static boolean negativeSet = false;
+    private static boolean propertyNegativeSet;
 
     /*
      * Initialize
      */
     static {
-
-        set = false;
-        negativeSet = false;
-
-        cachePolicy = FOREVER;
-        negativeCachePolicy =  0;
-
         Integer tmp = null;
 
         try {
@@ -110,7 +102,7 @@
             if (cachePolicy < 0) {
                 cachePolicy = FOREVER;
             }
-            set = true;
+            propertySet = true;
         } else {
             tmp = java.security.AccessController.doPrivileged
                 (new sun.security.action.GetIntegerAction(cachePolicyPropFallback));
@@ -119,7 +111,14 @@
                 if (cachePolicy < 0) {
                     cachePolicy = FOREVER;
                 }
-                set = true;
+                propertySet = true;
+            } else {
+                /* No properties defined for positive caching. If there is no
+                 * security manager then use the default positive cache value.
+                 */
+                if (System.getSecurityManager() == null) {
+                    cachePolicy = DEFAULT_POSITIVE;
+                }
             }
         }
 
@@ -140,7 +139,7 @@
             if (negativeCachePolicy < 0) {
                 negativeCachePolicy = FOREVER;
             }
-            negativeSet = true;
+            propertyNegativeSet = true;
         } else {
             tmp = java.security.AccessController.doPrivileged
                 (new sun.security.action.GetIntegerAction(negativeCachePolicyPropFallback));
@@ -149,17 +148,13 @@
                 if (negativeCachePolicy < 0) {
                     negativeCachePolicy = FOREVER;
                 }
-                negativeSet = true;
+                propertyNegativeSet = true;
             }
         }
     }
 
     public static synchronized int get() {
-        if (!set && System.getSecurityManager() == null) {
-            return DEFAULT_POSITIVE;
-        } else {
-            return cachePolicy;
-        }
+        return cachePolicy;
     }
 
     public static synchronized int getNegative() {
@@ -174,21 +169,17 @@
      * should be cached
      */
     public static synchronized void setIfNotSet(int newPolicy) {
-
         /*
          * When setting the new value we may want to signal that the
          * cache should be flushed, though this doesn't seem strictly
          * necessary.
          */
-
-        if (!set) {
+        if (!propertySet) {
             checkValue(newPolicy, cachePolicy);
             cachePolicy = newPolicy;
         }
-
     }
 
-
     /**
      * Sets the cache policy for negative lookups if the user has not
      * already specified a cache policy for it using a
@@ -197,14 +188,12 @@
      * should be cached
      */
     public static synchronized void setNegativeIfNotSet(int newPolicy) {
-
         /*
          * When setting the new value we may want to signal that the
          * cache should be flushed, though this doesn't seem strictly
          * necessary.
          */
-
-        if (!negativeSet) {
+        if (!propertyNegativeSet) {
             // Negative caching does not seem to have any security
             // implications.
             // checkValue(newPolicy, negativeCachePolicy);
@@ -213,13 +202,11 @@
     }
 
     private static void checkValue(int newPolicy, int oldPolicy) {
-
         /*
          * If malicious code gets a hold of this method, prevent
          * setting the cache policy to something laxer or some
          * invalid negative value.
          */
-
         if (newPolicy == FOREVER)
             return;
 
@@ -229,7 +216,6 @@
 
             throw new
                 SecurityException("can't make InetAddress cache more lax");
-
         }
     }
 }
--- a/jdk/src/share/classes/sun/net/NetworkClient.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/net/NetworkClient.java	Wed Jul 05 17:26:57 2017 +0200
@@ -40,6 +40,12 @@
  * @author      Jonathan Payne
  */
 public class NetworkClient {
+    /* Default value of read timeout, if not specified (infinity) */
+    public static final int DEFAULT_READ_TIMEOUT = -1;
+
+    /* Default value of connect timeout, if not specified (infinity) */
+    public static final int DEFAULT_CONNECT_TIMEOUT = -1;
+
     protected Proxy     proxy = Proxy.NO_PROXY;
     /** Socket for communicating with server. */
     protected Socket    serverSocket = null;
@@ -53,8 +59,8 @@
     protected static int defaultSoTimeout;
     protected static int defaultConnectTimeout;
 
-    protected int readTimeout = -1;
-    protected int connectTimeout = -1;
+    protected int readTimeout = DEFAULT_READ_TIMEOUT;
+    protected int connectTimeout = DEFAULT_CONNECT_TIMEOUT;
     /* Name of encoding to use for output */
     protected static String encoding;
 
@@ -71,16 +77,12 @@
                         return null;
             }
         });
-        if (vals[0] == 0)
-            defaultSoTimeout = -1;
-        else
+        if (vals[0] != 0) {
             defaultSoTimeout = vals[0];
-
-        if (vals[1] == 0)
-            defaultConnectTimeout = -1;
-        else
+        }
+        if (vals[1] != 0) {
             defaultConnectTimeout = vals[1];
-
+        }
 
         encoding = encs[0];
         try {
@@ -232,7 +234,23 @@
         return connectTimeout;
     }
 
+    /**
+     * Sets the read timeout.
+     *
+     * Note: Public URLConnection (and protocol specific implementations)
+     * protect against negative timeout values being set. This implemenation,
+     * and protocol specific implementations, use -1 to represent the default
+     * read timeout.
+     *
+     * This method may be invoked with the default timeout value when the
+     * protocol handler is trying to reset the timeout after doing a
+     * potentially blocking internal operation, e.g. cleaning up unread
+     * response data, buffering error stream response data, etc
+     */
     public void setReadTimeout(int timeout) {
+        if (timeout == DEFAULT_READ_TIMEOUT)
+            timeout = defaultSoTimeout;
+
         if (serverSocket != null && timeout >= 0) {
             try {
                 serverSocket.setSoTimeout(timeout);
--- a/jdk/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java	Wed Jul 05 17:26:57 2017 +0200
@@ -46,6 +46,7 @@
 import java.util.StringTokenizer;
 import java.util.Iterator;
 import java.security.Permission;
+import sun.net.NetworkClient;
 import sun.net.www.MessageHeader;
 import sun.net.www.MeteredStream;
 import sun.net.www.URLConnection;
@@ -102,11 +103,11 @@
     static final int BIN = 2;
     static final int DIR = 3;
     int type = NONE;
-    /* Redefine timeouts from java.net.URLConnection as we nee -1 to mean
+    /* Redefine timeouts from java.net.URLConnection as we need -1 to mean
      * not set. This is to ensure backward compatibility.
      */
-    private int connectTimeout = -1;
-    private int readTimeout = -1;
+    private int connectTimeout = NetworkClient.DEFAULT_CONNECT_TIMEOUT;;
+    private int readTimeout = NetworkClient.DEFAULT_READ_TIMEOUT;;
 
     /**
      * For FTP URLs we need to have a special InputStream because we
--- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Wed Jul 05 17:26:57 2017 +0200
@@ -359,11 +359,11 @@
 
     private TunnelState tunnelState = TunnelState.NONE;
 
-    /* Redefine timeouts from java.net.URLConnection as we nee -1 to mean
+    /* Redefine timeouts from java.net.URLConnection as we need -1 to mean
      * not set. This is to ensure backward compatibility.
      */
-    private int connectTimeout = -1;
-    private int readTimeout = -1;
+    private int connectTimeout = NetworkClient.DEFAULT_CONNECT_TIMEOUT;
+    private int readTimeout = NetworkClient.DEFAULT_READ_TIMEOUT;
 
     /* Logging support */
     private static final PlatformLogger logger =
@@ -1041,9 +1041,9 @@
                     throw new ProtocolException("Server rejected operation");
                 }
             }
-            if (oldTimeout > 0) {
-                http.setReadTimeout(oldTimeout);
-            }
+
+            http.setReadTimeout(oldTimeout);
+
             responseCode = -1;
             responses.reset();
             // Proceed
--- a/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, 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
@@ -109,6 +109,10 @@
     // HTTPS uses a different default port number than HTTP.
     private static final int    httpsPortNumber = 443;
 
+    // default HostnameVerifier class canonical name
+    private static final String defaultHVCanonicalName =
+            "javax.net.ssl.HttpsURLConnection.DefaultHostnameVerifier";
+
     /** Returns the default HTTPS port (443) */
     @Override
     protected int getDefaultPort() { return httpsPortNumber; }
@@ -427,13 +431,93 @@
             }
             s.addHandshakeCompletedListener(this);
 
-            // if the HostnameVerifier is not set, try to enable endpoint
-            // identification during handshaking
-            boolean enabledIdentification = false;
-            if (hv instanceof DefaultHostnameVerifier &&
-                (s instanceof SSLSocketImpl) &&
-                ((SSLSocketImpl)s).trySetHostnameVerification("HTTPS")) {
-                enabledIdentification = true;
+            // We have two hostname verification approaches. One is in
+            // SSL/TLS socket layer, where the algorithm is configured with
+            // SSLParameters.setEndpointIdentificationAlgorithm(), and the
+            // hostname verification is done by X509ExtendedTrustManager when
+            // the algorithm is "HTTPS". The other one is in HTTPS layer,
+            // where the algorithm is customized by
+            // HttpsURLConnection.setHostnameVerifier(), and the hostname
+            // verification is done by HostnameVerifier when the default
+            // rules for hostname verification fail.
+            //
+            // The relationship between two hostname verification approaches
+            // likes the following:
+            //
+            //               |             EIA algorithm
+            //               +----------------------------------------------
+            //               |     null      |   HTTPS    |   LDAP/other   |
+            // -------------------------------------------------------------
+            //     |         |1              |2           |3               |
+            // HNV | default | Set HTTPS EIA | use EIA    | HTTPS          |
+            //     |--------------------------------------------------------
+            //     | non -   |4              |5           |6               |
+            //     | default | HTTPS/HNV     | use EIA    | HTTPS/HNV      |
+            // -------------------------------------------------------------
+            //
+            // Abbreviation:
+            //     EIA: the endpoint identification algorithm in SSL/TLS
+            //           socket layer
+            //     HNV: the hostname verification object in HTTPS layer
+            // Notes:
+            //     case 1. default HNV and EIA is null
+            //           Set EIA as HTTPS, hostname check done in SSL/TLS
+            //           layer.
+            //     case 2. default HNV and EIA is HTTPS
+            //           Use existing EIA, hostname check done in SSL/TLS
+            //           layer.
+            //     case 3. default HNV and EIA is other than HTTPS
+            //           Use existing EIA, EIA check done in SSL/TLS
+            //           layer, then do HTTPS check in HTTPS layer.
+            //     case 4. non-default HNV and EIA is null
+            //           No EIA, no EIA check done in SSL/TLS layer, then do
+            //           HTTPS check in HTTPS layer using HNV as override.
+            //     case 5. non-default HNV and EIA is HTTPS
+            //           Use existing EIA, hostname check done in SSL/TLS
+            //           layer. No HNV override possible. We will review this
+            //           decision and may update the architecture for JDK 7.
+            //     case 6. non-default HNV and EIA is other than HTTPS
+            //           Use existing EIA, EIA check done in SSL/TLS layer,
+            //           then do HTTPS check in HTTPS layer as override.
+            boolean needToCheckSpoofing = true;
+            String identification =
+                s.getSSLParameters().getEndpointIdentificationAlgorithm();
+            if (identification != null && identification.length() != 0) {
+                if (identification.equalsIgnoreCase("HTTPS")) {
+                    // Do not check server identity again out of SSLSocket,
+                    // the endpoint will be identified during TLS handshaking
+                    // in SSLSocket.
+                    needToCheckSpoofing = false;
+                }   // else, we don't understand the identification algorithm,
+                    // need to check URL spoofing here.
+            } else {
+                boolean isDefaultHostnameVerifier = false;
+
+                // We prefer to let the SSLSocket do the spoof checks, but if
+                // the application has specified a HostnameVerifier (HNV),
+                // we will always use that.
+                if (hv != null) {
+                    String canonicalName = hv.getClass().getCanonicalName();
+                    if (canonicalName != null &&
+                    canonicalName.equalsIgnoreCase(defaultHVCanonicalName)) {
+                        isDefaultHostnameVerifier = true;
+                    }
+                } else {
+                    // Unlikely to happen! As the behavior is the same as the
+                    // default hostname verifier, so we prefer to let the
+                    // SSLSocket do the spoof checks.
+                    isDefaultHostnameVerifier = true;
+                }
+
+                if (isDefaultHostnameVerifier) {
+                    // If the HNV is the default from HttpsURLConnection, we
+                    // will do the spoof checks in SSLSocket.
+                    SSLParameters paramaters = s.getSSLParameters();
+                    paramaters.setEndpointIdentificationAlgorithm("HTTPS");
+                    s.setSSLParameters(paramaters);
+
+                    needToCheckSpoofing = false;
+                }
             }
 
             s.startHandshake();
@@ -449,7 +533,7 @@
             }
 
             // check URL spoofing if it has not been checked under handshaking
-            if (!enabledIdentification) {
+            if (needToCheckSpoofing) {
                 checkURLSpoofing(hv);
             }
         } else {
@@ -463,8 +547,7 @@
     // Server identity checking is done according to RFC 2818: HTTP over TLS
     // Section 3.1 Server Identity
     private void checkURLSpoofing(HostnameVerifier hostnameVerifier)
-            throws IOException
-    {
+            throws IOException {
         //
         // Get authenticated server name, if any
         //
--- a/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -711,10 +711,8 @@
                     cachedSenderInetAddress = isa.getAddress();
                     cachedSenderPort = isa.getPort();
 
-                    // Socket was not bound before connecting,
-                    if (localAddress == null) {
-                        localAddress = Net.localAddress(fd);
-                    }
+                    // set or refresh local address
+                    localAddress = Net.localAddress(fd);
                 }
             }
         }
@@ -735,6 +733,9 @@
                     disconnect0(fd);
                     remoteAddress = null;
                     state = ST_UNCONNECTED;
+
+                    // refresh local address
+                    localAddress = Net.localAddress(fd);
                 }
             }
         }
--- a/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -699,15 +699,19 @@
         static volatile long totalSize;
         static volatile long totalCapacity;
 
-        private long address;
-        private long size;
-        private int cap;
+        private volatile long address;
+        private final long size;
+        private final int cap;
+        private final FileDescriptor fd;
 
-        private Unmapper(long address, long size, int cap) {
+        private Unmapper(long address, long size, int cap,
+                         FileDescriptor fd)
+        {
             assert (address != 0);
             this.address = address;
             this.size = size;
             this.cap = cap;
+            this.fd = fd;
 
             synchronized (Unmapper.class) {
                 count++;
@@ -722,6 +726,15 @@
             unmap0(address, size);
             address = 0;
 
+            // if this mapping has a valid file descriptor then we close it
+            if (fd.valid()) {
+                try {
+                    nd.close(fd);
+                } catch (IOException ignore) {
+                    // nothing we can do
+                }
+            }
+
             synchronized (Unmapper.class) {
                 count--;
                 totalSize -= size;
@@ -784,10 +797,12 @@
             }
             if (size == 0) {
                 addr = 0;
+                // a valid file descriptor is not required
+                FileDescriptor dummy = new FileDescriptor();
                 if ((!writable) || (imode == MAP_RO))
-                    return Util.newMappedByteBufferR(0, 0, null);
+                    return Util.newMappedByteBufferR(0, 0, dummy, null);
                 else
-                    return Util.newMappedByteBuffer(0, 0, null);
+                    return Util.newMappedByteBuffer(0, 0, dummy, null);
             }
 
             int pagePosition = (int)(position % allocationGranularity);
@@ -813,14 +828,31 @@
                 }
             }
 
+            // On Windows, and potentially other platforms, we need an open
+            // file descriptor for some mapping operations.
+            FileDescriptor mfd;
+            try {
+                mfd = nd.duplicateForMapping(fd);
+            } catch (IOException ioe) {
+                unmap0(addr, mapSize);
+                throw ioe;
+            }
+
             assert (IOStatus.checkAll(addr));
             assert (addr % allocationGranularity == 0);
             int isize = (int)size;
-            Unmapper um = new Unmapper(addr, size + pagePosition, isize);
-            if ((!writable) || (imode == MAP_RO))
-                return Util.newMappedByteBufferR(isize, addr + pagePosition, um);
-            else
-                return Util.newMappedByteBuffer(isize, addr + pagePosition, um);
+            Unmapper um = new Unmapper(addr, mapSize, isize, mfd);
+            if ((!writable) || (imode == MAP_RO)) {
+                return Util.newMappedByteBufferR(isize,
+                                                 addr + pagePosition,
+                                                 mfd,
+                                                 um);
+            } else {
+                return Util.newMappedByteBuffer(isize,
+                                                addr + pagePosition,
+                                                mfd,
+                                                um);
+            }
         } finally {
             threads.remove(ti);
             end(IOStatus.checkAll(addr));
--- a/jdk/src/share/classes/sun/nio/ch/FileDispatcher.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/nio/ch/FileDispatcher.java	Wed Jul 05 17:26:57 2017 +0200
@@ -45,4 +45,12 @@
 
     abstract void release(FileDescriptor fd, long pos, long size)
         throws IOException;
+
+    /**
+     * Returns a dup of fd if a file descriptor is required for
+     * memory-mapping operations, otherwise returns an invalid
+     * FileDescriptor (meaning a newly allocated FileDescriptor)
+     */
+    abstract FileDescriptor duplicateForMapping(FileDescriptor fd)
+        throws IOException;
 }
--- a/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,667 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 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.
- */
-
-package sun.nio.ch;
-
-import java.nio.ByteBuffer;
-import java.nio.channels.*;
-import java.net.*;
-import java.io.IOException;
-import java.util.*;
-import java.util.concurrent.*;
-import java.security.AccessController;
-import java.security.AccessControlContext;
-import java.security.PrivilegedExceptionAction;
-import java.security.PrivilegedActionException;
-
-/**
- * A prototype implementation of AsynchronousDatagramChannel, used to aid
- * test and spec development.
- */
-
-class SimpleAsynchronousDatagramChannelImpl
-    extends AsynchronousDatagramChannel implements Groupable, Cancellable
-{
-    private final DatagramChannel dc;
-    private final AsynchronousChannelGroupImpl group;
-    private final Object attachKey;
-    private boolean closed;
-
-    // used to coordinate timed and blocking reads
-    private final Object readLock = new Object();
-
-    // channel blocking mode (requires readLock)
-    private boolean isBlocking = true;
-
-    // number of blocking readers (requires readLock)
-    private int blockingReaderCount;
-
-    // true if timed read attempted while blocking read in progress (requires readLock)
-    private boolean transitionToNonBlocking;
-
-    // true if a blocking read is cancelled (requires readLock)
-    private boolean blockingReadKilledByCancel;
-
-    // temporary Selectors used by timed reads (requires readLock)
-    private Selector firstReader;
-    private Set<Selector> otherReaders;
-
-    SimpleAsynchronousDatagramChannelImpl(ProtocolFamily family,
-                                          AsynchronousChannelGroupImpl group)
-        throws IOException
-    {
-        super(group.provider());
-        this.dc = (family == null) ?
-            DatagramChannel.open() : DatagramChannel.open(family);
-        this.group = group;
-
-        // attach this channel to the group as foreign channel
-        boolean registered = false;
-        try {
-            if (!(dc instanceof DatagramChannelImpl))
-                throw new UnsupportedOperationException();
-            attachKey = group
-                .attachForeignChannel(this, ((DatagramChannelImpl)dc).getFD());
-            registered = true;
-        } finally {
-            if (!registered)
-                dc.close();
-        }
-    }
-
-    // throws RuntimeException if blocking read has been cancelled
-    private void ensureBlockingReadNotKilled() {
-        assert Thread.holdsLock(readLock);
-        if (blockingReadKilledByCancel)
-            throw new RuntimeException("Reading not allowed due to cancellation");
-    }
-
-    // invoke prior to non-timed read/receive
-    private void beginNoTimeoutRead() {
-        synchronized (readLock) {
-            ensureBlockingReadNotKilled();
-            if (isBlocking)
-                blockingReaderCount++;
-        }
-    }
-
-    // invoke after non-timed read/receive has completed
-    private void endNoTimeoutRead() {
-        synchronized (readLock) {
-            if (isBlocking) {
-                if (--blockingReaderCount == 0 && transitionToNonBlocking) {
-                    // notify any threads waiting to make channel non-blocking
-                    readLock.notifyAll();
-                }
-            }
-        }
-    }
-
-    // invoke prior to timed read
-    // returns the timeout remaining
-    private long prepareForTimedRead(PendingFuture<?,?> result, long timeout)
-        throws IOException
-    {
-        synchronized (readLock) {
-            ensureBlockingReadNotKilled();
-            if (isBlocking) {
-                transitionToNonBlocking = true;
-                while (blockingReaderCount > 0 &&
-                       timeout > 0L &&
-                       !result.isCancelled())
-                {
-                    long st = System.currentTimeMillis();
-                    try {
-                        readLock.wait(timeout);
-                    } catch (InterruptedException e) { }
-                    timeout -= System.currentTimeMillis() - st;
-                }
-                if (blockingReaderCount == 0) {
-                    // re-check that blocked read wasn't cancelled
-                    ensureBlockingReadNotKilled();
-                    // no blocking reads so change channel to non-blocking
-                    dc.configureBlocking(false);
-                    isBlocking = false;
-                }
-            }
-            return timeout;
-        }
-    }
-
-    // returns a temporary Selector
-    private Selector getSelector() throws IOException {
-        Selector sel = Util.getTemporarySelector(dc);
-        synchronized (readLock) {
-            if (firstReader == null) {
-                firstReader = sel;
-            } else {
-                if (otherReaders == null)
-                    otherReaders = new HashSet<Selector>();
-                otherReaders.add(sel);
-            }
-        }
-        return sel;
-    }
-
-    // releases a temporary Selector
-    private void releaseSelector(Selector sel) throws IOException {
-        synchronized (readLock) {
-            if (firstReader == sel) {
-                firstReader = null;
-            } else {
-                otherReaders.remove(sel);
-            }
-        }
-        Util.releaseTemporarySelector(sel);
-    }
-
-    // wakeup all Selectors currently in use
-    private void wakeupSelectors() {
-        synchronized (readLock) {
-            if (firstReader != null)
-                firstReader.wakeup();
-            if (otherReaders != null) {
-                for (Selector sel: otherReaders) {
-                    sel.wakeup();
-                }
-            }
-        }
-    }
-
-    @Override
-    public AsynchronousChannelGroupImpl group() {
-        return group;
-    }
-
-    @Override
-    public boolean isOpen() {
-        return dc.isOpen();
-    }
-
-    @Override
-    public void onCancel(PendingFuture<?,?> task) {
-        synchronized (readLock) {
-            if (blockingReaderCount > 0) {
-                blockingReadKilledByCancel = true;
-                readLock.notifyAll();
-                return;
-            }
-        }
-        wakeupSelectors();
-    }
-
-    @Override
-    public void close() throws IOException {
-        synchronized (dc) {
-            if (closed)
-                return;
-            closed = true;
-        }
-        // detach from group and close underlying channel
-        group.detachForeignChannel(attachKey);
-        dc.close();
-
-        // wakeup any threads blocked in timed read/receives
-        wakeupSelectors();
-    }
-
-    @Override
-    public AsynchronousDatagramChannel connect(SocketAddress remote)
-        throws IOException
-    {
-        dc.connect(remote);
-        return this;
-    }
-
-    @Override
-    public AsynchronousDatagramChannel disconnect() throws IOException {
-        dc.disconnect();
-        return this;
-    }
-
-    private static class WrappedMembershipKey extends MembershipKey {
-        private final MulticastChannel channel;
-        private final MembershipKey key;
-
-        WrappedMembershipKey(MulticastChannel channel, MembershipKey key) {
-            this.channel = channel;
-            this.key = key;
-        }
-
-        @Override
-        public boolean isValid() {
-            return key.isValid();
-        }
-
-        @Override
-        public void drop() {
-            key.drop();
-        }
-
-        @Override
-        public MulticastChannel channel() {
-            return channel;
-        }
-
-        @Override
-        public InetAddress group() {
-            return key.group();
-        }
-
-        @Override
-        public NetworkInterface networkInterface() {
-            return key.networkInterface();
-        }
-
-        @Override
-        public InetAddress sourceAddress() {
-            return key.sourceAddress();
-        }
-
-        @Override
-        public MembershipKey block(InetAddress toBlock) throws IOException {
-            key.block(toBlock);
-            return this;
-        }
-
-        @Override
-        public MembershipKey unblock(InetAddress toUnblock) {
-            key.unblock(toUnblock);
-            return this;
-        }
-
-        @Override
-        public String toString() {
-            return key.toString();
-        }
-    }
-
-    @Override
-    public MembershipKey join(InetAddress group,
-                              NetworkInterface interf)
-        throws IOException
-    {
-        MembershipKey key = ((MulticastChannel)dc).join(group, interf);
-        return new WrappedMembershipKey(this, key);
-    }
-
-    @Override
-    public MembershipKey join(InetAddress group,
-                              NetworkInterface interf,
-                              InetAddress source)
-        throws IOException
-    {
-        MembershipKey key = ((MulticastChannel)dc).join(group, interf, source);
-        return new WrappedMembershipKey(this, key);
-    }
-
-    private <A> Future<Integer> implSend(ByteBuffer src,
-                                         SocketAddress target,
-                                         A attachment,
-                                         CompletionHandler<Integer,? super A> handler)
-    {
-        int n = 0;
-        Throwable exc = null;
-        try {
-            n = dc.send(src, target);
-        } catch (IOException ioe) {
-            exc = ioe;
-        }
-        if (handler == null)
-            return CompletedFuture.withResult(n, exc);
-        Invoker.invoke(this, handler, attachment, n, exc);
-        return null;
-    }
-
-    @Override
-    public Future<Integer> send(ByteBuffer src, SocketAddress target) {
-        return implSend(src, target, null, null);
-    }
-
-    @Override
-    public <A> void send(ByteBuffer src,
-                         SocketAddress target,
-                         A attachment,
-                         CompletionHandler<Integer,? super A> handler)
-    {
-        if (handler == null)
-            throw new NullPointerException("'handler' is null");
-        implSend(src, target, attachment, handler);
-    }
-
-    private <A> Future<Integer> implWrite(ByteBuffer src,
-                                          A attachment,
-                                          CompletionHandler<Integer,? super A> handler)
-    {
-        int n = 0;
-        Throwable exc = null;
-        try {
-            n = dc.write(src);
-        } catch (IOException ioe) {
-            exc = ioe;
-        }
-        if (handler == null)
-            return CompletedFuture.withResult(n, exc);
-        Invoker.invoke(this, handler, attachment, n, exc);
-        return null;
-
-    }
-
-    @Override
-    public Future<Integer> write(ByteBuffer src) {
-        return implWrite(src, null, null);
-    }
-
-    @Override
-    public <A> void write(ByteBuffer src,
-                          A attachment,
-                          CompletionHandler<Integer,? super A> handler)
-    {
-        if (handler == null)
-            throw new NullPointerException("'handler' is null");
-        implWrite(src, attachment, handler);
-    }
-
-    /**
-     * Receive into the given buffer with privileges enabled and restricted by
-     * the given AccessControlContext (can be null).
-     */
-    private SocketAddress doRestrictedReceive(final ByteBuffer dst,
-                                              AccessControlContext acc)
-        throws IOException
-    {
-        if (acc == null) {
-            return dc.receive(dst);
-        } else {
-            try {
-                return AccessController.doPrivileged(
-                    new PrivilegedExceptionAction<SocketAddress>() {
-                        public SocketAddress run() throws IOException {
-                            return dc.receive(dst);
-                        }}, acc);
-            } catch (PrivilegedActionException pae) {
-                Exception cause = pae.getException();
-                if (cause instanceof SecurityException)
-                    throw (SecurityException)cause;
-                throw (IOException)cause;
-            }
-        }
-    }
-
-    private <A> Future<SocketAddress> implReceive(final ByteBuffer dst,
-                                                  final long timeout,
-                                                  final TimeUnit unit,
-                                                  A attachment,
-                                                  final CompletionHandler<SocketAddress,? super A> handler)
-    {
-        if (dst.isReadOnly())
-            throw new IllegalArgumentException("Read-only buffer");
-        if (timeout < 0L)
-            throw new IllegalArgumentException("Negative timeout");
-        if (unit == null)
-            throw new NullPointerException();
-
-        // complete immediately if channel closed
-        if (!isOpen()) {
-            Throwable exc = new ClosedChannelException();
-            if (handler == null)
-                return CompletedFuture.withFailure(exc);
-            Invoker.invoke(this, handler, attachment, null, exc);
-            return null;
-        }
-
-        final AccessControlContext acc = (System.getSecurityManager() == null) ?
-            null : AccessController.getContext();
-        final PendingFuture<SocketAddress,A> result =
-            new PendingFuture<SocketAddress,A>(this, handler, attachment);
-        Runnable task = new Runnable() {
-            public void run() {
-                try {
-                    SocketAddress remote = null;
-                    long to;
-                    if (timeout == 0L) {
-                        beginNoTimeoutRead();
-                        try {
-                            remote = doRestrictedReceive(dst, acc);
-                        } finally {
-                            endNoTimeoutRead();
-                        }
-                        to = 0L;
-                    } else {
-                        to = prepareForTimedRead(result, unit.toMillis(timeout));
-                        if (to <= 0L)
-                            throw new InterruptedByTimeoutException();
-                        remote = doRestrictedReceive(dst, acc);
-                    }
-                    if (remote == null) {
-                        Selector sel = getSelector();
-                        SelectionKey sk = null;
-                        try {
-                            sk = dc.register(sel, SelectionKey.OP_READ);
-                            for (;;) {
-                                if (!dc.isOpen())
-                                    throw new AsynchronousCloseException();
-                                if (result.isCancelled())
-                                    break;
-                                long st = System.currentTimeMillis();
-                                int ns = sel.select(to);
-                                if (ns > 0) {
-                                    remote = doRestrictedReceive(dst, acc);
-                                    if (remote != null)
-                                        break;
-                                }
-                                sel.selectedKeys().remove(sk);
-                                if (timeout != 0L) {
-                                    to -= System.currentTimeMillis() - st;
-                                    if (to <= 0)
-                                        throw new InterruptedByTimeoutException();
-                                }
-                            }
-                        } finally {
-                            if (sk != null)
-                                sk.cancel();
-                            releaseSelector(sel);
-                        }
-                    }
-                    result.setResult(remote);
-                } catch (Throwable x) {
-                    if (x instanceof ClosedChannelException)
-                        x = new AsynchronousCloseException();
-                    result.setFailure(x);
-                }
-                Invoker.invokeUnchecked(result);
-            }
-        };
-        try {
-            group.executeOnPooledThread(task);
-        } catch (RejectedExecutionException ree) {
-            throw new ShutdownChannelGroupException();
-        }
-        return result;
-    }
-
-    @Override
-    public Future<SocketAddress> receive(ByteBuffer dst) {
-        return implReceive(dst, 0L, TimeUnit.MILLISECONDS, null, null);
-    }
-
-    @Override
-    public <A> void receive(ByteBuffer dst,
-                            long timeout,
-                            TimeUnit unit,
-                            A attachment,
-                            CompletionHandler<SocketAddress,? super A> handler)
-    {
-        if (handler == null)
-            throw new NullPointerException("'handler' is null");
-        implReceive(dst, timeout, unit, attachment, handler);
-    }
-
-    private <A> Future<Integer> implRead(final ByteBuffer dst,
-                                         final long timeout,
-                                         final TimeUnit unit,
-                                         A attachment,
-                                         final CompletionHandler<Integer,? super A> handler)
-    {
-        if (dst.isReadOnly())
-            throw new IllegalArgumentException("Read-only buffer");
-        if (timeout < 0L)
-            throw new IllegalArgumentException("Negative timeout");
-        if (unit == null)
-            throw new NullPointerException();
-
-        // complete immediately if channel closed
-        if (!isOpen()) {
-            Throwable exc = new ClosedChannelException();
-            if (handler == null)
-                return CompletedFuture.withFailure(exc);
-            Invoker.invoke(this, handler, attachment, null, exc);
-            return null;
-        }
-
-        // another thread may disconnect before read is initiated
-        if (!dc.isConnected())
-            throw new NotYetConnectedException();
-
-        final PendingFuture<Integer,A> result =
-            new PendingFuture<Integer,A>(this, handler, attachment);
-        Runnable task = new Runnable() {
-            public void run() {
-                try {
-                    int n = 0;
-                    long to;
-                    if (timeout == 0L) {
-                        beginNoTimeoutRead();
-                        try {
-                            n = dc.read(dst);
-                        } finally {
-                            endNoTimeoutRead();
-                        }
-                        to = 0L;
-                    } else {
-                        to = prepareForTimedRead(result, unit.toMillis(timeout));
-                        if (to <= 0L)
-                            throw new InterruptedByTimeoutException();
-                        n = dc.read(dst);
-                    }
-                    if (n == 0) {
-                        Selector sel = getSelector();
-                        SelectionKey sk = null;
-                        try {
-                            sk = dc.register(sel, SelectionKey.OP_READ);
-                            for (;;) {
-                                if (!dc.isOpen())
-                                    throw new AsynchronousCloseException();
-                                if (result.isCancelled())
-                                    break;
-                                long st = System.currentTimeMillis();
-                                int ns = sel.select(to);
-                                if (ns > 0) {
-                                    if ((n = dc.read(dst)) != 0)
-                                        break;
-                                }
-                                sel.selectedKeys().remove(sk);
-                                if (timeout != 0L) {
-                                    to -= System.currentTimeMillis() - st;
-                                    if (to <= 0)
-                                        throw new InterruptedByTimeoutException();
-                                }
-                            }
-                        } finally {
-                            if (sk != null)
-                                sk.cancel();
-                            releaseSelector(sel);
-                        }
-                    }
-                    result.setResult(n);
-                } catch (Throwable x) {
-                    if (x instanceof ClosedChannelException)
-                        x = new AsynchronousCloseException();
-                    result.setFailure(x);
-                }
-                Invoker.invokeUnchecked(result);
-            }
-        };
-        try {
-            group.executeOnPooledThread(task);
-        } catch (RejectedExecutionException ree) {
-            throw new ShutdownChannelGroupException();
-        }
-        return result;
-    }
-
-    @Override
-    public Future<Integer> read(ByteBuffer dst) {
-        return implRead(dst, 0L, TimeUnit.MILLISECONDS, null, null);
-    }
-
-    @Override
-    public <A> void read(ByteBuffer dst,
-                            long timeout,
-                            TimeUnit unit,
-                            A attachment,
-                            CompletionHandler<Integer,? super A> handler)
-    {
-        if (handler == null)
-            throw new NullPointerException("'handler' is null");
-        implRead(dst, timeout, unit, attachment, handler);
-    }
-
-    @Override
-    public  AsynchronousDatagramChannel bind(SocketAddress local)
-        throws IOException
-    {
-        dc.bind(local);
-        return this;
-    }
-
-    @Override
-    public SocketAddress getLocalAddress() throws IOException {
-        return dc.getLocalAddress();
-    }
-
-    @Override
-    public <T> AsynchronousDatagramChannel setOption(SocketOption<T> name, T value)
-        throws IOException
-    {
-        dc.setOption(name, value);
-        return this;
-    }
-
-    @Override
-    public  <T> T getOption(SocketOption<T> name) throws IOException {
-        return dc.getOption(name);
-    }
-
-    @Override
-    public Set<SocketOption<?>> supportedOptions() {
-        return dc.supportedOptions();
-    }
-
-    @Override
-    public SocketAddress getRemoteAddress() throws IOException {
-        return dc.getRemoteAddress();
-    }
-}
--- a/jdk/src/share/classes/sun/nio/ch/Util.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/nio/ch/Util.java	Wed Jul 05 17:26:57 2017 +0200
@@ -28,6 +28,7 @@
 import java.lang.ref.SoftReference;
 import java.lang.reflect.*;
 import java.io.IOException;
+import java.io.FileDescriptor;
 import java.nio.ByteBuffer;
 import java.nio.MappedByteBuffer;
 import java.nio.channels.*;
@@ -364,6 +365,7 @@
                         Constructor ctor = cl.getDeclaredConstructor(
                             new Class[] { int.class,
                                           long.class,
+                                          FileDescriptor.class,
                                           Runnable.class });
                         ctor.setAccessible(true);
                         directByteBufferConstructor = ctor;
@@ -381,6 +383,7 @@
     }
 
     static MappedByteBuffer newMappedByteBuffer(int size, long addr,
+                                                FileDescriptor fd,
                                                 Runnable unmapper)
     {
         MappedByteBuffer dbb;
@@ -390,6 +393,7 @@
             dbb = (MappedByteBuffer)directByteBufferConstructor.newInstance(
               new Object[] { new Integer(size),
                              new Long(addr),
+                             fd,
                              unmapper });
         } catch (InstantiationException e) {
             throw new InternalError();
@@ -411,6 +415,7 @@
                         Constructor ctor = cl.getDeclaredConstructor(
                             new Class[] { int.class,
                                           long.class,
+                                          FileDescriptor.class,
                                           Runnable.class });
                         ctor.setAccessible(true);
                         directByteBufferRConstructor = ctor;
@@ -428,6 +433,7 @@
     }
 
     static MappedByteBuffer newMappedByteBufferR(int size, long addr,
+                                                 FileDescriptor fd,
                                                  Runnable unmapper)
     {
         MappedByteBuffer dbb;
@@ -437,6 +443,7 @@
             dbb = (MappedByteBuffer)directByteBufferRConstructor.newInstance(
               new Object[] { new Integer(size),
                              new Long(addr),
+                             fd,
                              unmapper });
         } catch (InstantiationException e) {
             throw new InternalError();
--- a/jdk/src/share/classes/sun/security/internal/interfaces/TlsMasterSecret.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/internal/interfaces/TlsMasterSecret.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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,7 +38,8 @@
  *
  * @since   1.6
  * @author  Andreas Sterbenz
- * @deprecated Sun JDK internal use only --- WILL BE REMOVED in Dolphin (JDK 7)
+ * @deprecated Sun JDK internal use only --- WILL BE REMOVED in a future
+ * release.
  */
 @Deprecated
 public interface TlsMasterSecret extends SecretKey {
--- a/jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialParameterSpec.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialParameterSpec.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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,7 +39,8 @@
  *
  * @since   1.6
  * @author  Andreas Sterbenz
- * @deprecated Sun JDK internal use only --- WILL BE REMOVED in Dolphin (JDK 7)
+ * @deprecated Sun JDK internal use only --- WILL BE REMOVED in a future
+ * release.
  */
 @Deprecated
 public class TlsKeyMaterialParameterSpec implements AlgorithmParameterSpec {
@@ -50,6 +51,9 @@
     private final String cipherAlgorithm;
     private final int cipherKeyLength, ivLength, macKeyLength;
     private final int expandedCipherKeyLength; // == 0 for domestic ciphersuites
+    private final String prfHashAlg;
+    private final int prfHashLength;
+    private final int prfBlockSize;
 
     /**
      * Constructs a new TlsKeyMaterialParameterSpec.
@@ -71,6 +75,12 @@
      * @param ivLength the length in bytes of the initialization vector
      *    to be generated, or 0 if no initialization vector is required
      * @param macKeyLength the length in bytes of the MAC key to be generated
+     * @param prfHashAlg the name of the TLS PRF hash algorithm to use.
+     *        Used only for TLS 1.2+.  TLS1.1 and earlier use a fixed PRF.
+     * @param prfHashLength the output length of the TLS PRF hash algorithm.
+     *        Used only for TLS 1.2+.
+     * @param prfBlockSize the input block size of the TLS PRF hash algorithm.
+     *        Used only for TLS 1.2+.
      *
      * @throws NullPointerException if masterSecret, clientRandom,
      *   serverRandom, or cipherAlgorithm are null
@@ -82,7 +92,8 @@
     public TlsKeyMaterialParameterSpec(SecretKey masterSecret,
             int majorVersion, int minorVersion, byte[] clientRandom,
             byte[] serverRandom, String cipherAlgorithm, int cipherKeyLength,
-            int expandedCipherKeyLength, int ivLength, int macKeyLength) {
+            int expandedCipherKeyLength, int ivLength, int macKeyLength,
+            String prfHashAlg, int prfHashLength, int prfBlockSize) {
         if (masterSecret.getAlgorithm().equals("TlsMasterSecret") == false) {
             throw new IllegalArgumentException("Not a TLS master secret");
         }
@@ -90,8 +101,10 @@
             throw new NullPointerException();
         }
         this.masterSecret = masterSecret;
-        this.majorVersion = TlsMasterSecretParameterSpec.checkVersion(majorVersion);
-        this.minorVersion = TlsMasterSecretParameterSpec.checkVersion(minorVersion);
+        this.majorVersion =
+            TlsMasterSecretParameterSpec.checkVersion(majorVersion);
+        this.minorVersion =
+            TlsMasterSecretParameterSpec.checkVersion(minorVersion);
         this.clientRandom = clientRandom.clone();
         this.serverRandom = serverRandom.clone();
         this.cipherAlgorithm = cipherAlgorithm;
@@ -99,6 +112,9 @@
         this.expandedCipherKeyLength = checkSign(expandedCipherKeyLength);
         this.ivLength = checkSign(ivLength);
         this.macKeyLength = checkSign(macKeyLength);
+        this.prfHashAlg = prfHashAlg;
+        this.prfHashLength = prfHashLength;
+        this.prfBlockSize = prfBlockSize;
     }
 
     private static int checkSign(int k) {
@@ -172,20 +188,36 @@
     }
 
     /**
-     * Returns the length in bytes of the expanded encryption key to be generated.
+     * Returns the length in bytes of the expanded encryption key to be
+     * generated. Returns zero if the expanded encryption key is not
+     * supposed to be generated.
      *
-     * @return the length in bytes of the expanded encryption key to be generated.
+     * @return the length in bytes of the expanded encryption key to be
+     *     generated.
      */
     public int getExpandedCipherKeyLength() {
+        // TLS v1.1 disables the exportable weak cipher suites.
+        if (majorVersion >= 0x03 && minorVersion >= 0x02) {
+            return 0;
+        }
         return expandedCipherKeyLength;
     }
 
     /**
-     * Returns the length in bytes of the initialization vector to be generated.
+     * Returns the length in bytes of the initialization vector to be
+     * generated. Returns zero if the initialization vector is not
+     * supposed to be generated.
      *
-     * @return the length in bytes of the initialization vector to be generated.
+     * @return the length in bytes of the initialization vector to be
+     *     generated.
      */
     public int getIvLength() {
+        // TLS v1.1 or later uses an explicit IV to protect against
+        // the CBC attacks.
+        if (majorVersion >= 0x03 && minorVersion >= 0x02) {
+            return 0;
+        }
+
         return ivLength;
     }
 
@@ -198,4 +230,30 @@
         return macKeyLength;
     }
 
+    /**
+     * Obtains the PRF hash algorithm to use in the PRF calculation.
+     *
+     * @return the hash algorithm.
+     */
+    public String getPRFHashAlg() {
+        return prfHashAlg;
+    }
+
+    /**
+     * Obtains the length of the PRF hash algorithm.
+     *
+     * @return the hash algorithm length.
+     */
+    public int getPRFHashLength() {
+        return prfHashLength;
+    }
+
+    /**
+     * Obtains the block size of the PRF hash algorithm.
+     *
+     * @return the hash algorithm block size
+     */
+    public int getPRFBlockSize() {
+        return prfBlockSize;
+    }
 }
--- a/jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialSpec.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialSpec.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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,7 +39,8 @@
  *
  * @since   1.6
  * @author  Andreas Sterbenz
- * @deprecated Sun JDK internal use only --- WILL BE REMOVED in Dolphin (JDK 7)
+ * @deprecated Sun JDK internal use only --- WILL BE REMOVED in a future
+ * release.
  */
 @Deprecated
 public class TlsKeyMaterialSpec implements KeySpec, SecretKey {
@@ -80,7 +81,8 @@
      */
     public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey,
             SecretKey clientCipherKey, SecretKey serverCipherKey) {
-        this(clientMacKey, serverMacKey, clientCipherKey, null, serverCipherKey, null);
+        this(clientMacKey, serverMacKey, clientCipherKey, null,
+            serverCipherKey, null);
     }
 
     /**
--- a/jdk/src/share/classes/sun/security/internal/spec/TlsMasterSecretParameterSpec.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/internal/spec/TlsMasterSecretParameterSpec.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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,7 +39,8 @@
  *
  * @since   1.6
  * @author  Andreas Sterbenz
- * @deprecated Sun JDK internal use only --- WILL BE REMOVED in Dolphin (JDK 7)
+ * @deprecated Sun JDK internal use only --- WILL BE REMOVED in a future
+ * release.
  */
 @Deprecated
 public class TlsMasterSecretParameterSpec implements AlgorithmParameterSpec {
@@ -47,6 +48,9 @@
     private final SecretKey premasterSecret;
     private final int majorVersion, minorVersion;
     private final byte[] clientRandom, serverRandom;
+    private final String prfHashAlg;
+    private final int prfHashLength;
+    private final int prfBlockSize;
 
     /**
      * Constructs a new TlsMasterSecretParameterSpec.
@@ -60,6 +64,12 @@
      * @param minorVersion the minor number of the protocol version
      * @param clientRandom the client's random value
      * @param serverRandom the server's random value
+     * @param prfHashAlg the name of the TLS PRF hash algorithm to use.
+     *        Used only for TLS 1.2+.  TLS1.1 and earlier use a fixed PRF.
+     * @param prfHashLength the output length of the TLS PRF hash algorithm.
+     *        Used only for TLS 1.2+.
+     * @param prfBlockSize the input block size of the TLS PRF hash algorithm.
+     *        Used only for TLS 1.2+.
      *
      * @throws NullPointerException if premasterSecret, clientRandom,
      *   or serverRandom are null
@@ -67,7 +77,9 @@
      *   negative or larger than 255
      */
     public TlsMasterSecretParameterSpec(SecretKey premasterSecret,
-            int majorVersion, int minorVersion, byte[] clientRandom, byte[] serverRandom) {
+            int majorVersion, int minorVersion,
+            byte[] clientRandom, byte[] serverRandom,
+            String prfHashAlg, int prfHashLength, int prfBlockSize) {
         if (premasterSecret == null) {
             throw new NullPointerException("premasterSecret must not be null");
         }
@@ -76,11 +88,15 @@
         this.minorVersion = checkVersion(minorVersion);
         this.clientRandom = clientRandom.clone();
         this.serverRandom = serverRandom.clone();
+        this.prfHashAlg = prfHashAlg;
+        this.prfHashLength = prfHashLength;
+        this.prfBlockSize = prfBlockSize;
     }
 
     static int checkVersion(int version) {
         if ((version < 0) || (version > 255)) {
-            throw new IllegalArgumentException("Version must be between 0 and 255");
+            throw new IllegalArgumentException(
+                        "Version must be between 0 and 255");
         }
         return version;
     }
@@ -130,4 +146,30 @@
         return serverRandom.clone();
     }
 
+    /**
+     * Obtains the PRF hash algorithm to use in the PRF calculation.
+     *
+     * @return the hash algorithm.
+     */
+    public String getPRFHashAlg() {
+        return prfHashAlg;
+    }
+
+    /**
+     * Obtains the length of the PRF hash algorithm.
+     *
+     * @return the hash algorithm length.
+     */
+    public int getPRFHashLength() {
+        return prfHashLength;
+    }
+
+    /**
+     * Obtains the block size of the PRF hash algorithm.
+     *
+     * @return the hash algorithm block size.
+     */
+    public int getPRFBlockSize() {
+        return prfBlockSize;
+    }
 }
--- a/jdk/src/share/classes/sun/security/internal/spec/TlsPrfParameterSpec.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/internal/spec/TlsPrfParameterSpec.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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,7 +38,8 @@
  *
  * @since   1.6
  * @author  Andreas Sterbenz
- * @deprecated Sun JDK internal use only --- WILL BE REMOVED in Dolphin (JDK 7)
+ * @deprecated Sun JDK internal use only --- WILL BE REMOVED in a future
+ * release.
  */
 @Deprecated
 public class TlsPrfParameterSpec implements AlgorithmParameterSpec {
@@ -47,6 +48,9 @@
     private final String label;
     private final byte[] seed;
     private final int outputLength;
+    private final String prfHashAlg;
+    private final int prfHashLength;
+    private final int prfBlockSize;
 
     /**
      * Constructs a new TlsPrfParameterSpec.
@@ -55,11 +59,19 @@
      * @param label the label to use in the calculation
      * @param seed the random seed to use in the calculation
      * @param outputLength the length in bytes of the output key to be produced
+     * @param prfHashAlg the name of the TLS PRF hash algorithm to use.
+     *        Used only for TLS 1.2+.  TLS1.1 and earlier use a fixed PRF.
+     * @param prfHashLength the output length of the TLS PRF hash algorithm.
+     *        Used only for TLS 1.2+.
+     * @param prfBlockSize the input block size of the TLS PRF hash algorithm.
+     *        Used only for TLS 1.2+.
      *
      * @throws NullPointerException if label or seed is null
      * @throws IllegalArgumentException if outputLength is negative
      */
-    public TlsPrfParameterSpec(SecretKey secret, String label, byte[] seed, int outputLength) {
+    public TlsPrfParameterSpec(SecretKey secret, String label,
+            byte[] seed, int outputLength,
+            String prfHashAlg, int prfHashLength, int prfBlockSize) {
         if ((label == null) || (seed == null)) {
             throw new NullPointerException("label and seed must not be null");
         }
@@ -70,6 +82,9 @@
         this.label = label;
         this.seed = seed.clone();
         this.outputLength = outputLength;
+        this.prfHashAlg = prfHashAlg;
+        this.prfHashLength = prfHashLength;
+        this.prfBlockSize = prfBlockSize;
     }
 
     /**
@@ -110,4 +125,33 @@
         return outputLength;
     }
 
+    /**
+     * Obtains the PRF hash algorithm to use in the PRF calculation.
+     *
+     * @return the hash algorithm, or null if no algorithm was specified.
+     */
+    public String getPRFHashAlg() {
+        return prfHashAlg;
+    }
+
+    /**
+     * Obtains the length of PRF hash algorithm.
+     *
+     * It would have been preferred to use MessageDigest.getDigestLength(),
+     * but the API does not require implementations to support the method.
+     *
+     * @return the hash algorithm length.
+     */
+    public int getPRFHashLength() {
+        return prfHashLength;
+    }
+
+    /**
+     * Obtains the length of PRF hash algorithm.
+     *
+     * @return the hash algorithm length.
+     */
+    public int getPRFBlockSize() {
+        return prfBlockSize;
+    }
 }
--- a/jdk/src/share/classes/sun/security/internal/spec/TlsRsaPremasterSecretParameterSpec.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/internal/spec/TlsRsaPremasterSecretParameterSpec.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -36,10 +36,12 @@
  *
  * @since   1.6
  * @author  Andreas Sterbenz
- * @deprecated Sun JDK internal use only --- WILL BE REMOVED in Dolphin (JDK 7)
+ * @deprecated Sun JDK internal use only --- WILL BE REMOVED in a future
+ * release.
  */
 @Deprecated
-public class TlsRsaPremasterSecretParameterSpec implements AlgorithmParameterSpec {
+public class TlsRsaPremasterSecretParameterSpec
+        implements AlgorithmParameterSpec {
 
     private final int majorVersion;
     private final int minorVersion;
@@ -58,10 +60,12 @@
      * @throws IllegalArgumentException if minorVersion or majorVersion are
      *   negative or larger than 255
      */
-    public TlsRsaPremasterSecretParameterSpec(int majorVersion, int minorVersion) {
-        this.majorVersion = TlsMasterSecretParameterSpec.checkVersion(majorVersion);
-        this.minorVersion = TlsMasterSecretParameterSpec.checkVersion(minorVersion);
-    }
+    public TlsRsaPremasterSecretParameterSpec(int majorVersion,
+            int minorVersion) {
+        this.majorVersion =
+            TlsMasterSecretParameterSpec.checkVersion(majorVersion);
+        this.minorVersion =
+            TlsMasterSecretParameterSpec.checkVersion(minorVersion); }
 
     /**
      * Returns the major version.
--- a/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java	Wed Jul 05 17:26:57 2017 +0200
@@ -34,7 +34,6 @@
 import sun.security.krb5.*;
 import sun.security.krb5.internal.*;
 import sun.security.krb5.internal.crypto.*;
-import java.util.Vector;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.io.IOException;
@@ -42,7 +41,10 @@
 import java.io.FileOutputStream;
 import java.io.File;
 import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.StringTokenizer;
+import java.util.Vector;
 
 /**
  * This class represents key table. The key table functions deal with storing
@@ -239,23 +241,22 @@
         EncryptionKey key;
         int size = entries.size();
         ArrayList<EncryptionKey> keys = new ArrayList<EncryptionKey> (size);
-        if (entries != null) {
-            for (int i = size-1; i >= 0; i--) {
-                entry = entries.elementAt(i);
-                if (entry.service.match(service)) {
-                    if (EType.isSupported(entry.keyType)) {
-                        key = new EncryptionKey(entry.keyblock,
-                                            entry.keyType,
-                                            new Integer(entry.keyVersion));
-                        keys.add(key);
-                        if (DEBUG) {
-                            System.out.println("Added key: " + entry.keyType +
-                                "version: " + entry.keyVersion);
-                        }
-                    } else if (DEBUG) {
-                        System.out.println("Found unsupported keytype (" +
-                            entry.keyType + ") for " + service);
+
+        for (int i = size-1; i >= 0; i--) {
+            entry = entries.elementAt(i);
+            if (entry.service.match(service)) {
+                if (EType.isSupported(entry.keyType)) {
+                    key = new EncryptionKey(entry.keyblock,
+                                        entry.keyType,
+                                        new Integer(entry.keyVersion));
+                    keys.add(key);
+                    if (DEBUG) {
+                        System.out.println("Added key: " + entry.keyType +
+                            "version: " + entry.keyVersion);
                     }
+                } else if (DEBUG) {
+                    System.out.println("Found unsupported keytype (" +
+                        entry.keyType + ") for " + service);
                 }
             }
         }
@@ -313,16 +314,14 @@
      */
     public boolean findServiceEntry(PrincipalName service) {
         KeyTabEntry entry;
-        if (entries != null) {
-            for (int i = 0; i < entries.size(); i++) {
-                entry = entries.elementAt(i);
-                if (entry.service.match(service)) {
-                    if (EType.isSupported(entry.keyType)) {
-                        return true;
-                    } else if (DEBUG) {
-                        System.out.println("Found unsupported keytype (" +
-                            entry.keyType + ") for " + service);
-                    }
+        for (int i = 0; i < entries.size(); i++) {
+            entry = entries.elementAt(i);
+            if (entry.service.match(service)) {
+                if (EType.isSupported(entry.keyType)) {
+                    return true;
+                } else if (DEBUG) {
+                    System.out.println("Found unsupported keytype (" +
+                        entry.keyType + ") for " + service);
                 }
             }
         }
@@ -337,94 +336,57 @@
      * Adds a new entry in the key table.
      * @param service the service which will have a new entry in the key table.
      * @param psswd the password which generates the key.
+     * @param kvno the kvno to use, -1 means automatic increasing
+     * @param append false if entries with old kvno would be removed.
+     * Note: if kvno is not -1, entries with the same kvno are always removed
      */
-    public void addEntry(PrincipalName service, char[] psswd)
-         throws KrbException {
+    public void addEntry(PrincipalName service, char[] psswd,
+            int kvno, boolean append) throws KrbException {
 
         EncryptionKey[] encKeys = EncryptionKey.acquireSecretKeys(
             psswd, service.getSalt());
 
+        // There should be only one maximum KVNO value for all etypes, so that
+        // all added keys can have the same KVNO.
+
+        int maxKvno = 0;    // only useful when kvno == -1
+        for (int i = entries.size()-1; i >= 0; i--) {
+            KeyTabEntry e = entries.get(i);
+            if (e.service.match(service)) {
+                if (e.keyVersion > maxKvno) {
+                    maxKvno = e.keyVersion;
+                }
+                if (!append || e.keyVersion == kvno) {
+                    entries.removeElementAt(i);
+                }
+            }
+        }
+        if (kvno == -1) {
+            kvno = maxKvno + 1;
+        }
+
         for (int i = 0; encKeys != null && i < encKeys.length; i++) {
             int keyType = encKeys[i].getEType();
             byte[] keyValue = encKeys[i].getBytes();
-            int result = retrieveEntry(service, keyType);
-            int kvno = 1;
-            if (result != -1) {
-                KeyTabEntry oldEntry = entries.elementAt(result);
-                kvno = oldEntry.keyVersion;
-                entries.removeElementAt(result);
-                kvno += 1;
-            } else
-                kvno = 1;
 
             KeyTabEntry newEntry = new KeyTabEntry(service,
                             service.getRealm(),
                             new KerberosTime(System.currentTimeMillis()),
                                                kvno, keyType, keyValue);
-            if (entries == null)
-                entries = new Vector<KeyTabEntry> ();
             entries.addElement(newEntry);
         }
     }
 
     /**
-     * Only used by KDC test. This method can specify kvno and does not
-     * remove any old keys.
-     */
-    public void addEntry(PrincipalName service, char[] psswd, int kvno)
-         throws KrbException {
-
-        EncryptionKey[] encKeys = EncryptionKey.acquireSecretKeys(
-            psswd, service.getSalt());
-
-        for (int i = 0; encKeys != null && i < encKeys.length; i++) {
-            int keyType = encKeys[i].getEType();
-            byte[] keyValue = encKeys[i].getBytes();
-            KeyTabEntry newEntry = new KeyTabEntry(service,
-                            service.getRealm(),
-                            new KerberosTime(System.currentTimeMillis()),
-                                               kvno, keyType, keyValue);
-            if (entries == null)
-                entries = new Vector<KeyTabEntry> ();
-            entries.addElement(newEntry);
-        }
-    }
-
-    /**
-     * Retrieves the key table entry with the specified service name.
-     * @param service the service which may have an entry in the key table.
-     * @param keyType the etype to match, returns the 1st one if -1 provided
-     * @return -1 if the entry is not found, else return the entry index
-     * in the list.
-     */
-    private int retrieveEntry(PrincipalName service, int keyType) {
-        KeyTabEntry e;
-        if (entries != null) {
-            for (int i = 0; i < entries.size(); i++) {
-                e = entries.elementAt(i);
-                if (service.match(e.getService()) &&
-                    (keyType == -1 || e.keyType == keyType)) {
-                    return i;
-                }
-            }
-        }
-        return -1;
-    }
-
-    /**
      * Gets the list of service entries in key table.
      * @return array of <code>KeyTabEntry</code>.
      */
     public KeyTabEntry[] getEntries() {
-        if (entries != null) {
-            KeyTabEntry[] kentries = new KeyTabEntry[entries.size()];
-            for (int i = 0; i < kentries.length; i++) {
-                kentries[i] = entries.elementAt(i);
-            }
-            return kentries;
-        } else {
-            return null;
+        KeyTabEntry[] kentries = new KeyTabEntry[entries.size()];
+        for (int i = 0; i < kentries.length; i++) {
+            kentries[i] = entries.elementAt(i);
         }
+        return kentries;
     }
 
     /**
@@ -464,29 +426,55 @@
     }
 
     /**
-     * Removes an entry from the key table.
+     * Removes entries from the key table.
      * @param service the service <code>PrincipalName</code>.
-     * @param etype the etype to match, first one if -1 provided
-     * @return 1 if removed successfully, 0 otherwise
+     * @param etype the etype to match, remove all if -1
+     * @param kvno what kvno to remove, -1 for all, -2 for old
+     * @return the number of entries deleted
      */
-    public int deleteEntry(PrincipalName service, int etype) {
-        int result = retrieveEntry(service, etype);
-        if (result != -1) {
-            entries.removeElementAt(result);
-            return 1;
+    public int deleteEntries(PrincipalName service, int etype, int kvno) {
+        int count = 0;
+
+        // Remember the highest KVNO for each etype. Used for kvno == -2
+        Map<Integer,Integer> highest = new HashMap<>();
+
+        for (int i = entries.size()-1; i >= 0; i--) {
+            KeyTabEntry e = entries.get(i);
+            if (service.match(e.getService())) {
+                if (etype == -1 || e.keyType == etype) {
+                    if (kvno == -2) {
+                        // Two rounds for kvno == -2. In the first round (here),
+                        // only find out highest KVNO for each etype
+                        if (highest.containsKey(e.keyType)) {
+                            int n = highest.get(e.keyType);
+                            if (e.keyVersion > n) {
+                                highest.put(e.keyType, e.keyVersion);
+                            }
+                        } else {
+                            highest.put(e.keyType, e.keyVersion);
+                        }
+                    } else if (kvno == -1 || e.keyVersion == kvno) {
+                        entries.removeElementAt(i);
+                        count++;
+                    }
+                }
+            }
         }
-        return 0;
-    }
 
-    /**
-     * Removes an entry from the key table.
-     * @param service the service <code>PrincipalName</code>.
-     * @return number of entries removed
-     */
-    public int deleteEntry(PrincipalName service) {
-        int count = 0;
-        while (deleteEntry(service, -1) > 0) {
-            count++;
+        // Second round for kvno == -2, remove old entries
+        if (kvno == -2) {
+            for (int i = entries.size()-1; i >= 0; i--) {
+                KeyTabEntry e = entries.get(i);
+                if (service.match(e.getService())) {
+                    if (etype == -1 || e.keyType == etype) {
+                        int n = highest.get(e.keyType);
+                        if (e.keyVersion != n) {
+                            entries.removeElementAt(i);
+                            count++;
+                        }
+                    }
+                }
+            }
         }
         return count;
     }
--- a/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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
@@ -655,6 +655,25 @@
         d(SIG, "SHA512withRSA", P11Signature,
                 m(CKM_SHA512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
 
+        /*
+         * TLS 1.2 uses a different hash algorithm than 1.0/1.1 for the
+         * PRF calculations.  As of 2010, there is no PKCS11-level
+         * support for TLS 1.2 PRF calculations, and no known OS's have
+         * an internal variant we could use.  Therefore for TLS 1.2, we
+         * are updating JSSE to request different provider algorithms
+         * (e.g. "SunTls12Prf"), and currently only SunJCE has these
+         * TLS 1.2 algorithms.
+         *
+         * If we reused the names such as "SunTlsPrf", the PKCS11
+         * providers would need be updated to fail correctly when
+         * presented with the wrong version number (via
+         * Provider.Service.supportsParameters()), and we would also
+         * need to add the appropriate supportsParamters() checks into
+         * KeyGenerators (not currently there).
+         *
+         * In the future, if PKCS11 support is added, we will restructure
+         * this.
+         */
         d(KG, "SunTlsRsaPremasterSecret",
                     "sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",
                 m(CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_PRE_MASTER_KEY_GEN));
@@ -887,7 +906,8 @@
             return (aliases == null) ? null : Arrays.asList(aliases);
         }
 
-        public Object newInstance(Object param) throws NoSuchAlgorithmException {
+        public Object newInstance(Object param)
+                throws NoSuchAlgorithmException {
             if (token.isValid() == false) {
                 throw new NoSuchAlgorithmException("Token has been removed");
             }
--- a/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2010, 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,95 +25,336 @@
 
 package sun.security.provider.certpath;
 
-import java.util.Set;
+import java.security.AlgorithmConstraints;
+import java.security.CryptoPrimitive;
 import java.util.Collection;
-import java.util.Locale;
+import java.util.Collections;
+import java.util.Set;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.math.BigInteger;
+import java.security.PublicKey;
+import java.security.KeyFactory;
+import java.security.AlgorithmParameters;
+import java.security.NoSuchAlgorithmException;
+import java.security.GeneralSecurityException;
 import java.security.cert.Certificate;
+import java.security.cert.X509CRL;
 import java.security.cert.X509Certificate;
-import java.security.cert.X509CRL;
+import java.security.cert.PKIXCertPathChecker;
+import java.security.cert.TrustAnchor;
+import java.security.cert.CRLException;
+import java.security.cert.CertificateException;
 import java.security.cert.CertPathValidatorException;
-import java.security.cert.PKIXCertPathChecker;
+import java.io.IOException;
+import java.security.interfaces.*;
+import java.security.spec.*;
 
+import sun.security.util.DisabledAlgorithmConstraints;
+import sun.security.x509.X509CertImpl;
+import sun.security.x509.X509CRLImpl;
 import sun.security.x509.AlgorithmId;
 
 /**
- * AlgorithmChecker is a <code>PKIXCertPathChecker</code> that checks that
- * the signature algorithm of the specified certificate is not disabled.
+ * A <code>PKIXCertPathChecker</code> implementation to check whether a
+ * specified certificate contains the required algorithm constraints.
+ * <p>
+ * Certificate fields such as the subject public key, the signature
+ * algorithm, key usage, extended key usage, etc. need to conform to
+ * the specified algorithm constraints.
  *
- * @author      Xuelei Fan
+ * @see PKIXCertPathChecker
+ * @see PKIXParameters
  */
 final public class AlgorithmChecker extends PKIXCertPathChecker {
 
-    // the disabled algorithms
-    private static final String[] disabledAlgorithms = new String[] {"md2"};
+    private final AlgorithmConstraints constraints;
+    private final PublicKey trustedPubKey;
+    private PublicKey prevPubKey;
 
-    // singleton instance
-    static final AlgorithmChecker INSTANCE = new AlgorithmChecker();
+    private final static Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
+                                    EnumSet.of(CryptoPrimitive.SIGNATURE);
+
+    private final static DisabledAlgorithmConstraints
+        certPathDefaultConstraints = new DisabledAlgorithmConstraints(
+            DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
 
     /**
-     * Default Constructor
+     * Create a new <code>AlgorithmChecker</code> with the algorithm
+     * constraints specified in security property
+     * "jdk.certpath.disabledAlgorithms".
+     *
+     * @param anchor the trust anchor selected to validate the target
+     *     certificate
      */
-    private AlgorithmChecker() {
-        // do nothing
+    public AlgorithmChecker(TrustAnchor anchor) {
+        this(anchor, certPathDefaultConstraints);
+    }
+
+    /**
+     * Create a new <code>AlgorithmChecker</code> with the
+     * given {@code AlgorithmConstraints}.
+     * <p>
+     * Note that this constructor will be used to check a certification
+     * path where the trust anchor is unknown, or a certificate list which may
+     * contain the trust anchor. This constructor is used by SunJSSE.
+     *
+     * @param constraints the algorithm constraints (or null)
+     */
+    public AlgorithmChecker(AlgorithmConstraints constraints) {
+        this.prevPubKey = null;
+        this.trustedPubKey = null;
+        this.constraints = constraints;
     }
 
     /**
-     * Return a AlgorithmChecker instance.
+     * Create a new <code>AlgorithmChecker</code> with the
+     * given <code>TrustAnchor</code> and <code>AlgorithmConstraints</code>.
+     *
+     * @param anchor the trust anchor selected to validate the target
+     *     certificate
+     * @param constraints the algorithm constraints (or null)
+     *
+     * @throws IllegalArgumentException if the <code>anchor</code> is null
      */
-    static AlgorithmChecker getInstance() {
-        return INSTANCE;
+    public AlgorithmChecker(TrustAnchor anchor,
+            AlgorithmConstraints constraints) {
+
+        if (anchor == null) {
+            throw new IllegalArgumentException(
+                        "The trust anchor cannot be null");
+        }
+
+        if (anchor.getTrustedCert() != null) {
+            this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
+        } else {
+            this.trustedPubKey = anchor.getCAPublicKey();
+        }
+
+        this.prevPubKey = trustedPubKey;
+        this.constraints = constraints;
     }
 
-    /**
-     * Initializes the internal state of the checker from parameters
-     * specified in the constructor.
-     */
+    @Override
     public void init(boolean forward) throws CertPathValidatorException {
-        // do nothing
+        //  Note that this class does not support forward mode.
+        if (!forward) {
+            if (trustedPubKey != null) {
+                prevPubKey = trustedPubKey;
+            } else {
+                prevPubKey = null;
+            }
+        } else {
+            throw new
+                CertPathValidatorException("forward checking not supported");
+        }
     }
 
+    @Override
     public boolean isForwardCheckingSupported() {
+        //  Note that as this class does not support forward mode, the method
+        //  will always returns false.
         return false;
     }
 
+    @Override
     public Set<String> getSupportedExtensions() {
         return null;
     }
 
-    /**
-     * Checks the signature algorithm of the specified certificate.
-     */
-    public void check(Certificate cert, Collection<String> unresolvedCritExts)
+    @Override
+    public void check(Certificate cert,
+            Collection<String> unresolvedCritExts)
             throws CertPathValidatorException {
-        check(cert);
-    }
+
+        if (!(cert instanceof X509Certificate) || constraints == null) {
+            // ignore the check for non-x.509 certificate or null constraints
+            return;
+        }
+
+        X509CertImpl x509Cert = null;
+        try {
+            x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
+        } catch (CertificateException ce) {
+            throw new CertPathValidatorException(ce);
+        }
+
+        PublicKey currPubKey = x509Cert.getPublicKey();
+        String currSigAlg = x509Cert.getSigAlgName();
+
+        AlgorithmId algorithmId = null;
+        try {
+            algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG);
+        } catch (CertificateException ce) {
+            throw new CertPathValidatorException(ce);
+        }
+
+        AlgorithmParameters currSigAlgParams = algorithmId.getParameters();
+
+        // Check the current signature algorithm
+        if (!constraints.permits(
+                SIGNATURE_PRIMITIVE_SET,
+                currSigAlg, currSigAlgParams)) {
+            throw new CertPathValidatorException(
+                "Algorithm constraints check failed: " + currSigAlg);
+        }
+
+        // check the key usage and key size
+        boolean[] keyUsage = x509Cert.getKeyUsage();
+        if (keyUsage != null && keyUsage.length < 9) {
+            throw new CertPathValidatorException(
+                        "incorrect KeyUsage extension");
+        }
+
+        if (keyUsage != null) {
+            Set<CryptoPrimitive> primitives =
+                        EnumSet.noneOf(CryptoPrimitive.class);
+
+            if (keyUsage[0] || keyUsage[1] || keyUsage[5] || keyUsage[6]) {
+                // keyUsage[0]: KeyUsage.digitalSignature
+                // keyUsage[1]: KeyUsage.nonRepudiation
+                // keyUsage[5]: KeyUsage.keyCertSign
+                // keyUsage[6]: KeyUsage.cRLSign
+                primitives.add(CryptoPrimitive.SIGNATURE);
+            }
+
+            if (keyUsage[2]) {      // KeyUsage.keyEncipherment
+                primitives.add(CryptoPrimitive.KEY_ENCAPSULATION);
+            }
+
+            if (keyUsage[3]) {      // KeyUsage.dataEncipherment
+                primitives.add(CryptoPrimitive.PUBLIC_KEY_ENCRYPTION);
+            }
 
-    public static void check(Certificate cert)
-            throws CertPathValidatorException {
-        X509Certificate xcert = (X509Certificate)cert;
-        check(xcert.getSigAlgName());
+            if (keyUsage[4]) {      // KeyUsage.keyAgreement
+                primitives.add(CryptoPrimitive.KEY_AGREEMENT);
+            }
+
+            // KeyUsage.encipherOnly and KeyUsage.decipherOnly are
+            // undefined in the absence of the keyAgreement bit.
+
+            if (!primitives.isEmpty()) {
+                if (!constraints.permits(primitives, currPubKey)) {
+                    throw new CertPathValidatorException(
+                        "algorithm constraints check failed");
+                }
+            }
+        }
+
+        // Check with previous cert for signature algorithm and public key
+        if (prevPubKey != null) {
+            if (currSigAlg != null) {
+                if (!constraints.permits(
+                        SIGNATURE_PRIMITIVE_SET,
+                        currSigAlg, prevPubKey, currSigAlgParams)) {
+                    throw new CertPathValidatorException(
+                        "Algorithm constraints check failed: " + currSigAlg);
+                }
+            }
+
+            // Inherit key parameters from previous key
+            if (currPubKey instanceof DSAPublicKey &&
+                ((DSAPublicKey)currPubKey).getParams() == null) {
+                // Inherit DSA parameters from previous key
+                if (!(prevPubKey instanceof DSAPublicKey)) {
+                    throw new CertPathValidatorException("Input key is not " +
+                         "of a appropriate type for inheriting parameters");
+                }
+
+                DSAParams params = ((DSAPublicKey)prevPubKey).getParams();
+                if (params == null) {
+                    throw new CertPathValidatorException(
+                                    "Key parameters missing");
+                }
+
+                try {
+                    BigInteger y = ((DSAPublicKey)currPubKey).getY();
+                    KeyFactory kf = KeyFactory.getInstance("DSA");
+                    DSAPublicKeySpec ks = new DSAPublicKeySpec(y,
+                                                       params.getP(),
+                                                       params.getQ(),
+                                                       params.getG());
+                    currPubKey = kf.generatePublic(ks);
+                } catch (GeneralSecurityException e) {
+                    throw new CertPathValidatorException("Unable to generate " +
+                        "key with inherited parameters: " + e.getMessage(), e);
+                }
+            }
+        }
+
+        // reset the previous public key
+        prevPubKey = currPubKey;
+
+        // check the extended key usage, ignore the check now
+        // List<String> extendedKeyUsages = x509Cert.getExtendedKeyUsage();
+
+        // DO NOT remove any unresolved critical extensions
     }
 
-    static void check(AlgorithmId aid) throws CertPathValidatorException {
-        check(aid.getName());
-    }
-
-    static void check(X509CRL crl) throws CertPathValidatorException {
-        check(crl.getSigAlgName());
-    }
+    /**
+     * Try to set the trust anchor of the checker.
+     * <p>
+     * If there is no trust anchor specified and the checker has not started,
+     * set the trust anchor.
+     *
+     * @param anchor the trust anchor selected to validate the target
+     *     certificate
+     */
+    void trySetTrustAnchor(TrustAnchor anchor) {
+        // Don't bother if the check has started or trust anchor has already
+        // specified.
+        if (prevPubKey == null) {
+            if (anchor == null) {
+                throw new IllegalArgumentException(
+                        "The trust anchor cannot be null");
+            }
 
-    private static void check(String algName)
-            throws CertPathValidatorException {
-
-        String lowerCaseAlgName = algName.toLowerCase(Locale.ENGLISH);
-
-        for (String disabled : disabledAlgorithms) {
-            // checking the signature algorithm name
-            if (lowerCaseAlgName.indexOf(disabled) != -1) {
-                throw new CertPathValidatorException(
-                    "algorithm check failed: " + algName + " is disabled");
+            // Don't bother to change the trustedPubKey.
+            if (anchor.getTrustedCert() != null) {
+                prevPubKey = anchor.getTrustedCert().getPublicKey();
+            } else {
+                prevPubKey = anchor.getCAPublicKey();
             }
         }
     }
 
+    /**
+     * Check the signature algorithm with the specified public key.
+     *
+     * @param key the public key to verify the CRL signature
+     * @param crl the target CRL
+     */
+    static void check(PublicKey key, X509CRL crl)
+                        throws CertPathValidatorException {
+
+        X509CRLImpl x509CRLImpl = null;
+        try {
+            x509CRLImpl = X509CRLImpl.toImpl(crl);
+        } catch (CRLException ce) {
+            throw new CertPathValidatorException(ce);
+        }
+
+        AlgorithmId algorithmId = x509CRLImpl.getSigAlgId();
+        check(key, algorithmId);
+    }
+
+    /**
+     * Check the signature algorithm with the specified public key.
+     *
+     * @param key the public key to verify the CRL signature
+     * @param crl the target CRL
+     */
+    static void check(PublicKey key, AlgorithmId algorithmId)
+                        throws CertPathValidatorException {
+        String sigAlgName = algorithmId.getName();
+        AlgorithmParameters sigAlgParams = algorithmId.getParameters();
+
+        if (!certPathDefaultConstraints.permits(
+                SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) {
+            throw new CertPathValidatorException(
+                "algorithm check failed: " + sigAlgName + " is disabled");
+        }
+    }
+
 }
+
--- a/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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
@@ -289,16 +289,6 @@
         X500Name certIssuer = (X500Name) certImpl.getIssuerDN();
         X500Name crlIssuer = (X500Name) crlImpl.getIssuerDN();
 
-        // check the crl signature algorithm
-        try {
-            AlgorithmChecker.check(crl);
-        } catch (CertPathValidatorException cpve) {
-            if (debug != null) {
-                debug.println("CRL signature algorithm check failed: " + cpve);
-            }
-            return false;
-        }
-
         // if crlIssuer is set, verify that it matches the issuer of the
         // CRL and the CRL contains an IDP extension with the indirectCRL
         // boolean asserted. Otherwise, verify that the CRL issuer matches the
@@ -637,6 +627,16 @@
             }
         }
 
+        // check the crl signature algorithm
+        try {
+            AlgorithmChecker.check(prevKey, crl);
+        } catch (CertPathValidatorException cpve) {
+            if (debug != null) {
+                debug.println("CRL signature algorithm check failed: " + cpve);
+            }
+            return false;
+        }
+
         // validate the signature on the CRL
         try {
             crl.verify(prevKey, provider);
--- a/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -719,11 +719,6 @@
         /* we don't perform any validation of the trusted cert */
         if (!isTrustedCert) {
             /*
-             * check that the signature algorithm is not disabled.
-             */
-            AlgorithmChecker.check(cert);
-
-            /*
              * Check CRITICAL private extensions for user checkers that
              * support forward checking (forwardCheckers) and remove
              * ones we know how to check.
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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
@@ -327,6 +327,10 @@
                 "(set using the OCSP security properties).");
         }
 
+        // The algorithm constraints of the OCSP trusted responder certificate
+        // does not need to be checked in this code. The constraints will be
+        // checked when the responder's certificate is validated.
+
         CertId certId = null;
         OCSPResponse response = null;
         try {
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
 import java.security.cert.CertificateParsingException;
 import java.security.cert.CertPathValidatorException;
 import java.security.cert.CRLReason;
+import java.security.cert.TrustAnchor;
 import java.security.cert.X509Certificate;
 import java.util.Collections;
 import java.util.Date;
@@ -371,6 +372,13 @@
                         "OCSP responses", cpe);
                 }
 
+                // Check algorithm constraints specified in security property
+                // "jdk.certpath.disabledAlgorithms".
+                AlgorithmChecker algChecker = new AlgorithmChecker(
+                                    new TrustAnchor(responderCert, null));
+                algChecker.init(false);
+                algChecker.check(cert, Collections.<String>emptySet());
+
                 // check the validity
                 try {
                     if (dateCheckedAgainst == null) {
@@ -422,6 +430,10 @@
         // Confirm that the signed response was generated using the public
         // key from the trusted responder cert
         if (responderCert != null) {
+            // Check algorithm constraints specified in security property
+            // "jdk.certpath.disabledAlgorithms".
+            AlgorithmChecker.check(responderCert.getPublicKey(), sigAlgId);
+
             if (!verifyResponse(responseDataDer, responderCert,
                 sigAlgId, signature)) {
                 throw new CertPathValidatorException(
--- a/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -275,7 +275,7 @@
         int certPathLen = certList.size();
 
         basicChecker = new BasicChecker(anchor, testDate, sigProvider, false);
-        AlgorithmChecker algorithmChecker= AlgorithmChecker.getInstance();
+        AlgorithmChecker algorithmChecker = new AlgorithmChecker(anchor);
         KeyChecker keyChecker = new KeyChecker(certPathLen,
             pkixParam.getTargetCertConstraints());
         ConstraintsChecker constraintsChecker =
--- a/jdk/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -347,9 +347,6 @@
             return;
         }
 
-        /* check that the signature algorithm is not disabled. */
-        AlgorithmChecker.check(cert);
-
         /*
          * check for looping - abort a loop if
          * ((we encounter the same certificate twice) AND
@@ -470,9 +467,16 @@
         if (unresolvedCritExts == null) {
             unresolvedCritExts = Collections.<String>emptySet();
         }
+
+        /*
+         * Check that the signature algorithm is not disabled.
+         */
+        currentState.algorithmChecker.check(cert, unresolvedCritExts);
+
         for (PKIXCertPathChecker checker : currentState.userCheckers) {
             checker.check(cert, unresolvedCritExts);
         }
+
         /*
          * Look at the remaining extensions and remove any ones we have
          * already checked. If there are any left, throw an exception!
--- a/jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -96,6 +96,9 @@
     /* the checker used for revocation status */
     public CrlRevocationChecker crlChecker;
 
+    /* the algorithm checker */
+    AlgorithmChecker algorithmChecker;
+
     /* the trust anchor used to validate the path */
     TrustAnchor trustAnchor;
 
@@ -241,6 +244,14 @@
             updateState(anchor.getCAPublicKey(), caName);
         }
 
+        // The user specified AlgorithmChecker may not be
+        // able to set the trust anchor until now.
+        for (PKIXCertPathChecker checker : userCheckers) {
+            if (checker instanceof AlgorithmChecker) {
+                ((AlgorithmChecker)checker).trySetTrustAnchor(anchor);
+            }
+        }
+
         init = false;
     }
 
--- a/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -302,6 +302,7 @@
             // init the crl checker
             currentState.crlChecker =
                 new CrlRevocationChecker(null, buildParams, null, onlyEECert);
+            currentState.algorithmChecker = new AlgorithmChecker(anchor);
             try {
                 depthFirstSearchReverse(null, currentState,
                 new ReverseBuilder(buildParams, targetSubjectDN), adjacencyList,
@@ -475,29 +476,41 @@
                 userCheckers.add(mustCheck, policyChecker);
                 mustCheck++;
 
+                // add the algorithm checker
+                userCheckers.add(mustCheck,
+                        new AlgorithmChecker(builder.trustAnchor));
+                mustCheck++;
+
                 if (nextState.keyParamsNeeded()) {
                     PublicKey rootKey = cert.getPublicKey();
                     if (builder.trustAnchor.getTrustedCert() == null) {
                         rootKey = builder.trustAnchor.getCAPublicKey();
                         if (debug != null)
-                            debug.println("SunCertPathBuilder.depthFirstSearchForward" +
-                                          " using buildParams public key: " +
-                                          rootKey.toString());
+                            debug.println(
+                                "SunCertPathBuilder.depthFirstSearchForward " +
+                                "using buildParams public key: " +
+                                rootKey.toString());
                     }
                     TrustAnchor anchor = new TrustAnchor
                         (cert.getSubjectX500Principal(), rootKey, null);
+
+                    // add the basic checker
                     basicChecker = new BasicChecker(anchor,
                                            builder.date,
                                            buildParams.getSigProvider(),
                                            true);
                     userCheckers.add(mustCheck, basicChecker);
                     mustCheck++;
+
+                    // add the crl revocation checker
                     if (buildParams.isRevocationEnabled()) {
                         userCheckers.add(mustCheck, new CrlRevocationChecker
                             (anchor, buildParams, null, onlyEECert));
                         mustCheck++;
                     }
                 }
+                // Why we don't need BasicChecker and CrlRevocationChecker
+                // if nextState.keyParamsNeeded() is false?
 
                 for (int i=0; i<appendedCerts.size(); i++) {
                     X509Certificate currCert = appendedCerts.get(i);
@@ -513,10 +526,18 @@
                     for (int j=0; j<userCheckers.size(); j++) {
                         PKIXCertPathChecker currChecker = userCheckers.get(j);
                         if (j < mustCheck ||
-                            !currChecker.isForwardCheckingSupported())
-                        {
+                            !currChecker.isForwardCheckingSupported()) {
                             if (i == 0) {
                                 currChecker.init(false);
+
+                                // The user specified
+                                // AlgorithmChecker may not be
+                                // able to set the trust anchor until now.
+                                if (j >= mustCheck &&
+                                    currChecker instanceof AlgorithmChecker) {
+                                    ((AlgorithmChecker)currChecker).
+                                        trySetTrustAnchor(builder.trustAnchor);
+                                }
                             }
 
                             try {
--- a/jdk/src/share/classes/sun/security/rsa/RSASignature.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/rsa/RSASignature.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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
@@ -49,7 +49,7 @@
 public abstract class RSASignature extends SignatureSpi {
 
     // we sign an ASN.1 SEQUENCE of AlgorithmId and digest
-    // it has the form 30:xx:30:0c:[digestOID]:05:00:04:xx:[digest]
+    // it has the form 30:xx:30:xx:[digestOID]:05:00:04:xx:[digest]
     // this means the encoded length is (8 + digestOID.length + digest.length)
     private static final int baseLength = 8;
 
@@ -104,7 +104,8 @@
     // initialize for signing. See JCA doc
     protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
             throws InvalidKeyException {
-        RSAPrivateKey rsaKey = (RSAPrivateKey)RSAKeyFactory.toRSAKey(privateKey);
+        RSAPrivateKey rsaKey =
+            (RSAPrivateKey)RSAKeyFactory.toRSAKey(privateKey);
         this.privateKey = rsaKey;
         this.publicKey = null;
         initCommon(rsaKey, random);
@@ -212,7 +213,8 @@
         DerOutputStream out = new DerOutputStream();
         new AlgorithmId(oid).encode(out);
         out.putOctetString(digest);
-        DerValue result = new DerValue(DerValue.tag_Sequence, out.toByteArray());
+        DerValue result =
+            new DerValue(DerValue.tag_Sequence, out.toByteArray());
         return result.toByteArray();
     }
 
@@ -229,7 +231,8 @@
         }
         AlgorithmId algId = AlgorithmId.parse(values[0]);
         if (algId.getOID().equals(oid) == false) {
-            throw new IOException("ObjectIdentifier mismatch: " + algId.getOID());
+            throw new IOException("ObjectIdentifier mismatch: "
+                + algId.getOID());
         }
         if (algId.getEncodedParams() != null) {
             throw new IOException("Unexpected AlgorithmId parameters");
--- a/jdk/src/share/classes/sun/security/ssl/CipherBox.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/CipherBox.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, 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
@@ -28,6 +28,7 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.util.Hashtable;
 
 import java.security.*;
 import javax.crypto.*;
@@ -50,6 +51,37 @@
  * Individual instances are obtained by calling the static method
  * newCipherBox(), which should only be invoked by BulkCipher.newCipher().
  *
+ * In RFC 2246, with bock ciphers in CBC mode, the Initialization
+ * Vector (IV) for the first record is generated with the other keys
+ * and secrets when the security parameters are set.  The IV for
+ * subsequent records is the last ciphertext block from the previous
+ * record.
+ *
+ * In RFC 4346, the implicit Initialization Vector (IV) is replaced
+ * with an explicit IV to protect against CBC attacks.  RFC 4346
+ * recommends two algorithms used to generated the per-record IV.
+ * The implementation uses the algorithm (2)(b), as described at
+ * section 6.2.3.2 of RFC 4346.
+ *
+ * The usage of IV in CBC block cipher can be illustrated in
+ * the following diagrams.
+ *
+ *   (random)
+ *        R         P1                    IV        C1
+ *        |          |                     |         |
+ *  SIV---+    |-----+    |-...            |-----    |------
+ *        |    |     |    |                |    |    |     |
+ *     +----+  |  +----+  |             +----+  |  +----+  |
+ *     | Ek |  |  + Ek +  |             | Dk |  |  | Dk |  |
+ *     +----+  |  +----+  |             +----+  |  +----+  |
+ *        |    |     |    |                |    |    |     |
+ *        |----|     |----|           SIV--+    |----|     |-...
+ *        |          |                     |       |
+ *       IV         C1                     R      P1
+ *                                     (discard)
+ *
+ *       CBC Encryption                    CBC Decryption
+ *
  * NOTE that any ciphering involved in key exchange (e.g. with RSA) is
  * handled separately.
  *
@@ -76,6 +108,21 @@
     private int blockSize;
 
     /**
+     * secure random
+     */
+    private SecureRandom random;
+
+    /**
+     * Fixed masks of various block size, as the initial decryption IVs
+     * for TLS 1.1 or later.
+     *
+     * For performance, we do not use random IVs. As the initial decryption
+     * IVs will be discarded by TLS decryption processes, so the fixed masks
+     * do not hurt cryptographic strength.
+     */
+    private static Hashtable<Integer, IvParameterSpec> masks;
+
+    /**
      * NULL cipherbox. Identity operation, no encryption.
      */
     private CipherBox() {
@@ -90,14 +137,37 @@
      * implementation could be found.
      */
     private CipherBox(ProtocolVersion protocolVersion, BulkCipher bulkCipher,
-            SecretKey key,  IvParameterSpec iv, boolean encrypt)
-            throws NoSuchAlgorithmException {
+            SecretKey key, IvParameterSpec iv, SecureRandom random,
+            boolean encrypt) throws NoSuchAlgorithmException {
         try {
             this.protocolVersion = protocolVersion;
             this.cipher = JsseJce.getCipher(bulkCipher.transformation);
             int mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
-            cipher.init(mode, key, iv);
-            // do not call getBlockSize until after init()
+
+            if (random == null) {
+                random = JsseJce.getSecureRandom();
+            }
+            this.random = random;
+
+            /*
+             * RFC 4346 recommends two algorithms used to generated the
+             * per-record IV. The implementation uses the algorithm (2)(b),
+             * as described at section 6.2.3.2 of RFC 4346.
+             *
+             * As we don't care about the initial IV value for TLS 1.1 or
+             * later, so if the "iv" parameter is null, we use the default
+             * value generated by Cipher.init() for encryption, and a fixed
+             * mask for decryption.
+             */
+            if (iv == null && bulkCipher.ivSize != 0 &&
+                    mode == Cipher.DECRYPT_MODE &&
+                    protocolVersion.v >= ProtocolVersion.TLS11.v) {
+                iv = getFixedMask(bulkCipher.ivSize);
+            }
+
+            cipher.init(mode, key, iv, random);
+
+            // Do not call getBlockSize until after init()
             // otherwise we would disrupt JCE delayed provider selection
             blockSize = cipher.getBlockSize();
             // some providers implement getBlockSize() incorrectly
@@ -119,19 +189,37 @@
      * Factory method to obtain a new CipherBox object.
      */
     static CipherBox newCipherBox(ProtocolVersion version, BulkCipher cipher,
-            SecretKey key, IvParameterSpec iv, boolean encrypt)
-            throws NoSuchAlgorithmException {
+            SecretKey key, IvParameterSpec iv, SecureRandom random,
+            boolean encrypt) throws NoSuchAlgorithmException {
         if (cipher.allowed == false) {
             throw new NoSuchAlgorithmException("Unsupported cipher " + cipher);
         }
+
         if (cipher == B_NULL) {
             return NULL;
         } else {
-            return new CipherBox(version, cipher, key, iv, encrypt);
+            return new CipherBox(version, cipher, key, iv, random, encrypt);
         }
     }
 
     /*
+     * Get a fixed mask, as the initial decryption IVs for TLS 1.1 or later.
+     */
+    private static IvParameterSpec getFixedMask(int ivSize) {
+        if (masks == null) {
+            masks = new Hashtable<Integer, IvParameterSpec>(5);
+        }
+
+        IvParameterSpec iv = masks.get(ivSize);
+        if (iv == null) {
+            iv = new IvParameterSpec(new byte[ivSize]);
+            masks.put(ivSize, iv);
+        }
+
+        return iv;
+    }
+
+    /*
      * Encrypts a block of data, returning the size of the
      * resulting block.
      */
@@ -139,8 +227,26 @@
         if (cipher == null) {
             return len;
         }
+
         try {
             if (blockSize != 0) {
+                // TLSv1.1 needs a IV block
+                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
+                    // generate a random number
+                    byte[] prefix = new byte[blockSize];
+                    random.nextBytes(prefix);
+
+                    // move forward the plaintext
+                    System.arraycopy(buf, offset,
+                                     buf, offset + prefix.length, len);
+
+                    // prefix the plaintext
+                    System.arraycopy(prefix, 0,
+                                     buf, offset, prefix.length);
+
+                    len += prefix.length;
+                }
+
                 len = addPadding(buf, offset, len, blockSize);
             }
             if (debug != null && Debug.isOn("plaintext")) {
@@ -189,6 +295,34 @@
             int pos = bb.position();
 
             if (blockSize != 0) {
+                // TLSv1.1 needs a IV block
+                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
+                    // generate a random number
+                    byte[] prefix = new byte[blockSize];
+                    random.nextBytes(prefix);
+
+                    // move forward the plaintext
+                    byte[] buf = null;
+                    int limit = bb.limit();
+                    if (bb.hasArray()) {
+                        buf = bb.array();
+                        System.arraycopy(buf, pos,
+                                buf, pos + prefix.length, limit - pos);
+                        bb.limit(limit + prefix.length);
+                    } else {
+                        buf = new byte[limit - pos];
+                        bb.get(buf, 0, limit - pos);
+                        bb.position(pos + prefix.length);
+                        bb.limit(limit + prefix.length);
+                        bb.put(buf);
+                    }
+                    bb.position(pos);
+
+                    // prefix the plaintext
+                    bb.put(prefix);
+                    bb.position(pos);
+                }
+
                 // addPadding adjusts pos/limit
                 len = addPadding(bb, blockSize);
                 bb.position(pos);
@@ -236,11 +370,25 @@
     /*
      * Decrypts a block of data, returning the size of the
      * resulting block if padding was required.
+     *
+     * For SSLv3 and TLSv1.0, with block ciphers in CBC mode the
+     * Initialization Vector (IV) for the first record is generated by
+     * the handshake protocol, the IV for subsequent records is the
+     * last ciphertext block from the previous record.
+     *
+     * From TLSv1.1, the implicit IV is replaced with an explicit IV to
+     * protect against CBC attacks.
+     *
+     * Differentiating between bad_record_mac and decryption_failed alerts
+     * may permit certain attacks against CBC mode. It is preferable to
+     * uniformly use the bad_record_mac alert to hide the specific type of
+     * the error.
      */
     int decrypt(byte[] buf, int offset, int len) throws BadPaddingException {
         if (cipher == null) {
             return len;
         }
+
         try {
             int newLen = cipher.update(buf, offset, len, buf, offset);
             if (newLen != len) {
@@ -263,6 +411,18 @@
             if (blockSize != 0) {
                 newLen = removePadding(buf, offset, newLen,
                              blockSize, protocolVersion);
+
+                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
+                    if (newLen < blockSize) {
+                        throw new BadPaddingException("invalid explicit IV");
+                    }
+
+                    // discards the first cipher block, the IV component.
+                    System.arraycopy(buf, offset + blockSize,
+                                     buf, offset, newLen - blockSize);
+
+                    newLen -= blockSize;
+                }
             }
             return newLen;
         } catch (ShortBufferException e) {
@@ -277,6 +437,8 @@
      * point to the end of the decrypted/depadded data.  The initial
      * limit and new limit may be different, given we may
      * have stripped off some padding bytes.
+     *
+     *  @see decrypt(byte[], int, int)
      */
     int decrypt(ByteBuffer bb) throws BadPaddingException {
 
@@ -292,7 +454,6 @@
              * Decrypt "in-place".
              */
             int pos = bb.position();
-
             ByteBuffer dup = bb.duplicate();
             int newLen = cipher.update(dup, bb);
             if (newLen != len) {
@@ -320,6 +481,33 @@
             if (blockSize != 0) {
                 bb.position(pos);
                 newLen = removePadding(bb, blockSize, protocolVersion);
+
+                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
+                    if (newLen < blockSize) {
+                        throw new BadPaddingException("invalid explicit IV");
+                    }
+
+                    // discards the first cipher block, the IV component.
+                    byte[] buf = null;
+                    int limit = bb.limit();
+                    if (bb.hasArray()) {
+                        buf = bb.array();
+                        System.arraycopy(buf, pos + blockSize,
+                                         buf, pos, limit - pos - blockSize);
+                        bb.limit(limit - blockSize);
+                    } else {
+                        buf = new byte[limit - pos - blockSize];
+                        bb.position(pos + blockSize);
+                        bb.get(buf);
+                        bb.position(pos);
+                        bb.put(buf);
+                        bb.limit(limit - blockSize);
+                    }
+
+                    // reset the position to the end of the decrypted data
+                    limit = bb.limit();
+                    bb.position(limit);
+                }
             }
             return newLen;
         } catch (ShortBufferException e) {
--- a/jdk/src/share/classes/sun/security/ssl/CipherSuite.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/CipherSuite.java	Wed Jul 05 17:26:57 2017 +0200
@@ -30,6 +30,7 @@
 
 import java.security.NoSuchAlgorithmException;
 import java.security.InvalidKeyException;
+import java.security.SecureRandom;
 
 import javax.crypto.SecretKey;
 import javax.crypto.spec.IvParameterSpec;
@@ -37,6 +38,7 @@
 
 import sun.security.ssl.CipherSuite.*;
 import static sun.security.ssl.CipherSuite.KeyExchange.*;
+import static sun.security.ssl.CipherSuite.PRF.*;
 import static sun.security.ssl.JsseJce.*;
 
 /**
@@ -101,19 +103,32 @@
     // by default
     final int priority;
 
-    // key exchange, bulk cipher, and mac algorithms. See those classes below.
+    // key exchange, bulk cipher, mac and prf algorithms. See those
+    // classes below.
     final KeyExchange keyExchange;
     final BulkCipher cipher;
     final MacAlg macAlg;
+    final PRF prfAlg;
 
     // whether a CipherSuite qualifies as exportable under 512/40 bit rules.
+    // TLS 1.1+ (RFC 4346) must not negotiate to these suites.
     final boolean exportable;
 
     // true iff implemented and enabled at compile time
     final boolean allowed;
 
+    // obsoleted since protocol version
+    final int obsoleted;
+
+    // supported since protocol version
+    final int supported;
+
+    /**
+     * Constructor for implemented CipherSuites.
+     */
     private CipherSuite(String name, int id, int priority,
-            KeyExchange keyExchange, BulkCipher cipher, boolean allowed) {
+            KeyExchange keyExchange, BulkCipher cipher,
+            boolean allowed, int obsoleted, int supported, PRF prfAlg) {
         this.name = name;
         this.id = id;
         this.priority = priority;
@@ -124,6 +139,10 @@
             macAlg = M_MD5;
         } else if (name.endsWith("_SHA")) {
             macAlg = M_SHA;
+        } else if (name.endsWith("_SHA256")) {
+            macAlg = M_SHA256;
+        } else if (name.endsWith("_SHA384")) {
+            macAlg = M_SHA384;
         } else if (name.endsWith("_NULL")) {
             macAlg = M_NULL;
         } else if (name.endsWith("_SCSV")) {
@@ -136,8 +155,14 @@
         allowed &= keyExchange.allowed;
         allowed &= cipher.allowed;
         this.allowed = allowed;
+        this.obsoleted = obsoleted;
+        this.supported = supported;
+        this.prfAlg = prfAlg;
     }
 
+    /**
+     * Constructor for unimplemented CipherSuites.
+     */
     private CipherSuite(String name, int id) {
         this.name = name;
         this.id = id;
@@ -148,6 +173,9 @@
         this.cipher = null;
         this.macAlg = null;
         this.exportable = false;
+        this.obsoleted = ProtocolVersion.LIMIT_MAX_VALUE;
+        this.supported = ProtocolVersion.LIMIT_MIN_VALUE;
+        this.prfAlg = P_NONE;
     }
 
     /**
@@ -197,10 +225,12 @@
         if (s == null) {
             throw new IllegalArgumentException("Name must not be null");
         }
+
         CipherSuite c = nameMap.get(s);
         if ((c == null) || (c.allowed == false)) {
             throw new IllegalArgumentException("Unsupported ciphersuite " + s);
         }
+
         return c;
     }
 
@@ -227,10 +257,17 @@
         return nameMap.values();
     }
 
+    /*
+     * Use this method when all of the values need to be specified.
+     * This is primarily used when defining a new ciphersuite for
+     * TLS 1.2+ that doesn't use the "default" PRF.
+     */
     private static void add(String name, int id, int priority,
-            KeyExchange keyExchange, BulkCipher cipher, boolean allowed) {
+            KeyExchange keyExchange, BulkCipher cipher,
+            boolean allowed, int obsoleted, int supported, PRF prf) {
+
         CipherSuite c = new CipherSuite(name, id, priority, keyExchange,
-                                        cipher, allowed);
+            cipher, allowed, obsoleted, supported, prf);
         if (idMap.put(id, c) != null) {
             throw new RuntimeException("Duplicate ciphersuite definition: "
                                         + id + ", " + name);
@@ -243,6 +280,41 @@
         }
     }
 
+    /*
+     * Use this method when there is no lower protocol limit where this
+     * suite can be used, and the PRF is P_SHA256.  That is, the
+     * existing ciphersuites.  From RFC 5246:
+     *
+     *     All cipher suites in this document use P_SHA256.
+     */
+    private static void add(String name, int id, int priority,
+            KeyExchange keyExchange, BulkCipher cipher,
+            boolean allowed, int obsoleted) {
+        // If this is an obsoleted suite, then don't let the TLS 1.2
+        // protocol have a valid PRF value.
+        PRF prf = P_SHA256;
+        if (obsoleted < ProtocolVersion.TLS12.v) {
+            prf = P_NONE;
+        }
+
+        add(name, id, priority, keyExchange, cipher, allowed, obsoleted,
+            ProtocolVersion.LIMIT_MIN_VALUE, prf);
+    }
+
+    /*
+     * Use this method when there is no upper protocol limit.  That is,
+     * suites which have not been obsoleted.
+     */
+    private static void add(String name, int id, int priority,
+            KeyExchange keyExchange, BulkCipher cipher, boolean allowed) {
+        add(name, id, priority, keyExchange,
+            cipher, allowed, ProtocolVersion.LIMIT_MAX_VALUE);
+    }
+
+    /*
+     * Use this method to define an unimplemented suite.  This provides
+     * a number<->name mapping that can be used for debugging.
+     */
     private static void add(String name, int id) {
         CipherSuite c = new CipherSuite(name, id);
         if (idMap.put(id, c) != null) {
@@ -380,10 +452,11 @@
          *
          * @exception NoSuchAlgorithmException if anything goes wrong
          */
-        CipherBox newCipher(ProtocolVersion version,
-                SecretKey key, IvParameterSpec iv,
+        CipherBox newCipher(ProtocolVersion version, SecretKey key,
+                IvParameterSpec iv, SecureRandom random,
                 boolean encrypt) throws NoSuchAlgorithmException {
-            return CipherBox.newCipherBox(version, this, key, iv, encrypt);
+            return CipherBox.newCipherBox(version, this,
+                                            key, iv, random, encrypt);
         }
 
         /**
@@ -402,6 +475,7 @@
             if (this == B_AES_256) {
                 return isAvailable(this);
             }
+
             // always available
             return true;
         }
@@ -421,7 +495,8 @@
                         (new byte[cipher.expandedKeySize], cipher.algorithm);
                     IvParameterSpec iv =
                         new IvParameterSpec(new byte[cipher.ivSize]);
-                    cipher.newCipher(ProtocolVersion.DEFAULT, key, iv, true);
+                    cipher.newCipher(ProtocolVersion.DEFAULT,
+                                                key, iv, null, true);
                     b = Boolean.TRUE;
                 } catch (NoSuchAlgorithmException e) {
                     b = Boolean.FALSE;
@@ -439,7 +514,7 @@
     /**
      * An SSL/TLS key MAC algorithm.
      *
-     * Also contains a factory method to obtain in initialized MAC
+     * Also contains a factory method to obtain an initialized MAC
      * for this algorithm.
      */
     final static class MacAlg {
@@ -499,6 +574,48 @@
     final static MacAlg M_NULL = new MacAlg("NULL", 0);
     final static MacAlg M_MD5  = new MacAlg("MD5", 16);
     final static MacAlg M_SHA  = new MacAlg("SHA", 20);
+    final static MacAlg M_SHA256  = new MacAlg("SHA256", 32);
+    final static MacAlg M_SHA384  = new MacAlg("SHA384", 48);
+
+    // PRFs (PseudoRandom Function) from TLS specifications.
+    //
+    // TLS 1.1- uses a single MD5/SHA1-based PRF algorithm for generating
+    // the necessary material.
+    //
+    // In TLS 1.2+, all existing/known CipherSuites use SHA256, however
+    // new Ciphersuites (e.g. RFC 5288) can define specific PRF hash
+    // algorithms.
+    static enum PRF {
+
+        // PRF algorithms
+        P_NONE(     "NONE",  0,   0),
+        P_SHA256("SHA-256", 32,  64),
+        P_SHA384("SHA-384", 48, 128),
+        P_SHA512("SHA-512", 64, 128);  // not currently used.
+
+        // PRF characteristics
+        private final String prfHashAlg;
+        private final int prfHashLength;
+        private final int prfBlockSize;
+
+        PRF(String prfHashAlg, int prfHashLength, int prfBlockSize) {
+            this.prfHashAlg = prfHashAlg;
+            this.prfHashLength = prfHashLength;
+            this.prfBlockSize = prfBlockSize;
+        }
+
+        String getPRFHashAlg() {
+            return prfHashAlg;
+        }
+
+        int getPRFHashLength() {
+            return prfHashLength;
+        }
+
+        int getPRFBlockSize() {
+            return prfBlockSize;
+        }
+    }
 
     static {
         idMap = new HashMap<Integer,CipherSuite>();
@@ -509,6 +626,239 @@
         // N: ciphersuites only allowed if we are not in FIPS mode
         final boolean N = (SunJSSE.isFIPS() == false);
 
+        /*
+         * TLS Cipher Suite Registry, as of August 2010.
+         *
+         * http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
+         *
+         * Range      Registration Procedures   Notes
+         * 000-191    Standards Action          Refers to value of first byte
+         * 192-254    Specification Required    Refers to value of first byte
+         * 255        Reserved for Private Use  Refers to value of first byte
+         *
+         * Value      Description                               Reference
+         * 0x00,0x00  TLS_NULL_WITH_NULL_NULL                   [RFC5246]
+         * 0x00,0x01  TLS_RSA_WITH_NULL_MD5                     [RFC5246]
+         * 0x00,0x02  TLS_RSA_WITH_NULL_SHA                     [RFC5246]
+         * 0x00,0x03  TLS_RSA_EXPORT_WITH_RC4_40_MD5            [RFC4346]
+         * 0x00,0x04  TLS_RSA_WITH_RC4_128_MD5                  [RFC5246]
+         * 0x00,0x05  TLS_RSA_WITH_RC4_128_SHA                  [RFC5246]
+         * 0x00,0x06  TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5        [RFC4346]
+         * 0x00,0x07  TLS_RSA_WITH_IDEA_CBC_SHA                 [RFC5469]
+         * 0x00,0x08  TLS_RSA_EXPORT_WITH_DES40_CBC_SHA         [RFC4346]
+         * 0x00,0x09  TLS_RSA_WITH_DES_CBC_SHA                  [RFC5469]
+         * 0x00,0x0A  TLS_RSA_WITH_3DES_EDE_CBC_SHA             [RFC5246]
+         * 0x00,0x0B  TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA      [RFC4346]
+         * 0x00,0x0C  TLS_DH_DSS_WITH_DES_CBC_SHA               [RFC5469]
+         * 0x00,0x0D  TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA          [RFC5246]
+         * 0x00,0x0E  TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA      [RFC4346]
+         * 0x00,0x0F  TLS_DH_RSA_WITH_DES_CBC_SHA               [RFC5469]
+         * 0x00,0x10  TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA          [RFC5246]
+         * 0x00,0x11  TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA     [RFC4346]
+         * 0x00,0x12  TLS_DHE_DSS_WITH_DES_CBC_SHA              [RFC5469]
+         * 0x00,0x13  TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA         [RFC5246]
+         * 0x00,0x14  TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA     [RFC4346]
+         * 0x00,0x15  TLS_DHE_RSA_WITH_DES_CBC_SHA              [RFC5469]
+         * 0x00,0x16  TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA         [RFC5246]
+         * 0x00,0x17  TLS_DH_anon_EXPORT_WITH_RC4_40_MD5        [RFC4346]
+         * 0x00,0x18  TLS_DH_anon_WITH_RC4_128_MD5              [RFC5246]
+         * 0x00,0x19  TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA     [RFC4346]
+         * 0x00,0x1A  TLS_DH_anon_WITH_DES_CBC_SHA              [RFC5469]
+         * 0x00,0x1B  TLS_DH_anon_WITH_3DES_EDE_CBC_SHA         [RFC5246]
+         * 0x00,0x1C-1D Reserved to avoid conflicts with SSLv3  [RFC5246]
+         * 0x00,0x1E  TLS_KRB5_WITH_DES_CBC_SHA                 [RFC2712]
+         * 0x00,0x1F  TLS_KRB5_WITH_3DES_EDE_CBC_SHA            [RFC2712]
+         * 0x00,0x20  TLS_KRB5_WITH_RC4_128_SHA                 [RFC2712]
+         * 0x00,0x21  TLS_KRB5_WITH_IDEA_CBC_SHA                [RFC2712]
+         * 0x00,0x22  TLS_KRB5_WITH_DES_CBC_MD5                 [RFC2712]
+         * 0x00,0x23  TLS_KRB5_WITH_3DES_EDE_CBC_MD5            [RFC2712]
+         * 0x00,0x24  TLS_KRB5_WITH_RC4_128_MD5                 [RFC2712]
+         * 0x00,0x25  TLS_KRB5_WITH_IDEA_CBC_MD5                [RFC2712]
+         * 0x00,0x26  TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA       [RFC2712]
+         * 0x00,0x27  TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA       [RFC2712]
+         * 0x00,0x28  TLS_KRB5_EXPORT_WITH_RC4_40_SHA           [RFC2712]
+         * 0x00,0x29  TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5       [RFC2712]
+         * 0x00,0x2A  TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5       [RFC2712]
+         * 0x00,0x2B  TLS_KRB5_EXPORT_WITH_RC4_40_MD5           [RFC2712]
+         * 0x00,0x2C  TLS_PSK_WITH_NULL_SHA                     [RFC4785]
+         * 0x00,0x2D  TLS_DHE_PSK_WITH_NULL_SHA                 [RFC4785]
+         * 0x00,0x2E  TLS_RSA_PSK_WITH_NULL_SHA                 [RFC4785]
+         * 0x00,0x2F  TLS_RSA_WITH_AES_128_CBC_SHA              [RFC5246]
+         * 0x00,0x30  TLS_DH_DSS_WITH_AES_128_CBC_SHA           [RFC5246]
+         * 0x00,0x31  TLS_DH_RSA_WITH_AES_128_CBC_SHA           [RFC5246]
+         * 0x00,0x32  TLS_DHE_DSS_WITH_AES_128_CBC_SHA          [RFC5246]
+         * 0x00,0x33  TLS_DHE_RSA_WITH_AES_128_CBC_SHA          [RFC5246]
+         * 0x00,0x34  TLS_DH_anon_WITH_AES_128_CBC_SHA          [RFC5246]
+         * 0x00,0x35  TLS_RSA_WITH_AES_256_CBC_SHA              [RFC5246]
+         * 0x00,0x36  TLS_DH_DSS_WITH_AES_256_CBC_SHA           [RFC5246]
+         * 0x00,0x37  TLS_DH_RSA_WITH_AES_256_CBC_SHA           [RFC5246]
+         * 0x00,0x38  TLS_DHE_DSS_WITH_AES_256_CBC_SHA          [RFC5246]
+         * 0x00,0x39  TLS_DHE_RSA_WITH_AES_256_CBC_SHA          [RFC5246]
+         * 0x00,0x3A  TLS_DH_anon_WITH_AES_256_CBC_SHA          [RFC5246]
+         * 0x00,0x3B  TLS_RSA_WITH_NULL_SHA256                  [RFC5246]
+         * 0x00,0x3C  TLS_RSA_WITH_AES_128_CBC_SHA256           [RFC5246]
+         * 0x00,0x3D  TLS_RSA_WITH_AES_256_CBC_SHA256           [RFC5246]
+         * 0x00,0x3E  TLS_DH_DSS_WITH_AES_128_CBC_SHA256        [RFC5246]
+         * 0x00,0x3F  TLS_DH_RSA_WITH_AES_128_CBC_SHA256        [RFC5246]
+         * 0x00,0x40  TLS_DHE_DSS_WITH_AES_128_CBC_SHA256       [RFC5246]
+         * 0x00,0x41  TLS_RSA_WITH_CAMELLIA_128_CBC_SHA         [RFC5932]
+         * 0x00,0x42  TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA      [RFC5932]
+         * 0x00,0x43  TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA      [RFC5932]
+         * 0x00,0x44  TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA     [RFC5932]
+         * 0x00,0x45  TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA     [RFC5932]
+         * 0x00,0x46  TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA     [RFC5932]
+         * 0x00,0x47-4F Reserved to avoid conflicts with
+         *            deployed implementations                  [Pasi_Eronen]
+         * 0x00,0x50-58 Reserved to avoid conflicts             [Pasi Eronen]
+         * 0x00,0x59-5C Reserved to avoid conflicts with
+         *            deployed implementations                  [Pasi_Eronen]
+         * 0x00,0x5D-5F Unassigned
+         * 0x00,0x60-66 Reserved to avoid conflicts with widely
+         *            deployed implementations                  [Pasi_Eronen]
+         * 0x00,0x67  TLS_DHE_RSA_WITH_AES_128_CBC_SHA256       [RFC5246]
+         * 0x00,0x68  TLS_DH_DSS_WITH_AES_256_CBC_SHA256        [RFC5246]
+         * 0x00,0x69  TLS_DH_RSA_WITH_AES_256_CBC_SHA256        [RFC5246]
+         * 0x00,0x6A  TLS_DHE_DSS_WITH_AES_256_CBC_SHA256       [RFC5246]
+         * 0x00,0x6B  TLS_DHE_RSA_WITH_AES_256_CBC_SHA256       [RFC5246]
+         * 0x00,0x6C  TLS_DH_anon_WITH_AES_128_CBC_SHA256       [RFC5246]
+         * 0x00,0x6D  TLS_DH_anon_WITH_AES_256_CBC_SHA256       [RFC5246]
+         * 0x00,0x6E-83 Unassigned
+         * 0x00,0x84  TLS_RSA_WITH_CAMELLIA_256_CBC_SHA         [RFC5932]
+         * 0x00,0x85  TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA      [RFC5932]
+         * 0x00,0x86  TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA      [RFC5932]
+         * 0x00,0x87  TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA     [RFC5932]
+         * 0x00,0x88  TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA     [RFC5932]
+         * 0x00,0x89  TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA     [RFC5932]
+         * 0x00,0x8A  TLS_PSK_WITH_RC4_128_SHA                  [RFC4279]
+         * 0x00,0x8B  TLS_PSK_WITH_3DES_EDE_CBC_SHA             [RFC4279]
+         * 0x00,0x8C  TLS_PSK_WITH_AES_128_CBC_SHA              [RFC4279]
+         * 0x00,0x8D  TLS_PSK_WITH_AES_256_CBC_SHA              [RFC4279]
+         * 0x00,0x8E  TLS_DHE_PSK_WITH_RC4_128_SHA              [RFC4279]
+         * 0x00,0x8F  TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA         [RFC4279]
+         * 0x00,0x90  TLS_DHE_PSK_WITH_AES_128_CBC_SHA          [RFC4279]
+         * 0x00,0x91  TLS_DHE_PSK_WITH_AES_256_CBC_SHA          [RFC4279]
+         * 0x00,0x92  TLS_RSA_PSK_WITH_RC4_128_SHA              [RFC4279]
+         * 0x00,0x93  TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA         [RFC4279]
+         * 0x00,0x94  TLS_RSA_PSK_WITH_AES_128_CBC_SHA          [RFC4279]
+         * 0x00,0x95  TLS_RSA_PSK_WITH_AES_256_CBC_SHA          [RFC4279]
+         * 0x00,0x96  TLS_RSA_WITH_SEED_CBC_SHA                 [RFC4162]
+         * 0x00,0x97  TLS_DH_DSS_WITH_SEED_CBC_SHA              [RFC4162]
+         * 0x00,0x98  TLS_DH_RSA_WITH_SEED_CBC_SHA              [RFC4162]
+         * 0x00,0x99  TLS_DHE_DSS_WITH_SEED_CBC_SHA             [RFC4162]
+         * 0x00,0x9A  TLS_DHE_RSA_WITH_SEED_CBC_SHA             [RFC4162]
+         * 0x00,0x9B  TLS_DH_anon_WITH_SEED_CBC_SHA             [RFC4162]
+         * 0x00,0x9C  TLS_RSA_WITH_AES_128_GCM_SHA256           [RFC5288]
+         * 0x00,0x9D  TLS_RSA_WITH_AES_256_GCM_SHA384           [RFC5288]
+         * 0x00,0x9E  TLS_DHE_RSA_WITH_AES_128_GCM_SHA256       [RFC5288]
+         * 0x00,0x9F  TLS_DHE_RSA_WITH_AES_256_GCM_SHA384       [RFC5288]
+         * 0x00,0xA0  TLS_DH_RSA_WITH_AES_128_GCM_SHA256        [RFC5288]
+         * 0x00,0xA1  TLS_DH_RSA_WITH_AES_256_GCM_SHA384        [RFC5288]
+         * 0x00,0xA2  TLS_DHE_DSS_WITH_AES_128_GCM_SHA256       [RFC5288]
+         * 0x00,0xA3  TLS_DHE_DSS_WITH_AES_256_GCM_SHA384       [RFC5288]
+         * 0x00,0xA4  TLS_DH_DSS_WITH_AES_128_GCM_SHA256        [RFC5288]
+         * 0x00,0xA5  TLS_DH_DSS_WITH_AES_256_GCM_SHA384        [RFC5288]
+         * 0x00,0xA6  TLS_DH_anon_WITH_AES_128_GCM_SHA256       [RFC5288]
+         * 0x00,0xA7  TLS_DH_anon_WITH_AES_256_GCM_SHA384       [RFC5288]
+         * 0x00,0xA8  TLS_PSK_WITH_AES_128_GCM_SHA256           [RFC5487]
+         * 0x00,0xA9  TLS_PSK_WITH_AES_256_GCM_SHA384           [RFC5487]
+         * 0x00,0xAA  TLS_DHE_PSK_WITH_AES_128_GCM_SHA256       [RFC5487]
+         * 0x00,0xAB  TLS_DHE_PSK_WITH_AES_256_GCM_SHA384       [RFC5487]
+         * 0x00,0xAC  TLS_RSA_PSK_WITH_AES_128_GCM_SHA256       [RFC5487]
+         * 0x00,0xAD  TLS_RSA_PSK_WITH_AES_256_GCM_SHA384       [RFC5487]
+         * 0x00,0xAE  TLS_PSK_WITH_AES_128_CBC_SHA256           [RFC5487]
+         * 0x00,0xAF  TLS_PSK_WITH_AES_256_CBC_SHA384           [RFC5487]
+         * 0x00,0xB0  TLS_PSK_WITH_NULL_SHA256                  [RFC5487]
+         * 0x00,0xB1  TLS_PSK_WITH_NULL_SHA384                  [RFC5487]
+         * 0x00,0xB2  TLS_DHE_PSK_WITH_AES_128_CBC_SHA256       [RFC5487]
+         * 0x00,0xB3  TLS_DHE_PSK_WITH_AES_256_CBC_SHA384       [RFC5487]
+         * 0x00,0xB4  TLS_DHE_PSK_WITH_NULL_SHA256              [RFC5487]
+         * 0x00,0xB5  TLS_DHE_PSK_WITH_NULL_SHA384              [RFC5487]
+         * 0x00,0xB6  TLS_RSA_PSK_WITH_AES_128_CBC_SHA256       [RFC5487]
+         * 0x00,0xB7  TLS_RSA_PSK_WITH_AES_256_CBC_SHA384       [RFC5487]
+         * 0x00,0xB8  TLS_RSA_PSK_WITH_NULL_SHA256              [RFC5487]
+         * 0x00,0xB9  TLS_RSA_PSK_WITH_NULL_SHA384              [RFC5487]
+         * 0x00,0xBA  TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256      [RFC5932]
+         * 0x00,0xBB  TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256   [RFC5932]
+         * 0x00,0xBC  TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256   [RFC5932]
+         * 0x00,0xBD  TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256  [RFC5932]
+         * 0x00,0xBE  TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256  [RFC5932]
+         * 0x00,0xBF  TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256  [RFC5932]
+         * 0x00,0xC0  TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256      [RFC5932]
+         * 0x00,0xC1  TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256   [RFC5932]
+         * 0x00,0xC2  TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256   [RFC5932]
+         * 0x00,0xC3  TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256  [RFC5932]
+         * 0x00,0xC4  TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256  [RFC5932]
+         * 0x00,0xC5  TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256  [RFC5932]
+         * 0x00,0xC6-FE         Unassigned
+         * 0x00,0xFF  TLS_EMPTY_RENEGOTIATION_INFO_SCSV         [RFC5746]
+         * 0x01-BF,*  Unassigned
+         * 0xC0,0x01  TLS_ECDH_ECDSA_WITH_NULL_SHA              [RFC4492]
+         * 0xC0,0x02  TLS_ECDH_ECDSA_WITH_RC4_128_SHA           [RFC4492]
+         * 0xC0,0x03  TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA      [RFC4492]
+         * 0xC0,0x04  TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA       [RFC4492]
+         * 0xC0,0x05  TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA       [RFC4492]
+         * 0xC0,0x06  TLS_ECDHE_ECDSA_WITH_NULL_SHA             [RFC4492]
+         * 0xC0,0x07  TLS_ECDHE_ECDSA_WITH_RC4_128_SHA          [RFC4492]
+         * 0xC0,0x08  TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA     [RFC4492]
+         * 0xC0,0x09  TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA      [RFC4492]
+         * 0xC0,0x0A  TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA      [RFC4492]
+         * 0xC0,0x0B  TLS_ECDH_RSA_WITH_NULL_SHA                [RFC4492]
+         * 0xC0,0x0C  TLS_ECDH_RSA_WITH_RC4_128_SHA             [RFC4492]
+         * 0xC0,0x0D  TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA        [RFC4492]
+         * 0xC0,0x0E  TLS_ECDH_RSA_WITH_AES_128_CBC_SHA         [RFC4492]
+         * 0xC0,0x0F  TLS_ECDH_RSA_WITH_AES_256_CBC_SHA         [RFC4492]
+         * 0xC0,0x10  TLS_ECDHE_RSA_WITH_NULL_SHA               [RFC4492]
+         * 0xC0,0x11  TLS_ECDHE_RSA_WITH_RC4_128_SHA            [RFC4492]
+         * 0xC0,0x12  TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA       [RFC4492]
+         * 0xC0,0x13  TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA        [RFC4492]
+         * 0xC0,0x14  TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA        [RFC4492]
+         * 0xC0,0x15  TLS_ECDH_anon_WITH_NULL_SHA               [RFC4492]
+         * 0xC0,0x16  TLS_ECDH_anon_WITH_RC4_128_SHA            [RFC4492]
+         * 0xC0,0x17  TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA       [RFC4492]
+         * 0xC0,0x18  TLS_ECDH_anon_WITH_AES_128_CBC_SHA        [RFC4492]
+         * 0xC0,0x19  TLS_ECDH_anon_WITH_AES_256_CBC_SHA        [RFC4492]
+         * 0xC0,0x1A  TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA         [RFC5054]
+         * 0xC0,0x1B  TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA     [RFC5054]
+         * 0xC0,0x1C  TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA     [RFC5054]
+         * 0xC0,0x1D  TLS_SRP_SHA_WITH_AES_128_CBC_SHA          [RFC5054]
+         * 0xC0,0x1E  TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA      [RFC5054]
+         * 0xC0,0x1F  TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA      [RFC5054]
+         * 0xC0,0x20  TLS_SRP_SHA_WITH_AES_256_CBC_SHA          [RFC5054]
+         * 0xC0,0x21  TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA      [RFC5054]
+         * 0xC0,0x22  TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA      [RFC5054]
+         * 0xC0,0x23  TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256   [RFC5289]
+         * 0xC0,0x24  TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384   [RFC5289]
+         * 0xC0,0x25  TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256    [RFC5289]
+         * 0xC0,0x26  TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384    [RFC5289]
+         * 0xC0,0x27  TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256     [RFC5289]
+         * 0xC0,0x28  TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384     [RFC5289]
+         * 0xC0,0x29  TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256      [RFC5289]
+         * 0xC0,0x2A  TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384      [RFC5289]
+         * 0xC0,0x2B  TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256   [RFC5289]
+         * 0xC0,0x2C  TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384   [RFC5289]
+         * 0xC0,0x2D  TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256    [RFC5289]
+         * 0xC0,0x2E  TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384    [RFC5289]
+         * 0xC0,0x2F  TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256     [RFC5289]
+         * 0xC0,0x30  TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384     [RFC5289]
+         * 0xC0,0x31  TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256      [RFC5289]
+         * 0xC0,0x32  TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384      [RFC5289]
+         * 0xC0,0x33  TLS_ECDHE_PSK_WITH_RC4_128_SHA            [RFC5489]
+         * 0xC0,0x34  TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA       [RFC5489]
+         * 0xC0,0x35  TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA        [RFC5489]
+         * 0xC0,0x36  TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA        [RFC5489]
+         * 0xC0,0x37  TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256     [RFC5489]
+         * 0xC0,0x38  TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384     [RFC5489]
+         * 0xC0,0x39  TLS_ECDHE_PSK_WITH_NULL_SHA               [RFC5489]
+         * 0xC0,0x3A  TLS_ECDHE_PSK_WITH_NULL_SHA256            [RFC5489]
+         * 0xC0,0x3B  TLS_ECDHE_PSK_WITH_NULL_SHA384            [RFC5489]
+         * 0xC0,0x3C-FF Unassigned
+         * 0xC1-FD,*  Unassigned
+         * 0xFE,0x00-FD Unassigned
+         * 0xFE,0xFE-FF Reserved to avoid conflicts with widely
+         *            deployed implementations                  [Pasi_Eronen]
+         * 0xFF,0x00-FF Reserved for Private Use                [RFC5246]
+         */
+
         add("SSL_NULL_WITH_NULL_NULL",
                               0x0000,   1, K_NULL,       B_NULL,    F);
 
@@ -516,191 +866,377 @@
         // They are listed in preference order, most preferred first.
         int p = DEFAULT_SUITES_PRIORITY * 2;
 
+        // shorten names to fit the following table cleanly.
+        int max = ProtocolVersion.LIMIT_MAX_VALUE;
+        int tls11 = ProtocolVersion.TLS11.v;
+        int tls12 = ProtocolVersion.TLS12.v;
+
+        //  ID           Key Exchange   Cipher     A  obs  suprt  PRF
+        //  ======       ============   =========  =  ===  =====  ========
+        add("TLS_RSA_WITH_AES_128_CBC_SHA256",
+            0x003c, --p, K_RSA,         B_AES_128, T, max, tls12, P_SHA256);
+        add("TLS_RSA_WITH_AES_256_CBC_SHA256",
+            0x003d, --p, K_RSA,         B_AES_256, T, max, tls12, P_SHA256);
+        add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
+            0x0040, --p, K_DHE_DSS,     B_AES_128, T, max, tls12, P_SHA256);
+        add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
+            0x0067, --p, K_DHE_RSA,     B_AES_128, T, max, tls12, P_SHA256);
+        add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
+            0x006a, --p, K_DHE_DSS,     B_AES_256, T, max, tls12, P_SHA256);
+        add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
+            0x006b, --p, K_DHE_RSA,     B_AES_256, T, max, tls12, P_SHA256);
+
+        add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
+            0xc023, --p, K_ECDHE_ECDSA, B_AES_128, T, max, tls12, P_SHA256);
+        add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
+            0xc024, --p, K_ECDHE_ECDSA, B_AES_256, T, max, tls12, P_SHA384);
+        add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
+            0xc025, --p, K_ECDH_ECDSA,  B_AES_128, T, max, tls12, P_SHA256);
+        add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",
+            0xc026, --p, K_ECDH_ECDSA,  B_AES_256, T, max, tls12, P_SHA384);
+        add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
+            0xc027, --p, K_ECDHE_RSA,   B_AES_128, T, max, tls12, P_SHA256);
+        add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
+            0xc028, --p, K_ECDHE_RSA,   B_AES_256, T, max, tls12, P_SHA384);
+        add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
+            0xc029, --p, K_ECDH_RSA,    B_AES_128, T, max, tls12, P_SHA256);
+        add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",
+            0xc02a, --p, K_ECDH_RSA,    B_AES_256, T, max, tls12, P_SHA384);
+
         add("SSL_RSA_WITH_RC4_128_MD5",
-                              0x0004, --p, K_RSA,        B_RC4_128, N);
+            0x0004, --p, K_RSA,         B_RC4_128, N);
         add("SSL_RSA_WITH_RC4_128_SHA",
-                              0x0005, --p, K_RSA,        B_RC4_128, N);
+            0x0005, --p, K_RSA,         B_RC4_128, N);
         add("TLS_RSA_WITH_AES_128_CBC_SHA",
-                              0x002f, --p, K_RSA,        B_AES_128, T);
+            0x002f, --p, K_RSA,         B_AES_128, T);
         add("TLS_RSA_WITH_AES_256_CBC_SHA",
-                              0x0035, --p, K_RSA,        B_AES_256, T);
+            0x0035, --p, K_RSA,         B_AES_256, T);
 
         add("TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
-                              0xC002, --p, K_ECDH_ECDSA, B_RC4_128, N);
+            0xC002, --p, K_ECDH_ECDSA,  B_RC4_128, N);
         add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
-                              0xC004, --p, K_ECDH_ECDSA, B_AES_128, T);
+            0xC004, --p, K_ECDH_ECDSA,  B_AES_128, T);
         add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
-                              0xC005, --p, K_ECDH_ECDSA, B_AES_256, T);
+            0xC005, --p, K_ECDH_ECDSA,  B_AES_256, T);
         add("TLS_ECDH_RSA_WITH_RC4_128_SHA",
-                              0xC00C, --p, K_ECDH_RSA,   B_RC4_128, N);
+            0xC00C, --p, K_ECDH_RSA,    B_RC4_128, N);
         add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
-                              0xC00E, --p, K_ECDH_RSA,   B_AES_128, T);
+            0xC00E, --p, K_ECDH_RSA,    B_AES_128, T);
         add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
-                              0xC00F, --p, K_ECDH_RSA,   B_AES_256, T);
+            0xC00F, --p, K_ECDH_RSA,    B_AES_256, T);
 
         add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
-                              0xC007, --p, K_ECDHE_ECDSA,B_RC4_128, N);
+            0xC007, --p, K_ECDHE_ECDSA, B_RC4_128, N);
         add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
-                              0xC009, --p, K_ECDHE_ECDSA,B_AES_128, T);
+            0xC009, --p, K_ECDHE_ECDSA, B_AES_128, T);
         add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
-                              0xC00A, --p, K_ECDHE_ECDSA,B_AES_256, T);
+            0xC00A, --p, K_ECDHE_ECDSA, B_AES_256, T);
         add("TLS_ECDHE_RSA_WITH_RC4_128_SHA",
-                              0xC011, --p, K_ECDHE_RSA,  B_RC4_128, N);
+            0xC011, --p, K_ECDHE_RSA,   B_RC4_128, N);
         add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
-                              0xC013, --p, K_ECDHE_RSA,  B_AES_128, T);
+            0xC013, --p, K_ECDHE_RSA,   B_AES_128, T);
         add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
-                              0xC014, --p, K_ECDHE_RSA,  B_AES_256, T);
+            0xC014, --p, K_ECDHE_RSA,   B_AES_256, T);
 
         add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
-                              0x0033, --p, K_DHE_RSA,    B_AES_128, T);
+            0x0033, --p, K_DHE_RSA,     B_AES_128, T);
         add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
-                              0x0039, --p, K_DHE_RSA,    B_AES_256, T);
+            0x0039, --p, K_DHE_RSA,     B_AES_256, T);
         add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
-                              0x0032, --p, K_DHE_DSS,    B_AES_128, T);
+            0x0032, --p, K_DHE_DSS,     B_AES_128, T);
         add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
-                              0x0038, --p, K_DHE_DSS,    B_AES_256, T);
+            0x0038, --p, K_DHE_DSS,     B_AES_256, T);
 
         add("SSL_RSA_WITH_3DES_EDE_CBC_SHA",
-                              0x000a, --p, K_RSA,        B_3DES,    T);
+            0x000a, --p, K_RSA,         B_3DES,    T);
         add("TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
-                              0xC003, --p, K_ECDH_ECDSA, B_3DES,    T);
+            0xC003, --p, K_ECDH_ECDSA,  B_3DES,    T);
         add("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
-                              0xC00D, --p, K_ECDH_RSA,   B_3DES,    T);
+            0xC00D, --p, K_ECDH_RSA,    B_3DES,    T);
         add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
-                              0xC008, --p, K_ECDHE_ECDSA,B_3DES,    T);
+            0xC008, --p, K_ECDHE_ECDSA, B_3DES,    T);
         add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
-                              0xC012, --p, K_ECDHE_RSA,  B_3DES,    T);
+            0xC012, --p, K_ECDHE_RSA,   B_3DES,    T);
         add("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
-                              0x0016, --p, K_DHE_RSA,    B_3DES,    T);
+            0x0016, --p, K_DHE_RSA,     B_3DES,    T);
         add("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
-                              0x0013, --p, K_DHE_DSS,    B_3DES,    N);
-
-        add("SSL_RSA_WITH_DES_CBC_SHA",
-                              0x0009, --p, K_RSA,        B_DES,     N);
-        add("SSL_DHE_RSA_WITH_DES_CBC_SHA",
-                              0x0015, --p, K_DHE_RSA,    B_DES,     N);
-        add("SSL_DHE_DSS_WITH_DES_CBC_SHA",
-                              0x0012, --p, K_DHE_DSS,    B_DES,     N);
-        add("SSL_RSA_EXPORT_WITH_RC4_40_MD5",
-                              0x0003, --p, K_RSA_EXPORT, B_RC4_40,  N);
-        add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
-                              0x0008, --p, K_RSA_EXPORT, B_DES_40,  N);
-        add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
-                              0x0014, --p, K_DHE_RSA,    B_DES_40,  N);
-        add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
-                              0x0011, --p, K_DHE_DSS,    B_DES_40,  N);
+            0x0013, --p, K_DHE_DSS,     B_3DES,    N);
 
         // Renegotiation protection request Signalling Cipher Suite Value (SCSV)
         add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
-                              0x00ff, --p, K_SCSV,       B_NULL,    T);
+            0x00ff, --p, K_SCSV,        B_NULL,    T);
 
         // Definition of the CipherSuites that are supported but not enabled
         // by default.
         // They are listed in preference order, preferred first.
         p = DEFAULT_SUITES_PRIORITY;
 
+        // weak single-DES cipher suites
+        add("SSL_RSA_WITH_DES_CBC_SHA",
+            0x0009, --p, K_RSA,         B_DES,     N, tls12);
+        add("SSL_DHE_RSA_WITH_DES_CBC_SHA",
+            0x0015, --p, K_DHE_RSA,     B_DES,     N, tls12);
+        add("SSL_DHE_DSS_WITH_DES_CBC_SHA",
+            0x0012, --p, K_DHE_DSS,     B_DES,     N, tls12);
+
         // Anonymous key exchange and the NULL ciphers
         add("SSL_RSA_WITH_NULL_MD5",
-                              0x0001, --p, K_RSA,        B_NULL,    N);
+            0x0001, --p, K_RSA,         B_NULL,    N);
         add("SSL_RSA_WITH_NULL_SHA",
-                              0x0002, --p, K_RSA,        B_NULL,    N);
+            0x0002, --p, K_RSA,         B_NULL,    N);
+        add("TLS_RSA_WITH_NULL_SHA256",
+            0x003b, --p, K_RSA,         B_NULL,    N, max, tls12, P_SHA256);
+
         add("TLS_ECDH_ECDSA_WITH_NULL_SHA",
-                              0xC001, --p, K_ECDH_ECDSA, B_NULL,    N);
+            0xC001, --p, K_ECDH_ECDSA,  B_NULL,    N);
         add("TLS_ECDH_RSA_WITH_NULL_SHA",
-                              0xC00B, --p, K_ECDH_RSA,   B_NULL,    N);
+            0xC00B, --p, K_ECDH_RSA,    B_NULL,    N);
         add("TLS_ECDHE_ECDSA_WITH_NULL_SHA",
-                              0xC006, --p, K_ECDHE_ECDSA,B_NULL,    N);
+            0xC006, --p, K_ECDHE_ECDSA, B_NULL,    N);
         add("TLS_ECDHE_RSA_WITH_NULL_SHA",
-                              0xC010, --p, K_ECDHE_RSA,  B_NULL,    N);
+            0xC010, --p, K_ECDHE_RSA,   B_NULL,    N);
 
         add("SSL_DH_anon_WITH_RC4_128_MD5",
-                              0x0018, --p, K_DH_ANON,    B_RC4_128, N);
+            0x0018, --p, K_DH_ANON,     B_RC4_128, N);
         add("TLS_DH_anon_WITH_AES_128_CBC_SHA",
-                              0x0034, --p, K_DH_ANON,    B_AES_128, N);
+            0x0034, --p, K_DH_ANON,     B_AES_128, N);
         add("TLS_DH_anon_WITH_AES_256_CBC_SHA",
-                              0x003a, --p, K_DH_ANON,    B_AES_256, N);
+            0x003a, --p, K_DH_ANON,     B_AES_256, N);
         add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
-                              0x001b, --p, K_DH_ANON,    B_3DES,    N);
+            0x001b, --p, K_DH_ANON,     B_3DES,    N);
         add("SSL_DH_anon_WITH_DES_CBC_SHA",
-                              0x001a, --p, K_DH_ANON,    B_DES,     N);
+            0x001a, --p, K_DH_ANON,     B_DES,     N, tls12);
+
+        add("TLS_DH_anon_WITH_AES_128_CBC_SHA256",
+            0x006c, --p, K_DH_ANON,     B_AES_128, N, max, tls12, P_SHA256);
+        add("TLS_DH_anon_WITH_AES_256_CBC_SHA256",
+            0x006d, --p, K_DH_ANON,     B_AES_256, N, max, tls12, P_SHA256);
 
         add("TLS_ECDH_anon_WITH_RC4_128_SHA",
-                              0xC016, --p, K_ECDH_ANON,  B_RC4_128, N);
+            0xC016, --p, K_ECDH_ANON,   B_RC4_128, N);
         add("TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
-                              0xC018, --p, K_ECDH_ANON,  B_AES_128, T);
+            0xC018, --p, K_ECDH_ANON,   B_AES_128, T);
         add("TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
-                              0xC019, --p, K_ECDH_ANON,  B_AES_256, T);
+            0xC019, --p, K_ECDH_ANON,   B_AES_256, T);
         add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
-                              0xC017, --p, K_ECDH_ANON,  B_3DES,    T);
+            0xC017, --p, K_ECDH_ANON,   B_3DES,    T);
 
         add("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
-                              0x0017, --p, K_DH_ANON,    B_RC4_40,  N);
+            0x0017, --p, K_DH_ANON,     B_RC4_40,  N, tls11);
         add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
-                              0x0019, --p, K_DH_ANON,    B_DES_40,  N);
+            0x0019, --p, K_DH_ANON,     B_DES_40,  N, tls11);
 
         add("TLS_ECDH_anon_WITH_NULL_SHA",
-                              0xC015, --p, K_ECDH_ANON,  B_NULL,    N);
+            0xC015, --p, K_ECDH_ANON,   B_NULL,    N);
+
+        add("SSL_RSA_EXPORT_WITH_RC4_40_MD5",
+            0x0003, --p, K_RSA_EXPORT,  B_RC4_40,  N, tls11);
+        add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
+            0x0008, --p, K_RSA_EXPORT,  B_DES_40,  N, tls11);
+        add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
+            0x0014, --p, K_DHE_RSA,     B_DES_40,  N, tls11);
+        add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
+            0x0011, --p, K_DHE_DSS,     B_DES_40,  N, tls11);
 
         // Supported Kerberos ciphersuites from RFC2712
         add("TLS_KRB5_WITH_RC4_128_SHA",
-                              0x0020, --p, K_KRB5,        B_RC4_128, N);
+            0x0020, --p, K_KRB5,        B_RC4_128, N);
         add("TLS_KRB5_WITH_RC4_128_MD5",
-                              0x0024, --p, K_KRB5,        B_RC4_128, N);
+            0x0024, --p, K_KRB5,        B_RC4_128, N);
         add("TLS_KRB5_WITH_3DES_EDE_CBC_SHA",
-                              0x001f, --p, K_KRB5,        B_3DES,    N);
+            0x001f, --p, K_KRB5,        B_3DES,    N);
         add("TLS_KRB5_WITH_3DES_EDE_CBC_MD5",
-                              0x0023, --p, K_KRB5,        B_3DES,    N);
+            0x0023, --p, K_KRB5,        B_3DES,    N);
         add("TLS_KRB5_WITH_DES_CBC_SHA",
-                              0x001e, --p, K_KRB5,        B_DES,     N);
+            0x001e, --p, K_KRB5,        B_DES,     N, tls12);
         add("TLS_KRB5_WITH_DES_CBC_MD5",
-                              0x0022, --p, K_KRB5,        B_DES,     N);
+            0x0022, --p, K_KRB5,        B_DES,     N, tls12);
         add("TLS_KRB5_EXPORT_WITH_RC4_40_SHA",
-                              0x0028, --p, K_KRB5_EXPORT, B_RC4_40,  N);
+            0x0028, --p, K_KRB5_EXPORT, B_RC4_40,  N, tls11);
         add("TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
-                              0x002b, --p, K_KRB5_EXPORT, B_RC4_40,  N);
+            0x002b, --p, K_KRB5_EXPORT, B_RC4_40,  N, tls11);
         add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
-                              0x0026, --p, K_KRB5_EXPORT, B_DES_40,  N);
+            0x0026, --p, K_KRB5_EXPORT, B_DES_40,  N, tls11);
         add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
-                              0x0029, --p, K_KRB5_EXPORT, B_DES_40,  N);
+            0x0029, --p, K_KRB5_EXPORT, B_DES_40,  N, tls11);
+
+        /*
+         * Other values from the TLS Cipher Suite Registry, as of August 2010.
+         *
+         * http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
+         *
+         * Range      Registration Procedures   Notes
+         * 000-191    Standards Action          Refers to value of first byte
+         * 192-254    Specification Required    Refers to value of first byte
+         * 255        Reserved for Private Use  Refers to value of first byte
+         */
 
         // Register the names of a few additional CipherSuites.
         // Makes them show up as names instead of numbers in
         // the debug output.
 
         // remaining unsupported ciphersuites defined in RFC2246.
-        add("SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5",      0x0006);
-        add("SSL_RSA_WITH_IDEA_CBC_SHA",               0x0007);
-        add("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA",    0x000b);
-        add("SSL_DH_DSS_WITH_DES_CBC_SHA",             0x000c);
-        add("SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA",        0x000d);
-        add("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA",    0x000e);
-        add("SSL_DH_RSA_WITH_DES_CBC_SHA",             0x000f);
-        add("SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA",        0x0010);
+        add("SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5",          0x0006);
+        add("SSL_RSA_WITH_IDEA_CBC_SHA",                   0x0007);
+        add("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA",        0x000b);
+        add("SSL_DH_DSS_WITH_DES_CBC_SHA",                 0x000c);
+        add("SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA",            0x000d);
+        add("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA",        0x000e);
+        add("SSL_DH_RSA_WITH_DES_CBC_SHA",                 0x000f);
+        add("SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA",            0x0010);
 
         // SSL 3.0 Fortezza ciphersuites
-        add("SSL_FORTEZZA_DMS_WITH_NULL_SHA",          0x001c);
-        add("SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA",  0x001d);
+        add("SSL_FORTEZZA_DMS_WITH_NULL_SHA",              0x001c);
+        add("SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA",      0x001d);
 
         // 1024/56 bit exportable ciphersuites from expired internet draft
-        add("SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA",     0x0062);
-        add("SSL_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA", 0x0063);
-        add("SSL_RSA_EXPORT1024_WITH_RC4_56_SHA",      0x0064);
-        add("SSL_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA",  0x0065);
-        add("SSL_DHE_DSS_WITH_RC4_128_SHA",            0x0066);
+        add("SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA",         0x0062);
+        add("SSL_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA",     0x0063);
+        add("SSL_RSA_EXPORT1024_WITH_RC4_56_SHA",          0x0064);
+        add("SSL_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA",      0x0065);
+        add("SSL_DHE_DSS_WITH_RC4_128_SHA",                0x0066);
 
         // Netscape old and new SSL 3.0 FIPS ciphersuites
         // see http://www.mozilla.org/projects/security/pki/nss/ssl/fips-ssl-ciphersuites.html
-        add("NETSCAPE_RSA_FIPS_WITH_3DES_EDE_CBC_SHA", 0xffe0);
-        add("NETSCAPE_RSA_FIPS_WITH_DES_CBC_SHA",      0xffe1);
-        add("SSL_RSA_FIPS_WITH_DES_CBC_SHA",           0xfefe);
-        add("SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA",      0xfeff);
+        add("NETSCAPE_RSA_FIPS_WITH_3DES_EDE_CBC_SHA",     0xffe0);
+        add("NETSCAPE_RSA_FIPS_WITH_DES_CBC_SHA",          0xffe1);
+        add("SSL_RSA_FIPS_WITH_DES_CBC_SHA",               0xfefe);
+        add("SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA",          0xfeff);
 
         // Unsupported Kerberos cipher suites from RFC 2712
-        add("TLS_KRB5_WITH_IDEA_CBC_SHA",              0x0021);
-        add("TLS_KRB5_WITH_IDEA_CBC_MD5",              0x0025);
-        add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA",     0x0027);
-        add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5",     0x002a);
+        add("TLS_KRB5_WITH_IDEA_CBC_SHA",                  0x0021);
+        add("TLS_KRB5_WITH_IDEA_CBC_MD5",                  0x0025);
+        add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA",         0x0027);
+        add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5",         0x002a);
+
+        // Unsupported cipher suites from RFC 4162
+        add("TLS_RSA_WITH_SEED_CBC_SHA",                   0x0096);
+        add("TLS_DH_DSS_WITH_SEED_CBC_SHA",                0x0097);
+        add("TLS_DH_RSA_WITH_SEED_CBC_SHA",                0x0098);
+        add("TLS_DHE_DSS_WITH_SEED_CBC_SHA",               0x0099);
+        add("TLS_DHE_RSA_WITH_SEED_CBC_SHA",               0x009a);
+        add("TLS_DH_anon_WITH_SEED_CBC_SHA",               0x009b);
+
+        // Unsupported cipher suites from RFC 4279
+        add("TLS_PSK_WITH_RC4_128_SHA",                    0x008a);
+        add("TLS_PSK_WITH_3DES_EDE_CBC_SHA",               0x008b);
+        add("TLS_PSK_WITH_AES_128_CBC_SHA",                0x008c);
+        add("TLS_PSK_WITH_AES_256_CBC_SHA",                0x008d);
+        add("TLS_DHE_PSK_WITH_RC4_128_SHA",                0x008e);
+        add("TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA",           0x008f);
+        add("TLS_DHE_PSK_WITH_AES_128_CBC_SHA",            0x0090);
+        add("TLS_DHE_PSK_WITH_AES_256_CBC_SHA",            0x0091);
+        add("TLS_RSA_PSK_WITH_RC4_128_SHA",                0x0092);
+        add("TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA",           0x0093);
+        add("TLS_RSA_PSK_WITH_AES_128_CBC_SHA",            0x0094);
+        add("TLS_RSA_PSK_WITH_AES_256_CBC_SHA",            0x0095);
+
+        // Unsupported cipher suites from RFC 4785
+        add("TLS_PSK_WITH_NULL_SHA",                       0x002c);
+        add("TLS_DHE_PSK_WITH_NULL_SHA",                   0x002d);
+        add("TLS_RSA_PSK_WITH_NULL_SHA",                   0x002e);
+
+        // Unsupported cipher suites from RFC 5246
+        add("TLS_DH_DSS_WITH_AES_128_CBC_SHA",             0x0030);
+        add("TLS_DH_RSA_WITH_AES_128_CBC_SHA",             0x0031);
+        add("TLS_DH_DSS_WITH_AES_256_CBC_SHA",             0x0036);
+        add("TLS_DH_RSA_WITH_AES_256_CBC_SHA",             0x0037);
+        add("TLS_DH_DSS_WITH_AES_128_CBC_SHA256",          0x003e);
+        add("TLS_DH_RSA_WITH_AES_128_CBC_SHA256",          0x003f);
+        add("TLS_DH_DSS_WITH_AES_256_CBC_SHA256",          0x0068);
+        add("TLS_DH_RSA_WITH_AES_256_CBC_SHA256",          0x0069);
+
+        // Unsupported cipher suites from RFC 5288
+        add("TLS_RSA_WITH_AES_128_GCM_SHA256",             0x009c);
+        add("TLS_RSA_WITH_AES_256_GCM_SHA384",             0x009d);
+        add("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",         0x009e);
+        add("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",         0x009f);
+        add("TLS_DH_RSA_WITH_AES_128_GCM_SHA256",          0x00a0);
+        add("TLS_DH_RSA_WITH_AES_256_GCM_SHA384",          0x00a1);
+        add("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",         0x00a2);
+        add("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",         0x00a3);
+        add("TLS_DH_DSS_WITH_AES_128_GCM_SHA256",          0x00a4);
+        add("TLS_DH_DSS_WITH_AES_256_GCM_SHA384",          0x00a5);
+        add("TLS_DH_anon_WITH_AES_128_GCM_SHA256",         0x00a6);
+        add("TLS_DH_anon_WITH_AES_256_GCM_SHA384",         0x00a7);
 
+        // Unsupported cipher suites from RFC 5487
+        add("TLS_PSK_WITH_AES_128_GCM_SHA256",             0x00a8);
+        add("TLS_PSK_WITH_AES_256_GCM_SHA384",             0x00a9);
+        add("TLS_DHE_PSK_WITH_AES_128_GCM_SHA256",         0x00aa);
+        add("TLS_DHE_PSK_WITH_AES_256_GCM_SHA384",         0x00ab);
+        add("TLS_RSA_PSK_WITH_AES_128_GCM_SHA256",         0x00ac);
+        add("TLS_RSA_PSK_WITH_AES_256_GCM_SHA384",         0x00ad);
+        add("TLS_PSK_WITH_AES_128_CBC_SHA256",             0x00ae);
+        add("TLS_PSK_WITH_AES_256_CBC_SHA384",             0x00af);
+        add("TLS_PSK_WITH_NULL_SHA256",                    0x00b0);
+        add("TLS_PSK_WITH_NULL_SHA384",                    0x00b1);
+        add("TLS_DHE_PSK_WITH_AES_128_CBC_SHA256",         0x00b2);
+        add("TLS_DHE_PSK_WITH_AES_256_CBC_SHA384",         0x00b3);
+        add("TLS_DHE_PSK_WITH_NULL_SHA256",                0x00b4);
+        add("TLS_DHE_PSK_WITH_NULL_SHA384",                0x00b5);
+        add("TLS_RSA_PSK_WITH_AES_128_CBC_SHA256",         0x00b6);
+        add("TLS_RSA_PSK_WITH_AES_256_CBC_SHA384",         0x00b7);
+        add("TLS_RSA_PSK_WITH_NULL_SHA256",                0x00b8);
+        add("TLS_RSA_PSK_WITH_NULL_SHA384",                0x00b9);
+
+        // Unsupported cipher suites from RFC 5932
+        add("TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",           0x0041);
+        add("TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA",        0x0042);
+        add("TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA",        0x0043);
+        add("TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA",       0x0044);
+        add("TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",       0x0045);
+        add("TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA",       0x0046);
+        add("TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",           0x0084);
+        add("TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA",        0x0085);
+        add("TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA",        0x0086);
+        add("TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA",       0x0087);
+        add("TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",       0x0088);
+        add("TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA",       0x0089);
+        add("TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",        0x00ba);
+        add("TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256",     0x00bb);
+        add("TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256",     0x00bc);
+        add("TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256",    0x00bd);
+        add("TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",    0x00be);
+        add("TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256",    0x00bf);
+        add("TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",        0x00c0);
+        add("TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256",     0x00c1);
+        add("TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256",     0x00c2);
+        add("TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256",    0x00c3);
+        add("TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",    0x00c4);
+        add("TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256",    0x00c5);
+
+        // Unsupported cipher suites from RFC 5054
+        add("TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA",           0xc01a);
+        add("TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA",       0xc01b);
+        add("TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA",       0xc01c);
+        add("TLS_SRP_SHA_WITH_AES_128_CBC_SHA",            0xc01d);
+        add("TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA",        0xc01e);
+        add("TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA",        0xc01f);
+        add("TLS_SRP_SHA_WITH_AES_256_CBC_SHA",            0xc020);
+        add("TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA",        0xc021);
+        add("TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA",        0xc022);
+
+        // Unsupported cipher suites from RFC 5289
+        add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",     0xc02b);
+        add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",     0xc02c);
+        add("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",      0xc02d);
+        add("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",      0xc02e);
+        add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",       0xc02f);
+        add("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",       0xc030);
+        add("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",        0xc031);
+        add("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",        0xc032);
+
+        // Unsupported cipher suites from RFC 5489
+        add("TLS_ECDHE_PSK_WITH_RC4_128_SHA",              0xc033);
+        add("TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA",         0xc034);
+        add("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA",          0xc035);
+        add("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA",          0xc036);
+        add("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256",       0xc037);
+        add("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384",       0xc038);
+        add("TLS_ECDHE_PSK_WITH_NULL_SHA",                 0xc039);
+        add("TLS_ECDHE_PSK_WITH_NULL_SHA256",              0xc03a);
+        add("TLS_ECDHE_PSK_WITH_NULL_SHA384",              0xc03b);
     }
 
     // ciphersuite SSL_NULL_WITH_NULL_NULL
--- a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java	Wed Jul 05 17:26:57 2017 +0200
@@ -23,7 +23,6 @@
  * questions.
  */
 
-
 package sun.security.ssl;
 
 import java.io.*;
@@ -45,12 +44,12 @@
 
 import javax.security.auth.Subject;
 
-import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
-
 import sun.security.ssl.HandshakeMessage.*;
 import sun.security.ssl.CipherSuite.*;
 import static sun.security.ssl.CipherSuite.KeyExchange.*;
 
+import sun.net.util.IPAddressUtil;
+
 /**
  * ClientHandshaker does the protocol handshaking from the point
  * of view of a client.  It is driven asychronously by handshake messages
@@ -89,6 +88,10 @@
      */
     private ProtocolVersion maxProtocolVersion;
 
+    // To switch off the SNI extension.
+    private final static boolean enableSNIExtension =
+            Debug.getBooleanProperty("jsse.enableSNIExtension", true);
+
     /*
      * Constructors
      */
@@ -190,7 +193,8 @@
                 }
                 break;
             case K_DH_ANON:
-                this.serverKeyExchange(new DH_ServerKeyExchange(input));
+                this.serverKeyExchange(new DH_ServerKeyExchange(
+                                                input, protocolVersion));
                 break;
             case K_DHE_DSS:
             case K_DHE_RSA:
@@ -198,7 +202,8 @@
                     this.serverKeyExchange(new DH_ServerKeyExchange(
                         input, serverKey,
                         clnt_random.random_bytes, svr_random.random_bytes,
-                        messageLen));
+                        messageLen,
+                        localSupportedSignAlgs, protocolVersion));
                 } catch (GeneralSecurityException e) {
                     throwSSLException("Server key", e);
                 }
@@ -209,7 +214,8 @@
                 try {
                     this.serverKeyExchange(new ECDH_ServerKeyExchange
                         (input, serverKey, clnt_random.random_bytes,
-                        svr_random.random_bytes));
+                        svr_random.random_bytes,
+                        localSupportedSignAlgs, protocolVersion));
                 } catch (GeneralSecurityException e) {
                     throwSSLException("Server key", e);
                 }
@@ -219,8 +225,9 @@
             case K_DH_DSS:
             case K_ECDH_ECDSA:
             case K_ECDH_RSA:
-                throw new SSLProtocolException("Protocol violation: server sent"
-                    + " a server key exchange message for key exchange " + keyExchange);
+                throw new SSLProtocolException(
+                    "Protocol violation: server sent a server key exchange"
+                    + "message for key exchange " + keyExchange);
             case K_KRB5:
             case K_KRB5_EXPORT:
                 throw new SSLProtocolException(
@@ -243,10 +250,32 @@
                     "Client certificate requested for "+
                     "kerberos cipher suite.");
             }
-            certRequest = new CertificateRequest(input);
+            certRequest = new CertificateRequest(input, protocolVersion);
             if (debug != null && Debug.isOn("handshake")) {
                 certRequest.print(System.out);
             }
+
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                Collection<SignatureAndHashAlgorithm> peerSignAlgs =
+                                        certRequest.getSignAlgorithms();
+                if (peerSignAlgs == null || peerSignAlgs.isEmpty()) {
+                    throw new SSLHandshakeException(
+                        "No peer supported signature algorithms");
+                }
+
+                Collection<SignatureAndHashAlgorithm> supportedPeerSignAlgs =
+                    SignatureAndHashAlgorithm.getSupportedAlgorithms(
+                                                            peerSignAlgs);
+                if (supportedPeerSignAlgs.isEmpty()) {
+                    throw new SSLHandshakeException(
+                        "No supported signature and hash algorithm in common");
+                }
+
+                setPeerSupportedSignAlgs(supportedPeerSignAlgs);
+                session.setPeerSupportedSignatureAlgorithms(
+                                                supportedPeerSignAlgs);
+            }
+
             break;
 
         case HandshakeMessage.ht_server_hello_done:
@@ -254,7 +283,8 @@
             break;
 
         case HandshakeMessage.ht_finished:
-            this.serverFinished(new Finished(protocolVersion, input));
+            this.serverFinished(
+                new Finished(protocolVersion, input, cipherSuite));
             break;
 
         default:
@@ -345,11 +375,15 @@
 
         // check if the server selected protocol version is OK for us
         ProtocolVersion mesgVersion = mesg.protocolVersion;
-        if (enabledProtocols.contains(mesgVersion) == false) {
-            throw new SSLHandshakeException
-            ("Server chose unsupported or disabled protocol: " + mesgVersion);
+        if (!isNegotiable(mesgVersion)) {
+            throw new SSLHandshakeException(
+                    "Server chose unsupported or disabled protocol: " +
+                    mesgVersion);
         }
 
+        handshakeHash.protocolDetermined(
+            mesgVersion.v >= ProtocolVersion.TLS12.v);
+
         // Set protocolVersion and propagate to SSLSocket and the
         // Handshake streams
         setVersion(mesgVersion);
@@ -425,10 +459,13 @@
 
         if (isNegotiable(mesg.cipherSuite) == false) {
             fatalSE(Alerts.alert_illegal_parameter,
-                "Server selected improper ciphersuite " + cipherSuite);
+                "Server selected improper ciphersuite " + mesg.cipherSuite);
         }
 
         setCipherSuite(mesg.cipherSuite);
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            handshakeHash.setFinishedAlg(cipherSuite.prfAlg.getPRFHashAlg());
+        }
 
         if (mesg.compression_method != 0) {
             fatalSE(Alerts.alert_illegal_parameter,
@@ -507,7 +544,6 @@
                 if (debug != null && Debug.isOn("session")) {
                     System.out.println("%% Server resumed " + session);
                 }
-                return;
             } else {
                 // we wanted to resume, but the server refused
                 session = null;
@@ -518,11 +554,21 @@
             }
         }
 
+        if (resumingSession && session != null) {
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                handshakeHash.setCertificateVerifyAlg(null);
+            }
+
+            setHandshakeSessionSE(session);
+            return;
+        }
+
         // check extensions
         for (HelloExtension ext : mesg.extensions.list()) {
             ExtensionType type = ext.type;
             if ((type != ExtensionType.EXT_ELLIPTIC_CURVES)
                     && (type != ExtensionType.EXT_EC_POINT_FORMATS)
+                    && (type != ExtensionType.EXT_SERVER_NAME)
                     && (type != ExtensionType.EXT_RENEGOTIATION_INFO)) {
                 fatalSE(Alerts.alert_unsupported_extension,
                     "Server sent an unsupported extension: " + type);
@@ -531,7 +577,9 @@
 
         // Create a new session, we need to do the full handshake
         session = new SSLSessionImpl(protocolVersion, cipherSuite,
+                            getLocalSupportedSignAlgs(),
                             mesg.sessionId, getHostSE(), getPortSE());
+        setHandshakeSessionSE(session);
         if (debug != null && Debug.isOn("handshake")) {
             System.out.println("** " + cipherSuite);
         }
@@ -567,11 +615,13 @@
         if (debug != null && Debug.isOn("handshake")) {
             mesg.print(System.out);
         }
-        dh = new DHCrypt(mesg.getModulus(), mesg.getBase(), sslContext.getSecureRandom());
+        dh = new DHCrypt(mesg.getModulus(), mesg.getBase(),
+                                            sslContext.getSecureRandom());
         serverDH = mesg.getServerPublicKey();
     }
 
-    private void serverKeyExchange(ECDH_ServerKeyExchange mesg) throws IOException {
+    private void serverKeyExchange(ECDH_ServerKeyExchange mesg)
+            throws IOException {
         if (debug != null && Debug.isOn("handshake")) {
             mesg.print(System.out);
         }
@@ -665,9 +715,13 @@
                     PublicKey publicKey = certs[0].getPublicKey();
                     // for EC, make sure we use a supported named curve
                     if (publicKey instanceof ECPublicKey) {
-                        ECParameterSpec params = ((ECPublicKey)publicKey).getParams();
-                        int index = SupportedEllipticCurvesExtension.getCurveIndex(params);
-                        if (!SupportedEllipticCurvesExtension.isSupported(index)) {
+                        ECParameterSpec params =
+                            ((ECPublicKey)publicKey).getParams();
+                        int index =
+                            SupportedEllipticCurvesExtension.getCurveIndex(
+                                params);
+                        if (!SupportedEllipticCurvesExtension.isSupported(
+                                index)) {
                             publicKey = null;
                         }
                     }
@@ -813,8 +867,9 @@
                 throw new IOException("Hostname is required" +
                                 " to use Kerberos cipher suites");
             }
-            KerberosClientKeyExchange kerberosMsg = new KerberosClientKeyExchange
-                (hostname, isLoopbackSE(), getAccSE(), protocolVersion,
+            KerberosClientKeyExchange kerberosMsg =
+                new KerberosClientKeyExchange(
+                    hostname, isLoopbackSE(), getAccSE(), protocolVersion,
                 sslContext.getSecureRandom());
             // Record the principals involved in exchange
             session.setPeerPrincipal(kerberosMsg.getPeerPrincipal());
@@ -861,7 +916,8 @@
         case K_KRB5_EXPORT:
             byte[] secretBytes =
                 ((KerberosClientKeyExchange)m2).getUnencryptedPreMasterSecret();
-            preMasterSecret = new SecretKeySpec(secretBytes, "TlsPremasterSecret");
+            preMasterSecret = new SecretKeySpec(secretBytes,
+                "TlsPremasterSecret");
             break;
         case K_DHE_RSA:
         case K_DHE_DSS:
@@ -878,7 +934,8 @@
             preMasterSecret = ecdh.getAgreedSecret(serverKey);
             break;
         default:
-            throw new IOException("Internal error: unknown key exchange " + keyExchange);
+            throw new IOException("Internal error: unknown key exchange "
+                + keyExchange);
         }
 
         calculateKeys(preMasterSecret, null);
@@ -896,9 +953,32 @@
         if (signingKey != null) {
             CertificateVerify m3;
             try {
+                SignatureAndHashAlgorithm preferableSignatureAlgorithm = null;
+                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                    preferableSignatureAlgorithm =
+                        SignatureAndHashAlgorithm.getPreferableAlgorithm(
+                            peerSupportedSignAlgs, signingKey.getAlgorithm());
+
+                    if (preferableSignatureAlgorithm == null) {
+                        throw new SSLHandshakeException(
+                            "No supported signature algorithm");
+                    }
+
+                    String hashAlg =
+                        SignatureAndHashAlgorithm.getHashAlgorithmName(
+                                preferableSignatureAlgorithm);
+                    if (hashAlg == null || hashAlg.length() == 0) {
+                        throw new SSLHandshakeException(
+                                "No supported hash algorithm");
+                    }
+
+                    handshakeHash.setCertificateVerifyAlg(hashAlg);
+                }
+
                 m3 = new CertificateVerify(protocolVersion, handshakeHash,
                     signingKey, session.getMasterSecret(),
-                    sslContext.getSecureRandom());
+                    sslContext.getSecureRandom(),
+                    preferableSignatureAlgorithm);
             } catch (GeneralSecurityException e) {
                 fatalSE(Alerts.alert_handshake_failure,
                     "Error signing certificate verify", e);
@@ -910,6 +990,10 @@
             }
             m3.write(output);
             output.doHashes();
+        } else {
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                handshakeHash.setCertificateVerifyAlg(null);
+            }
         }
 
         /*
@@ -930,8 +1014,8 @@
             mesg.print(System.out);
         }
 
-        boolean verified = mesg.verify(protocolVersion, handshakeHash,
-                                Finished.SERVER, session.getMasterSecret());
+        boolean verified = mesg.verify(handshakeHash, Finished.SERVER,
+            session.getMasterSecret());
 
         if (!verified) {
             fatalSE(Alerts.alert_illegal_parameter,
@@ -988,7 +1072,7 @@
     private void sendChangeCipherAndFinish(boolean finishedTag)
             throws IOException {
         Finished mesg = new Finished(protocolVersion, handshakeHash,
-                                Finished.CLIENT, session.getMasterSecret());
+            Finished.CLIENT, session.getMasterSecret(), cipherSuite);
 
         /*
          * Send the change_cipher_spec message, then the Finished message
@@ -1022,7 +1106,7 @@
         SessionId sessionId = SSLSessionImpl.nullSession.getSessionId();
 
         // a list of cipher suites sent by the client
-        CipherSuiteList cipherSuites = enabledCipherSuites;
+        CipherSuiteList cipherSuites = getActiveCipherSuites();
 
         // set the max protocol version this client is supporting.
         maxProtocolVersion = protocolVersion;
@@ -1057,8 +1141,7 @@
                 session = null;
             }
 
-            if ((session != null) &&
-                        (enabledProtocols.contains(sessionVersion) == false)) {
+            if ((session != null) && !isNegotiable(sessionVersion)) {
                 if (debug != null && Debug.isOn("session")) {
                     System.out.println("%% can't resume, protocol disabled");
                 }
@@ -1088,7 +1171,7 @@
              */
             if (!enableNewSession) {
                 if (session == null) {
-                    throw new SSLException(
+                    throw new SSLHandshakeException(
                         "Can't reuse existing SSL client session");
                 }
 
@@ -1105,7 +1188,7 @@
         }
 
         if (session == null && !enableNewSession) {
-            throw new SSLException("No existing session to resume");
+            throw new SSLHandshakeException("No existing session to resume");
         }
 
         // exclude SCSV for secure renegotiation
@@ -1131,14 +1214,52 @@
         }
 
         if (!negotiable) {
-            throw new SSLException("No negotiable cipher suite");
+            throw new SSLHandshakeException("No negotiable cipher suite");
         }
 
+        // Not a TLS1.2+ handshake
+        // For SSLv2Hello, HandshakeHash.reset() will be called, so we
+        // cannot call HandshakeHash.protocolDetermined() here. As it does
+        // not follow the spec that HandshakeHash.reset() can be only be
+        // called before protocolDetermined.
+        // if (maxProtocolVersion.v < ProtocolVersion.TLS12.v) {
+        //     handshakeHash.protocolDetermined(false);
+        // }
+
         // create the ClientHello message
         ClientHello clientHelloMessage = new ClientHello(
                 sslContext.getSecureRandom(), maxProtocolVersion,
                 sessionId, cipherSuites);
 
+        // add signature_algorithm extension
+        if (maxProtocolVersion.v >= ProtocolVersion.TLS12.v) {
+            // we will always send the signature_algorithm extension
+            Collection<SignatureAndHashAlgorithm> localSignAlgs =
+                                                getLocalSupportedSignAlgs();
+            if (localSignAlgs.isEmpty()) {
+                throw new SSLHandshakeException(
+                            "No supported signature algorithm");
+            }
+
+            clientHelloMessage.addSignatureAlgorithmsExtension(localSignAlgs);
+        }
+
+        // add server_name extension
+        if (enableSNIExtension) {
+            // We cannot use the hostname resolved from name services.  For
+            // virtual hosting, multiple hostnames may be bound to the same IP
+            // address, so the hostname resolved from name services is not
+            // reliable.
+            String hostname = getRawHostnameSE();
+
+            // we only allow FQDN
+            if (hostname != null && hostname.indexOf('.') > 0 &&
+                    !IPAddressUtil.isIPv4LiteralAddress(hostname) &&
+                    !IPAddressUtil.isIPv6LiteralAddress(hostname)) {
+                clientHelloMessage.addServerNameIndicationExtension(hostname);
+            }
+        }
+
         // reset the client random cookie
         clnt_random = clientHelloMessage.clnt_random;
 
@@ -1194,26 +1315,23 @@
                 keyExchangeString = keyExchange.name;
             }
 
-            String identificator = getHostnameVerificationSE();
             if (tm instanceof X509ExtendedTrustManager) {
-                ((X509ExtendedTrustManager)tm).checkServerTrusted(
-                        (peerCerts != null ?
-                            peerCerts.clone() :
-                            null),
+                if (conn != null) {
+                    ((X509ExtendedTrustManager)tm).checkServerTrusted(
+                        peerCerts.clone(),
                         keyExchangeString,
-                        getHostSE(),
-                        identificator);
+                        conn);
+                } else {
+                    ((X509ExtendedTrustManager)tm).checkServerTrusted(
+                        peerCerts.clone(),
+                        keyExchangeString,
+                        engine);
+                }
             } else {
-                if (identificator != null) {
-                    throw new RuntimeException(
-                        "trust manager does not support peer identification");
-                }
-
-                tm.checkServerTrusted(
-                    (peerCerts != null ?
-                        peerCerts.clone() :
-                        peerCerts),
-                    keyExchangeString);
+                // Unlikely to happen, because we have wrapped the old
+                // X509TrustManager with the new X509ExtendedTrustManager.
+                throw new CertificateException(
+                    "Improper X509TrustManager implementation");
             }
         } catch (CertificateException e) {
             // This will throw an exception, so include the original error.
--- a/jdk/src/share/classes/sun/security/ssl/Debug.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/Debug.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, 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
@@ -27,6 +27,7 @@
 
 import java.io.PrintStream;
 import java.security.AccessController;
+import java.util.Locale;
 
 import sun.security.action.GetPropertyAction;
 
@@ -44,7 +45,7 @@
     static {
         args = java.security.AccessController.doPrivileged(
             new GetPropertyAction("javax.net.debug", ""));
-        args = args.toLowerCase();
+        args = args.toLowerCase(Locale.ENGLISH);
         if (args.equals("help")) {
             Help();
         }
@@ -114,7 +115,7 @@
             return false;
         } else {
             int n = 0;
-            option = option.toLowerCase();
+            option = option.toLowerCase(Locale.ENGLISH);
 
             if (args.indexOf("all") != -1) {
                 return true;
--- a/jdk/src/share/classes/sun/security/ssl/HandshakeHash.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/HandshakeHash.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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,7 +26,13 @@
 
 package sun.security.ssl;
 
+import java.io.ByteArrayOutputStream;
 import java.security.*;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
 
 /**
  * Abstraction for the SSL/TLS hash of all handshake messages that is
@@ -36,51 +42,161 @@
  *
  * This class transparently deals with cloneable and non-cloneable digests.
  *
+ * This class now supports TLS 1.2 also. The key difference for TLS 1.2
+ * is that you cannot determine the hash algorithms for CertificateVerify
+ * at a early stage. On the other hand, it's simpler than TLS 1.1 (and earlier)
+ * that there is no messy MD5+SHA1 digests.
+ *
+ * You need to obey these conventions when using this class:
+ *
+ * 1. protocolDetermined(boolean isTLS12) should be called when the negotiated
+ * protocol version is determined.
+ *
+ * 2. Before protocolDetermined() is called, only update(), reset(),
+ * restrictCertificateVerifyAlgs(), setFinishedAlg(), and
+ * setCertificateVerifyAlg() can be called.
+ *
+ * 3. After protocolDetermined(*) is called. reset() cannot be called.
+ *
+ * 4. After protocolDetermined(false) is called, getFinishedHash() and
+ * getCertificateVerifyHash() cannot be called. After protocolDetermined(true)
+ * is called, getMD5Clone() and getSHAClone() cannot be called.
+ *
+ * 5. getMD5Clone() and getSHAClone() can only be called after
+ * protocolDetermined(false) is called.
+ *
+ * 6. getFinishedHash() and getCertificateVerifyHash() can only be called after
+ * all protocolDetermined(true), setCertificateVerifyAlg() and setFinishedAlg()
+ * have been called. If a CertificateVerify message is to be used, call
+ * setCertificateVerifyAlg() with the hash algorithm as the argument.
+ * Otherwise, you still must call setCertificateVerifyAlg(null) before
+ * calculating any hash value.
+ *
+ * Suggestions: Call protocolDetermined(), restrictCertificateVerifyAlgs(),
+ * setFinishedAlg(), and setCertificateVerifyAlg() as early as possible.
+ *
+ * Example:
+ * <pre>
+ * HandshakeHash hh = new HandshakeHash(...)
+ * hh.update(clientHelloBytes);
+ * hh.setFinishedAlg("SHA-256");
+ * hh.update(serverHelloBytes);
+ * ...
+ * hh.setCertificateVerifyAlg("SHA-384");
+ * hh.update(CertificateVerifyBytes);
+ * byte[] cvDigest = hh.getCertificateVerifyHash();
+ * ...
+ * hh.update(finished1);
+ * byte[] finDigest1 = hh.getFinishedHash();
+ * hh.update(finished2);
+ * byte[] finDigest2 = hh.getFinishedHash();
+ * </pre>
+ * If no CertificateVerify message is to be used, call
+ * <pre>
+ * hh.setCertificateVerifyAlg(null);
+ * </pre>
+ * This call can be made once you are certain that this message
+ * will never be used.
  */
 final class HandshakeHash {
 
-    private final MessageDigest md5, sha;
+    // Common
+
+    // -1:  unknown
+    //  1:  <=TLS 1.1
+    //  2:  TLS 1.2
+    private int version = -1;
+    private ByteArrayOutputStream data = new ByteArrayOutputStream();
+    private final boolean isServer;
+
+    // For TLS 1.1
+    private MessageDigest md5, sha;
+    private final int clonesNeeded;    // needs to be saved for later use
+
+    // For TLS 1.2
+    // cvAlgDetermined == true means setCertificateVerifyAlg() is called
+    private boolean cvAlgDetermined = false;
+    private String cvAlg;
+    private MessageDigest finMD;
 
     /**
      * Create a new HandshakeHash. needCertificateVerify indicates whether
-     * a hash for the certificate verify message is required.
+     * a hash for the certificate verify message is required. The argument
+     * algs is a set of all possible hash algorithms that might be used in
+     * TLS 1.2. If the caller is sure that TLS 1.2 won't be used or no
+     * CertificateVerify message will be used, leave it null or empty.
      */
-    HandshakeHash(boolean needCertificateVerify) {
-        int n = needCertificateVerify ? 3 : 2;
-        try {
-            md5 = CloneableDigest.getDigest("MD5", n);
-            sha = CloneableDigest.getDigest("SHA", n);
-        } catch (NoSuchAlgorithmException e) {
-            throw new RuntimeException
-                        ("Algorithm MD5 or SHA not available", e);
+    HandshakeHash(boolean isServer, boolean needCertificateVerify,
+            Set<String> algs) {
+        this.isServer = isServer;
+        clonesNeeded = needCertificateVerify ? 3 : 2;
+    }
 
+    void update(byte[] b, int offset, int len) {
+        switch (version) {
+            case 1:
+                md5.update(b, offset, len);
+                sha.update(b, offset, len);
+                break;
+            default:
+                if (finMD != null) {
+                    finMD.update(b, offset, len);
+                }
+                data.write(b, offset, len);
+                break;
         }
     }
 
-    void update(byte b) {
-        md5.update(b);
-        sha.update(b);
-    }
-
-    void update(byte[] b, int offset, int len) {
-        md5.update(b, offset, len);
-        sha.update(b, offset, len);
-    }
-
     /**
-     * Reset the remaining digests. Note this does *not* reset the numbe of
+     * Reset the remaining digests. Note this does *not* reset the number of
      * digest clones that can be obtained. Digests that have already been
      * cloned and are gone remain gone.
      */
     void reset() {
-        md5.reset();
-        sha.reset();
+        if (version != -1) {
+            throw new RuntimeException(
+                    "reset() can be only be called before protocolDetermined");
+        }
+        data.reset();
     }
 
+
+    void protocolDetermined(boolean isTLS12) {
+
+        // Do not set again, will ignore
+        if (version != -1) return;
+
+        version = isTLS12 ? 2 : 1;
+        switch (version) {
+            case 1:
+                // initiate md5, sha and call update on saved array
+                try {
+                    md5 = CloneableDigest.getDigest("MD5", clonesNeeded);
+                    sha = CloneableDigest.getDigest("SHA", clonesNeeded);
+                } catch (NoSuchAlgorithmException e) {
+                    throw new RuntimeException
+                                ("Algorithm MD5 or SHA not available", e);
+                }
+                byte[] bytes = data.toByteArray();
+                update(bytes, 0, bytes.length);
+                break;
+            case 2:
+                break;
+        }
+    }
+
+    /////////////////////////////////////////////////////////////
+    // Below are old methods for pre-TLS 1.1
+    /////////////////////////////////////////////////////////////
+
     /**
      * Return a new MD5 digest updated with all data hashed so far.
      */
     MessageDigest getMD5Clone() {
+        if (version != 1) {
+            throw new RuntimeException(
+                    "getMD5Clone() can be only be called for TLS 1.1");
+        }
         return cloneDigest(md5);
     }
 
@@ -88,6 +204,10 @@
      * Return a new SHA digest updated with all data hashed so far.
      */
     MessageDigest getSHAClone() {
+        if (version != 1) {
+            throw new RuntimeException(
+                    "getSHAClone() can be only be called for TLS 1.1");
+        }
         return cloneDigest(sha);
     }
 
@@ -100,6 +220,181 @@
         }
     }
 
+    /////////////////////////////////////////////////////////////
+    // Below are new methods for TLS 1.2
+    /////////////////////////////////////////////////////////////
+
+    private static String normalizeAlgName(String alg) {
+        alg = alg.toUpperCase(Locale.US);
+        if (alg.startsWith("SHA")) {
+            if (alg.length() == 3) {
+                return "SHA-1";
+            }
+            if (alg.charAt(3) != '-') {
+                return "SHA-" + alg.substring(3);
+            }
+        }
+        return alg;
+    }
+    /**
+     * Specifies the hash algorithm used in Finished. This should be called
+     * based in info in ServerHello.
+     * Can be called multiple times.
+     */
+    void setFinishedAlg(String s) {
+        if (s == null) {
+            throw new RuntimeException(
+                    "setFinishedAlg's argument cannot be null");
+        }
+
+        // Can be called multiple times, but only set once
+        if (finMD != null) return;
+
+        try {
+            finMD = CloneableDigest.getDigest(normalizeAlgName(s), 2);
+        } catch (NoSuchAlgorithmException e) {
+            throw new Error(e);
+        }
+        finMD.update(data.toByteArray());
+    }
+
+    /**
+     * Restricts the possible algorithms for the CertificateVerify. Called by
+     * the server based on info in CertRequest. The argument must be a subset
+     * of the argument with the same name in the constructor. The method can be
+     * called multiple times. If the caller is sure that no CertificateVerify
+     * message will be used, leave this argument null or empty.
+     */
+    void restrictCertificateVerifyAlgs(Set<String> algs) {
+        if (version == 1) {
+            throw new RuntimeException(
+                    "setCertificateVerifyAlg() cannot be called for TLS 1.1");
+        }
+        // Not used yet
+    }
+
+    /**
+     * Specifies the hash algorithm used in CertificateVerify.
+     * Can be called multiple times.
+     */
+    void setCertificateVerifyAlg(String s) {
+
+        // Can be called multiple times, but only set once
+        if (cvAlgDetermined) return;
+
+        cvAlg = s == null ? null : normalizeAlgName(s);
+        cvAlgDetermined = true;
+    }
+
+    byte[] getAllHandshakeMessages() {
+        return data.toByteArray();
+    }
+
+    /**
+     * Calculates the hash in the CertificateVerify. Must be called right
+     * after setCertificateVerifyAlg()
+     */
+    /*byte[] getCertificateVerifyHash() {
+        throw new Error("Do not call getCertificateVerifyHash()");
+    }*/
+
+    /**
+     * Calculates the hash in Finished. Must be called after setFinishedAlg().
+     * This method can be called twice, for Finished messages of the server
+     * side and client side respectively.
+     */
+    byte[] getFinishedHash() {
+        try {
+            return cloneDigest(finMD).digest();
+        } catch (Exception e) {
+            throw new Error("BAD");
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////
+    // TEST
+    ////////////////////////////////////////////////////////////////
+
+    public static void main(String[] args) throws Exception {
+        Test t = new Test();
+        t.test(null, "SHA-256");
+        t.test("", "SHA-256");
+        t.test("SHA-1", "SHA-256");
+        t.test("SHA-256", "SHA-256");
+        t.test("SHA-384", "SHA-256");
+        t.test("SHA-512", "SHA-256");
+        t.testSame("sha", "SHA-1");
+        t.testSame("SHA", "SHA-1");
+        t.testSame("SHA1", "SHA-1");
+        t.testSame("SHA-1", "SHA-1");
+        t.testSame("SHA256", "SHA-256");
+        t.testSame("SHA-256", "SHA-256");
+    }
+
+    static class Test {
+        void update(HandshakeHash hh, String s) {
+            hh.update(s.getBytes(), 0, s.length());
+        }
+        static byte[] digest(String alg, String data) throws Exception {
+            return MessageDigest.getInstance(alg).digest(data.getBytes());
+        }
+        static void equals(byte[] b1, byte[] b2) {
+            if (!Arrays.equals(b1, b2)) {
+                throw new RuntimeException("Bad");
+            }
+        }
+        void testSame(String a, String a2) {
+            System.out.println("testSame: " + a + " " + a2);
+            if (!HandshakeHash.normalizeAlgName(a).equals(a2)) {
+                throw new RuntimeException("Bad");
+            }
+        }
+        /**
+         * Special convention: when it's certain that CV will not be used at the
+         * very beginning, use null as cvAlg. If known at a late stage, use "".
+         */
+        void test(String cvAlg, String finAlg) throws Exception {
+            System.out.println("test: " + cvAlg + " " + finAlg);
+            byte[] cv = null, f1, f2;
+            HandshakeHash hh = new HandshakeHash(true, true, null);
+            if (cvAlg == null) {
+                hh.setCertificateVerifyAlg(cvAlg);
+            }
+
+            update(hh, "ClientHello,");
+            hh.reset();
+            update(hh, "ClientHellov2,");
+            hh.setFinishedAlg(finAlg);
+
+            // Useless calls
+            hh.setFinishedAlg("SHA-1");
+            hh.setFinishedAlg("SHA-512");
+
+            update(hh, "More,");
+            if (cvAlg != null) {
+                if (cvAlg.isEmpty()) cvAlg = null;
+                hh.setCertificateVerifyAlg(cvAlg);
+            }
+
+            // Useless calls
+            hh.setCertificateVerifyAlg("SHA-1");
+            hh.setCertificateVerifyAlg(null);
+
+            hh.protocolDetermined(true);
+
+            if (cvAlg != null) {
+                cv = hh.getAllHandshakeMessages();
+                equals(cv, "ClientHellov2,More,".getBytes());
+            }
+
+            update(hh, "FIN1,");
+            f1 = hh.getFinishedHash();
+            equals(f1, digest(finAlg, "ClientHellov2,More,FIN1,"));
+            update(hh, "FIN2,");
+            f2 = hh.getFinishedHash();
+            equals(f2, digest(finAlg, "ClientHellov2,More,FIN1,FIN2,"));
+        }
+    }
 }
 
 /**
--- a/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
+ * copyright (c) 1996, 2010, 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
@@ -41,15 +41,12 @@
 
 import javax.crypto.KeyGenerator;
 import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
 
 import javax.net.ssl.*;
 
-import sun.security.action.GetPropertyAction;
-
 import sun.security.internal.spec.TlsPrfParameterSpec;
-
 import sun.security.ssl.CipherSuite.*;
+import static sun.security.ssl.CipherSuite.PRF.*;
 
 /**
  * Many data structures are involved in the handshake messages.  These
@@ -258,6 +255,27 @@
         extensions.add(renegotiationInfo);
     }
 
+    // add server_name extension
+    void addServerNameIndicationExtension(String hostname) {
+        // We would have checked that the hostname ia a FQDN.
+        ArrayList<String> hostnames = new ArrayList<String>(1);
+        hostnames.add(hostname);
+
+        try {
+            extensions.add(new ServerNameExtension(hostnames));
+        } catch (IOException ioe) {
+            // ignore the exception and return
+        }
+    }
+
+    // add signature_algorithm extension
+    void addSignatureAlgorithmsExtension(
+            Collection<SignatureAndHashAlgorithm> algorithms) {
+        HelloExtension signatureAlgorithm =
+                new SignatureAlgorithmsExtension(algorithms);
+        extensions.add(signatureAlgorithm);
+    }
+
     @Override
     int messageType() { return ht_client_hello; }
 
@@ -290,7 +308,8 @@
         s.println("*** ClientHello, " + protocolVersion);
 
         if (debug != null && Debug.isOn("verbose")) {
-            s.print   ("RandomCookie:  "); clnt_random.print(s);
+            s.print("RandomCookie:  ");
+            clnt_random.print(s);
 
             s.print("Session ID:  ");
             s.println(sessionId);
@@ -327,7 +346,8 @@
         // empty
     }
 
-    ServerHello(HandshakeInStream input, int messageLength) throws IOException {
+    ServerHello(HandshakeInStream input, int messageLength)
+            throws IOException {
         protocolVersion = ProtocolVersion.valueOf(input.getInt8(),
                                                   input.getInt8());
         svr_random = new RandomCookie(input);
@@ -367,7 +387,8 @@
         s.println("*** ServerHello, " + protocolVersion);
 
         if (debug != null && Debug.isOn("verbose")) {
-            s.print   ("RandomCookie:  "); svr_random.print(s);
+            s.print("RandomCookie:  ");
+            svr_random.print(s);
 
             int i;
 
@@ -425,8 +446,8 @@
                 }
                 v.add(cf.generateCertificate(new ByteArrayInputStream(cert)));
             } catch (CertificateException e) {
-                throw (SSLProtocolException)new SSLProtocolException
-                        (e.getMessage()).initCause(e);
+                throw (SSLProtocolException)new SSLProtocolException(
+                    e.getMessage()).initCause(e);
             }
         }
 
@@ -469,7 +490,7 @@
     }
 
     X509Certificate[] getCertificateChain() {
-        return chain;
+        return chain.clone();
     }
 }
 
@@ -597,9 +618,9 @@
         try {
             KeyFactory kfac = JsseJce.getKeyFactory("RSA");
             // modulus and exponent are always positive
-            RSAPublicKeySpec kspec = new RSAPublicKeySpec
-                                         (new BigInteger(1, rsa_modulus),
-                                          new BigInteger(1, rsa_exponent));
+            RSAPublicKeySpec kspec = new RSAPublicKeySpec(
+                new BigInteger(1, rsa_modulus),
+                new BigInteger(1, rsa_exponent));
             return kfac.generatePublic(kspec);
         } catch (Exception e) {
             throw new RuntimeException(e);
@@ -667,6 +688,12 @@
 
     private byte                signature [];
 
+    // protocol version being established using this ServerKeyExchange message
+    ProtocolVersion protocolVersion;
+
+    // the preferable signature algorithm used by this ServerKeyExchange message
+    private SignatureAndHashAlgorithm preferableSignatureAlgorithm;
+
     /* Return the Diffie-Hellman modulus */
     BigInteger getModulus() {
         return new BigInteger(1, dh_p);
@@ -712,8 +739,11 @@
      * Construct from initialized DH key object, for DH_anon
      * key exchange.
      */
-    DH_ServerKeyExchange(DHCrypt obj) {
-        getValues(obj);
+    DH_ServerKeyExchange(DHCrypt obj, ProtocolVersion protocolVersion) {
+        this.protocolVersion = protocolVersion;
+        this.preferableSignatureAlgorithm = null;
+
+        setValues(obj);
         signature = null;
     }
 
@@ -723,22 +753,33 @@
      * key exchange.  (Constructor called by server.)
      */
     DH_ServerKeyExchange(DHCrypt obj, PrivateKey key, byte clntNonce[],
-            byte svrNonce[], SecureRandom sr) throws GeneralSecurityException {
+            byte svrNonce[], SecureRandom sr,
+            SignatureAndHashAlgorithm signAlgorithm,
+            ProtocolVersion protocolVersion) throws GeneralSecurityException {
 
-        getValues(obj);
+        this.protocolVersion = protocolVersion;
+
+        setValues(obj);
 
         Signature sig;
-        if (key.getAlgorithm().equals("DSA")) {
-            sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            this.preferableSignatureAlgorithm = signAlgorithm;
+            sig = JsseJce.getSignature(signAlgorithm.getAlgorithmName());
         } else {
-            sig = RSASignature.getInstance();
+            this.preferableSignatureAlgorithm = null;
+            if (key.getAlgorithm().equals("DSA")) {
+                sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
+            } else {
+                sig = RSASignature.getInstance();
+            }
         }
+
         sig.initSign(key, sr);
         updateSignature(sig, clntNonce, svrNonce);
         signature = sig.sign();
     }
 
-    private void getValues(DHCrypt obj) {
+    private void setValues(DHCrypt obj) {
         dh_p = toByteArray(obj.getModulus());
         dh_g = toByteArray(obj.getBase());
         dh_Ys = toByteArray(obj.getPublicKey());
@@ -749,7 +790,12 @@
      * stream, as if sent from server to client for use with
      * DH_anon key exchange
      */
-    DH_ServerKeyExchange(HandshakeInStream input) throws IOException {
+    DH_ServerKeyExchange(HandshakeInStream input,
+            ProtocolVersion protocolVersion) throws IOException {
+
+        this.protocolVersion = protocolVersion;
+        this.preferableSignatureAlgorithm = null;
+
         dh_p = input.getBytes16();
         dh_g = input.getBytes16();
         dh_Ys = input.getBytes16();
@@ -762,13 +808,38 @@
      * DHE_DSS or DHE_RSA key exchange.  (Called by client.)
      */
     DH_ServerKeyExchange(HandshakeInStream input, PublicKey publicKey,
-            byte clntNonce[], byte svrNonce[], int messageSize)
+            byte clntNonce[], byte svrNonce[], int messageSize,
+            Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs,
+            ProtocolVersion protocolVersion)
             throws IOException, GeneralSecurityException {
 
+        this.protocolVersion = protocolVersion;
+
+        // read params: ServerDHParams
         dh_p = input.getBytes16();
         dh_g = input.getBytes16();
         dh_Ys = input.getBytes16();
 
+        // read the signature and hash algorithm
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            int hash = input.getInt8();         // hash algorithm
+            int signature = input.getInt8();    // signature algorithm
+
+            preferableSignatureAlgorithm =
+                SignatureAndHashAlgorithm.valueOf(hash, signature, 0);
+
+            // Is it a local supported signature algorithm?
+            if (!localSupportedSignAlgs.contains(
+                    preferableSignatureAlgorithm)) {
+                throw new SSLHandshakeException(
+                        "Unsupported SignatureAndHashAlgorithm in " +
+                        "ServerKeyExchange message");
+            }
+        } else {
+            this.preferableSignatureAlgorithm = null;
+        }
+
+        // read the signature
         byte signature[];
         if (dhKeyExchangeFix) {
             signature = input.getBytes16();
@@ -783,12 +854,17 @@
 
         Signature sig;
         String algorithm = publicKey.getAlgorithm();
-        if (algorithm.equals("DSA")) {
-            sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
-        } else if (algorithm.equals("RSA")) {
-            sig = RSASignature.getInstance();
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            sig = JsseJce.getSignature(
+                        preferableSignatureAlgorithm.getAlgorithmName());
         } else {
-            throw new SSLKeyException("neither an RSA or a DSA key");
+            if (algorithm.equals("DSA")) {
+                sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
+            } else if (algorithm.equals("RSA")) {
+                sig = RSASignature.getInstance();
+            } else {
+                throw new SSLKeyException("neither an RSA or a DSA key");
+            }
         }
 
         sig.initVerify(publicKey);
@@ -805,12 +881,18 @@
         temp += dh_p.length;
         temp += dh_g.length;
         temp += dh_Ys.length;
+
         if (signature != null) {
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                temp += SignatureAndHashAlgorithm.sizeInRecord();
+            }
+
             temp += signature.length;
             if (dhKeyExchangeFix) {
                 temp += 2;
             }
         }
+
         return temp;
     }
 
@@ -818,7 +900,13 @@
         s.putBytes16(dh_p);
         s.putBytes16(dh_g);
         s.putBytes16(dh_Ys);
+
         if (signature != null) {
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                s.putInt8(preferableSignatureAlgorithm.getHashValue());
+                s.putInt8(preferableSignatureAlgorithm.getSignatureValue());
+            }
+
             if (dhKeyExchangeFix) {
                 s.putBytes16(signature);
             } else {
@@ -838,6 +926,11 @@
             if (signature == null) {
                 s.println("Anonymous");
             } else {
+                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                    s.println("Signature Algorithm " +
+                        preferableSignatureAlgorithm.getAlgorithmName());
+                }
+
                 s.println("Signed with a DSA or RSA public key");
             }
         }
@@ -871,9 +964,19 @@
     // public key object encapsulated in this message
     private ECPublicKey publicKey;
 
+    // protocol version being established using this ServerKeyExchange message
+    ProtocolVersion protocolVersion;
+
+    // the preferable signature algorithm used by this ServerKeyExchange message
+    private SignatureAndHashAlgorithm preferableSignatureAlgorithm;
+
     ECDH_ServerKeyExchange(ECDHCrypt obj, PrivateKey privateKey,
-            byte[] clntNonce, byte[] svrNonce, SecureRandom sr)
-            throws GeneralSecurityException {
+            byte[] clntNonce, byte[] svrNonce, SecureRandom sr,
+            SignatureAndHashAlgorithm signAlgorithm,
+            ProtocolVersion protocolVersion) throws GeneralSecurityException {
+
+        this.protocolVersion = protocolVersion;
+
         publicKey = (ECPublicKey)obj.getPublicKey();
         ECParameterSpec params = publicKey.getParams();
         ECPoint point = publicKey.getW();
@@ -885,8 +988,14 @@
             return;
         }
 
-        Signature sig = getSignature(privateKey.getAlgorithm());
-        sig.initSign(privateKey);
+        Signature sig;
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            this.preferableSignatureAlgorithm = signAlgorithm;
+            sig = JsseJce.getSignature(signAlgorithm.getAlgorithmName());
+        } else {
+            sig = getSignature(privateKey.getAlgorithm());
+        }
+        sig.initSign(privateKey);  // where is the SecureRandom?
 
         updateSignature(sig, clntNonce, svrNonce);
         signatureBytes = sig.sign();
@@ -896,49 +1005,87 @@
      * Parse an ECDH server key exchange message.
      */
     ECDH_ServerKeyExchange(HandshakeInStream input, PublicKey signingKey,
-            byte[] clntNonce, byte[] svrNonce)
+            byte[] clntNonce, byte[] svrNonce,
+            Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs,
+            ProtocolVersion protocolVersion)
             throws IOException, GeneralSecurityException {
+
+        this.protocolVersion = protocolVersion;
+
+        // read params: ServerECDHParams
         int curveType = input.getInt8();
         ECParameterSpec parameters;
         // These parsing errors should never occur as we negotiated
         // the supported curves during the exchange of the Hello messages.
         if (curveType == CURVE_NAMED_CURVE) {
             curveId = input.getInt16();
-            if (SupportedEllipticCurvesExtension.isSupported(curveId) == false) {
-                throw new SSLHandshakeException("Unsupported curveId: " + curveId);
+            if (SupportedEllipticCurvesExtension.isSupported(curveId)
+                    == false) {
+                throw new SSLHandshakeException(
+                    "Unsupported curveId: " + curveId);
             }
-            String curveOid = SupportedEllipticCurvesExtension.getCurveOid(curveId);
+            String curveOid =
+                SupportedEllipticCurvesExtension.getCurveOid(curveId);
             if (curveOid == null) {
-                throw new SSLHandshakeException("Unknown named curve: " + curveId);
+                throw new SSLHandshakeException(
+                    "Unknown named curve: " + curveId);
             }
             parameters = JsseJce.getECParameterSpec(curveOid);
             if (parameters == null) {
-                throw new SSLHandshakeException("Unsupported curve: " + curveOid);
+                throw new SSLHandshakeException(
+                    "Unsupported curve: " + curveOid);
             }
         } else {
-            throw new SSLHandshakeException("Unsupported ECCurveType: " + curveType);
+            throw new SSLHandshakeException(
+                "Unsupported ECCurveType: " + curveType);
         }
         pointBytes = input.getBytes8();
 
         ECPoint point = JsseJce.decodePoint(pointBytes, parameters.getCurve());
         KeyFactory factory = JsseJce.getKeyFactory("EC");
-        publicKey = (ECPublicKey)factory.generatePublic(new ECPublicKeySpec(point, parameters));
+        publicKey = (ECPublicKey)factory.generatePublic(
+            new ECPublicKeySpec(point, parameters));
 
         if (signingKey == null) {
             // ECDH_anon
             return;
         }
 
-        // verify the signature
+        // read the signature and hash algorithm
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            int hash = input.getInt8();         // hash algorithm
+            int signature = input.getInt8();    // signature algorithm
+
+            preferableSignatureAlgorithm =
+                SignatureAndHashAlgorithm.valueOf(hash, signature, 0);
+
+            // Is it a local supported signature algorithm?
+            if (!localSupportedSignAlgs.contains(
+                    preferableSignatureAlgorithm)) {
+                throw new SSLHandshakeException(
+                        "Unsupported SignatureAndHashAlgorithm in " +
+                        "ServerKeyExchange message");
+            }
+        }
+
+        // read the signature
         signatureBytes = input.getBytes16();
-        Signature sig = getSignature(signingKey.getAlgorithm());
+
+        // verify the signature
+        Signature sig;
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            sig = JsseJce.getSignature(
+                        preferableSignatureAlgorithm.getAlgorithmName());
+        } else {
+            sig = getSignature(signingKey.getAlgorithm());
+        }
         sig.initVerify(signingKey);
 
         updateSignature(sig, clntNonce, svrNonce);
 
         if (sig.verify(signatureBytes) == false ) {
-            throw new SSLKeyException
-                ("Invalid signature on ECDH server key exchange message");
+            throw new SSLKeyException(
+                "Invalid signature on ECDH server key exchange message");
         }
     }
 
@@ -949,7 +1096,8 @@
         return publicKey;
     }
 
-    private static Signature getSignature(String keyAlgorithm) throws NoSuchAlgorithmException {
+    private static Signature getSignature(String keyAlgorithm)
+            throws NoSuchAlgorithmException {
         if (keyAlgorithm.equals("EC")) {
             return JsseJce.getSignature(JsseJce.SIGNATURE_ECDSA);
         } else if (keyAlgorithm.equals("RSA")) {
@@ -973,6 +1121,11 @@
 
     int messageLength() {
         int sigLen = (signatureBytes == null) ? 0 : 2 + signatureBytes.length;
+
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            sigLen += SignatureAndHashAlgorithm.sizeInRecord();
+        }
+
         return 4 + pointBytes.length + sigLen;
     }
 
@@ -980,6 +1133,11 @@
         s.putInt8(CURVE_NAMED_CURVE);
         s.putInt16(curveId);
         s.putBytes8(pointBytes);
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            s.putInt8(preferableSignatureAlgorithm.getHashValue());
+            s.putInt8(preferableSignatureAlgorithm.getSignatureValue());
+        }
+
         if (signatureBytes != null) {
             s.putBytes16(signatureBytes);
         }
@@ -989,6 +1147,11 @@
         s.println("*** ECDH ServerKeyExchange");
 
         if (debug != null && Debug.isOn("verbose")) {
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                s.println("Signature Algorithm " +
+                        preferableSignatureAlgorithm.getAlgorithmName());
+            }
+
             s.println("Server key: " + publicKey);
         }
     }
@@ -1014,8 +1177,8 @@
         try {
             return new X500Principal(name);
         } catch (IllegalArgumentException e) {
-            throw (SSLProtocolException)new SSLProtocolException
-                    (e.getMessage()).initCause(e);
+            throw (SSLProtocolException)new SSLProtocolException(
+                e.getMessage()).initCause(e);
         }
     }
 
@@ -1038,12 +1201,25 @@
  *
  * Authenticated servers may ask clients to authenticate themselves
  * in turn, using this message.
+ *
+ * Prior to TLS 1.2, the structure of the message is defined as:
+ *     struct {
+ *         ClientCertificateType certificate_types<1..2^8-1>;
+ *         DistinguishedName certificate_authorities<0..2^16-1>;
+ *     } CertificateRequest;
+ *
+ * In TLS 1.2, the structure is changed to:
+ *     struct {
+ *         ClientCertificateType certificate_types<1..2^8-1>;
+ *         SignatureAndHashAlgorithm
+ *           supported_signature_algorithms<2^16-1>;
+ *         DistinguishedName certificate_authorities<0..2^16-1>;
+ *     } CertificateRequest;
+ *
  */
 static final
 class CertificateRequest extends HandshakeMessage
 {
-    int messageType() { return ht_certificate_request; }
-
     // enum ClientCertificateType
     static final int   cct_rsa_sign = 1;
     static final int   cct_dss_sign = 2;
@@ -1068,8 +1244,21 @@
     DistinguishedName   authorities [];         // 3 to 2^16 - 1
         // ... "3" because that's the smallest DER-encoded X500 DN
 
-    CertificateRequest(X509Certificate ca[], KeyExchange keyExchange)
-            throws IOException {
+    // protocol version being established using this CertificateRequest message
+    ProtocolVersion protocolVersion;
+
+    // supported_signature_algorithms for TLS 1.2 or later
+    private Collection<SignatureAndHashAlgorithm> algorithms;
+
+    // length of supported_signature_algorithms
+    private int algorithmsLen;
+
+    CertificateRequest(X509Certificate ca[], KeyExchange keyExchange,
+            Collection<SignatureAndHashAlgorithm> signAlgs,
+            ProtocolVersion protocolVersion) throws IOException {
+
+        this.protocolVersion = protocolVersion;
+
         // always use X500Principal
         authorities = new DistinguishedName[ca.length];
         for (int i = 0; i < ca.length; i++) {
@@ -1081,10 +1270,63 @@
         // needs to be adapted to take keyExchange into account.
         // We only request ECDSA client auth if we have ECC crypto available.
         this.types = JsseJce.isEcAvailable() ? TYPES_ECC : TYPES_NO_ECC;
+
+        // Use supported_signature_algorithms for TLS 1.2 or later.
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            if (signAlgs == null || signAlgs.isEmpty()) {
+                throw new SSLProtocolException(
+                        "No supported signature algorithms");
+            }
+
+            algorithms = new ArrayList<SignatureAndHashAlgorithm>(signAlgs);
+            algorithmsLen =
+                SignatureAndHashAlgorithm.sizeInRecord() * algorithms.size();
+        } else {
+            algorithms = new ArrayList<SignatureAndHashAlgorithm>();
+            algorithmsLen = 0;
+        }
     }
 
-    CertificateRequest(HandshakeInStream input) throws IOException {
+    CertificateRequest(HandshakeInStream input,
+            ProtocolVersion protocolVersion) throws IOException {
+
+        this.protocolVersion = protocolVersion;
+
+        // Read the certificate_types.
         types = input.getBytes8();
+
+        // Read the supported_signature_algorithms for TLS 1.2 or later.
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            algorithmsLen = input.getInt16();
+            if (algorithmsLen < 2) {
+                throw new SSLProtocolException(
+                        "Invalid supported_signature_algorithms field");
+            }
+
+            algorithms = new ArrayList<SignatureAndHashAlgorithm>();
+            int remains = algorithmsLen;
+            int sequence = 0;
+            while (remains > 1) {    // needs at least two bytes
+                int hash = input.getInt8();         // hash algorithm
+                int signature = input.getInt8();    // signature algorithm
+
+                SignatureAndHashAlgorithm algorithm =
+                    SignatureAndHashAlgorithm.valueOf(hash, signature,
+                                                                ++sequence);
+                algorithms.add(algorithm);
+                remains -= 2;  // one byte for hash, one byte for signature
+            }
+
+            if (remains != 0) {
+                throw new SSLProtocolException(
+                        "Invalid supported_signature_algorithms field");
+            }
+        } else {
+            algorithms = new ArrayList<SignatureAndHashAlgorithm>();
+            algorithmsLen = 0;
+        }
+
+        // read the certificate_authorities
         int len = input.getInt16();
         ArrayList<DistinguishedName> v = new ArrayList<DistinguishedName>();
         while (len >= 3) {
@@ -1108,31 +1350,58 @@
         return ret;
     }
 
-    int messageLength()
-    {
-        int len;
+    Collection<SignatureAndHashAlgorithm> getSignAlgorithms() {
+        return algorithms;
+    }
+
+    @Override
+    int messageType() {
+        return ht_certificate_request;
+    }
 
-        len = 1 + types.length + 2;
-        for (int i = 0; i < authorities.length; i++)
+    @Override
+    int messageLength() {
+        int len = 1 + types.length + 2;
+
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            len += algorithmsLen + 2;
+        }
+
+        for (int i = 0; i < authorities.length; i++) {
             len += authorities[i].length();
+        }
+
         return len;
     }
 
-    void send(HandshakeOutStream output) throws IOException
-    {
-        int     len = 0;
+    @Override
+    void send(HandshakeOutStream output) throws IOException {
+        // put certificate_types
+        output.putBytes8(types);
 
-        for (int i = 0; i < authorities.length; i++)
+        // put supported_signature_algorithms
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            output.putInt16(algorithmsLen);
+            for (SignatureAndHashAlgorithm algorithm : algorithms) {
+                output.putInt8(algorithm.getHashValue());      // hash
+                output.putInt8(algorithm.getSignatureValue()); // signature
+            }
+        }
+
+        // put certificate_authorities
+        int len = 0;
+        for (int i = 0; i < authorities.length; i++) {
             len += authorities[i].length();
+        }
 
-        output.putBytes8(types);
         output.putInt16(len);
-        for (int i = 0; i < authorities.length; i++)
+        for (int i = 0; i < authorities.length; i++) {
             authorities[i].send(output);
+        }
     }
 
-    void print(PrintStream s) throws IOException
-    {
+    @Override
+    void print(PrintStream s) throws IOException {
         s.println("*** CertificateRequest");
 
         if (debug != null && Debug.isOn("verbose")) {
@@ -1166,9 +1435,28 @@
             }
             s.println();
 
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                StringBuffer buffer = new StringBuffer();
+                boolean opened = false;
+                for (SignatureAndHashAlgorithm signAlg : algorithms) {
+                    if (opened) {
+                        buffer.append(", " + signAlg.getAlgorithmName());
+                    } else {
+                        buffer.append(signAlg.getAlgorithmName());
+                        opened = true;
+                    }
+                }
+                s.println("Supported Signature Algorithms: " + buffer);
+            }
+
             s.println("Cert Authorities:");
-            for (int i = 0; i < authorities.length; i++)
-                authorities[i].print(s);
+            if (authorities.length == 0) {
+                s.println("<Empty>");
+            } else {
+                for (int i = 0; i < authorities.length; i++) {
+                    authorities[i].print(s);
+                }
+            }
         }
     }
 }
@@ -1219,18 +1507,34 @@
  */
 static final class CertificateVerify extends HandshakeMessage {
 
-    int messageType() { return ht_certificate_verify; }
+    // the signature bytes
+    private byte[] signature;
 
-    private byte[] signature;
+    // protocol version being established using this ServerKeyExchange message
+    ProtocolVersion protocolVersion;
+
+    // the preferable signature algorithm used by this CertificateVerify message
+    private SignatureAndHashAlgorithm preferableSignatureAlgorithm = null;
 
     /*
      * Create an RSA or DSA signed certificate verify message.
      */
-    CertificateVerify(ProtocolVersion protocolVersion, HandshakeHash
-            handshakeHash, PrivateKey privateKey, SecretKey masterSecret,
-            SecureRandom sr) throws GeneralSecurityException {
+    CertificateVerify(ProtocolVersion protocolVersion,
+            HandshakeHash handshakeHash, PrivateKey privateKey,
+            SecretKey masterSecret, SecureRandom sr,
+            SignatureAndHashAlgorithm signAlgorithm)
+            throws GeneralSecurityException {
+
+        this.protocolVersion = protocolVersion;
+
         String algorithm = privateKey.getAlgorithm();
-        Signature sig = getSignature(protocolVersion, algorithm);
+        Signature sig = null;
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            this.preferableSignatureAlgorithm = signAlgorithm;
+            sig = JsseJce.getSignature(signAlgorithm.getAlgorithmName());
+        } else {
+            sig = getSignature(protocolVersion, algorithm);
+        }
         sig.initSign(privateKey, sr);
         updateSignature(sig, protocolVersion, handshakeHash, algorithm,
                         masterSecret);
@@ -1240,11 +1544,41 @@
     //
     // Unmarshal the signed data from the input stream.
     //
-    CertificateVerify(HandshakeInStream input) throws IOException  {
+    CertificateVerify(HandshakeInStream input,
+            Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs,
+            ProtocolVersion protocolVersion) throws IOException  {
+
+        this.protocolVersion = protocolVersion;
+
+        // read the signature and hash algorithm
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            int hashAlg = input.getInt8();         // hash algorithm
+            int signAlg = input.getInt8();         // signature algorithm
+
+            preferableSignatureAlgorithm =
+                SignatureAndHashAlgorithm.valueOf(hashAlg, signAlg, 0);
+
+            // Is it a local supported signature algorithm?
+            if (!localSupportedSignAlgs.contains(
+                    preferableSignatureAlgorithm)) {
+                throw new SSLHandshakeException(
+                        "Unsupported SignatureAndHashAlgorithm in " +
+                        "ServerKeyExchange message");
+            }
+        }
+
+        // read the signature
         signature = input.getBytes16();
     }
 
     /*
+     * Get the preferable signature algorithm used by this message
+     */
+    SignatureAndHashAlgorithm getPreferableSignatureAlgorithm() {
+        return preferableSignatureAlgorithm;
+    }
+
+    /*
      * Verify a certificate verify message. Return the result of verification,
      * if there is a problem throw a GeneralSecurityException.
      */
@@ -1252,7 +1586,13 @@
             HandshakeHash handshakeHash, PublicKey publicKey,
             SecretKey masterSecret) throws GeneralSecurityException {
         String algorithm = publicKey.getAlgorithm();
-        Signature sig = getSignature(protocolVersion, algorithm);
+        Signature sig = null;
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            sig = JsseJce.getSignature(
+                        preferableSignatureAlgorithm.getAlgorithmName());
+        } else {
+            sig = getSignature(protocolVersion, algorithm);
+        }
         sig.initVerify(publicKey);
         updateSignature(sig, protocolVersion, handshakeHash, algorithm,
                         masterSecret);
@@ -1286,25 +1626,35 @@
             ProtocolVersion protocolVersion,
             HandshakeHash handshakeHash, String algorithm, SecretKey masterKey)
             throws SignatureException {
-        MessageDigest md5Clone = handshakeHash.getMD5Clone();
-        MessageDigest shaClone = handshakeHash.getSHAClone();
-        boolean tls = protocolVersion.v >= ProtocolVersion.TLS10.v;
+
         if (algorithm.equals("RSA")) {
-            if (tls) {
-                // nothing to do
-            } else { // SSLv3
-                updateDigest(md5Clone, MD5_pad1, MD5_pad2, masterKey);
-                updateDigest(shaClone, SHA_pad1, SHA_pad2, masterKey);
+            if (protocolVersion.v < ProtocolVersion.TLS12.v) { // TLS1.1-
+                MessageDigest md5Clone = handshakeHash.getMD5Clone();
+                MessageDigest shaClone = handshakeHash.getSHAClone();
+
+                if (protocolVersion.v < ProtocolVersion.TLS10.v) { // SSLv3
+                    updateDigest(md5Clone, MD5_pad1, MD5_pad2, masterKey);
+                    updateDigest(shaClone, SHA_pad1, SHA_pad2, masterKey);
+                }
+
+                // The signature must be an instance of RSASignature, need
+                // to use these hashes directly.
+                RSASignature.setHashes(sig, md5Clone, shaClone);
+            } else {  // TLS1.2+
+                sig.update(handshakeHash.getAllHandshakeMessages());
             }
-            // need to use these hashes directly
-            RSASignature.setHashes(sig, md5Clone, shaClone);
         } else { // DSA, ECDSA
-            if (tls) {
-                // nothing to do
-            } else { // SSLv3
-                updateDigest(shaClone, SHA_pad1, SHA_pad2, masterKey);
+            if (protocolVersion.v < ProtocolVersion.TLS12.v) { // TLS1.1-
+                MessageDigest shaClone = handshakeHash.getSHAClone();
+
+                if (protocolVersion.v < ProtocolVersion.TLS10.v) { // SSLv3
+                    updateDigest(shaClone, SHA_pad1, SHA_pad2, masterKey);
+                }
+
+                sig.update(shaClone.digest());
+            } else {  // TLS1.2+
+                sig.update(handshakeHash.getAllHandshakeMessages());
             }
-            sig.update(shaClone.digest());
         }
     }
 
@@ -1314,7 +1664,8 @@
      * all preceding handshake messages.
      * Used by the Finished class as well.
      */
-    static void updateDigest(MessageDigest md, byte[] pad1, byte[] pad2,
+    private static void updateDigest(MessageDigest md,
+            byte[] pad1, byte[] pad2,
             SecretKey masterSecret) {
         // Digest the key bytes if available.
         // Otherwise (sensitive key), try digesting the key directly.
@@ -1390,26 +1741,54 @@
                 methodCache.put(clazz, r);
             }
             if (r == NULL_OBJECT) {
-                throw new Exception("Digest does not support implUpdate(SecretKey)");
+                throw new Exception(
+                    "Digest does not support implUpdate(SecretKey)");
             }
             Method update = (Method)r;
             update.invoke(spi, key);
         } catch (Exception e) {
-            throw new RuntimeException
-            ("Could not obtain encoded key and MessageDigest cannot digest key", e);
+            throw new RuntimeException(
+                "Could not obtain encoded key and "
+                + "MessageDigest cannot digest key", e);
         }
     }
 
-    int messageLength() {
-        return 2 + signature.length;
+    @Override
+    int messageType() {
+        return ht_certificate_verify;
     }
 
+    @Override
+    int messageLength() {
+        int temp = 2;
+
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            temp += SignatureAndHashAlgorithm.sizeInRecord();
+        }
+
+        return temp + signature.length;
+    }
+
+    @Override
     void send(HandshakeOutStream s) throws IOException {
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            s.putInt8(preferableSignatureAlgorithm.getHashValue());
+            s.putInt8(preferableSignatureAlgorithm.getSignatureValue());
+        }
+
         s.putBytes16(signature);
     }
 
+    @Override
     void print(PrintStream s) throws IOException {
         s.println("*** CertificateVerify");
+
+        if (debug != null && Debug.isOn("verbose")) {
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                s.println("Signature Algorithm " +
+                        preferableSignatureAlgorithm.getAlgorithmName());
+            }
+        }
     }
 }
 
@@ -1448,19 +1827,29 @@
     private byte[] verifyData;
 
     /*
+     * Current cipher suite we are negotiating.  TLS 1.2 has
+     * ciphersuite-defined PRF algorithms.
+     */
+    private ProtocolVersion protocolVersion;
+    private CipherSuite cipherSuite;
+
+    /*
      * Create a finished message to send to the remote peer.
      */
     Finished(ProtocolVersion protocolVersion, HandshakeHash handshakeHash,
-            int sender, SecretKey master) {
-        verifyData = getFinished(protocolVersion, handshakeHash, sender,
-                                 master);
+            int sender, SecretKey master, CipherSuite cipherSuite) {
+        this.protocolVersion = protocolVersion;
+        this.cipherSuite = cipherSuite;
+        verifyData = getFinished(handshakeHash, sender, master);
     }
 
     /*
      * Constructor that reads FINISHED message from stream.
      */
-    Finished(ProtocolVersion protocolVersion, HandshakeInStream input)
-            throws IOException {
+    Finished(ProtocolVersion protocolVersion, HandshakeInStream input,
+            CipherSuite cipherSuite) throws IOException {
+        this.protocolVersion = protocolVersion;
+        this.cipherSuite = cipherSuite;
         int msgLen = (protocolVersion.v >= ProtocolVersion.TLS10.v) ? 12 : 36;
         verifyData = new byte[msgLen];
         input.read(verifyData);
@@ -1472,18 +1861,16 @@
      * both client and server are fully in sync, and that the handshake
      * computations have been successful.
      */
-    boolean verify(ProtocolVersion protocolVersion,
-             HandshakeHash handshakeHash, int sender, SecretKey master) {
-        byte[] myFinished = getFinished(protocolVersion, handshakeHash,
-                                        sender, master);
+    boolean verify(HandshakeHash handshakeHash, int sender, SecretKey master) {
+        byte[] myFinished = getFinished(handshakeHash, sender, master);
         return Arrays.equals(myFinished, verifyData);
     }
 
     /*
      * Perform the actual finished message calculation.
      */
-    private static byte[] getFinished(ProtocolVersion protocolVersion,
-            HandshakeHash handshakeHash, int sender, SecretKey masterKey) {
+    private byte[] getFinished(HandshakeHash handshakeHash,
+            int sender, SecretKey masterKey) {
         byte[] sslLabel;
         String tlsLabel;
         if (sender == CLIENT) {
@@ -1495,23 +1882,53 @@
         } else {
             throw new RuntimeException("Invalid sender: " + sender);
         }
-        MessageDigest md5Clone = handshakeHash.getMD5Clone();
-        MessageDigest shaClone = handshakeHash.getSHAClone();
+
         if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
-            // TLS
+            // TLS 1.0+
             try {
-                byte[] seed = new byte[36];
-                md5Clone.digest(seed, 0, 16);
-                shaClone.digest(seed, 16, 20);
+                byte [] seed;
+                String prfAlg;
+                PRF prf;
+
+                // Get the KeyGenerator alg and calculate the seed.
+                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                    // TLS 1.2
+                    seed = handshakeHash.getFinishedHash();
+
+                    prfAlg = "SunTls12Prf";
+                    prf = cipherSuite.prfAlg;
+                } else {
+                    // TLS 1.0/1.1
+                    MessageDigest md5Clone = handshakeHash.getMD5Clone();
+                    MessageDigest shaClone = handshakeHash.getSHAClone();
+                    seed = new byte[36];
+                    md5Clone.digest(seed, 0, 16);
+                    shaClone.digest(seed, 16, 20);
 
-                TlsPrfParameterSpec spec = new TlsPrfParameterSpec
-                                                (masterKey, tlsLabel, seed, 12);
-                KeyGenerator prf = JsseJce.getKeyGenerator("SunTlsPrf");
-                prf.init(spec);
-                SecretKey prfKey = prf.generateKey();
+                    prfAlg = "SunTlsPrf";
+                    prf = P_NONE;
+                }
+
+                String prfHashAlg = prf.getPRFHashAlg();
+                int prfHashLength = prf.getPRFHashLength();
+                int prfBlockSize = prf.getPRFBlockSize();
+
+                /*
+                 * RFC 5246/7.4.9 says that finished messages can
+                 * be ciphersuite-specific in both length/PRF hash
+                 * algorithm.  If we ever run across a different
+                 * length, this call will need to be updated.
+                 */
+                TlsPrfParameterSpec spec = new TlsPrfParameterSpec(
+                    masterKey, tlsLabel, seed, 12,
+                    prfHashAlg, prfHashLength, prfBlockSize);
+
+                KeyGenerator kg = JsseJce.getKeyGenerator(prfAlg);
+                kg.init(spec);
+                SecretKey prfKey = kg.generateKey();
                 if ("RAW".equals(prfKey.getFormat()) == false) {
-                    throw new ProviderException
-                        ("Invalid PRF output, format must be RAW");
+                    throw new ProviderException(
+                        "Invalid PRF output, format must be RAW");
                 }
                 byte[] finished = prfKey.getEncoded();
                 return finished;
@@ -1520,6 +1937,8 @@
             }
         } else {
             // SSLv3
+            MessageDigest md5Clone = handshakeHash.getMD5Clone();
+            MessageDigest shaClone = handshakeHash.getSHAClone();
             updateDigest(md5Clone, sslLabel, MD5_pad1, MD5_pad2, masterKey);
             updateDigest(shaClone, sslLabel, SHA_pad1, SHA_pad2, masterKey);
             byte[] finished = new byte[36];
--- a/jdk/src/share/classes/sun/security/ssl/Handshaker.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/Handshaker.java	Wed Jul 05 17:26:57 2017 +0200
@@ -29,13 +29,12 @@
 import java.io.*;
 import java.util.*;
 import java.security.*;
-import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.AccessController;
+import java.security.AlgorithmConstraints;
 import java.security.AccessControlContext;
 import java.security.PrivilegedExceptionAction;
 import java.security.PrivilegedActionException;
-import java.security.cert.X509Certificate;
 
 import javax.crypto.*;
 import javax.crypto.spec.*;
@@ -49,6 +48,8 @@
 import sun.security.ssl.HandshakeMessage.*;
 import sun.security.ssl.CipherSuite.*;
 
+import static sun.security.ssl.CipherSuite.PRF.*;
+
 /**
  * Handshaker ... processes handshake records from an SSL V3.0
  * data stream, handling all the details of the handshake protocol.
@@ -71,13 +72,48 @@
     byte[]              clientVerifyData;
     byte[]              serverVerifyData;
 
-    // is it an initial negotiation  or a renegotiation?
+    // Is it an initial negotiation  or a renegotiation?
     boolean                     isInitialHandshake;
 
-    // list of enabled protocols
-    ProtocolList enabledProtocols;
+    // List of enabled protocols
+    private ProtocolList        enabledProtocols;
+
+    // List of enabled CipherSuites
+    private CipherSuiteList     enabledCipherSuites;
+
+    // The endpoint identification protocol
+    String              identificationProtocol;
+
+    // The cryptographic algorithm constraints
+    private AlgorithmConstraints    algorithmConstraints = null;
+
+    // Local supported signature and algorithms
+    Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs;
+
+    // Peer supported signature and algorithms
+    Collection<SignatureAndHashAlgorithm> peerSupportedSignAlgs;
+
+    /*
+
+    /*
+     * List of active protocols
+     *
+     * Active protocols is a subset of enabled protocols, and will
+     * contain only those protocols that have vaild cipher suites
+     * enabled.
+     */
+    private ProtocolList       activeProtocols;
+
+    /*
+     * List of active cipher suites
+     *
+     * Active cipher suites is a subset of enabled cipher suites, and will
+     * contain only those cipher suites available for the active protocols.
+     */
+    private CipherSuiteList    activeCipherSuites;
 
     private boolean             isClient;
+    private boolean             needCertVerify;
 
     SSLSocketImpl               conn = null;
     SSLEngineImpl               engine = null;
@@ -90,13 +126,6 @@
     RandomCookie                clnt_random, svr_random;
     SSLSessionImpl              session;
 
-    // Temporary MD5 and SHA message digests. Must always be left
-    // in reset state after use.
-    private MessageDigest md5Tmp, shaTmp;
-
-    // list of enabled CipherSuites
-    CipherSuiteList     enabledCipherSuites;
-
     // current CipherSuite. Never null, initially SSL_NULL_WITH_NULL_NULL
     CipherSuite         cipherSuite;
 
@@ -191,6 +220,7 @@
 
         this.sslContext = context;
         this.isClient = isClient;
+        this.needCertVerify = needCertVerify;
         this.activeProtocolVersion = activeProtocolVersion;
         this.isInitialHandshake = isInitialHandshake;
         this.secureRenegotiation = secureRenegotiation;
@@ -200,23 +230,12 @@
         invalidated = false;
 
         setCipherSuite(CipherSuite.C_NULL);
-
-        md5Tmp = JsseJce.getMD5();
-        shaTmp = JsseJce.getSHA();
-
-        //
-        // We accumulate digests of the handshake messages so that
-        // we can read/write CertificateVerify and Finished messages,
-        // getting assurance against some particular active attacks.
-        //
-        handshakeHash = new HandshakeHash(needCertVerify);
-
         setEnabledProtocols(enabledProtocols);
 
         if (conn != null) {
-            conn.getAppInputStream().r.setHandshakeHash(handshakeHash);
+            algorithmConstraints = new SSLAlgorithmConstraints(conn, true);
         } else {        // engine != null
-            engine.inputRecord.setHandshakeHash(handshakeHash);
+            algorithmConstraints = new SSLAlgorithmConstraints(engine, true);
         }
 
 
@@ -233,7 +252,7 @@
         // client's cert verify, those constants are in a convenient
         // order to drastically simplify state machine checking.
         //
-        state = -1;
+        state = -2;  // initialized but not activated
     }
 
     /*
@@ -268,6 +287,14 @@
         }
     }
 
+    String getRawHostnameSE() {
+        if (conn != null) {
+            return conn.getRawHostname();
+        } else {
+            return engine.getPeerHost();
+        }
+    }
+
     String getHostSE() {
         if (conn != null) {
             return conn.getHost();
@@ -313,14 +340,6 @@
         }
     }
 
-    String getHostnameVerificationSE() {
-        if (conn != null) {
-            return conn.getHostnameVerification();
-        } else {
-            return engine.getHostnameVerification();
-        }
-    }
-
     AccessControlContext getAccSE() {
         if (conn != null) {
             return conn.getAcc();
@@ -345,39 +364,139 @@
     void setVersion(ProtocolVersion protocolVersion) {
         this.protocolVersion = protocolVersion;
         setVersionSE(protocolVersion);
+
         output.r.setVersion(protocolVersion);
     }
 
+    /**
+     * Set the enabled protocols. Called from the constructor or
+     * SSLSocketImpl/SSLEngineImpl.setEnabledProtocols() (if the
+     * handshake is not yet in progress).
+     */
+    void setEnabledProtocols(ProtocolList enabledProtocols) {
+        activeCipherSuites = null;
+        activeProtocols = null;
+
+        this.enabledProtocols = enabledProtocols;
+    }
+
+    /**
+     * Set the enabled cipher suites. Called from
+     * SSLSocketImpl/SSLEngineImpl.setEnabledCipherSuites() (if the
+     * handshake is not yet in progress).
+     */
+    void setEnabledCipherSuites(CipherSuiteList enabledCipherSuites) {
+        activeCipherSuites = null;
+        activeProtocols = null;
+        this.enabledCipherSuites = enabledCipherSuites;
+    }
+
+    /**
+     * Set the algorithm constraints. Called from the constructor or
+     * SSLSocketImpl/SSLEngineImpl.setAlgorithmConstraints() (if the
+     * handshake is not yet in progress).
+     */
+    void setAlgorithmConstraints(AlgorithmConstraints algorithmConstraints) {
+        activeCipherSuites = null;
+        activeProtocols = null;
+
+        this.algorithmConstraints =
+            new SSLAlgorithmConstraints(algorithmConstraints);
+        this.localSupportedSignAlgs = null;
+    }
+
+    Collection<SignatureAndHashAlgorithm> getLocalSupportedSignAlgs() {
+        if (localSupportedSignAlgs == null) {
+            localSupportedSignAlgs =
+                SignatureAndHashAlgorithm.getSupportedAlgorithms(
+                                                    algorithmConstraints);
+        }
+
+        return localSupportedSignAlgs;
+    }
+
+    void setPeerSupportedSignAlgs(
+            Collection<SignatureAndHashAlgorithm> algorithms) {
+        peerSupportedSignAlgs =
+            new ArrayList<SignatureAndHashAlgorithm>(algorithms);
+    }
+
+    Collection<SignatureAndHashAlgorithm> getPeerSupportedSignAlgs() {
+        return peerSupportedSignAlgs;
+    }
+
 
     /**
-     * Set the enabled protocols. Called from the constructor or
-     * SSLSocketImpl.setEnabledProtocols() (if the handshake is not yet
-     * in progress).
+     * Set the identification protocol. Called from the constructor or
+     * SSLSocketImpl/SSLEngineImpl.setIdentificationProtocol() (if the
+     * handshake is not yet in progress).
+     */
+    void setIdentificationProtocol(String protocol) {
+        this.identificationProtocol = protocol;
+    }
+
+    /**
+     * Prior to handshaking, activate the handshake and initialize the version,
+     * input stream and output stream.
      */
-    void setEnabledProtocols(ProtocolList enabledProtocols) {
-        this.enabledProtocols = enabledProtocols;
+    void activate(ProtocolVersion helloVersion) throws IOException {
+        if (activeProtocols == null) {
+            activeProtocols = getActiveProtocols();
+        }
+
+        if (activeProtocols.collection().isEmpty() ||
+                activeProtocols.max.v == ProtocolVersion.NONE.v) {
+            throw new SSLHandshakeException("No appropriate protocol");
+        }
+
+        if (activeCipherSuites == null) {
+            activeCipherSuites = getActiveCipherSuites();
+        }
+
+        if (activeCipherSuites.collection().isEmpty()) {
+            throw new SSLHandshakeException("No appropriate cipher suite");
+        }
 
         // temporary protocol version until the actual protocol version
         // is negotiated in the Hello exchange. This affects the record
-        // version we sent with the ClientHello. Using max() as the record
-        // version is not really correct but some implementations fail to
-        // correctly negotiate TLS otherwise.
-        protocolVersion = enabledProtocols.max;
+        // version we sent with the ClientHello.
+        if (!isInitialHandshake) {
+            protocolVersion = activeProtocolVersion;
+        } else {
+            protocolVersion = activeProtocols.max;
+        }
+
+        if (helloVersion == null || helloVersion.v == ProtocolVersion.NONE.v) {
+            helloVersion = activeProtocols.helloVersion;
+        }
 
-        ProtocolVersion helloVersion = enabledProtocols.helloVersion;
+        // We accumulate digests of the handshake messages so that
+        // we can read/write CertificateVerify and Finished messages,
+        // getting assurance against some particular active attacks.
+        Set<String> localSupportedHashAlgorithms =
+            SignatureAndHashAlgorithm.getHashAlgorithmNames(
+                getLocalSupportedSignAlgs());
+        handshakeHash = new HandshakeHash(!isClient, needCertVerify,
+            localSupportedHashAlgorithms);
 
+        // Generate handshake input/output stream.
         input = new HandshakeInStream(handshakeHash);
-
         if (conn != null) {
             output = new HandshakeOutStream(protocolVersion, helloVersion,
                                         handshakeHash, conn);
+            conn.getAppInputStream().r.setHandshakeHash(handshakeHash);
             conn.getAppInputStream().r.setHelloVersion(helloVersion);
+            conn.getAppOutputStream().r.setHelloVersion(helloVersion);
         } else {
             output = new HandshakeOutStream(protocolVersion, helloVersion,
                                         handshakeHash, engine);
+            engine.inputRecord.setHandshakeHash(handshakeHash);
+            engine.inputRecord.setHelloVersion(helloVersion);
             engine.outputRecord.setHelloVersion(helloVersion);
         }
 
+        // move state to activated
+        state = -1;
     }
 
     /**
@@ -392,20 +511,150 @@
 
     /**
      * Check if the given ciphersuite is enabled and available.
-     * (Enabled ciphersuites are always available unless the status has
-     * changed due to change in JCE providers since it was enabled).
      * Does not check if the required server certificates are available.
      */
     boolean isNegotiable(CipherSuite s) {
-        return enabledCipherSuites.contains(s) && s.isNegotiable();
+        if (activeCipherSuites == null) {
+            activeCipherSuites = getActiveCipherSuites();
+        }
+
+        return activeCipherSuites.contains(s) && s.isNegotiable();
+    }
+
+    /**
+     * Check if the given protocol version is enabled and available.
+     */
+    boolean isNegotiable(ProtocolVersion protocolVersion) {
+        if (activeProtocols == null) {
+            activeProtocols = getActiveProtocols();
+        }
+
+        return activeProtocols.contains(protocolVersion);
+    }
+
+    /**
+     * Select a protocol version from the list. Called from
+     * ServerHandshaker to negotiate protocol version.
+     *
+     * Return the lower of the protocol version suggested in the
+     * clien hello and the highest supported by the server.
+     */
+    ProtocolVersion selectProtocolVersion(ProtocolVersion protocolVersion) {
+        if (activeProtocols == null) {
+            activeProtocols = getActiveProtocols();
+        }
+
+        return activeProtocols.selectProtocolVersion(protocolVersion);
     }
 
     /**
-     * As long as handshaking has not started, we can
+     * Get the active cipher suites.
+     *
+     * In TLS 1.1, many weak or vulnerable cipher suites were obsoleted,
+     * such as TLS_RSA_EXPORT_WITH_RC4_40_MD5. The implementation MUST NOT
+     * negotiate these cipher suites in TLS 1.1 or later mode.
+     *
+     * Therefore, when the active protocols only include TLS 1.1 or later,
+     * the client cannot request to negotiate those obsoleted cipher
+     * suites.  That is, the obsoleted suites should not be included in the
+     * client hello. So we need to create a subset of the enabled cipher
+     * suites, the active cipher suites, which does not contain obsoleted
+     * cipher suites of the minimum active protocol.
+     *
+     * Return empty list instead of null if no active cipher suites.
+     */
+    CipherSuiteList getActiveCipherSuites() {
+        if (activeCipherSuites == null) {
+            if (activeProtocols == null) {
+                activeProtocols = getActiveProtocols();
+            }
+
+            ArrayList<CipherSuite> suites = new ArrayList<CipherSuite>();
+            if (!(activeProtocols.collection().isEmpty()) &&
+                    activeProtocols.min.v != ProtocolVersion.NONE.v) {
+                for (CipherSuite suite : enabledCipherSuites.collection()) {
+                    if (suite.obsoleted > activeProtocols.min.v &&
+                            suite.supported <= activeProtocols.max.v) {
+                        if (algorithmConstraints.permits(
+                                EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
+                                suite.name, null)) {
+                            suites.add(suite);
+                        }
+                    } else if (debug != null && Debug.isOn("verbose")) {
+                        if (suite.obsoleted <= activeProtocols.min.v) {
+                            System.out.println(
+                                "Ignoring obsoleted cipher suite: " + suite);
+                        } else {
+                            System.out.println(
+                                "Ignoring unsupported cipher suite: " + suite);
+                        }
+                    }
+                }
+            }
+            activeCipherSuites = new CipherSuiteList(suites);
+        }
+
+        return activeCipherSuites;
+    }
+
+    /*
+     * Get the active protocol versions.
+     *
+     * In TLS 1.1, many weak or vulnerable cipher suites were obsoleted,
+     * such as TLS_RSA_EXPORT_WITH_RC4_40_MD5. The implementation MUST NOT
+     * negotiate these cipher suites in TLS 1.1 or later mode.
+     *
+     * For example, if "TLS_RSA_EXPORT_WITH_RC4_40_MD5" is the
+     * only enabled cipher suite, the client cannot request TLS 1.1 or
+     * later, even though TLS 1.1 or later is enabled.  We need to create a
+     * subset of the enabled protocols, called the active protocols, which
+     * contains protocols appropriate to the list of enabled Ciphersuites.
+     *
+     * Return empty list instead of null if no active protocol versions.
+     */
+    ProtocolList getActiveProtocols() {
+        if (activeProtocols == null) {
+            ArrayList<ProtocolVersion> protocols =
+                                            new ArrayList<ProtocolVersion>(4);
+            for (ProtocolVersion protocol : enabledProtocols.collection()) {
+                boolean found = false;
+                for (CipherSuite suite : enabledCipherSuites.collection()) {
+                    if (suite.isAvailable() && suite.obsoleted > protocol.v &&
+                                               suite.supported <= protocol.v) {
+                        if (algorithmConstraints.permits(
+                                EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
+                                suite.name, null)) {
+                            protocols.add(protocol);
+                            found = true;
+                            break;
+                        } else if (debug != null && Debug.isOn("verbose")) {
+                            System.out.println(
+                                "Ignoring disabled cipher suite: " + suite +
+                                 " for " + protocol);
+                        }
+                    } else if (debug != null && Debug.isOn("verbose")) {
+                        System.out.println(
+                            "Ignoring unsupported cipher suite: " + suite +
+                                 " for " + protocol);
+                    }
+                }
+                if (!found && (debug != null) && Debug.isOn("handshake")) {
+                    System.out.println(
+                        "No available cipher suite for " + protocol);
+                }
+            }
+            activeProtocols = new ProtocolList(protocols);
+        }
+
+        return activeProtocols;
+    }
+
+    /**
+     * As long as handshaking has not activated, we can
      * change whether session creations are allowed.
      *
      * Callers should do their own checking if handshaking
-     * has started.
+     * has activated.
      */
     void setEnableSessionCreation(boolean newSessions) {
         enableNewSession = newSessions;
@@ -419,12 +668,12 @@
         CipherBox box;
         if (isClient) {
             box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV,
-                                   false);
+                                   sslContext.getSecureRandom(), false);
             svrWriteKey = null;
             svrWriteIV = null;
         } else {
             box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV,
-                                   false);
+                                   sslContext.getSecureRandom(), false);
             clntWriteKey = null;
             clntWriteIV = null;
         }
@@ -439,12 +688,12 @@
         CipherBox box;
         if (isClient) {
             box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV,
-                                   true);
+                                   sslContext.getSecureRandom(), true);
             clntWriteKey = null;
             clntWriteIV = null;
         } else {
             box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV,
-                                   true);
+                                   sslContext.getSecureRandom(), true);
             svrWriteKey = null;
             svrWriteIV = null;
         }
@@ -502,6 +751,17 @@
     }
 
     /*
+     * Set the handshake session
+     */
+    void setHandshakeSessionSE(SSLSessionImpl handshakeSession) {
+        if (conn != null) {
+            conn.setHandshakeSession(handshakeSession);
+        } else {
+            engine.setHandshakeSession(handshakeSession);
+        }
+    }
+
+    /*
      * Returns true if renegotiation is in use for this connection.
      */
     boolean isSecureRenegotiation() {
@@ -614,13 +874,20 @@
 
 
     /**
+     * Returns true iff the handshaker has been activated.
+     *
+     * In activated state, the handshaker may not send any messages out.
+     */
+    boolean activated() {
+        return state >= -1;
+    }
+
+    /**
      * Returns true iff the handshaker has sent any messages.
-     * Server kickstarting is not as neat as it should be; we
-     * need to create a new handshaker, this method lets us
-     * know if we should.
      */
     boolean started() {
-        return state >= 0;
+        return state >= 0;  // 0: HandshakeMessage.ht_hello_request
+                            // 1: HandshakeMessage.ht_client_hello
     }
 
 
@@ -633,6 +900,7 @@
         if (state >= 0) {
             return;
         }
+
         HandshakeMessage m = getKickstartMessage();
 
         if (debug != null && Debug.isOn("handshake")) {
@@ -746,9 +1014,6 @@
      */
     private SecretKey calculateMasterSecret(SecretKey preMasterSecret,
             ProtocolVersion requestedVersion) {
-        TlsMasterSecretParameterSpec spec = new TlsMasterSecretParameterSpec
-                (preMasterSecret, protocolVersion.major, protocolVersion.minor,
-                clnt_random.random_bytes, svr_random.random_bytes);
 
         if (debug != null && Debug.isOn("keygen")) {
             HexDumpEncoder      dump = new HexDumpEncoder();
@@ -762,33 +1027,70 @@
             // benefit to doing it twice
         }
 
+        // What algs/params do we need to use?
+        String masterAlg;
+        PRF prf;
+
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            masterAlg = "SunTls12MasterSecret";
+            prf = cipherSuite.prfAlg;
+        } else {
+            masterAlg = "SunTlsMasterSecret";
+            prf = P_NONE;
+        }
+
+        String prfHashAlg = prf.getPRFHashAlg();
+        int prfHashLength = prf.getPRFHashLength();
+        int prfBlockSize = prf.getPRFBlockSize();
+
+        TlsMasterSecretParameterSpec spec = new TlsMasterSecretParameterSpec(
+                preMasterSecret, protocolVersion.major, protocolVersion.minor,
+                clnt_random.random_bytes, svr_random.random_bytes,
+                prfHashAlg, prfHashLength, prfBlockSize);
+
         SecretKey masterSecret;
         try {
-            KeyGenerator kg = JsseJce.getKeyGenerator("SunTlsMasterSecret");
+            KeyGenerator kg = JsseJce.getKeyGenerator(masterAlg);
             kg.init(spec);
             masterSecret = kg.generateKey();
         } catch (GeneralSecurityException e) {
             // For RSA premaster secrets, do not signal a protocol error
             // due to the Bleichenbacher attack. See comments further down.
-            if (!preMasterSecret.getAlgorithm().equals("TlsRsaPremasterSecret")) {
+            if (!preMasterSecret.getAlgorithm().equals(
+                    "TlsRsaPremasterSecret")) {
                 throw new ProviderException(e);
             }
+
             if (debug != null && Debug.isOn("handshake")) {
                 System.out.println("RSA master secret generation error:");
                 e.printStackTrace(System.out);
                 System.out.println("Generating new random premaster secret");
             }
-            preMasterSecret = RSAClientKeyExchange.generateDummySecret(protocolVersion);
+
+            if (requestedVersion != null) {
+                preMasterSecret =
+                    RSAClientKeyExchange.generateDummySecret(requestedVersion);
+            } else {
+                preMasterSecret =
+                    RSAClientKeyExchange.generateDummySecret(protocolVersion);
+            }
+
             // recursive call with new premaster secret
             return calculateMasterSecret(preMasterSecret, null);
         }
 
-        // if no version check requested (client side handshake),
-        // or version information is not available (not an RSA premaster secret),
+        // if no version check requested (client side handshake), or version
+        // information is not available (not an RSA premaster secret),
         // return master secret immediately.
-        if ((requestedVersion == null) || !(masterSecret instanceof TlsMasterSecret)) {
+        if ((requestedVersion == null) ||
+                !(masterSecret instanceof TlsMasterSecret)) {
             return masterSecret;
         }
+
+        // we have checked the ClientKeyExchange message when reading TLS
+        // record, the following check is necessary to ensure that
+        // JCE provider does not ignore the checking, or the previous
+        // checking process bypassed the premaster secret version checking.
         TlsMasterSecret tlsKey = (TlsMasterSecret)masterSecret;
         int major = tlsKey.getMajorVersion();
         int minor = tlsKey.getMinorVersion();
@@ -800,13 +1102,21 @@
         // the specification says that it must be the maximum version supported
         // by the client from its ClientHello message. However, many
         // implementations send the negotiated version, so accept both
-        // NOTE that we may be comparing two unsupported version numbers in
-        // the second case, which is why we cannot use object reference
-        // equality in this special case
-        ProtocolVersion premasterVersion = ProtocolVersion.valueOf(major, minor);
-        boolean versionMismatch = (premasterVersion != protocolVersion) &&
-                                  (premasterVersion.v != requestedVersion.v);
+        // for SSL v3.0 and TLS v1.0.
+        // NOTE that we may be comparing two unsupported version numbers, which
+        // is why we cannot use object reference equality in this special case.
+        ProtocolVersion premasterVersion =
+                                    ProtocolVersion.valueOf(major, minor);
+        boolean versionMismatch = (premasterVersion.v != requestedVersion.v);
 
+        /*
+         * we never checked the client_version in server side
+         * for TLS v1.0 and SSL v3.0. For compatibility, we
+         * maintain this behavior.
+         */
+        if (versionMismatch && requestedVersion.v <= ProtocolVersion.TLS10.v) {
+            versionMismatch = (premasterVersion.v != protocolVersion.v);
+        }
 
         if (versionMismatch == false) {
             // check passed, return key
@@ -823,7 +1133,9 @@
                 + premasterVersion);
             System.out.println("Generating new random premaster secret");
         }
-        preMasterSecret = RSAClientKeyExchange.generateDummySecret(protocolVersion);
+        preMasterSecret =
+            RSAClientKeyExchange.generateDummySecret(requestedVersion);
+
         // recursive call with new premaster secret
         return calculateMasterSecret(preMasterSecret, null);
     }
@@ -849,24 +1161,41 @@
         int hashSize = cipherSuite.macAlg.size;
         boolean is_exportable = cipherSuite.exportable;
         BulkCipher cipher = cipherSuite.cipher;
-        int keySize = cipher.keySize;
-        int ivSize = cipher.ivSize;
         int expandedKeySize = is_exportable ? cipher.expandedKeySize : 0;
 
-        TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec
-            (masterKey, protocolVersion.major, protocolVersion.minor,
+        // Which algs/params do we need to use?
+        String keyMaterialAlg;
+        PRF prf;
+
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            keyMaterialAlg = "SunTls12KeyMaterial";
+            prf = cipherSuite.prfAlg;
+        } else {
+            keyMaterialAlg = "SunTlsKeyMaterial";
+            prf = P_NONE;
+        }
+
+        String prfHashAlg = prf.getPRFHashAlg();
+        int prfHashLength = prf.getPRFHashLength();
+        int prfBlockSize = prf.getPRFBlockSize();
+
+        TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec(
+            masterKey, protocolVersion.major, protocolVersion.minor,
             clnt_random.random_bytes, svr_random.random_bytes,
             cipher.algorithm, cipher.keySize, expandedKeySize,
-            cipher.ivSize, hashSize);
+            cipher.ivSize, hashSize,
+            prfHashAlg, prfHashLength, prfBlockSize);
 
         try {
-            KeyGenerator kg = JsseJce.getKeyGenerator("SunTlsKeyMaterial");
+            KeyGenerator kg = JsseJce.getKeyGenerator(keyMaterialAlg);
             kg.init(spec);
             TlsKeyMaterialSpec keySpec = (TlsKeyMaterialSpec)kg.generateKey();
 
             clntWriteKey = keySpec.getClientCipherKey();
             svrWriteKey = keySpec.getServerCipherKey();
 
+            // Return null if IVs are not supposed to be generated.
+            // e.g. TLS 1.1+.
             clntWriteIV = keySpec.getClientIv();
             svrWriteIV = keySpec.getServerIv();
 
@@ -914,7 +1243,12 @@
                     System.out.println("Server write IV:");
                     printHex(dump, svrWriteIV.getIV());
                 } else {
-                    System.out.println("... no IV used for this cipher");
+                    if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
+                        System.out.println(
+                                "... no IV derived for this protocol");
+                    } else {
+                        System.out.println("... no IV used for this cipher");
+                    }
                 }
                 System.out.flush();
             }
--- a/jdk/src/share/classes/sun/security/ssl/HelloExtensions.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/HelloExtensions.java	Wed Jul 05 17:26:57 2017 +0200
@@ -50,7 +50,8 @@
  *
  *  . UnknownExtension: used to represent all parsed extensions that we do not
  *      explicitly support.
- *  . ServerNameExtension: partially implemented server_name extension.
+ *  . ServerNameExtension: the server_name extension.
+ *  . SignatureAlgorithmsExtension: the signature_algorithms extension.
  *  . SupportedEllipticCurvesExtension: the ECC supported curves extension.
  *  . SupportedEllipticPointFormatsExtension: the ECC supported point formats
  *      (compressed/uncompressed) extension.
@@ -78,6 +79,8 @@
             HelloExtension extension;
             if (extType == ExtensionType.EXT_SERVER_NAME) {
                 extension = new ServerNameExtension(s, extlen);
+            } else if (extType == ExtensionType.EXT_SIGNATURE_ALGORITHMS) {
+                extension = new SignatureAlgorithmsExtension(s, extlen);
             } else if (extType == ExtensionType.EXT_ELLIPTIC_CURVES) {
                 extension = new SupportedEllipticCurvesExtension(s, extlen);
             } else if (extType == ExtensionType.EXT_EC_POINT_FORMATS) {
@@ -266,31 +269,102 @@
     }
 
     public String toString() {
-        return "Unsupported extension " + type + ", data: " + Debug.toString(data);
+        return "Unsupported extension " + type + ", data: " +
+            Debug.toString(data);
     }
 }
 
 /*
- * Support for the server_name extension is incomplete. Parsing is implemented
- * so that we get nicer debug output, but we neither send it nor do we do
- * act on it if we receive it.
+ * [RFC4366] To facilitate secure connections to servers that host multiple
+ * 'virtual' servers at a single underlying network address, clients MAY
+ * include an extension of type "server_name" in the (extended) client hello.
+ * The "extension_data" field of this extension SHALL contain "ServerNameList"
+ * where:
+ *
+ *     struct {
+ *         NameType name_type;
+ *         select (name_type) {
+ *             case host_name: HostName;
+ *         } name;
+ *     } ServerName;
+ *
+ *     enum {
+ *         host_name(0), (255)
+ *     } NameType;
+ *
+ *     opaque HostName<1..2^16-1>;
+ *
+ *     struct {
+ *         ServerName server_name_list<1..2^16-1>
+ *     } ServerNameList;
  */
 final class ServerNameExtension extends HelloExtension {
 
     final static int NAME_HOST_NAME = 0;
 
     private List<ServerName> names;
+    private int listLength;     // ServerNameList length
+
+    ServerNameExtension(List<String> hostnames) throws IOException {
+        super(ExtensionType.EXT_SERVER_NAME);
+
+        listLength = 0;
+        names = new ArrayList<ServerName>(hostnames.size());
+        for (String hostname : hostnames) {
+            if (hostname != null && hostname.length() != 0) {
+                // we only support DNS hostname now.
+                ServerName serverName =
+                        new ServerName(NAME_HOST_NAME, hostname);
+                names.add(serverName);
+                listLength += serverName.length;
+            }
+        }
+
+        // As we only support DNS hostname now, the hostname list must
+        // not contain more than one hostname
+        if (names.size() > 1) {
+            throw new SSLProtocolException(
+                    "The ServerNameList MUST NOT contain more than " +
+                    "one name of the same name_type");
+        }
+
+        // We only need to add "server_name" extension in ClientHello unless
+        // we support SNI in server side in the future. It is possible that
+        // the SNI is empty in ServerHello. As we don't support SNI in
+        // ServerHello now, we will throw exception for empty list for now.
+        if (listLength == 0) {
+            throw new SSLProtocolException(
+                    "The ServerNameList cannot be empty");
+        }
+    }
 
     ServerNameExtension(HandshakeInStream s, int len)
             throws IOException {
         super(ExtensionType.EXT_SERVER_NAME);
-        names = new ArrayList<ServerName>();
-        while (len > 0) {
-            ServerName name = new ServerName(s);
-            names.add(name);
-            len -= name.length + 2;
+
+        int remains = len;
+        if (len >= 2) {    // "server_name" extension in ClientHello
+            listLength = s.getInt16();     // ServerNameList length
+            if (listLength == 0 || listLength + 2 != len) {
+                throw new SSLProtocolException(
+                        "Invalid " + type + " extension");
+            }
+
+            remains -= 2;
+            names = new ArrayList<ServerName>();
+            while (remains > 0) {
+                ServerName name = new ServerName(s);
+                names.add(name);
+                remains -= name.length;
+
+                // we may need to check the duplicated ServerName type
+            }
+        } else if (len == 0) {     // "server_name" extension in ServerHello
+            listLength = 0;
+            names = Collections.<ServerName>emptyList();
         }
-        if (len != 0) {
+
+        if (remains != 0) {
             throw new SSLProtocolException("Invalid server_name extension");
         }
     }
@@ -301,10 +375,19 @@
         final byte[] data;
         final String hostname;
 
+        ServerName(int type, String hostname) throws IOException {
+            this.type = type;                       // NameType
+            this.hostname = hostname;
+            this.data = hostname.getBytes("UTF8");  // HostName
+            this.length = data.length + 3;          // NameType: 1 byte
+                                                    // HostName length: 2 bytes
+        }
+
         ServerName(HandshakeInStream s) throws IOException {
-            length = s.getInt16();      // ServerNameList length
             type = s.getInt8();         // NameType
             data = s.getBytes16();      // HostName (length read in getBytes16)
+            length = data.length + 3;   // NameType: 1 byte
+                                        // HostName length: 2 bytes
             if (type == NAME_HOST_NAME) {
                 hostname = new String(data, "UTF8");
             } else {
@@ -322,15 +405,29 @@
     }
 
     int length() {
-        throw new RuntimeException("not yet supported");
+        return listLength == 0 ? 4 : 6 + listLength;
     }
 
     void send(HandshakeOutStream s) throws IOException {
-        throw new RuntimeException("not yet supported");
+        s.putInt16(type.id);
+        s.putInt16(listLength + 2);
+        if (listLength != 0) {
+            s.putInt16(listLength);
+
+            for (ServerName name : names) {
+                s.putInt8(name.type);           // NameType
+                s.putBytes16(name.data);        // HostName
+            }
+        }
     }
 
     public String toString() {
-        return "Unsupported extension " + type + ", " + names.toString();
+        StringBuffer buffer = new StringBuffer();
+        for (ServerName name : names) {
+            buffer.append("[" + name + "]");
+        }
+
+        return "Extension " + type + ", server_name: " + buffer;
     }
 }
 
@@ -523,7 +620,8 @@
     final static int FMT_ANSIX962_COMPRESSED_CHAR2 = 2;
 
     static final HelloExtension DEFAULT =
-        new SupportedEllipticPointFormatsExtension(new byte[] {FMT_UNCOMPRESSED});
+        new SupportedEllipticPointFormatsExtension(
+            new byte[] {FMT_UNCOMPRESSED});
 
     private final byte[] formats;
 
@@ -665,3 +763,105 @@
     }
 
 }
+
+/*
+ * [RFC5246] The client uses the "signature_algorithms" extension to
+ * indicate to the server which signature/hash algorithm pairs may be
+ * used in digital signatures.  The "extension_data" field of this
+ * extension contains a "supported_signature_algorithms" value.
+ *
+ *     enum {
+ *         none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
+ *         sha512(6), (255)
+ *     } HashAlgorithm;
+ *
+ *     enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
+ *       SignatureAlgorithm;
+ *
+ *     struct {
+ *           HashAlgorithm hash;
+ *           SignatureAlgorithm signature;
+ *     } SignatureAndHashAlgorithm;
+ *
+ *     SignatureAndHashAlgorithm
+ *       supported_signature_algorithms<2..2^16-2>;
+ */
+final class SignatureAlgorithmsExtension extends HelloExtension {
+
+    private Collection<SignatureAndHashAlgorithm> algorithms;
+    private int algorithmsLen;  // length of supported_signature_algorithms
+
+    SignatureAlgorithmsExtension(
+            Collection<SignatureAndHashAlgorithm> signAlgs) {
+
+        super(ExtensionType.EXT_SIGNATURE_ALGORITHMS);
+
+        algorithms = new ArrayList<SignatureAndHashAlgorithm>(signAlgs);
+        algorithmsLen =
+            SignatureAndHashAlgorithm.sizeInRecord() * algorithms.size();
+    }
+
+    SignatureAlgorithmsExtension(HandshakeInStream s, int len)
+                throws IOException {
+        super(ExtensionType.EXT_SIGNATURE_ALGORITHMS);
+
+        algorithmsLen = s.getInt16();
+        if (algorithmsLen == 0 || algorithmsLen + 2 != len) {
+            throw new SSLProtocolException("Invalid " + type + " extension");
+        }
+
+        algorithms = new ArrayList<SignatureAndHashAlgorithm>();
+        int remains = algorithmsLen;
+        int sequence = 0;
+        while (remains > 1) {   // needs at least two bytes
+            int hash = s.getInt8();         // hash algorithm
+            int signature = s.getInt8();    // signature algorithm
+
+            SignatureAndHashAlgorithm algorithm =
+                SignatureAndHashAlgorithm.valueOf(hash, signature, ++sequence);
+            algorithms.add(algorithm);
+            remains -= 2;  // one byte for hash, one byte for signature
+        }
+
+        if (remains != 0) {
+            throw new SSLProtocolException("Invalid server_name extension");
+        }
+    }
+
+    Collection<SignatureAndHashAlgorithm> getSignAlgorithms() {
+        return algorithms;
+    }
+
+    @Override
+    int length() {
+        return 6 + algorithmsLen;
+    }
+
+    @Override
+    void send(HandshakeOutStream s) throws IOException {
+        s.putInt16(type.id);
+        s.putInt16(algorithmsLen + 2);
+        s.putInt16(algorithmsLen);
+
+        for (SignatureAndHashAlgorithm algorithm : algorithms) {
+            s.putInt8(algorithm.getHashValue());      // HashAlgorithm
+            s.putInt8(algorithm.getSignatureValue()); // SignatureAlgorithm
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer buffer = new StringBuffer();
+        boolean opened = false;
+        for (SignatureAndHashAlgorithm signAlg : algorithms) {
+            if (opened) {
+                buffer.append(", " + signAlg.getAlgorithmName());
+            } else {
+                buffer.append(signAlg.getAlgorithmName());
+                opened = true;
+            }
+        }
+
+        return "Extension " + type + ", signature_algorithms: " + buffer;
+    }
+}
--- a/jdk/src/share/classes/sun/security/ssl/KerberosClientKeyExchange.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/KerberosClientKeyExchange.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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
@@ -69,6 +69,7 @@
     }
 
     public KerberosClientKeyExchange() {
+        // empty
     }
 
     public KerberosClientKeyExchange(String serverName, boolean isLoopback,
@@ -93,14 +94,17 @@
         }
     }
 
+    @Override
     int messageType() {
         return ht_client_key_exchange;
     }
 
+    @Override
     public int  messageLength() {
         return impl.messageLength();
     }
 
+    @Override
     public void send(HandshakeOutStream s) throws IOException {
         impl.send(s);
     }
--- a/jdk/src/share/classes/sun/security/ssl/MAC.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/MAC.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, 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
@@ -105,6 +105,10 @@
             algorithm = tls ? "HmacMD5" : "SslMacMD5";
         } else if (macAlg == M_SHA) {
             algorithm = tls ? "HmacSHA1" : "SslMacSHA1";
+        } else if (macAlg == M_SHA256) {
+            algorithm = "HmacSHA256";    // TLS 1.2+
+        } else if (macAlg == M_SHA384) {
+            algorithm = "HmacSHA384";    // TLS 1.2+
         } else {
             throw new RuntimeException("Unknown Mac " + macAlg);
         }
@@ -155,6 +159,42 @@
         return compute(type, bb, null, 0, bb.remaining());
     }
 
+    /**
+     * Check whether the sequence number is close to wrap
+     *
+     * Sequence numbers are of type uint64 and may not exceed 2^64-1.
+     * Sequence numbers do not wrap. When the sequence number is near
+     * to wrap, we need to close the connection immediately.
+     */
+    final boolean seqNumOverflow() {
+        /*
+         * Conservatively, we don't allow more records to be generated
+         * when there are only 2^8 sequence numbers left.
+         */
+        return (block != null && mac != null &&
+                block[0] == 0xFF && block[1] == 0xFF &&
+                block[2] == 0xFF && block[3] == 0xFF &&
+                block[4] == 0xFF && block[5] == 0xFF &&
+                block[6] == 0xFF);
+    }
+
+    /*
+     * Check whether to renew the sequence number
+     *
+     * Sequence numbers are of type uint64 and may not exceed 2^64-1.
+     * Sequence numbers do not wrap.  If a TLS
+     * implementation would need to wrap a sequence number, it must
+     * renegotiate instead.
+     */
+    final boolean seqNumIsHuge() {
+        /*
+         * Conservatively, we should ask for renegotiation when there are
+         * only 2^48 sequence numbers left.
+         */
+        return (block != null && mac != null &&
+                block[0] == 0xFF && block[1] == 0xFF);
+    }
+
     // increment the sequence number in the block array
     // it is a 64-bit number stored in big-endian format
     private void incrementSequenceNumber() {
@@ -168,7 +208,8 @@
      * Compute based on either buffer type, either bb.position/limit
      * or buf/offset/len.
      */
-    private byte[] compute(byte type, ByteBuffer bb, byte[] buf, int offset, int len) {
+    private byte[] compute(byte type, ByteBuffer bb, byte[] buf,
+            int offset, int len) {
 
         if (macSize == 0) {
             return nullMAC;
--- a/jdk/src/share/classes/sun/security/ssl/ProtocolList.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/ProtocolList.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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,8 +38,12 @@
 final class ProtocolList {
 
     private static final ProtocolList SUPPORTED;
+    private static final ProtocolList CLIENT_DEFAULT;
+    private static final ProtocolList SERVER_DEFAULT;
 
-    private final Collection<ProtocolVersion> protocols;
+    // the sorted protocol version list
+    private final ArrayList<ProtocolVersion> protocols;
+
     private String[] protocolNames;
 
     // the minimum and maximum ProtocolVersions in this list
@@ -49,30 +53,45 @@
     final ProtocolVersion helloVersion;
 
     ProtocolList(String[] names) {
+        this(convert(names));
+    }
+
+    ProtocolList(ArrayList<ProtocolVersion> versions) {
+        this.protocols = versions;
+
+        if ((protocols.size() == 1) &&
+                protocols.contains(ProtocolVersion.SSL20Hello)) {
+            throw new IllegalArgumentException("SSLv2Hello cannot be " +
+                "enabled unless at least one other supported version " +
+                "is also enabled.");
+        }
+
+        if (protocols.size() != 0) {
+            Collections.sort(protocols);
+            min = protocols.get(0);
+            max = protocols.get(protocols.size() - 1);
+            helloVersion = protocols.get(0);
+        } else {
+            min = ProtocolVersion.NONE;
+            max = ProtocolVersion.NONE;
+            helloVersion = ProtocolVersion.NONE;
+        }
+    }
+
+    private static ArrayList<ProtocolVersion> convert(String[] names) {
         if (names == null) {
             throw new IllegalArgumentException("Protocols may not be null");
         }
-        protocols = new ArrayList<ProtocolVersion>(3);
+
+        ArrayList<ProtocolVersion> versions = new ArrayList<ProtocolVersion>(3);
         for (int i = 0; i < names.length; i++ ) {
             ProtocolVersion version = ProtocolVersion.valueOf(names[i]);
-            if (protocols.contains(version) == false) {
-                protocols.add(version);
+            if (versions.contains(version) == false) {
+                versions.add(version);
             }
         }
-        if ((protocols.size() == 1)
-                && protocols.contains(ProtocolVersion.SSL20Hello)) {
-            throw new IllegalArgumentException("SSLv2Hello" +
-                  "cannot be enabled unless TLSv1 or SSLv3 is also enabled");
-        }
-        min = contains(ProtocolVersion.SSL30) ? ProtocolVersion.SSL30
-                                              : ProtocolVersion.TLS10;
-        max = contains(ProtocolVersion.TLS10) ? ProtocolVersion.TLS10
-                                              : ProtocolVersion.SSL30;
-        if (protocols.contains(ProtocolVersion.SSL20Hello)) {
-            helloVersion = ProtocolVersion.SSL20Hello;
-        } else {
-            helloVersion = min;
-        }
+
+        return versions;
     }
 
     /**
@@ -88,6 +107,37 @@
     }
 
     /**
+     * Return a reference to the internal Collection of CipherSuites.
+     * The Collection MUST NOT be modified.
+     */
+    Collection<ProtocolVersion> collection() {
+        return protocols;
+    }
+
+    /**
+     * Select a protocol version from the list.
+     *
+     * Return the lower of the protocol version of that suggested by
+     * the <code>protocolVersion</code> and the highest version of this
+     * protocol list, or null if no protocol version is available.
+     *
+     * The method is used by TLS server to negotiated the protocol
+     * version between client suggested protocol version in the
+     * client hello and protocol versions supported by the server.
+     */
+    ProtocolVersion selectProtocolVersion(ProtocolVersion protocolVersion) {
+        ProtocolVersion selectedVersion = null;
+        for (ProtocolVersion pv : protocols) {
+            if (pv.v > protocolVersion.v) {
+                break;  // Safe to break here as this.protocols is sorted
+            }
+            selectedVersion = pv;
+        }
+
+        return selectedVersion;
+    }
+
+    /**
      * Return an array with the names of the ProtocolVersions in this list.
      */
     synchronized String[] toStringArray() {
@@ -106,11 +156,18 @@
     }
 
     /**
-     * Return the list of default enabled protocols. Currently, this
-     * is identical to the supported protocols.
+     * Return the list of default enabled protocols.
      */
-    static ProtocolList getDefault() {
-        return SUPPORTED;
+    static ProtocolList getDefault(boolean isServer) {
+        return isServer ? SERVER_DEFAULT : CLIENT_DEFAULT;
+    }
+
+    /**
+     * Return whether a protocol list is the original default enabled
+     * protocols.  See: SSLSocket/SSLEngine.setEnabledProtocols()
+     */
+    static boolean isDefaultProtocolList(ProtocolList protocols) {
+        return protocols == CLIENT_DEFAULT || protocols == SERVER_DEFAULT;
     }
 
     /**
@@ -123,6 +180,13 @@
     static {
         if (SunJSSE.isFIPS()) {
             SUPPORTED = new ProtocolList(new String[] {
+                ProtocolVersion.TLS10.name,
+                ProtocolVersion.TLS11.name,
+                ProtocolVersion.TLS12.name
+            });
+
+            SERVER_DEFAULT = SUPPORTED;
+            CLIENT_DEFAULT = new ProtocolList(new String[] {
                 ProtocolVersion.TLS10.name
             });
         } else {
@@ -130,6 +194,24 @@
                 ProtocolVersion.SSL20Hello.name,
                 ProtocolVersion.SSL30.name,
                 ProtocolVersion.TLS10.name,
+                ProtocolVersion.TLS11.name,
+                ProtocolVersion.TLS12.name
+            });
+
+            SERVER_DEFAULT = SUPPORTED;
+
+            /*
+             * RFC 5246 says that sending SSLv2 backward-compatible
+             * hello SHOULD NOT be done any longer.
+             *
+             * We are not enabling TLS 1.1/1.2 by default yet on clients
+             * out of concern for interop with existing
+             * SSLv3/TLS1.0-only servers.  When these versions of TLS
+             * gain more traction, we'll enable them.
+             */
+            CLIENT_DEFAULT = new ProtocolList(new String[] {
+                ProtocolVersion.SSL30.name,
+                ProtocolVersion.TLS10.name
             });
         }
     }
--- a/jdk/src/share/classes/sun/security/ssl/ProtocolVersion.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/ProtocolVersion.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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
@@ -45,9 +45,15 @@
  * @author  Andreas Sterbenz
  * @since   1.4.1
  */
-public final class ProtocolVersion {
+public final class ProtocolVersion implements Comparable<ProtocolVersion> {
+
+    // The limit of maximum protocol version
+    final static int LIMIT_MAX_VALUE = 0xFFFF;
 
-    // dummy protocol version value for invalid SSLSession
+    // The limit of minimum protocol version
+    final static int LIMIT_MIN_VALUE = 0x0000;
+
+    // Dummy protocol version value for invalid SSLSession
     final static ProtocolVersion NONE = new ProtocolVersion(-1, "NONE");
 
     // If enabled, send/ accept SSLv2 hello messages
@@ -61,22 +67,24 @@
     final static ProtocolVersion TLS10 = new ProtocolVersion(0x0301, "TLSv1");
 
     // TLS 1.1
-    // not supported yet, but added for better readability of the debug trace
     final static ProtocolVersion TLS11 = new ProtocolVersion(0x0302, "TLSv1.1");
 
+    // TLS 1.2
+    final static ProtocolVersion TLS12 = new ProtocolVersion(0x0303, "TLSv1.2");
+
     private static final boolean FIPS = SunJSSE.isFIPS();
 
     // minimum version we implement (SSL 3.0)
     final static ProtocolVersion MIN = FIPS ? TLS10 : SSL30;
 
-    // maximum version we implement (TLS 1.0)
-    final static ProtocolVersion MAX = TLS10;
+    // maximum version we implement (TLS 1.2)
+    final static ProtocolVersion MAX = TLS12;
 
     // ProtocolVersion to use by default (TLS 1.0)
     final static ProtocolVersion DEFAULT = TLS10;
 
     // Default version for hello messages (SSLv2Hello)
-    final static ProtocolVersion DEFAULT_HELLO = FIPS ? TLS10 : SSL20Hello;
+    final static ProtocolVersion DEFAULT_HELLO = FIPS ? TLS10 : SSL30;
 
     // version in 16 bit MSB format as it appears in records and
     // messages, i.e. 0x0301 for TLS 1.0
@@ -104,6 +112,8 @@
             return TLS10;
         } else if (v == TLS11.v) {
             return TLS11;
+        } else if (v == TLS12.v) {
+            return TLS12;
         } else if (v == SSL20Hello.v) {
             return SSL20Hello;
         } else {
@@ -134,18 +144,20 @@
         if (name == null) {
             throw new IllegalArgumentException("Protocol cannot be null");
         }
-        if (FIPS) {
-            if (name.equals(TLS10.name)) {
-                return TLS10;
-            } else {
-                throw new IllegalArgumentException
-                    ("Only TLS 1.0 allowed in FIPS mode");
-            }
+
+        if (FIPS && (name.equals(SSL30.name) || name.equals(SSL20Hello.name))) {
+            throw new IllegalArgumentException
+                ("Only TLS 1.0 or later allowed in FIPS mode");
         }
+
         if (name.equals(SSL30.name)) {
             return SSL30;
         } else if (name.equals(TLS10.name)) {
             return TLS10;
+        } else if (name.equals(TLS11.name)) {
+            return TLS11;
+        } else if (name.equals(TLS12.name)) {
+            return TLS12;
         } else if (name.equals(SSL20Hello.name)) {
             return SSL20Hello;
         } else {
@@ -157,4 +169,10 @@
         return name;
     }
 
+    /**
+     * Compares this object with the specified object for order.
+     */
+    public int compareTo(ProtocolVersion protocolVersion) {
+        return this.v - protocolVersion.v;
+    }
 }
--- a/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, 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
@@ -55,20 +55,17 @@
      * requested in its client hello version). However, we (and other
      * implementations) used to send the active negotiated version. The
      * system property below allows to toggle the behavior.
-     *
-     * Default is "false" (old behavior) for compatibility reasons. This
-     * will be changed in the future.
      */
     private final static String PROP_NAME =
                                 "com.sun.net.ssl.rsaPreMasterSecretFix";
 
+    /*
+     * Default is "false" (old behavior) for compatibility reasons in
+     * SSLv3/TLSv1.  Later protocols (TLSv1.1+) do not use this property.
+     */
     private final static boolean rsaPreMasterSecretFix =
                                 Debug.getBooleanProperty(PROP_NAME, false);
 
-    int messageType() {
-        return ht_client_key_exchange;
-    }
-
     /*
      * The following field values were encrypted with the server's public
      * key (or temp key from server key exchange msg) and are presented
@@ -78,14 +75,14 @@
     SecretKey preMaster;
     private byte[] encrypted;           // same size as public modulus
 
-
     /*
      * Client randomly creates a pre-master secret and encrypts it
      * using the server's RSA public key; only the server can decrypt
      * it, using its RSA private key.  Result is the same size as the
      * server's public key, and uses PKCS #1 block format 02.
      */
-    RSAClientKeyExchange(ProtocolVersion protocolVersion, ProtocolVersion maxVersion,
+    RSAClientKeyExchange(ProtocolVersion protocolVersion,
+            ProtocolVersion maxVersion,
             SecureRandom generator, PublicKey publicKey) throws IOException {
         if (publicKey.getAlgorithm().equals("RSA") == false) {
             throw new SSLKeyException("Public key not of type RSA");
@@ -94,7 +91,7 @@
 
         int major, minor;
 
-        if (rsaPreMasterSecretFix) {
+        if (rsaPreMasterSecretFix || maxVersion.v >= ProtocolVersion.TLS11.v) {
             major = maxVersion.major;
             minor = maxVersion.minor;
         } else {
@@ -103,7 +100,9 @@
         }
 
         try {
-            KeyGenerator kg = JsseJce.getKeyGenerator("SunTlsRsaPremasterSecret");
+            String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ?
+                "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
+            KeyGenerator kg = JsseJce.getKeyGenerator(s);
             kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor));
             preMaster = kg.generateKey();
 
@@ -120,14 +119,15 @@
      * Server gets the PKCS #1 (block format 02) data, decrypts
      * it with its private key.
      */
-    RSAClientKeyExchange(ProtocolVersion currentVersion, HandshakeInStream input,
+    RSAClientKeyExchange(ProtocolVersion currentVersion,
+            ProtocolVersion maxVersion,
+            SecureRandom generator, HandshakeInStream input,
             int messageSize, PrivateKey privateKey) throws IOException {
 
         if (privateKey.getAlgorithm().equals("RSA") == false) {
             throw new SSLKeyException("Private key not of type RSA");
         }
 
-        this.protocolVersion = currentVersion;
         if (currentVersion.v >= ProtocolVersion.TLS10.v) {
             encrypted = input.getBytes16();
         } else {
@@ -143,31 +143,109 @@
             cipher.init(Cipher.UNWRAP_MODE, privateKey);
             preMaster = (SecretKey)cipher.unwrap(encrypted,
                                 "TlsRsaPremasterSecret", Cipher.SECRET_KEY);
+
+            // polish the premaster secret
+            preMaster = polishPreMasterSecretKey(currentVersion, maxVersion,
+                                                generator, preMaster, null);
         } catch (Exception e) {
-            /*
-             * Bogus decrypted ClientKeyExchange? If so, conjure a
-             * a random preMaster secret that will fail later during
-             * Finished message processing. This is a countermeasure against
-             * the "interactive RSA PKCS#1 encryption envelop attack" reported
-             * in June 1998. Preserving the executation path will
-             * mitigate timing attacks and force consistent error handling
-             * that will prevent an attacking client from differentiating
-             * different kinds of decrypted ClientKeyExchange bogosities.
-             */
-            if (debug != null && Debug.isOn("handshake")) {
+            // polish the premaster secret
+            preMaster =
+                    polishPreMasterSecretKey(currentVersion, maxVersion,
+                                                generator, null, e);
+        }
+    }
+
+    /**
+     * To avoid vulnerabilities described by section 7.4.7.1, RFC 5246,
+     * treating incorrectly formatted message blocks and/or mismatched
+     * version numbers in a manner indistinguishable from correctly
+     * formatted RSA blocks.
+     *
+     * RFC 5246 describes the approach as :
+     *
+     *  1. Generate a string R of 46 random bytes
+     *
+     *  2. Decrypt the message to recover the plaintext M
+     *
+     *  3. If the PKCS#1 padding is not correct, or the length of message
+     *     M is not exactly 48 bytes:
+     *        pre_master_secret = ClientHello.client_version || R
+     *     else If ClientHello.client_version <= TLS 1.0, and version
+     *     number check is explicitly disabled:
+     *        pre_master_secret = M
+     *     else:
+     *        pre_master_secret = ClientHello.client_version || M[2..47]
+     */
+    private SecretKey polishPreMasterSecretKey(ProtocolVersion currentVersion,
+            ProtocolVersion clientHelloVersion, SecureRandom generator,
+            SecretKey secretKey, Exception failoverException) {
+
+        this.protocolVersion = clientHelloVersion;
+
+        if (failoverException == null && secretKey != null) {
+            // check the length
+            byte[] encoded = secretKey.getEncoded();
+            if (encoded == null) {      // unable to get the encoded key
+                if (debug != null && Debug.isOn("handshake")) {
+                    System.out.println(
+                        "unable to get the plaintext of the premaster secret");
+                }
+
+                // We are not always able to get the encoded key of the
+                // premaster secret. Pass the cheking to master secret
+                // calculation.
+                return secretKey;
+            } else if (encoded.length == 48) {
+                // check the version
+                if (clientHelloVersion.major == encoded[0] &&
+                    clientHelloVersion.minor == encoded[1]) {
+                    return secretKey;
+                } else if (clientHelloVersion.v <= ProtocolVersion.TLS10.v) {
+                    /*
+                     * we never checked the client_version in server side
+                     * for TLS v1.0 and SSL v3.0. For compatibility, we
+                     * maintain this behavior.
+                     */
+                    if (currentVersion.major == encoded[0] &&
+                        currentVersion.minor == encoded[1]) {
+                        this.protocolVersion = currentVersion;
+                        return secretKey;
+                    }
+                }
+
+                if (debug != null && Debug.isOn("handshake")) {
+                    System.out.println("Mismatching Protocol Versions, " +
+                        "ClientHello.client_version is " + clientHelloVersion +
+                        ", while PreMasterSecret.client_version is " +
+                        ProtocolVersion.valueOf(encoded[0], encoded[1]));
+                }
+            } else {
+                if (debug != null && Debug.isOn("handshake")) {
+                    System.out.println(
+                        "incorrect length of premaster secret: " +
+                        encoded.length);
+                }
+            }
+        }
+
+        if (debug != null && Debug.isOn("handshake")) {
+            if (failoverException != null) {
                 System.out.println("Error decrypting premaster secret:");
-                e.printStackTrace(System.out);
-                System.out.println("Generating random secret");
+                failoverException.printStackTrace(System.out);
             }
-            preMaster = generateDummySecret(currentVersion);
+
+            System.out.println("Generating random secret");
         }
+
+        return generateDummySecret(clientHelloVersion);
     }
 
     // generate a premaster secret with the specified version number
     static SecretKey generateDummySecret(ProtocolVersion version) {
         try {
-            KeyGenerator kg =
-                    JsseJce.getKeyGenerator("SunTlsRsaPremasterSecret");
+            String s = ((version.v >= ProtocolVersion.TLS12.v) ?
+                "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
+            KeyGenerator kg = JsseJce.getKeyGenerator(s);
             kg.init(new TlsRsaPremasterSecretParameterSpec
                     (version.major, version.minor));
             return kg.generateKey();
@@ -176,6 +254,12 @@
         }
     }
 
+    @Override
+    int messageType() {
+        return ht_client_key_exchange;
+    }
+
+    @Override
     int messageLength() {
         if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
             return encrypted.length + 2;
@@ -184,6 +268,7 @@
         }
     }
 
+    @Override
     void send(HandshakeOutStream s) throws IOException {
         if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
             s.putBytes16(encrypted);
@@ -192,7 +277,9 @@
         }
     }
 
+    @Override
     void print(PrintStream s) throws IOException {
-        s.println("*** ClientKeyExchange, RSA PreMasterSecret, " + protocolVersion);
+        s.println("*** ClientKeyExchange, RSA PreMasterSecret, " +
+                                                        protocolVersion);
     }
 }
--- a/jdk/src/share/classes/sun/security/ssl/Record.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/Record.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, 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
@@ -47,11 +47,12 @@
     static final byte   ct_handshake = 22;
     static final byte   ct_application_data = 23;
 
-    static final int            headerSize = 5;         // SSLv3 record header
-    static final int            maxExpansion = 1024;    // for bad compression
-    static final int            trailerSize = 20;       // SHA1 hash size
-    static final int            maxDataSize = 16384;    // 2^14 bytes of data
-    static final int            maxPadding = 256;       // block cipher padding
+    static final int    headerSize = 5;         // SSLv3 record header
+    static final int    maxExpansion = 1024;    // for bad compression
+    static final int    trailerSize = 20;       // SHA1 hash size
+    static final int    maxDataSize = 16384;    // 2^14 bytes of data
+    static final int    maxPadding = 256;       // block cipher padding
+    static final int    maxIVLength = 256;      // block length
 
     /*
      * SSL has a maximum record size.  It's header, (compressed) data,
@@ -59,8 +60,9 @@
      * Some compression algorithms have rare cases where they expand the data.
      * As we don't support compression at this time, leave that out.
      */
-    static final int            maxRecordSize =
+    static final int    maxRecordSize =
                                       headerSize        // header
+                                    + maxIVLength       // iv
                                     + maxDataSize       // data
                                     + maxPadding        // padding
                                     + trailerSize;      // MAC
@@ -74,7 +76,7 @@
      * The maximum large record size is defined as maxRecordSize plus 2^14,
      * this is the amount OpenSSL is using.
      */
-    static final int            maxLargeRecordSize =
+    static final int    maxLargeRecordSize =
                 maxRecordSize   // Max size with a conforming implemenation
               + maxDataSize;    // extra 2^14 bytes for large data packets.
 
@@ -84,7 +86,11 @@
      * They only contain 2 and 1 bytes of data, respectively.
      * Allocate a smaller array.
      */
-    static final int maxAlertRecordSize =
-                        headerSize + 2 + maxPadding + trailerSize;
+    static final int    maxAlertRecordSize =
+                                      headerSize        // header
+                                    + maxIVLength       // iv
+                                    + 2                 // alert
+                                    + maxPadding        // padding
+                                    + trailerSize;      // MAC
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,469 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+package sun.security.ssl;
+
+import java.security.AlgorithmConstraints;
+import java.security.CryptoPrimitive;
+import java.security.AlgorithmParameters;
+
+import javax.net.ssl.*;
+
+import java.security.Key;
+
+import java.util.Set;
+import java.util.HashSet;
+
+import sun.security.util.DisabledAlgorithmConstraints;
+import sun.security.ssl.CipherSuite.*;
+
+/**
+ * Algorithm constraints for disabled algorithms property
+ *
+ * See the "jdk.certpath.disabledAlgorithms" specification in java.security
+ * for the syntax of the disabled algorithm string.
+ */
+final class SSLAlgorithmConstraints implements AlgorithmConstraints {
+    private final static AlgorithmConstraints tlsDisabledAlgConstraints =
+            new TLSDisabledAlgConstraints();
+    private final static AlgorithmConstraints x509DisabledAlgConstraints =
+            new X509DisabledAlgConstraints();
+    private AlgorithmConstraints userAlgConstraints = null;
+    private AlgorithmConstraints peerAlgConstraints = null;
+
+    private boolean enabledX509DisabledAlgConstraints = true;
+
+    SSLAlgorithmConstraints(AlgorithmConstraints algorithmConstraints) {
+        userAlgConstraints = algorithmConstraints;
+    }
+
+    SSLAlgorithmConstraints(SSLSocket socket,
+            boolean withDefaultCertPathConstraints) {
+        if (socket != null) {
+            userAlgConstraints =
+                socket.getSSLParameters().getAlgorithmConstraints();
+        }
+
+        if (!withDefaultCertPathConstraints) {
+            enabledX509DisabledAlgConstraints = false;
+        }
+    }
+
+    SSLAlgorithmConstraints(SSLEngine engine,
+            boolean withDefaultCertPathConstraints) {
+        if (engine != null) {
+            userAlgConstraints =
+                engine.getSSLParameters().getAlgorithmConstraints();
+        }
+
+        if (!withDefaultCertPathConstraints) {
+            enabledX509DisabledAlgConstraints = false;
+        }
+    }
+
+    SSLAlgorithmConstraints(SSLSocket socket, String[] supportedAlgorithms,
+            boolean withDefaultCertPathConstraints) {
+        if (socket != null) {
+            userAlgConstraints =
+                socket.getSSLParameters().getAlgorithmConstraints();
+            peerAlgConstraints =
+                new SupportedSignatureAlgorithmConstraints(supportedAlgorithms);
+        }
+
+        if (!withDefaultCertPathConstraints) {
+            enabledX509DisabledAlgConstraints = false;
+        }
+    }
+
+    SSLAlgorithmConstraints(SSLEngine engine, String[] supportedAlgorithms,
+            boolean withDefaultCertPathConstraints) {
+        if (engine != null) {
+            userAlgConstraints =
+                engine.getSSLParameters().getAlgorithmConstraints();
+            peerAlgConstraints =
+                new SupportedSignatureAlgorithmConstraints(supportedAlgorithms);
+        }
+
+        if (!withDefaultCertPathConstraints) {
+            enabledX509DisabledAlgConstraints = false;
+        }
+    }
+
+    public boolean permits(Set<CryptoPrimitive> primitives,
+            String algorithm, AlgorithmParameters parameters) {
+
+        boolean permitted = true;
+
+        if (peerAlgConstraints != null) {
+            permitted = peerAlgConstraints.permits(
+                                    primitives, algorithm, parameters);
+        }
+
+        if (permitted && userAlgConstraints != null) {
+            permitted = userAlgConstraints.permits(
+                                    primitives, algorithm, parameters);
+        }
+
+        if (permitted) {
+            permitted = tlsDisabledAlgConstraints.permits(
+                                    primitives, algorithm, parameters);
+        }
+
+        if (permitted && enabledX509DisabledAlgConstraints) {
+            permitted = x509DisabledAlgConstraints.permits(
+                                    primitives, algorithm, parameters);
+        }
+
+        return permitted;
+    }
+
+    public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
+
+        boolean permitted = true;
+
+        if (peerAlgConstraints != null) {
+            permitted = peerAlgConstraints.permits(primitives, key);
+        }
+
+        if (permitted && userAlgConstraints != null) {
+            permitted = userAlgConstraints.permits(primitives, key);
+        }
+
+        if (permitted) {
+            permitted = tlsDisabledAlgConstraints.permits(primitives, key);
+        }
+
+        if (permitted && enabledX509DisabledAlgConstraints) {
+            permitted = x509DisabledAlgConstraints.permits(primitives, key);
+        }
+
+        return permitted;
+    }
+
+    public boolean permits(Set<CryptoPrimitive> primitives,
+            String algorithm, Key key, AlgorithmParameters parameters) {
+
+        boolean permitted = true;
+
+        if (peerAlgConstraints != null) {
+            permitted = peerAlgConstraints.permits(
+                                    primitives, algorithm, key, parameters);
+        }
+
+        if (permitted && userAlgConstraints != null) {
+            permitted = userAlgConstraints.permits(
+                                    primitives, algorithm, key, parameters);
+        }
+
+        if (permitted) {
+            permitted = tlsDisabledAlgConstraints.permits(
+                                    primitives, algorithm, key, parameters);
+        }
+
+        if (permitted && enabledX509DisabledAlgConstraints) {
+            permitted = x509DisabledAlgConstraints.permits(
+                                    primitives, algorithm, key, parameters);
+        }
+
+        return permitted;
+    }
+
+
+    static private class SupportedSignatureAlgorithmConstraints
+                                    implements AlgorithmConstraints {
+        // supported signature algorithms
+        private String[] supportedAlgorithms;
+
+        SupportedSignatureAlgorithmConstraints(String[] supportedAlgorithms) {
+            if (supportedAlgorithms != null) {
+                this.supportedAlgorithms = supportedAlgorithms.clone();
+            } else {
+                this.supportedAlgorithms = null;
+            }
+        }
+
+        public boolean permits(Set<CryptoPrimitive> primitives,
+                String algorithm, AlgorithmParameters parameters) {
+
+            if (algorithm == null || algorithm.length() == 0) {
+                throw new IllegalArgumentException(
+                        "No algorithm name specified");
+            }
+
+            if (primitives == null || primitives.isEmpty()) {
+                throw new IllegalArgumentException(
+                        "No cryptographic primitive specified");
+            }
+
+            if (supportedAlgorithms == null ||
+                        supportedAlgorithms.length == 0) {
+                return false;
+            }
+
+            // trim the MGF part: <digest>with<encryption>and<mgf>
+            int position = algorithm.indexOf("and");
+            if (position > 0) {
+                algorithm = algorithm.substring(0, position);
+            }
+
+            for (String supportedAlgorithm : supportedAlgorithms) {
+                if (algorithm.equalsIgnoreCase(supportedAlgorithm)) {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        final public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
+            return true;
+        }
+
+        final public boolean permits(Set<CryptoPrimitive> primitives,
+                String algorithm, Key key, AlgorithmParameters parameters) {
+
+            if (algorithm == null || algorithm.length() == 0) {
+                throw new IllegalArgumentException(
+                        "No algorithm name specified");
+            }
+
+            return permits(primitives, algorithm, parameters);
+        }
+    }
+
+    static private class BasicDisabledAlgConstraints
+            extends DisabledAlgorithmConstraints {
+        BasicDisabledAlgConstraints(String propertyName) {
+            super(propertyName);
+        }
+
+        protected Set<String> decomposes(KeyExchange keyExchange,
+                        boolean forCertPathOnly) {
+            Set<String> components = new HashSet<String>();
+            switch (keyExchange) {
+                case K_NULL:
+                    if (!forCertPathOnly) {
+                        components.add("NULL");
+                    }
+                    break;
+                case K_RSA:
+                    components.add("RSA");
+                    break;
+                case K_RSA_EXPORT:
+                    components.add("RSA");
+                    components.add("RSA_EXPORT");
+                    break;
+                case K_DH_RSA:
+                    components.add("RSA");
+                    components.add("DH");
+                    components.add("DiffieHellman");
+                    components.add("DH_RSA");
+                    break;
+                case K_DH_DSS:
+                    components.add("DSA");
+                    components.add("DSS");
+                    components.add("DH");
+                    components.add("DiffieHellman");
+                    components.add("DH_DSS");
+                    break;
+                case K_DHE_DSS:
+                    components.add("DSA");
+                    components.add("DSS");
+                    components.add("DH");
+                    components.add("DHE");
+                    components.add("DiffieHellman");
+                    components.add("DHE_DSS");
+                    break;
+                case K_DHE_RSA:
+                    components.add("RSA");
+                    components.add("DH");
+                    components.add("DHE");
+                    components.add("DiffieHellman");
+                    components.add("DHE_RSA");
+                    break;
+                case K_DH_ANON:
+                    if (!forCertPathOnly) {
+                        components.add("ANON");
+                        components.add("DH");
+                        components.add("DiffieHellman");
+                        components.add("DH_ANON");
+                    }
+                    break;
+                case K_ECDH_ECDSA:
+                    components.add("ECDH");
+                    components.add("ECDSA");
+                    components.add("ECDH_ECDSA");
+                    break;
+                case K_ECDH_RSA:
+                    components.add("ECDH");
+                    components.add("RSA");
+                    components.add("ECDH_RSA");
+                    break;
+                case K_ECDHE_ECDSA:
+                    components.add("ECDHE");
+                    components.add("ECDSA");
+                    components.add("ECDHE_ECDSA");
+                    break;
+                case K_ECDHE_RSA:
+                    components.add("ECDHE");
+                    components.add("RSA");
+                    components.add("ECDHE_RSA");
+                    break;
+                case K_ECDH_ANON:
+                    if (!forCertPathOnly) {
+                        components.add("ECDH");
+                        components.add("ANON");
+                        components.add("ECDH_ANON");
+                    }
+                    break;
+                case K_KRB5:
+                    if (!forCertPathOnly) {
+                        components.add("KRB5");
+                    }
+                    break;
+                case K_KRB5_EXPORT:
+                    if (!forCertPathOnly) {
+                        components.add("KRB5_EXPORT");
+                    }
+                    break;
+                default:
+                    // ignore
+            }
+
+            return components;
+        }
+
+        protected Set<String> decomposes(BulkCipher bulkCipher) {
+            Set<String> components = new HashSet<String>();
+
+            if (bulkCipher.transformation != null) {
+                components.addAll(super.decomposes(bulkCipher.transformation));
+            }
+
+            return components;
+        }
+
+        protected Set<String> decomposes(MacAlg macAlg) {
+            Set<String> components = new HashSet<String>();
+
+            if (macAlg == CipherSuite.M_MD5) {
+                components.add("MD5");
+                components.add("HmacMD5");
+            } else if (macAlg == CipherSuite.M_SHA) {
+                components.add("SHA1");
+                components.add("SHA-1");
+                components.add("HmacSHA1");
+            } else if (macAlg == CipherSuite.M_SHA256) {
+                components.add("SHA256");
+                components.add("SHA-256");
+                components.add("HmacSHA256");
+            } else if (macAlg == CipherSuite.M_SHA384) {
+                components.add("SHA384");
+                components.add("SHA-384");
+                components.add("HmacSHA384");
+            }
+
+            return components;
+        }
+    }
+
+    static private class TLSDisabledAlgConstraints
+            extends BasicDisabledAlgConstraints {
+
+        TLSDisabledAlgConstraints() {
+            super(DisabledAlgorithmConstraints.PROPERTY_TLS_DISABLED_ALGS);
+        }
+
+        @Override
+        protected Set<String> decomposes(String algorithm) {
+            if (algorithm.startsWith("SSL_") || algorithm.startsWith("TLS_")) {
+                CipherSuite cipherSuite = null;
+                try {
+                    cipherSuite = CipherSuite.valueOf(algorithm);
+                } catch (IllegalArgumentException iae) {
+                    // ignore: unknown or unsupported ciphersuite
+                }
+
+                if (cipherSuite != null) {
+                    Set<String> components = new HashSet<String>();
+
+                    if(cipherSuite.keyExchange != null) {
+                        components.addAll(
+                            decomposes(cipherSuite.keyExchange, false));
+                    }
+
+                    if (cipherSuite.cipher != null) {
+                        components.addAll(decomposes(cipherSuite.cipher));
+                    }
+
+                    if (cipherSuite.macAlg != null) {
+                        components.addAll(decomposes(cipherSuite.macAlg));
+                    }
+
+                    return components;
+                }
+            }
+
+            return super.decomposes(algorithm);
+        }
+    }
+
+    static private class X509DisabledAlgConstraints
+            extends BasicDisabledAlgConstraints {
+
+        X509DisabledAlgConstraints() {
+            super(DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
+        }
+
+        @Override
+        protected Set<String> decomposes(String algorithm) {
+            if (algorithm.startsWith("SSL_") || algorithm.startsWith("TLS_")) {
+                CipherSuite cipherSuite = null;
+                try {
+                    cipherSuite = CipherSuite.valueOf(algorithm);
+                } catch (IllegalArgumentException iae) {
+                    // ignore: unknown or unsupported ciphersuite
+                }
+
+                if (cipherSuite != null) {
+                    Set<String> components = new HashSet<String>();
+
+                    if(cipherSuite.keyExchange != null) {
+                        components.addAll(
+                            decomposes(cipherSuite.keyExchange, true));
+                    }
+
+                    // Certification path algorithm constraints do not apply
+                    // to cipherSuite.cipher and cipherSuite.macAlg.
+
+                    return components;
+                }
+            }
+
+            return super.decomposes(algorithm);
+        }
+    }
+}
+
--- a/jdk/src/share/classes/sun/security/ssl/SSLContextImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/SSLContextImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, 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
@@ -27,11 +27,15 @@
 
 import java.net.Socket;
 
+import java.util.*;
 import java.security.*;
 import java.security.cert.*;
+import java.security.cert.Certificate;
 
 import javax.net.ssl.*;
 
+import sun.security.provider.certpath.AlgorithmChecker;
+
 public class SSLContextImpl extends SSLContextSpi {
 
     private static final Debug debug = Debug.getInstance("ssl");
@@ -82,7 +86,8 @@
         if (sr == null) {
             secureRandom = JsseJce.getSecureRandom();
         } else {
-            if (SunJSSE.isFIPS() && (sr.getProvider() != SunJSSE.cryptoProvider)) {
+            if (SunJSSE.isFIPS() &&
+                        (sr.getProvider() != SunJSSE.cryptoProvider)) {
                 throw new KeyManagementException
                     ("FIPS mode: SecureRandom must be from provider "
                     + SunJSSE.cryptoProvider.getName());
@@ -111,11 +116,18 @@
         // We only use the first instance of X509TrustManager passed to us.
         for (int i = 0; tm != null && i < tm.length; i++) {
             if (tm[i] instanceof X509TrustManager) {
-                if (SunJSSE.isFIPS() && !(tm[i] instanceof X509TrustManagerImpl)) {
+                if (SunJSSE.isFIPS() &&
+                        !(tm[i] instanceof X509TrustManagerImpl)) {
                     throw new KeyManagementException
                         ("FIPS mode: only SunJSSE TrustManagers may be used");
                 }
-                return (X509TrustManager)tm[i];
+
+                if (tm[i] instanceof X509ExtendedTrustManager) {
+                    return (X509TrustManager)tm[i];
+                } else {
+                    return new AbstractTrustManagerWrapper(
+                                        (X509TrustManager)tm[i]);
+                }
             }
         }
 
@@ -153,7 +165,7 @@
                     "SSLContext.init():  need an " +
                     "X509ExtendedKeyManager for SSLEngine use");
             }
-            return new AbstractWrapper((X509KeyManager)km);
+            return new AbstractKeyManagerWrapper((X509KeyManager)km);
         }
 
         // nothing found, return a dummy X509ExtendedKeyManager
@@ -217,9 +229,179 @@
 
 }
 
+
+final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
+            implements X509TrustManager {
+
+    private final X509TrustManager tm;
+
+    AbstractTrustManagerWrapper(X509TrustManager tm) {
+        this.tm = tm;
+    }
+
+    @Override
+    public void checkClientTrusted(X509Certificate[] chain, String authType)
+        throws CertificateException {
+        tm.checkClientTrusted(chain, authType);
+    }
+
+    @Override
+    public void checkServerTrusted(X509Certificate[] chain, String authType)
+        throws CertificateException {
+        tm.checkServerTrusted(chain, authType);
+    }
+
+    @Override
+    public X509Certificate[] getAcceptedIssuers() {
+        return tm.getAcceptedIssuers();
+    }
+
+    @Override
+    public void checkClientTrusted(X509Certificate[] chain, String authType,
+                Socket socket) throws CertificateException {
+        tm.checkClientTrusted(chain, authType);
+        checkAdditionalTrust(chain, authType, socket, true);
+    }
+
+    @Override
+    public void checkServerTrusted(X509Certificate[] chain, String authType,
+            Socket socket) throws CertificateException {
+        tm.checkServerTrusted(chain, authType);
+        checkAdditionalTrust(chain, authType, socket, false);
+    }
+
+    @Override
+    public void checkClientTrusted(X509Certificate[] chain, String authType,
+            SSLEngine engine) throws CertificateException {
+        tm.checkClientTrusted(chain, authType);
+        checkAdditionalTrust(chain, authType, engine, true);
+    }
+
+    @Override
+    public void checkServerTrusted(X509Certificate[] chain, String authType,
+            SSLEngine engine) throws CertificateException {
+        tm.checkServerTrusted(chain, authType);
+        checkAdditionalTrust(chain, authType, engine, false);
+    }
+
+    private void checkAdditionalTrust(X509Certificate[] chain, String authType,
+                Socket socket, boolean isClient) throws CertificateException {
+        if (socket != null && socket.isConnected() &&
+                                    socket instanceof SSLSocket) {
+
+            SSLSocket sslSocket = (SSLSocket)socket;
+            SSLSession session = sslSocket.getHandshakeSession();
+            if (session == null) {
+                throw new CertificateException("No handshake session");
+            }
+
+            // check endpoint identity
+            String identityAlg = sslSocket.getSSLParameters().
+                                        getEndpointIdentificationAlgorithm();
+            if (identityAlg != null && identityAlg.length() != 0) {
+                String hostname = session.getPeerHost();
+                X509TrustManagerImpl.checkIdentity(
+                                    hostname, chain[0], identityAlg);
+            }
+
+            // try the best to check the algorithm constraints
+            ProtocolVersion protocolVersion =
+                ProtocolVersion.valueOf(session.getProtocol());
+            AlgorithmConstraints constraints = null;
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                if (session instanceof ExtendedSSLSession) {
+                    ExtendedSSLSession extSession =
+                                    (ExtendedSSLSession)session;
+                    String[] peerSupportedSignAlgs =
+                            extSession.getLocalSupportedSignatureAlgorithms();
+
+                    constraints = new SSLAlgorithmConstraints(
+                                    sslSocket, peerSupportedSignAlgs, true);
+                } else {
+                    constraints =
+                            new SSLAlgorithmConstraints(sslSocket, true);
+                }
+            } else {
+                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");
+            }
+        }
+    }
+
+    private void checkAdditionalTrust(X509Certificate[] chain, String authType,
+            SSLEngine engine, boolean isClient) throws CertificateException {
+        if (engine != null) {
+            SSLSession session = engine.getHandshakeSession();
+            if (session == null) {
+                throw new CertificateException("No handshake session");
+            }
+
+            // check endpoint identity
+            String identityAlg = engine.getSSLParameters().
+                                        getEndpointIdentificationAlgorithm();
+            if (identityAlg != null && identityAlg.length() != 0) {
+                String hostname = session.getPeerHost();
+                X509TrustManagerImpl.checkIdentity(
+                                    hostname, chain[0], identityAlg);
+            }
+
+            // try the best to check the algorithm constraints
+            ProtocolVersion protocolVersion =
+                ProtocolVersion.valueOf(session.getProtocol());
+            AlgorithmConstraints constraints = null;
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                if (session instanceof ExtendedSSLSession) {
+                    ExtendedSSLSession extSession =
+                                    (ExtendedSSLSession)session;
+                    String[] peerSupportedSignAlgs =
+                            extSession.getLocalSupportedSignatureAlgorithms();
+
+                    constraints = new SSLAlgorithmConstraints(
+                                    engine, peerSupportedSignAlgs, true);
+                } else {
+                    constraints =
+                            new SSLAlgorithmConstraints(engine, true);
+                }
+            } else {
+                constraints = new SSLAlgorithmConstraints(engine, 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");
+            }
+        }
+    }
+}
+
 // Dummy X509TrustManager implementation, rejects all peer certificates.
 // Used if the application did not specify a proper X509TrustManager.
-final class DummyX509TrustManager implements X509TrustManager {
+final class DummyX509TrustManager extends X509ExtendedTrustManager
+            implements X509TrustManager {
 
     static final X509TrustManager INSTANCE = new DummyX509TrustManager();
 
@@ -234,6 +416,7 @@
      * validated and is trusted for client SSL authentication.
      * If not, it throws an exception.
      */
+    @Override
     public void checkClientTrusted(X509Certificate[] chain, String authType)
         throws CertificateException {
         throw new CertificateException(
@@ -247,6 +430,7 @@
      * validated and is trusted for server SSL authentication.
      * If not, it throws an exception.
      */
+    @Override
     public void checkServerTrusted(X509Certificate[] chain, String authType)
         throws CertificateException {
         throw new CertificateException(
@@ -257,19 +441,48 @@
      * Return an array of issuer certificates which are trusted
      * for authenticating peers.
      */
+    @Override
     public X509Certificate[] getAcceptedIssuers() {
         return new X509Certificate[0];
     }
+
+    @Override
+    public void checkClientTrusted(X509Certificate[] chain, String authType,
+                Socket socket) throws CertificateException {
+        throw new CertificateException(
+            "No X509TrustManager implementation available");
+    }
+
+    @Override
+    public void checkServerTrusted(X509Certificate[] chain, String authType,
+            Socket socket) throws CertificateException {
+        throw new CertificateException(
+            "No X509TrustManager implementation available");
+    }
+
+    @Override
+    public void checkClientTrusted(X509Certificate[] chain, String authType,
+            SSLEngine engine) throws CertificateException {
+        throw new CertificateException(
+            "No X509TrustManager implementation available");
+    }
+
+    @Override
+    public void checkServerTrusted(X509Certificate[] chain, String authType,
+            SSLEngine engine) throws CertificateException {
+        throw new CertificateException(
+            "No X509TrustManager implementation available");
+    }
 }
 
 /*
  * A wrapper class to turn a X509KeyManager into an X509ExtendedKeyManager
  */
-final class AbstractWrapper extends X509ExtendedKeyManager {
+final class AbstractKeyManagerWrapper extends X509ExtendedKeyManager {
 
     private final X509KeyManager km;
 
-    AbstractWrapper(X509KeyManager km) {
+    AbstractKeyManagerWrapper(X509KeyManager km) {
         this.km = km;
     }
 
--- a/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -200,8 +200,10 @@
      * is associated with a session at the same time.  (TLS/IETF may
      * change that to add client authentication w/o new key exchg.)
      */
-    private SSLSessionImpl      sess;
-    private Handshaker          handshaker;
+    private Handshaker                  handshaker;
+    private SSLSessionImpl              sess;
+    private volatile SSLSessionImpl     handshakeSession;
+
 
     /*
      * Client authentication be off, requested, or required.
@@ -240,26 +242,30 @@
      * session is changed.
      */
     private byte                        doClientAuth;
-    private CipherSuiteList             enabledCipherSuites;
     private boolean                     enableSessionCreation = true;
     EngineInputRecord                   inputRecord;
     EngineOutputRecord                  outputRecord;
     private AccessControlContext        acc;
 
-    // hostname identification algorithm, the hostname identification is
-    // disabled by default.
-    private String                      identificationAlg = null;
+    // The cipher suites enabled for use on this connection.
+    private CipherSuiteList             enabledCipherSuites;
+
+    // the endpoint identification protocol
+    private String                      identificationProtocol = null;
+
+    // The cryptographic algorithm constraints
+    private AlgorithmConstraints        algorithmConstraints = null;
 
     // Have we been told whether we're client or server?
     private boolean                     serverModeSet = false;
     private boolean                     roleIsServer;
 
     /*
-     * The protocols we support are SSL Version 3.0) and
-     * TLS (version 3.1).
-     * In addition we support a pseudo protocol called
-     * SSLv2Hello which when set will result in an SSL v2 Hello
-     * being sent with SSLv3 or TLSv1 version info.
+     * The protocol versions enabled for use on this connection.
+     *
+     * Note: we support a pseudo protocol called SSLv2Hello which when
+     * set will result in an SSL v2 Hello being sent with SSL (version 3.0)
+     * or TLS (version 3.1, 3.2, etc.) version info.
      */
     private ProtocolList        enabledProtocols;
 
@@ -342,6 +348,7 @@
 
         sslContext = ctx;
         sess = SSLSessionImpl.nullSession;
+        handshakeSession = null;
 
         /*
          * State is cs_START until we initialize the handshaker.
@@ -368,7 +375,7 @@
         serverVerifyData = new byte[0];
 
         enabledCipherSuites = CipherSuiteList.getDefault();
-        enabledProtocols = ProtocolList.getDefault();
+        enabledProtocols = ProtocolList.getDefault(roleIsServer);
 
         wrapLock = new Object();
         unwrapLock = new Object();
@@ -405,8 +412,8 @@
      *  . if the engine is already closed, throw an Exception (internal error)
      *
      *  . otherwise (cs_START or cs_DATA), create the appropriate handshaker
-     *    object, initialize it, and advance the connection state (to
-     *    cs_HANDSHAKE or cs_RENEGOTIATE, respectively).
+     *    object and advance the connection state (to cs_HANDSHAKE or
+     *    cs_RENEGOTIATE, respectively).
      *
      * This method is called right after a new engine is created, when
      * starting renegotiation, or when changing client/server mode of the
@@ -454,12 +461,8 @@
                     protocolVersion, connectionState == cs_HANDSHAKE,
                     secureRenegotiation, clientVerifyData, serverVerifyData);
         }
-        handshaker.enabledCipherSuites = enabledCipherSuites;
+        handshaker.setEnabledCipherSuites(enabledCipherSuites);
         handshaker.setEnableSessionCreation(enableSessionCreation);
-        if (connectionState == cs_RENEGOTIATE) {
-            // don't use SSLv2Hello when renegotiating
-            handshaker.output.r.setHelloVersion(protocolVersion);
-        }
     }
 
     /*
@@ -686,7 +689,15 @@
         // to its HandshakeOutStream, which calls back into
         // SSLSocketImpl.writeRecord() to send it.
         //
-        if (!handshaker.started()) {
+        if (!handshaker.activated()) {
+             // prior to handshaking, activate the handshake
+            if (connectionState == cs_RENEGOTIATE) {
+                // don't use SSLv2Hello when renegotiating
+                handshaker.activate(protocolVersion);
+            } else {
+                handshaker.activate(null);
+            }
+
             if (handshaker instanceof ClientHandshaker) {
                 // send client hello
                 handshaker.kickstart();
@@ -696,6 +707,7 @@
                 } else {
                     // we want to renegotiate, send hello request
                     handshaker.kickstart();
+
                     // hello request is not included in the handshake
                     // hashes, reset them
                     handshaker.handshakeHash.reset();
@@ -982,6 +994,15 @@
                      * in it.
                      */
                     initHandshaker();
+                    if (!handshaker.activated()) {
+                        // prior to handshaking, activate the handshake
+                        if (connectionState == cs_RENEGOTIATE) {
+                            // don't use SSLv2Hello when renegotiating
+                            handshaker.activate(protocolVersion);
+                        } else {
+                            handshaker.activate(null);
+                        }
+                    }
 
                     /*
                      * process the handshake record ... may contain just
@@ -1007,6 +1028,7 @@
                         serverVerifyData = handshaker.getServerVerifyData();
 
                         sess = handshaker.getSession();
+                        handshakeSession = null;
                         if (!writer.hasOutboundData()) {
                             hsStatus = HandshakeStatus.FINISHED;
                         }
@@ -1081,6 +1103,26 @@
                     }
                     break;
                 } // switch
+
+                /*
+                 * We only need to check the sequence number state for
+                 * non-handshaking record.
+                 *
+                 * Note that in order to maintain the handshake status
+                 * properly, we check the sequence number after the last
+                 * record reading process. As we request renegotiation
+                 * or close the connection for wrapped sequence number
+                 * when there is enough sequence number space left to
+                 * handle a few more records, so the sequence number
+                 * of the last record cannot be wrapped.
+                 */
+                if (connectionState < cs_ERROR && !isInboundDone() &&
+                        (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {
+                    if (checkSequenceNumber(readMAC,
+                            inputRecord.contentType())) {
+                        hsStatus = getHSStatus(null);
+                    }
+                }
             } // synchronized (this)
         }
 
@@ -1229,7 +1271,29 @@
             EngineArgs ea) throws IOException {
 
         // eventually compress as well.
-        return writer.writeRecord(eor, ea, writeMAC, writeCipher);
+        HandshakeStatus hsStatus =
+                writer.writeRecord(eor, ea, writeMAC, writeCipher);
+
+        /*
+         * We only need to check the sequence number state for
+         * non-handshaking record.
+         *
+         * Note that in order to maintain the handshake status
+         * properly, we check the sequence number after the last
+         * record writing process. As we request renegotiation
+         * or close the connection for wrapped sequence number
+         * when there is enough sequence number space left to
+         * handle a few more records, so the sequence number
+         * of the last record cannot be wrapped.
+         */
+        if (connectionState < cs_ERROR && !isOutboundDone() &&
+                (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {
+            if (checkSequenceNumber(writeMAC, eor.contentType())) {
+                hsStatus = getHSStatus(null);
+            }
+        }
+
+        return hsStatus;
     }
 
     /*
@@ -1238,6 +1302,21 @@
     void writeRecord(EngineOutputRecord eor) throws IOException {
         // eventually compress as well.
         writer.writeRecord(eor, writeMAC, writeCipher);
+
+        /*
+         * Check the sequence number state
+         *
+         * Note that in order to maintain the connection I/O
+         * properly, we check the sequence number after the last
+         * record writing process. As we request renegotiation
+         * or close the connection for wrapped sequence number
+         * when there is enough sequence number space left to
+         * handle a few more records, so the sequence number
+         * of the last record cannot be wrapped.
+         */
+        if ((connectionState < cs_ERROR) && !isOutboundDone()) {
+            checkSequenceNumber(writeMAC, eor.contentType());
+        }
     }
 
     //
@@ -1245,6 +1324,67 @@
     //
 
     /**
+     * Check the sequence number state
+     *
+     * RFC 4346 states that, "Sequence numbers are of type uint64 and
+     * may not exceed 2^64-1.  Sequence numbers do not wrap. If a TLS
+     * implementation would need to wrap a sequence number, it must
+     * renegotiate instead."
+     *
+     * Return true if the handshake status may be changed.
+     */
+    private boolean checkSequenceNumber(MAC mac, byte type)
+            throws IOException {
+
+        /*
+         * Don't bother to check the sequence number for error or
+         * closed connections, or NULL MAC
+         */
+        if (connectionState >= cs_ERROR || mac == MAC.NULL) {
+            return false;
+        }
+
+        /*
+         * Conservatively, close the connection immediately when the
+         * sequence number is close to overflow
+         */
+        if (mac.seqNumOverflow()) {
+            /*
+             * TLS protocols do not define a error alert for sequence
+             * number overflow. We use handshake_failure error alert
+             * for handshaking and bad_record_mac for other records.
+             */
+            if (debug != null && Debug.isOn("ssl")) {
+                System.out.println(threadName() +
+                    ", sequence number extremely close to overflow " +
+                    "(2^64-1 packets). Closing connection.");
+            }
+
+            fatal(Alerts.alert_handshake_failure, "sequence number overflow");
+
+            return true; // make the compiler happy
+        }
+
+        /*
+         * Ask for renegotiation when need to renew sequence number.
+         *
+         * Don't bother to kickstart the renegotiation when the local is
+         * asking for it.
+         */
+        if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) {
+            if (debug != null && Debug.isOn("ssl")) {
+                System.out.println(threadName() + ", request renegotiation " +
+                        "to avoid sequence number overflow");
+            }
+
+            beginHandshake();
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
      * Signals that no more outbound application data will be sent
      * on this <code>SSLEngine</code>.
      */
@@ -1394,6 +1534,15 @@
         return sess;
     }
 
+    @Override
+    synchronized public SSLSession getHandshakeSession() {
+        return handshakeSession;
+    }
+
+    synchronized void setHandshakeSession(SSLSessionImpl session) {
+        handshakeSession = session;
+    }
+
     /**
      * Returns a delegated <code>Runnable</code> task for
      * this <code>SSLEngine</code>.
@@ -1495,6 +1644,9 @@
         inboundDone = true;
 
         sess.invalidate();
+        if (handshakeSession != null) {
+            handshakeSession.invalidate();
+        }
 
         /*
          * If we haven't even started handshaking yet, no need
@@ -1594,10 +1746,18 @@
      * Emit alerts.  Caller must have synchronized with "this".
      */
     private void sendAlert(byte level, byte description) {
+        // the connectionState cannot be cs_START
         if (connectionState >= cs_CLOSED) {
             return;
         }
 
+        // For initial handshaking, don't send alert message to peer if
+        // handshaker has not started.
+        if (connectionState == cs_HANDSHAKE &&
+            (handshaker == null || !handshaker.started())) {
+            return;
+        }
+
         EngineOutputRecord r = new EngineOutputRecord(Record.ct_alert, this);
         r.setVersion(protocolVersion);
 
@@ -1647,7 +1807,7 @@
     synchronized public void setEnableSessionCreation(boolean flag) {
         enableSessionCreation = flag;
 
-        if ((handshaker != null) && !handshaker.started()) {
+        if ((handshaker != null) && !handshaker.activated()) {
             handshaker.setEnableSessionCreation(enableSessionCreation);
         }
     }
@@ -1675,7 +1835,7 @@
 
         if ((handshaker != null) &&
                 (handshaker instanceof ServerHandshaker) &&
-                !handshaker.started()) {
+                !handshaker.activated()) {
             ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
         }
     }
@@ -1698,7 +1858,7 @@
 
         if ((handshaker != null) &&
                 (handshaker instanceof ServerHandshaker) &&
-                !handshaker.started()) {
+                !handshaker.activated()) {
             ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
         }
     }
@@ -1717,6 +1877,16 @@
         switch (connectionState) {
 
         case cs_START:
+            /*
+             * If we need to change the engine mode and the enabled
+             * protocols haven't specifically been set by the user,
+             * change them to the corresponding default ones.
+             */
+            if (roleIsServer != (!flag) &&
+                    ProtocolList.isDefaultProtocolList(enabledProtocols)) {
+                enabledProtocols = ProtocolList.getDefault(!flag);
+            }
+
             roleIsServer = !flag;
             serverModeSet = true;
             break;
@@ -1730,7 +1900,17 @@
              * have the streams.
              */
             assert(handshaker != null);
-            if (!handshaker.started()) {
+            if (!handshaker.activated()) {
+                /*
+                 * If we need to change the engine mode and the enabled
+                 * protocols haven't specifically been set by the user,
+                 * change them to the corresponding default ones.
+                 */
+                if (roleIsServer != (!flag) &&
+                        ProtocolList.isDefaultProtocolList(enabledProtocols)) {
+                    enabledProtocols = ProtocolList.getDefault(!flag);
+                }
+
                 roleIsServer = !flag;
                 connectionState = cs_START;
                 initHandshaker();
@@ -1786,8 +1966,8 @@
      */
     synchronized public void setEnabledCipherSuites(String[] suites) {
         enabledCipherSuites = new CipherSuiteList(suites);
-        if ((handshaker != null) && !handshaker.started()) {
-            handshaker.enabledCipherSuites = enabledCipherSuites;
+        if ((handshaker != null) && !handshaker.activated()) {
+            handshaker.setEnabledCipherSuites(enabledCipherSuites);
         }
     }
 
@@ -1809,7 +1989,7 @@
     /**
      * Returns the protocols that are supported by this implementation.
      * A subset of the supported protocols may be enabled for this connection
-     * @ returns an array of protocol names.
+     * @return an array of protocol names.
      */
     public String[] getSupportedProtocols() {
         return ProtocolList.getSupported().toStringArray();
@@ -1826,7 +2006,7 @@
      */
     synchronized public void setEnabledProtocols(String[] protocols) {
         enabledProtocols = new ProtocolList(protocols);
-        if ((handshaker != null) && !handshaker.started()) {
+        if ((handshaker != null) && !handshaker.activated()) {
             handshaker.setEnabledProtocols(enabledProtocols);
         }
     }
@@ -1836,28 +2016,31 @@
     }
 
     /**
-     * Try to configure the endpoint identification algorithm of the engine.
-     *
-     * @param identificationAlgorithm the algorithm used to check the
-     *          endpoint identity.
-     * @return true if the identification algorithm configuration success.
+     * Returns the SSLParameters in effect for this SSLEngine.
      */
-    synchronized public boolean trySetHostnameVerification(
-        String identificationAlgorithm) {
-        if (sslContext.getX509TrustManager() instanceof
-                X509ExtendedTrustManager) {
-            this.identificationAlg = identificationAlgorithm;
-            return true;
-        } else {
-            return false;
-        }
+    synchronized public SSLParameters getSSLParameters() {
+        SSLParameters params = super.getSSLParameters();
+
+        // the super implementation does not handle the following parameters
+        params.setEndpointIdentificationAlgorithm(identificationProtocol);
+        params.setAlgorithmConstraints(algorithmConstraints);
+
+        return params;
     }
 
     /**
-     * Returns the endpoint identification algorithm of the engine.
+     * Applies SSLParameters to this engine.
      */
-    synchronized public String getHostnameVerification() {
-        return identificationAlg;
+    synchronized public void setSSLParameters(SSLParameters params) {
+        super.setSSLParameters(params);
+
+        // the super implementation does not handle the following parameters
+        identificationProtocol = params.getEndpointIdentificationAlgorithm();
+        algorithmConstraints = params.getAlgorithmConstraints();
+        if ((handshaker != null) && !handshaker.started()) {
+            handshaker.setIdentificationProtocol(identificationProtocol);
+            handshaker.setAlgorithmConstraints(algorithmConstraints);
+        }
     }
 
     /**
--- a/jdk/src/share/classes/sun/security/ssl/SSLServerSocketImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/SSLServerSocketImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -31,11 +31,14 @@
 import java.net.Socket;
 import java.net.ServerSocket;
 
+import java.security.AlgorithmConstraints;
+
 import java.util.*;
 
 import javax.net.ServerSocketFactory;
 import javax.net.ssl.SSLException;
 import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLParameters;
 
 
 /**
@@ -83,6 +86,12 @@
     /* could enabledCipherSuites ever complete handshaking? */
     private boolean             checkedEnabled = false;
 
+    // the endpoint identification protocol to use by default
+    private String              identificationProtocol = null;
+
+    // The cryptographic algorithm constraints
+    private AlgorithmConstraints    algorithmConstraints = null;
+
     /**
      * Create an SSL server socket on a port, using a non-default
      * authentication context and a specified connection backlog.
@@ -145,7 +154,7 @@
         }
         sslContext = context;
         enabledCipherSuites = CipherSuiteList.getDefault();
-        enabledProtocols = ProtocolList.getDefault();
+        enabledProtocols = ProtocolList.getDefault(true);
     }
 
     /**
@@ -238,6 +247,16 @@
      * rejoining the already-negotiated SSL connection.
      */
     public void setUseClientMode(boolean flag) {
+        /*
+         * If we need to change the socket mode and the enabled
+         * protocols haven't specifically been set by the user,
+         * change them to the corresponding default ones.
+         */
+        if (useServerMode != (!flag) &&
+                ProtocolList.isDefaultProtocolList(enabledProtocols)) {
+            enabledProtocols = ProtocolList.getDefault(!flag);
+        }
+
         useServerMode = !flag;
     }
 
@@ -262,6 +281,29 @@
         return enableSessionCreation;
     }
 
+    /**
+     * Returns the SSLParameters in effect for newly accepted connections.
+     */
+    synchronized public SSLParameters getSSLParameters() {
+        SSLParameters params = super.getSSLParameters();
+
+        // the super implementation does not handle the following parameters
+        params.setEndpointIdentificationAlgorithm(identificationProtocol);
+        params.setAlgorithmConstraints(algorithmConstraints);
+
+        return params;
+    }
+
+    /**
+     * Applies SSLParameters to newly accepted connections.
+     */
+    synchronized public void setSSLParameters(SSLParameters params) {
+        super.setSSLParameters(params);
+
+        // the super implementation does not handle the following parameters
+        identificationProtocol = params.getEndpointIdentificationAlgorithm();
+        algorithmConstraints = params.getAlgorithmConstraints();
+    }
 
     /**
      * Accept a new SSL connection.  This server identifies itself with
@@ -269,67 +311,15 @@
      * presented during construction.
      */
     public Socket accept() throws IOException {
-        checkEnabledSuites();
-
         SSLSocketImpl s = new SSLSocketImpl(sslContext, useServerMode,
             enabledCipherSuites, doClientAuth, enableSessionCreation,
-            enabledProtocols);
+            enabledProtocols, identificationProtocol, algorithmConstraints);
 
         implAccept(s);
         s.doneConnect();
         return s;
     }
 
-
-    /*
-     * This is a sometimes helpful diagnostic check that is performed
-     * once for each ServerSocket to verify that the initial set of
-     * enabled suites are capable of supporting a successful handshake.
-     */
-    private void checkEnabledSuites() throws IOException {
-        //
-        // We want to report an error if no cipher suites were actually
-        // enabled, since this is an error users are known to make.  Then
-        // they get vastly confused by having clients report an error!
-        //
-        synchronized (this) {
-            if (checkedEnabled) {
-                return;
-            }
-            if (useServerMode == false) {
-                return;
-            }
-
-            SSLSocketImpl tmp = new SSLSocketImpl(sslContext, useServerMode,
-                         enabledCipherSuites, doClientAuth,
-                         enableSessionCreation, enabledProtocols);
-
-            try {
-                ServerHandshaker handshaker = tmp.getServerHandshaker();
-
-                for (Iterator<CipherSuite> t = enabledCipherSuites.iterator();
-                        t.hasNext();) {
-                    CipherSuite suite = t.next();
-                    if (handshaker.trySetCipherSuite(suite)) {
-                        checkedEnabled = true;
-                        return;
-                    }
-                }
-            } finally {
-                tmp.closeSocket();
-            }
-
-            //
-            // diagnostic text here is currently appropriate
-            // since it's only certificate unavailability that can
-            // cause such problems ... but that might change someday.
-            //
-            throw new SSLException("No available certificate or key corresponds"
-                + " to the SSL cipher suites which are enabled.");
-        }
-    }
-
-
     /**
      * Provides a brief description of this SSL socket.
      */
--- a/jdk/src/share/classes/sun/security/ssl/SSLSessionImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/SSLSessionImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, 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
@@ -31,6 +31,8 @@
 import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.Vector;
+import java.util.Arrays;
+import java.util.Collection;
 
 import java.security.Principal;
 import java.security.PrivateKey;
@@ -47,6 +49,8 @@
 import javax.net.ssl.SSLPeerUnverifiedException;
 import javax.net.ssl.SSLSession;
 import javax.net.ssl.SSLPermission;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.ExtendedSSLSession;
 
 import javax.security.auth.x500.X500Principal;
 
@@ -71,7 +75,7 @@
  *
  * @author David Brownell
  */
-final class SSLSessionImpl implements SSLSession {
+final class SSLSessionImpl extends ExtendedSSLSession {
 
     /*
      * we only really need a single null session
@@ -89,7 +93,7 @@
     private final SessionId             sessionId;
     private X509Certificate[]   peerCerts;
     private byte                compressionMethod;
-    private final CipherSuite   cipherSuite;
+    private CipherSuite         cipherSuite;
     private SecretKey           masterSecret;
 
     /*
@@ -105,6 +109,8 @@
     private boolean             invalidated;
     private X509Certificate[]   localCerts;
     private PrivateKey          localPrivateKey;
+    private String[]            localSupportedSignAlgs;
+    private String[]            peerSupportedSignAlgs;
 
     // Principals for non-certificate based cipher suites
     private Principal peerPrincipal;
@@ -132,8 +138,8 @@
      * first opened and before handshaking begins.
      */
     private SSLSessionImpl() {
-        this(ProtocolVersion.NONE, CipherSuite.C_NULL,
-             new SessionId(false, null), null, -1);
+        this(ProtocolVersion.NONE, CipherSuite.C_NULL, null,
+            new SessionId(false, null), null, -1);
     }
 
     /*
@@ -142,8 +148,9 @@
      * is intended mostly for use by serves.
      */
     SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
+            Collection<SignatureAndHashAlgorithm> algorithms,
             SecureRandom generator, String host, int port) {
-        this(protocolVersion, cipherSuite,
+        this(protocolVersion, cipherSuite, algorithms,
              new SessionId(defaultRejoinable, generator), host, port);
     }
 
@@ -151,6 +158,7 @@
      * Record a new session, using a given cipher spec and session ID.
      */
     SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
+            Collection<SignatureAndHashAlgorithm> algorithms,
             SessionId id, String host, int port) {
         this.protocolVersion = protocolVersion;
         sessionId = id;
@@ -161,9 +169,11 @@
         this.host = host;
         this.port = port;
         sessionCount = ++counter;
+        localSupportedSignAlgs =
+            SignatureAndHashAlgorithm.getAlgorithmNames(algorithms);
 
         if (debug != null && Debug.isOn("session")) {
-            System.out.println("%% Created:  " + this);
+            System.out.println("%% Initialized:  " + this);
         }
     }
 
@@ -196,6 +206,12 @@
         localPrivateKey = privateKey;
     }
 
+    void setPeerSupportedSignatureAlgorithms(
+            Collection<SignatureAndHashAlgorithm> algorithms) {
+        peerSupportedSignAlgs =
+            SignatureAndHashAlgorithm.getAlgorithmNames(algorithms);
+    }
+
     /**
      * Set the peer principal.
      */
@@ -293,6 +309,17 @@
     }
 
     /**
+     * Resets the cipher spec in use on this session
+     */
+    void setSuite(CipherSuite suite) {
+       cipherSuite = suite;
+
+       if (debug != null && Debug.isOn("session")) {
+           System.out.println("%% Negotiating:  " + this);
+       }
+    }
+
+    /**
      * Returns the name of the cipher suite in use on this session
      */
     public String getCipherSuite() {
@@ -718,6 +745,30 @@
         return getPacketBufferSize() - Record.headerSize;
     }
 
+    /**
+     * Gets an array of supported signature algorithms that the local side is
+     * willing to verify.
+     */
+    public String[] getLocalSupportedSignatureAlgorithms() {
+        if (localSupportedSignAlgs != null) {
+            return localSupportedSignAlgs.clone();
+        }
+
+        return new String[0];
+    }
+
+    /**
+     * Gets an array of supported signature algorithms that the peer is
+     * able to verify.
+     */
+    public String[] getPeerSupportedSignatureAlgorithms() {
+        if (peerSupportedSignAlgs != null) {
+            return peerSupportedSignAlgs.clone();
+        }
+
+        return new String[0];
+    }
+
     /** Returns a string representation of this SSL session */
     public String toString() {
         return "[Session-" + sessionCount
--- a/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -32,6 +32,7 @@
 import java.security.AccessController;
 import java.security.AccessControlContext;
 import java.security.PrivilegedAction;
+import java.security.AlgorithmConstraints;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.ReentrantLock;
@@ -194,15 +195,27 @@
      */
     private byte                doClientAuth;
     private boolean             roleIsServer;
-    private CipherSuiteList     enabledCipherSuites;
     private boolean             enableSessionCreation = true;
     private String              host;
     private boolean             autoClose = true;
     private AccessControlContext acc;
 
-    // hostname identification algorithm, the hostname identification is
-    // disabled by default.
-    private String              identificationAlg = null;
+    /*
+     * We cannot use the hostname resolved from name services.  For
+     * virtual hosting, multiple hostnames may be bound to the same IP
+     * address, so the hostname resolved from name services is not
+     * reliable.
+     */
+    private String              rawHostname;
+
+    // The cipher suites enabled for use on this connection.
+    private CipherSuiteList     enabledCipherSuites;
+
+    // The endpoint identification protocol
+    private String              identificationProtocol = null;
+
+    // The cryptographic algorithm constraints
+    private AlgorithmConstraints    algorithmConstraints = null;
 
     /*
      * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
@@ -312,8 +325,9 @@
      * is associated with a session at the same time.  (TLS/IETF may
      * change that to add client authentication w/o new key exchg.)
      */
-    private SSLSessionImpl      sess;
-    private Handshaker          handshaker;
+    private Handshaker                  handshaker;
+    private SSLSessionImpl              sess;
+    private volatile SSLSessionImpl     handshakeSession;
 
 
     /*
@@ -341,11 +355,11 @@
     private AppOutputStream     output;
 
     /*
-     * The protocols we support are SSL Version 3.0) and
-     * TLS (version 3.1).
-     * In addition we support a pseudo protocol called
-     * SSLv2Hello which when set will result in an SSL v2 Hello
-     * being sent with SSLv3 or TLSv1 version info.
+     * The protocol versions enabled for use on this connection.
+     *
+     * Note: we support a pseudo protocol called SSLv2Hello which when
+     * set will result in an SSL v2 Hello being sent with SSL (version 3.0)
+     * or TLS (version 3.1, 3.2, etc.) version info.
      */
     private ProtocolList enabledProtocols;
 
@@ -374,6 +388,7 @@
             throws IOException, UnknownHostException {
         super();
         this.host = host;
+        this.rawHostname = host;
         init(context, false);
         SocketAddress socketAddress =
                host != null ? new InetSocketAddress(host, port) :
@@ -416,6 +431,7 @@
             throws IOException, UnknownHostException {
         super();
         this.host = host;
+        this.rawHostname = host;
         init(context, false);
         bind(new InetSocketAddress(localAddr, localPort));
         SocketAddress socketAddress =
@@ -455,11 +471,15 @@
      */
     SSLSocketImpl(SSLContextImpl context, boolean serverMode,
             CipherSuiteList suites, byte clientAuth,
-            boolean sessionCreation, ProtocolList protocols)
-            throws IOException {
+            boolean sessionCreation, ProtocolList protocols,
+            String identificationProtocol,
+            AlgorithmConstraints algorithmConstraints) throws IOException {
+
         super();
         doClientAuth = clientAuth;
         enableSessionCreation = sessionCreation;
+        this.identificationProtocol = identificationProtocol;
+        this.algorithmConstraints = algorithmConstraints;
         init(context, serverMode);
 
         /*
@@ -506,6 +526,7 @@
             throw new SocketException("Underlying socket is not connected");
         }
         this.host = host;
+        this.rawHostname = host;
         init(context, false);
         this.autoClose = autoClose;
         doneConnect();
@@ -517,6 +538,7 @@
     private void init(SSLContextImpl context, boolean isServer) {
         sslContext = context;
         sess = SSLSessionImpl.nullSession;
+        handshakeSession = null;
 
         /*
          * role is as specified, state is START until after
@@ -541,7 +563,7 @@
         serverVerifyData = new byte[0];
 
         enabledCipherSuites = CipherSuiteList.getDefault();
-        enabledProtocols = ProtocolList.getDefault();
+        enabledProtocols = ProtocolList.getDefault(roleIsServer);
         inrec = null;
 
         // save the acc
@@ -764,6 +786,21 @@
         r.addMAC(writeMAC);
         r.encrypt(writeCipher);
         r.write(sockOutput);
+
+        /*
+         * Check the sequence number state
+         *
+         * Note that in order to maintain the connection I/O
+         * properly, we check the sequence number after the last
+         * record writing process. As we request renegotiation
+         * or close the connection for wrapped sequence number
+         * when there is enough sequence number space left to
+         * handle a few more records, so the sequence number
+         * of the last record cannot be wrapped.
+         */
+        if (connectionState < cs_ERROR) {
+            checkSequenceNumber(writeMAC, r.contentType());
+        }
     }
 
 
@@ -883,6 +920,7 @@
                 }
             }
 
+
             // if (!r.decompress(c))
             //     fatal(Alerts.alert_decompression_failure,
             //         "decompression failure");
@@ -905,6 +943,15 @@
                      * in it.
                      */
                     initHandshaker();
+                    if (!handshaker.activated()) {
+                        // prior to handshaking, activate the handshake
+                        if (connectionState == cs_RENEGOTIATE) {
+                            // don't use SSLv2Hello when renegotiating
+                            handshaker.activate(protocolVersion);
+                        } else {
+                            handshaker.activate(null);
+                        }
+                    }
 
                     /*
                      * process the handshake record ... may contain just
@@ -930,6 +977,7 @@
                         serverVerifyData = handshaker.getServerVerifyData();
 
                         sess = handshaker.getSession();
+                        handshakeSession = null;
                         handshaker = null;
                         connectionState = cs_DATA;
 
@@ -949,9 +997,8 @@
 
                     if (needAppData || connectionState != cs_DATA) {
                         continue;
-                    } else {
-                        return;
                     }
+                    break;
 
                 case Record.ct_application_data:
                     // Pass this right back up to the application.
@@ -971,7 +1018,7 @@
                     }
 
                     r.setAppDataValid(true);
-                    return;
+                    break;
 
                 case Record.ct_alert:
                     recvAlert(r);
@@ -1010,6 +1057,23 @@
                     }
                     continue;
               } // switch
+
+              /*
+               * Check the sequence number state
+               *
+               * Note that in order to maintain the connection I/O
+               * properly, we check the sequence number after the last
+               * record reading process. As we request renegotiation
+               * or close the connection for wrapped sequence number
+               * when there is enough sequence number space left to
+               * handle a few more records, so the sequence number
+               * of the last record cannot be wrapped.
+               */
+              if (connectionState < cs_ERROR) {
+                  checkSequenceNumber(readMAC, r.contentType());
+              }
+
+              return;
             } // synchronized (this)
         }
 
@@ -1021,6 +1085,61 @@
       }  // synchronized (readLock)
     }
 
+    /**
+     * Check the sequence number state
+     *
+     * RFC 4346 states that, "Sequence numbers are of type uint64 and
+     * may not exceed 2^64-1.  Sequence numbers do not wrap. If a TLS
+     * implementation would need to wrap a sequence number, it must
+     * renegotiate instead."
+     */
+    private void checkSequenceNumber(MAC mac, byte type)
+            throws IOException {
+
+        /*
+         * Don't bother to check the sequence number for error or
+         * closed connections, or NULL MAC.
+         */
+        if (connectionState >= cs_ERROR || mac == MAC.NULL) {
+            return;
+        }
+
+        /*
+         * Conservatively, close the connection immediately when the
+         * sequence number is close to overflow
+         */
+        if (mac.seqNumOverflow()) {
+            /*
+             * TLS protocols do not define a error alert for sequence
+             * number overflow. We use handshake_failure error alert
+             * for handshaking and bad_record_mac for other records.
+             */
+            if (debug != null && Debug.isOn("ssl")) {
+                System.out.println(threadName() +
+                    ", sequence number extremely close to overflow " +
+                    "(2^64-1 packets). Closing connection.");
+
+            }
+
+            fatal(Alerts.alert_handshake_failure, "sequence number overflow");
+        }
+
+        /*
+         * Ask for renegotiation when need to renew sequence number.
+         *
+         * Don't bother to kickstart the renegotiation when the local is
+         * asking for it.
+         */
+        if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) {
+            if (debug != null && Debug.isOn("ssl")) {
+                System.out.println(threadName() + ", request renegotiation " +
+                        "to avoid sequence number overflow");
+            }
+
+            startHandshake();
+        }
+    }
+
     //
     // HANDSHAKE RELATED CODE
     //
@@ -1033,28 +1152,10 @@
     }
 
     /**
-     * Initialize and get the server handshaker. Used by SSLServerSocketImpl
-     * for the ciphersuite availability test *only*.
+     * Return the AppOutputStream. For use by Handshaker only.
      */
-    ServerHandshaker getServerHandshaker() throws SSLException {
-        initHandshaker();
-
-         // The connection state would have been set to cs_HANDSHAKE during the
-         // handshaking initializing, however the caller may not have the
-         // the low level connection's established, which is not consistent with
-         // the HANDSHAKE state. As if it is unconnected, we need to reset the
-         // connection state to cs_START.
-         if (!isConnected()) {
-             connectionState = cs_START;
-         }
-
-         // Make sure that we get a ServerHandshaker.
-         // This should never happen.
-         if (!(handshaker instanceof ServerHandshaker)) {
-             throw new SSLProtocolException("unexpected handshaker instance");
-         }
-
-        return (ServerHandshaker)handshaker;
+    AppOutputStream getAppOutputStream() {
+        return output;
     }
 
     /**
@@ -1066,8 +1167,8 @@
      *  . if the socket is already closed, throw an Exception (internal error)
      *
      *  . otherwise (cs_START or cs_DATA), create the appropriate handshaker
-     *    object, initialize it, and advance the connection state (to
-     *    cs_HANDSHAKE or cs_RENEGOTIATE, respectively).
+     *    object, and advance the connection state (to cs_HANDSHAKE or
+     *    cs_RENEGOTIATE, respectively).
      *
      * This method is called right after a new socket is created, when
      * starting renegotiation, or when changing client/ server mode of the
@@ -1115,12 +1216,8 @@
                     protocolVersion, connectionState == cs_HANDSHAKE,
                     secureRenegotiation, clientVerifyData, serverVerifyData);
         }
-        handshaker.enabledCipherSuites = enabledCipherSuites;
+        handshaker.setEnabledCipherSuites(enabledCipherSuites);
         handshaker.setEnableSessionCreation(enableSessionCreation);
-        if (connectionState == cs_RENEGOTIATE) {
-            // don't use SSLv2Hello when renegotiating
-            handshaker.output.r.setHelloVersion(protocolVersion);
-        }
     }
 
     /**
@@ -1135,6 +1232,8 @@
         // one thread performs the handshake
         synchronized (handshakeLock) {
             if (getConnectionState() == cs_HANDSHAKE) {
+                kickstartHandshake();
+
                 /*
                  * All initial handshaking goes through this
                  * InputRecord until we have a valid SSL connection.
@@ -1157,7 +1256,6 @@
                     inrec.enableFormatChecks();
                 }
 
-                kickstartHandshake();
                 readRecord(inrec, false);
                 inrec = null;
             }
@@ -1211,6 +1309,7 @@
      *    on servers when renegotiating).
      */
     private synchronized void kickstartHandshake() throws IOException {
+
         switch (connectionState) {
 
         case cs_HANDSHAKE:
@@ -1257,7 +1356,15 @@
         // to its HandshakeOutStream, which calls back into
         // SSLSocketImpl.writeRecord() to send it.
         //
-        if (!handshaker.started()) {
+        if (!handshaker.activated()) {
+             // prior to handshaking, activate the handshake
+            if (connectionState == cs_RENEGOTIATE) {
+                // don't use SSLv2Hello when renegotiating
+                handshaker.activate(protocolVersion);
+            } else {
+                handshaker.activate(null);
+            }
+
             if (handshaker instanceof ClientHandshaker) {
                 // send client hello
                 handshaker.kickstart();
@@ -1646,6 +1753,9 @@
             input.r.close();
         }
         sess.invalidate();
+        if (handshakeSession != null) {
+            handshakeSession.invalidate();
+        }
 
         int oldState = connectionState;
         connectionState = cs_ERROR;
@@ -1752,10 +1862,18 @@
      * Emit alerts.  Caller must have synchronized with "this".
      */
     private void sendAlert(byte level, byte description) {
+        // the connectionState cannot be cs_START
         if (connectionState >= cs_SENT_CLOSE) {
             return;
         }
 
+        // For initial handshaking, don't send alert message to peer if
+        // handshaker has not started.
+        if (connectionState == cs_HANDSHAKE &&
+            (handshaker == null || !handshaker.started())) {
+            return;
+        }
+
         OutputRecord r = new OutputRecord(Record.ct_alert);
         r.setVersion(protocolVersion);
 
@@ -1878,9 +1996,14 @@
         return host;
     }
 
+    synchronized String getRawHostname() {
+        return rawHostname;
+    }
+
     // ONLY used by HttpsClient to setup the URI specified hostname
     synchronized public void setHost(String host) {
         this.host = host;
+        this.rawHostname = host;
     }
 
     /**
@@ -1951,6 +2074,15 @@
         }
     }
 
+    @Override
+    synchronized public SSLSession getHandshakeSession() {
+        return handshakeSession;
+    }
+
+    synchronized void setHandshakeSession(SSLSessionImpl session) {
+        handshakeSession = session;
+    }
+
     /**
      * Controls whether new connections may cause creation of new SSL
      * sessions.
@@ -1962,7 +2094,7 @@
     synchronized public void setEnableSessionCreation(boolean flag) {
         enableSessionCreation = flag;
 
-        if ((handshaker != null) && !handshaker.started()) {
+        if ((handshaker != null) && !handshaker.activated()) {
             handshaker.setEnableSessionCreation(enableSessionCreation);
         }
     }
@@ -1990,7 +2122,7 @@
 
         if ((handshaker != null) &&
                 (handshaker instanceof ServerHandshaker) &&
-                !handshaker.started()) {
+                !handshaker.activated()) {
             ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
         }
     }
@@ -2013,7 +2145,7 @@
 
         if ((handshaker != null) &&
                 (handshaker instanceof ServerHandshaker) &&
-                !handshaker.started()) {
+                !handshaker.activated()) {
             ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
         }
     }
@@ -2032,6 +2164,15 @@
         switch (connectionState) {
 
         case cs_START:
+            /*
+             * If we need to change the socket mode and the enabled
+             * protocols haven't specifically been set by the user,
+             * change them to the corresponding default ones.
+             */
+            if (roleIsServer != (!flag) &&
+                    ProtocolList.isDefaultProtocolList(enabledProtocols)) {
+                enabledProtocols = ProtocolList.getDefault(!flag);
+            }
             roleIsServer = !flag;
             break;
 
@@ -2044,7 +2185,16 @@
              * have the streams.
              */
             assert(handshaker != null);
-            if (!handshaker.started()) {
+            if (!handshaker.activated()) {
+                /*
+                 * If we need to change the socket mode and the enabled
+                 * protocols haven't specifically been set by the user,
+                 * change them to the corresponding default ones.
+                 */
+                if (roleIsServer != (!flag) &&
+                        ProtocolList.isDefaultProtocolList(enabledProtocols)) {
+                    enabledProtocols = ProtocolList.getDefault(!flag);
+                }
                 roleIsServer = !flag;
                 connectionState = cs_START;
                 initHandshaker();
@@ -2095,8 +2245,8 @@
      */
     synchronized public void setEnabledCipherSuites(String[] suites) {
         enabledCipherSuites = new CipherSuiteList(suites);
-        if ((handshaker != null) && !handshaker.started()) {
-            handshaker.enabledCipherSuites = enabledCipherSuites;
+        if ((handshaker != null) && !handshaker.activated()) {
+            handshaker.setEnabledCipherSuites(enabledCipherSuites);
         }
     }
 
@@ -2118,7 +2268,7 @@
     /**
      * Returns the protocols that are supported by this implementation.
      * A subset of the supported protocols may be enabled for this connection
-     * @ returns an array of protocol names.
+     * @return an array of protocol names.
      */
     public String[] getSupportedProtocols() {
         return ProtocolList.getSupported().toStringArray();
@@ -2135,7 +2285,7 @@
      */
     synchronized public void setEnabledProtocols(String[] protocols) {
         enabledProtocols = new ProtocolList(protocols);
-        if ((handshaker != null) && !handshaker.started()) {
+        if ((handshaker != null) && !handshaker.activated()) {
             handshaker.setEnabledProtocols(enabledProtocols);
         }
     }
@@ -2194,28 +2344,31 @@
     }
 
     /**
-     * Try to configure the endpoint identification algorithm of the socket.
-     *
-     * @param identificationAlgorithm the algorithm used to check the
-     *        endpoint identity.
-     * @return true if the identification algorithm configuration success.
+     * Returns the SSLParameters in effect for this SSLSocket.
      */
-    synchronized public boolean trySetHostnameVerification(
-        String identificationAlgorithm) {
-        if (sslContext.getX509TrustManager() instanceof
-                X509ExtendedTrustManager) {
-            this.identificationAlg = identificationAlgorithm;
-            return true;
-        } else {
-            return false;
-        }
+    synchronized public SSLParameters getSSLParameters() {
+        SSLParameters params = super.getSSLParameters();
+
+        // the super implementation does not handle the following parameters
+        params.setEndpointIdentificationAlgorithm(identificationProtocol);
+        params.setAlgorithmConstraints(algorithmConstraints);
+
+        return params;
     }
 
     /**
-     * Returns the endpoint identification algorithm of the socket.
+     * Applies SSLParameters to this socket.
      */
-    synchronized public String getHostnameVerification() {
-        return identificationAlg;
+    synchronized public void setSSLParameters(SSLParameters params) {
+        super.setSSLParameters(params);
+
+        // the super implementation does not handle the following parameters
+        identificationProtocol = params.getEndpointIdentificationAlgorithm();
+        algorithmConstraints = params.getAlgorithmConstraints();
+        if ((handshaker != null) && !handshaker.started()) {
+            handshaker.setIdentificationProtocol(identificationProtocol);
+            handshaker.setAlgorithmConstraints(algorithmConstraints);
+        }
     }
 
     //
--- a/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java	Wed Jul 05 17:26:57 2017 +0200
@@ -40,10 +40,9 @@
 
 import javax.security.auth.Subject;
 
-import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
-
 import sun.security.ssl.HandshakeMessage.*;
 import sun.security.ssl.CipherSuite.*;
+import sun.security.ssl.SignatureAndHashAlgorithm.*;
 import static sun.security.ssl.CipherSuite.*;
 import static sun.security.ssl.CipherSuite.KeyExchange.*;
 
@@ -92,6 +91,9 @@
 
     private SupportedEllipticCurvesExtension supportedCurves;
 
+    // the preferable signature algorithm used by ServerKeyExchange message
+    SignatureAndHashAlgorithm preferableSignatureAlgorithm;
+
     /*
      * Constructor ... use the keys found in the auth context.
      */
@@ -185,8 +187,10 @@
                      * temporary one used for non-export or signing-only
                      * certificates/keys.
                      */
-                    RSAClientKeyExchange pms = new RSAClientKeyExchange
-                        (protocolVersion, input, message_len, privateKey);
+                    RSAClientKeyExchange pms = new RSAClientKeyExchange(
+                            protocolVersion, clientRequestedVersion,
+                            sslContext.getSecureRandom(), input,
+                            message_len, privateKey);
                     preMasterSecret = this.clientKeyExchange(pms);
                     break;
                 case K_KRB5:
@@ -231,11 +235,13 @@
                 break;
 
             case HandshakeMessage.ht_certificate_verify:
-                this.clientCertificateVerify(new CertificateVerify(input));
+                this.clientCertificateVerify(new CertificateVerify(input,
+                            localSupportedSignAlgs, protocolVersion));
                 break;
 
             case HandshakeMessage.ht_finished:
-                this.clientFinished(new Finished(protocolVersion, input));
+                this.clientFinished(
+                    new Finished(protocolVersion, input, cipherSuite));
                 break;
 
             default:
@@ -408,21 +414,18 @@
 
         clientRequestedVersion = mesg.protocolVersion;
 
-        // check if clientVersion is recent enough for us
-        if (clientRequestedVersion.v < enabledProtocols.min.v) {
+        // select a proper protocol version.
+        ProtocolVersion selectedVersion =
+               selectProtocolVersion(clientRequestedVersion);
+        if (selectedVersion == null ||
+                selectedVersion.v == ProtocolVersion.SSL20Hello.v) {
             fatalSE(Alerts.alert_handshake_failure,
                 "Client requested protocol " + clientRequestedVersion +
-                 " not enabled or not supported");
+                " not enabled or not supported");
         }
 
-        // now we know we have an acceptable version
-        // use the lower of our max and the client requested version
-        ProtocolVersion selectedVersion;
-        if (clientRequestedVersion.v <= enabledProtocols.max.v) {
-            selectedVersion = clientRequestedVersion;
-        } else {
-            selectedVersion = enabledProtocols.max;
-        }
+        handshakeHash.protocolDetermined(
+            selectedVersion.v >= ProtocolVersion.TLS12.v);
         setVersion(selectedVersion);
 
         m1.protocolVersion = protocolVersion;
@@ -566,14 +569,71 @@
             if (!enableNewSession) {
                 throw new SSLException("Client did not resume a session");
             }
+
             supportedCurves = (SupportedEllipticCurvesExtension)
                         mesg.extensions.get(ExtensionType.EXT_ELLIPTIC_CURVES);
+
+            // We only need to handle the "signature_algorithm" extension
+            // for full handshakes and TLS 1.2 or later.
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                SignatureAlgorithmsExtension signAlgs =
+                    (SignatureAlgorithmsExtension)mesg.extensions.get(
+                                    ExtensionType.EXT_SIGNATURE_ALGORITHMS);
+                if (signAlgs != null) {
+                    Collection<SignatureAndHashAlgorithm> peerSignAlgs =
+                                            signAlgs.getSignAlgorithms();
+                    if (peerSignAlgs == null || peerSignAlgs.isEmpty()) {
+                        throw new SSLHandshakeException(
+                            "No peer supported signature algorithms");
+                    }
+
+                    Collection<SignatureAndHashAlgorithm>
+                        supportedPeerSignAlgs =
+                            SignatureAndHashAlgorithm.getSupportedAlgorithms(
+                                                            peerSignAlgs);
+                    if (supportedPeerSignAlgs.isEmpty()) {
+                        throw new SSLHandshakeException(
+                            "No supported signature and hash algorithm " +
+                            "in common");
+                    }
+
+                    setPeerSupportedSignAlgs(supportedPeerSignAlgs);
+                } // else, need to use peer implicit supported signature algs
+            }
+
+            session = new SSLSessionImpl(protocolVersion, CipherSuite.C_NULL,
+                        getLocalSupportedSignAlgs(),
+                        sslContext.getSecureRandom(),
+                        getHostAddressSE(), getPortSE());
+
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                if (peerSupportedSignAlgs != null) {
+                    session.setPeerSupportedSignatureAlgorithms(
+                            peerSupportedSignAlgs);
+                }   // else, we will set the implicit peer supported signature
+                    // algorithms in chooseCipherSuite()
+            }
+
+            // set the handshake session
+            setHandshakeSessionSE(session);
+
+            // choose cipher suite and corresponding private key
             chooseCipherSuite(mesg);
-            session = new SSLSessionImpl(protocolVersion, cipherSuite,
-                sslContext.getSecureRandom(),
-                getHostAddressSE(), getPortSE());
+
+            session.setSuite(cipherSuite);
             session.setLocalPrivateKey(privateKey);
+
             // chooseCompression(mesg);
+        } else {
+            // set the handshake session
+            setHandshakeSessionSE(session);
+        }
+
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            if (resumingSession) {
+                handshakeHash.setCertificateVerifyAlg(null);
+            }
+            handshakeHash.setFinishedAlg(cipherSuite.prfAlg.getPRFHashAlg());
         }
 
         m1.cipherSuite = cipherSuite;
@@ -693,14 +753,16 @@
                     privateKey,
                     clnt_random.random_bytes,
                     svr_random.random_bytes,
-                    sslContext.getSecureRandom());
+                    sslContext.getSecureRandom(),
+                    preferableSignatureAlgorithm,
+                    protocolVersion);
             } catch (GeneralSecurityException e) {
                 throwSSLException("Error generating DH server key exchange", e);
                 m3 = null; // make compiler happy
             }
             break;
         case K_DH_ANON:
-            m3 = new DH_ServerKeyExchange(dh);
+            m3 = new DH_ServerKeyExchange(dh, protocolVersion);
             break;
         case K_ECDHE_RSA:
         case K_ECDHE_ECDSA:
@@ -710,9 +772,12 @@
                     privateKey,
                     clnt_random.random_bytes,
                     svr_random.random_bytes,
-                    sslContext.getSecureRandom());
+                    sslContext.getSecureRandom(),
+                    preferableSignatureAlgorithm,
+                    protocolVersion);
             } catch (GeneralSecurityException e) {
-                throwSSLException("Error generating ECDH server key exchange", e);
+                throwSSLException(
+                    "Error generating ECDH server key exchange", e);
                 m3 = null; // make compiler happy
             }
             break;
@@ -741,21 +806,48 @@
         // Needed only if server requires client to authenticate self.
         // Illegal for anonymous flavors, so we need to check that.
         //
-        if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
-            // CertificateRequest is omitted for Kerberos ciphers
+        // CertificateRequest is omitted for Kerberos ciphers
+        if (doClientAuth != SSLEngineImpl.clauth_none &&
+                keyExchange != K_DH_ANON && keyExchange != K_ECDH_ANON &&
+                keyExchange != K_KRB5 && keyExchange != K_KRB5_EXPORT) {
 
-        } else if (doClientAuth != SSLEngineImpl.clauth_none &&
-                keyExchange != K_DH_ANON && keyExchange != K_ECDH_ANON) {
             CertificateRequest m4;
             X509Certificate caCerts[];
 
+            Collection<SignatureAndHashAlgorithm> localSignAlgs = null;
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                // We currently use all local upported signature and hash
+                // algorithms. However, to minimize the computation cost
+                // of requested hash algorithms, we may use a restricted
+                // set of signature algorithms in the future.
+                localSignAlgs = getLocalSupportedSignAlgs();
+                if (localSignAlgs.isEmpty()) {
+                    throw new SSLHandshakeException(
+                            "No supported signature algorithm");
+                }
+
+                Set<String> localHashAlgs =
+                    SignatureAndHashAlgorithm.getHashAlgorithmNames(
+                        localSignAlgs);
+                if (localHashAlgs.isEmpty()) {
+                    throw new SSLHandshakeException(
+                            "No supported signature algorithm");
+                }
+                handshakeHash.restrictCertificateVerifyAlgs(localHashAlgs);
+            }
+
             caCerts = sslContext.getX509TrustManager().getAcceptedIssuers();
-            m4 = new CertificateRequest(caCerts, keyExchange);
+            m4 = new CertificateRequest(caCerts, keyExchange,
+                                            localSignAlgs, protocolVersion);
 
             if (debug != null && Debug.isOn("handshake")) {
                 m4.print(System.out);
             }
             m4.write(output);
+        } else {
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                handshakeHash.setCertificateVerifyAlg(null);
+            }
         }
 
         /*
@@ -813,8 +905,7 @@
      * method should only be called if you really want to use the
      * CipherSuite.
      *
-     * This method is called from chooseCipherSuite() in this class
-     * and SSLServerSocketImpl.checkEnabledSuites() (as a sanity check).
+     * This method is called from chooseCipherSuite() in this class.
      */
     boolean trySetCipherSuite(CipherSuite suite) {
         /*
@@ -831,6 +922,16 @@
             return false;
         }
 
+        // must not negotiate the obsoleted weak cipher suites.
+        if (protocolVersion.v >= suite.obsoleted) {
+            return false;
+        }
+
+        // must not negotiate unsupported cipher suites.
+        if (protocolVersion.v < suite.supported) {
+            return false;
+        }
+
         KeyExchange keyExchange = suite.keyExchange;
 
         // null out any existing references
@@ -840,36 +941,136 @@
         tempPrivateKey = null;
         tempPublicKey = null;
 
+        Collection<SignatureAndHashAlgorithm> supportedSignAlgs = null;
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            if (peerSupportedSignAlgs != null) {
+                supportedSignAlgs = peerSupportedSignAlgs;
+            } else {
+                SignatureAndHashAlgorithm algorithm = null;
+
+                // we may optimize the performance
+                switch (keyExchange) {
+                    // If the negotiated key exchange algorithm is one of
+                    // (RSA, DHE_RSA, DH_RSA, RSA_PSK, ECDH_RSA, ECDHE_RSA),
+                    // behave as if client had sent the value {sha1,rsa}.
+                    case K_RSA:
+                    case K_DHE_RSA:
+                    case K_DH_RSA:
+                    // case K_RSA_PSK:
+                    case K_ECDH_RSA:
+                    case K_ECDHE_RSA:
+                        algorithm = SignatureAndHashAlgorithm.valueOf(
+                                HashAlgorithm.SHA1.value,
+                                SignatureAlgorithm.RSA.value, 0);
+                        break;
+                    // If the negotiated key exchange algorithm is one of
+                    // (DHE_DSS, DH_DSS), behave as if the client had
+                    // sent the value {sha1,dsa}.
+                    case K_DHE_DSS:
+                    case K_DH_DSS:
+                        algorithm = SignatureAndHashAlgorithm.valueOf(
+                                HashAlgorithm.SHA1.value,
+                                SignatureAlgorithm.DSA.value, 0);
+                        break;
+                    // If the negotiated key exchange algorithm is one of
+                    // (ECDH_ECDSA, ECDHE_ECDSA), behave as if the client
+                    // had sent value {sha1,ecdsa}.
+                    case K_ECDH_ECDSA:
+                    case K_ECDHE_ECDSA:
+                        algorithm = SignatureAndHashAlgorithm.valueOf(
+                                HashAlgorithm.SHA1.value,
+                                SignatureAlgorithm.ECDSA.value, 0);
+                        break;
+                    default:
+                        // no peer supported signature algorithms
+                }
+
+                if (algorithm == null) {
+                    supportedSignAlgs =
+                        Collections.<SignatureAndHashAlgorithm>emptySet();
+                } else {
+                    supportedSignAlgs =
+                        new ArrayList<SignatureAndHashAlgorithm>(1);
+                    supportedSignAlgs.add(algorithm);
+                }
+
+                // Sets the peer supported signature algorithm to use in KM
+                // temporarily.
+                session.setPeerSupportedSignatureAlgorithms(supportedSignAlgs);
+            }
+        }
+
         switch (keyExchange) {
         case K_RSA:
+            // need RSA certs for authentication
+            if (setupPrivateKeyAndChain("RSA") == false) {
+                return false;
+            }
+            break;
         case K_RSA_EXPORT:
-        case K_DHE_RSA:
-        case K_ECDHE_RSA:
             // need RSA certs for authentication
             if (setupPrivateKeyAndChain("RSA") == false) {
                 return false;
             }
 
-            if (keyExchange == K_RSA_EXPORT) {
-                try {
-                   if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) {
-                        if (!setupEphemeralRSAKeys(suite.exportable)) {
-                            return false;
-                        }
-                   }
-                } catch (RuntimeException e) {
-                    // could not determine keylength, ignore key
+            try {
+               if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) {
+                    if (!setupEphemeralRSAKeys(suite.exportable)) {
+                        return false;
+                    }
+               }
+            } catch (RuntimeException e) {
+                // could not determine keylength, ignore key
+                return false;
+            }
+            break;
+        case K_DHE_RSA:
+            // get preferable peer signature algorithm for server key exchange
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                preferableSignatureAlgorithm =
+                    SignatureAndHashAlgorithm.getPreferableAlgorithm(
+                                                supportedSignAlgs, "RSA");
+                if (preferableSignatureAlgorithm == null) {
                     return false;
                 }
-            } else if (keyExchange == K_DHE_RSA) {
-                setupEphemeralDHKeys(suite.exportable);
-            } else if (keyExchange == K_ECDHE_RSA) {
-                if (setupEphemeralECDHKeys() == false) {
+            }
+
+            // need RSA certs for authentication
+            if (setupPrivateKeyAndChain("RSA") == false) {
+                return false;
+            }
+            setupEphemeralDHKeys(suite.exportable);
+            break;
+        case K_ECDHE_RSA:
+            // get preferable peer signature algorithm for server key exchange
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                preferableSignatureAlgorithm =
+                    SignatureAndHashAlgorithm.getPreferableAlgorithm(
+                                                supportedSignAlgs, "RSA");
+                if (preferableSignatureAlgorithm == null) {
                     return false;
                 }
-            } // else nothing more to do for K_RSA
+            }
+
+            // need RSA certs for authentication
+            if (setupPrivateKeyAndChain("RSA") == false) {
+                return false;
+            }
+            if (setupEphemeralECDHKeys() == false) {
+                return false;
+            }
             break;
         case K_DHE_DSS:
+            // get preferable peer signature algorithm for server key exchange
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                preferableSignatureAlgorithm =
+                    SignatureAndHashAlgorithm.getPreferableAlgorithm(
+                                                supportedSignAlgs, "DSA");
+                if (preferableSignatureAlgorithm == null) {
+                    return false;
+                }
+            }
+
             // need DSS certs for authentication
             if (setupPrivateKeyAndChain("DSA") == false) {
                 return false;
@@ -877,6 +1078,16 @@
             setupEphemeralDHKeys(suite.exportable);
             break;
         case K_ECDHE_ECDSA:
+            // get preferable peer signature algorithm for server key exchange
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                preferableSignatureAlgorithm =
+                    SignatureAndHashAlgorithm.getPreferableAlgorithm(
+                                            supportedSignAlgs, "ECDSA");
+                if (preferableSignatureAlgorithm == null) {
+                    return false;
+                }
+            }
+
             // need EC cert signed using EC
             if (setupPrivateKeyAndChain("EC_EC") == false) {
                 return false;
@@ -921,6 +1132,14 @@
             throw new RuntimeException("Unrecognized cipherSuite: " + suite);
         }
         setCipherSuite(suite);
+
+        // set the peer implicit supported signature algorithms
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            if (peerSupportedSignAlgs == null) {
+                setPeerSupportedSignAlgs(supportedSignAlgs);
+                // we had alreay update the session
+            }
+        }
         return true;
     }
 
@@ -1170,6 +1389,24 @@
             mesg.print(System.out);
         }
 
+        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+            SignatureAndHashAlgorithm signAlg =
+                mesg.getPreferableSignatureAlgorithm();
+            if (signAlg == null) {
+                throw new SSLHandshakeException(
+                        "Illegal CertificateVerify message");
+            }
+
+            String hashAlg =
+                SignatureAndHashAlgorithm.getHashAlgorithmName(signAlg);
+            if (hashAlg == null || hashAlg.length() == 0) {
+                throw new SSLHandshakeException(
+                        "No supported hash algorithm");
+            }
+
+            handshakeHash.setCertificateVerifyAlg(hashAlg);
+        }
+
         try {
             PublicKey publicKey =
                 session.getPeerCertificates()[0].getPublicKey();
@@ -1225,8 +1462,8 @@
          * Verify the client's message with the "before" digest of messages,
          * and forget about continuing to use that digest.
          */
-        boolean verified = mesg.verify(protocolVersion, handshakeHash,
-                                Finished.CLIENT, session.getMasterSecret());
+        boolean verified = mesg.verify(handshakeHash, Finished.CLIENT,
+            session.getMasterSecret());
 
         if (!verified) {
             fatalSE(Alerts.alert_handshake_failure,
@@ -1281,7 +1518,7 @@
         output.flush();
 
         Finished mesg = new Finished(protocolVersion, handshakeHash,
-                                Finished.SERVER, session.getMasterSecret());
+            Finished.SERVER, session.getMasterSecret(), cipherSuite);
 
         /*
          * Send the change_cipher_spec record; then our Finished handshake
@@ -1351,7 +1588,8 @@
      * ServerKeyExchange) message that was sent to it by the server.  That's
      * decrypted using the private key before we get here.
      */
-    private SecretKey clientKeyExchange(RSAClientKeyExchange mesg) throws IOException {
+    private SecretKey clientKeyExchange(RSAClientKeyExchange mesg)
+            throws IOException {
 
         if (debug != null && Debug.isOn("handshake")) {
             mesg.print(System.out);
@@ -1379,6 +1617,11 @@
              * not *REQUIRED*, this is an acceptable condition.)
              */
             if (doClientAuth == SSLEngineImpl.clauth_requested) {
+                // Smart (aka stupid) to forecast that no CertificateVerify
+                // message will be received.
+                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                    handshakeHash.setCertificateVerifyAlg(null);
+                }
                 return;
             } else {
                 fatalSE(Alerts.alert_bad_certificate,
@@ -1405,26 +1648,23 @@
                 authType = "UNKNOWN";
             }
 
-            String identificator = getHostnameVerificationSE();
             if (tm instanceof X509ExtendedTrustManager) {
-                ((X509ExtendedTrustManager)tm).checkClientTrusted(
-                        (peerCerts != null ?
-                            peerCerts.clone() :
-                            null),
+                if (conn != null) {
+                    ((X509ExtendedTrustManager)tm).checkClientTrusted(
+                        peerCerts.clone(),
                         authType,
-                        getHostSE(),
-                        identificator);
+                        conn);
+                } else {
+                    ((X509ExtendedTrustManager)tm).checkClientTrusted(
+                        peerCerts.clone(),
+                        authType,
+                        engine);
+                }
             } else {
-                if (identificator != null) {
-                    throw new RuntimeException(
-                        "trust manager does not support peer identification");
-                }
-
-                tm.checkClientTrusted(
-                    (peerCerts != null ?
-                        peerCerts.clone() :
-                        peerCerts),
-                    authType);
+                // Unlikely to happen, because we have wrapped the old
+                // X509TrustManager with the new X509ExtendedTrustManager.
+                throw new CertificateException(
+                    "Improper X509TrustManager implementation");
             }
         } catch (CertificateException e) {
             // This will throw an exception, so include the original error.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+package sun.security.ssl;
+
+import java.security.AlgorithmConstraints;
+import java.security.CryptoPrimitive;
+
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.EnumSet;
+import java.util.TreeMap;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.ArrayList;
+
+/**
+ * Signature and hash algorithm.
+ *
+ * [RFC5246] The client uses the "signature_algorithms" extension to
+ * indicate to the server which signature/hash algorithm pairs may be
+ * used in digital signatures.  The "extension_data" field of this
+ * extension contains a "supported_signature_algorithms" value.
+ *
+ *     enum {
+ *         none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
+ *         sha512(6), (255)
+ *     } HashAlgorithm;
+ *
+ *     enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
+ *       SignatureAlgorithm;
+ *
+ *     struct {
+ *           HashAlgorithm hash;
+ *           SignatureAlgorithm signature;
+ *     } SignatureAndHashAlgorithm;
+ */
+final class SignatureAndHashAlgorithm {
+
+    // minimum priority for default enabled algorithms
+    final static int SUPPORTED_ALG_PRIORITY_MAX_NUM = 0x00F0;
+
+    // performance optimization
+    private final static Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
+                                    EnumSet.of(CryptoPrimitive.SIGNATURE);
+
+    // supported pairs of signature and hash algorithm
+    private final static Map<Integer, SignatureAndHashAlgorithm> supportedMap;
+    private final static Map<Integer, SignatureAndHashAlgorithm> priorityMap;
+
+    // the hash algorithm
+    private HashAlgorithm hash;
+
+    // the signature algorithm
+    private SignatureAlgorithm signature;
+
+    // id in 16 bit MSB format, i.e. 0x0603 for SHA512withECDSA
+    private int id;
+
+    // the standard algorithm name, for example "SHA512withECDSA"
+    private String algorithm;
+
+    // Priority for the preference order. The lower the better.
+    //
+    // If the algorithm is unsupported, its priority should be bigger
+    // than SUPPORTED_ALG_PRIORITY_MAX_NUM.
+    private int priority;
+
+    // constructor for supported algorithm
+    private SignatureAndHashAlgorithm(HashAlgorithm hash,
+            SignatureAlgorithm signature, String algorithm, int priority) {
+        this.hash = hash;
+        this.signature = signature;
+        this.algorithm = algorithm;
+        this.id = ((hash.value & 0xFF) << 8) | (signature.value & 0xFF);
+        this.priority = priority;
+    }
+
+    // constructor for unsupported algorithm
+    private SignatureAndHashAlgorithm(String algorithm, int id, int sequence) {
+        this.hash = HashAlgorithm.valueOf((id >> 8) & 0xFF);
+        this.signature = SignatureAlgorithm.valueOf(id & 0xFF);
+        this.algorithm = algorithm;
+        this.id = id;
+
+        // add one more to the sequece number, in case that the number is zero
+        this.priority = SUPPORTED_ALG_PRIORITY_MAX_NUM + sequence + 1;
+    }
+
+    // Note that we do not use the sequence argument for supported algorithms,
+    // so please don't sort by comparing the objects read from handshake
+    // messages.
+    static SignatureAndHashAlgorithm valueOf(int hash,
+            int signature, int sequence) {
+        hash &= 0xFF;
+        signature &= 0xFF;
+
+        int id = (hash << 8) | signature;
+        SignatureAndHashAlgorithm signAlg = supportedMap.get(id);
+        if (signAlg == null) {
+            // unsupported algorithm
+            signAlg = new SignatureAndHashAlgorithm(
+                "Unknown (hash:0x" + Integer.toString(hash, 16) +
+                ", signature:0x" + Integer.toString(signature, 16) + ")",
+                id, sequence);
+        }
+
+        return signAlg;
+    }
+
+    int getHashValue() {
+        return (id >> 8) & 0xFF;
+    }
+
+    int getSignatureValue() {
+        return id & 0xFF;
+    }
+
+    String getAlgorithmName() {
+        return algorithm;
+    }
+
+    // return the size of a SignatureAndHashAlgorithm structure in TLS record
+    static int sizeInRecord() {
+        return 2;
+    }
+
+    // Get local supported algorithm collection complying to
+    // algorithm constraints
+    static Collection<SignatureAndHashAlgorithm>
+            getSupportedAlgorithms(AlgorithmConstraints constraints) {
+
+        Collection<SignatureAndHashAlgorithm> supported =
+                        new ArrayList<SignatureAndHashAlgorithm>();
+        synchronized (priorityMap) {
+            for (SignatureAndHashAlgorithm sigAlg : priorityMap.values()) {
+                if (sigAlg.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM &&
+                        constraints.permits(SIGNATURE_PRIMITIVE_SET,
+                                sigAlg.algorithm, null)) {
+                    supported.add(sigAlg);
+                }
+            }
+        }
+
+        return supported;
+    }
+
+    // Get supported algorithm collection from an untrusted collection
+    static Collection<SignatureAndHashAlgorithm> getSupportedAlgorithms(
+            Collection<SignatureAndHashAlgorithm> algorithms ) {
+        Collection<SignatureAndHashAlgorithm> supported =
+                        new ArrayList<SignatureAndHashAlgorithm>();
+        for (SignatureAndHashAlgorithm sigAlg : algorithms) {
+            if (sigAlg.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM) {
+                supported.add(sigAlg);
+            }
+        }
+
+        return supported;
+    }
+
+    static String[] getAlgorithmNames(
+            Collection<SignatureAndHashAlgorithm> algorithms) {
+        ArrayList<String> algorithmNames = new ArrayList<String>();
+        if (algorithms != null) {
+            for (SignatureAndHashAlgorithm sigAlg : algorithms) {
+                algorithmNames.add(sigAlg.algorithm);
+            }
+        }
+
+        String[] array = new String[algorithmNames.size()];
+        return algorithmNames.toArray(array);
+    }
+
+    static Set<String> getHashAlgorithmNames(
+            Collection<SignatureAndHashAlgorithm> algorithms) {
+        Set<String> algorithmNames = new HashSet<String>();
+        if (algorithms != null) {
+            for (SignatureAndHashAlgorithm sigAlg : algorithms) {
+                if (sigAlg.hash.value > 0) {
+                    algorithmNames.add(sigAlg.hash.standardName);
+                }
+            }
+        }
+
+        return algorithmNames;
+    }
+
+    static String getHashAlgorithmName(SignatureAndHashAlgorithm algorithm) {
+        return algorithm.hash.standardName;
+    }
+
+    private static void supports(HashAlgorithm hash,
+            SignatureAlgorithm signature, String algorithm, int priority) {
+
+        SignatureAndHashAlgorithm pair =
+            new SignatureAndHashAlgorithm(hash, signature, algorithm, priority);
+        if (supportedMap.put(pair.id, pair) != null) {
+            throw new RuntimeException(
+                "Duplicate SignatureAndHashAlgorithm definition, id: " +
+                pair.id);
+        }
+        if (priorityMap.put(pair.priority, pair) != null) {
+            throw new RuntimeException(
+                "Duplicate SignatureAndHashAlgorithm definition, priority: " +
+                pair.priority);
+        }
+    }
+
+    static SignatureAndHashAlgorithm getPreferableAlgorithm(
+        Collection<SignatureAndHashAlgorithm> algorithms, String expected) {
+
+        if (expected == null && !algorithms.isEmpty()) {
+            for (SignatureAndHashAlgorithm sigAlg : algorithms) {
+                if (sigAlg.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM) {
+                    return sigAlg;
+                }
+            }
+
+            return null;  // no supported algorithm
+        }
+
+
+        for (SignatureAndHashAlgorithm algorithm : algorithms) {
+            int signValue = algorithm.id & 0xFF;
+            if ((expected.equalsIgnoreCase("dsa") &&
+                    signValue == SignatureAlgorithm.DSA.value) ||
+                (expected.equalsIgnoreCase("rsa") &&
+                    signValue == SignatureAlgorithm.RSA.value) ||
+                (expected.equalsIgnoreCase("ecdsa") &&
+                    signValue == SignatureAlgorithm.ECDSA.value) ||
+                (expected.equalsIgnoreCase("ec") &&
+                    signValue == SignatureAlgorithm.ECDSA.value)) {
+                return algorithm;
+            }
+        }
+
+        return null;
+    }
+
+    static enum HashAlgorithm {
+        UNDEFINED("undefined",        "", -1),
+        NONE(          "none",    "NONE",  0),
+        MD5(            "md5",     "MD5",  1),
+        SHA1(          "sha1",   "SHA-1",  2),
+        SHA224(      "sha224", "SHA-224",  3),
+        SHA256(      "sha256", "SHA-256",  4),
+        SHA384(      "sha384", "SHA-384",  5),
+        SHA512(      "sha512", "SHA-512",  6);
+
+        final String name;  // not the standard signature algorithm name
+                            // except the UNDEFINED, other names are defined
+                            // by TLS 1.2 protocol
+        final String standardName; // the standard MessageDigest algorithm name
+        final int value;
+
+        private HashAlgorithm(String name, String standardName, int value) {
+            this.name = name;
+            this.standardName = standardName;
+            this.value = value;
+        }
+
+        static HashAlgorithm valueOf(int value) {
+            HashAlgorithm algorithm = UNDEFINED;
+            switch (value) {
+                case 0:
+                    algorithm = NONE;
+                    break;
+                case 1:
+                    algorithm = MD5;
+                    break;
+                case 2:
+                    algorithm = SHA1;
+                    break;
+                case 3:
+                    algorithm = SHA224;
+                    break;
+                case 4:
+                    algorithm = SHA256;
+                    break;
+                case 5:
+                    algorithm = SHA384;
+                    break;
+                case 6:
+                    algorithm = SHA512;
+                    break;
+            }
+
+            return algorithm;
+        }
+    }
+
+    static enum SignatureAlgorithm {
+        UNDEFINED("undefined", -1),
+        ANONYMOUS("anonymous",  0),
+        RSA(            "rsa",  1),
+        DSA(            "dsa",  2),
+        ECDSA(        "ecdsa",  3);
+
+        final String name;  // not the standard signature algorithm name
+                            // except the UNDEFINED, other names are defined
+                            // by TLS 1.2 protocol
+        final int value;
+
+        private SignatureAlgorithm(String name, int value) {
+            this.name = name;
+            this.value = value;
+        }
+
+        static SignatureAlgorithm valueOf(int value) {
+            SignatureAlgorithm algorithm = UNDEFINED;
+            switch (value) {
+                case 0:
+                    algorithm = ANONYMOUS;
+                    break;
+                case 1:
+                    algorithm = RSA;
+                    break;
+                case 2:
+                    algorithm = DSA;
+                    break;
+                case 3:
+                    algorithm = ECDSA;
+                    break;
+            }
+
+            return algorithm;
+        }
+    }
+
+    static {
+        supportedMap = Collections.synchronizedSortedMap(
+            new TreeMap<Integer, SignatureAndHashAlgorithm>());
+        priorityMap = Collections.synchronizedSortedMap(
+            new TreeMap<Integer, SignatureAndHashAlgorithm>());
+
+        synchronized (supportedMap) {
+            int p = SUPPORTED_ALG_PRIORITY_MAX_NUM;
+            supports(HashAlgorithm.MD5,         SignatureAlgorithm.RSA,
+                    "MD5withRSA",           --p);
+            supports(HashAlgorithm.SHA1,        SignatureAlgorithm.DSA,
+                    "SHA1withDSA",          --p);
+            supports(HashAlgorithm.SHA1,        SignatureAlgorithm.RSA,
+                    "SHA1withRSA",          --p);
+            supports(HashAlgorithm.SHA1,        SignatureAlgorithm.ECDSA,
+                    "SHA1withECDSA",        --p);
+            supports(HashAlgorithm.SHA224,      SignatureAlgorithm.RSA,
+                    "SHA224withRSA",        --p);
+            supports(HashAlgorithm.SHA224,      SignatureAlgorithm.ECDSA,
+                    "SHA224withECDSA",      --p);
+            supports(HashAlgorithm.SHA256,      SignatureAlgorithm.RSA,
+                    "SHA256withRSA",        --p);
+            supports(HashAlgorithm.SHA256,      SignatureAlgorithm.ECDSA,
+                    "SHA256withECDSA",      --p);
+            supports(HashAlgorithm.SHA384,      SignatureAlgorithm.RSA,
+                    "SHA384withRSA",        --p);
+            supports(HashAlgorithm.SHA384,      SignatureAlgorithm.ECDSA,
+                    "SHA384withECDSA",      --p);
+            supports(HashAlgorithm.SHA512,      SignatureAlgorithm.RSA,
+                    "SHA512withRSA",        --p);
+            supports(HashAlgorithm.SHA512,      SignatureAlgorithm.ECDSA,
+                    "SHA512withECDSA",      --p);
+        }
+    }
+}
+
--- a/jdk/src/share/classes/sun/security/ssl/SunJSSE.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/SunJSSE.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, 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,7 +38,7 @@
  *
  * SunJSSE now supports an experimental FIPS compliant mode when used with an
  * appropriate FIPS certified crypto provider. In FIPS mode, we:
- *  . allow only TLS 1.0
+ *  . allow only TLS 1.0 or later
  *  . allow only FIPS approved ciphersuites
  *  . perform all crypto in the FIPS crypto provider
  *
@@ -129,7 +129,8 @@
         return t;
     }
 
-    private SunJSSE(java.security.Provider cryptoProvider, String providerName) {
+    private SunJSSE(java.security.Provider cryptoProvider,
+            String providerName) {
         super("SunJSSE", 1.6d, fipsInfo + providerName + ")");
         subclassCheck();
         if (cryptoProvider == null) {
@@ -211,6 +212,10 @@
             "sun.security.ssl.SSLContextImpl");
         put("SSLContext.TLSv1",
             "sun.security.ssl.SSLContextImpl");
+        put("SSLContext.TLSv1.1",
+            "sun.security.ssl.SSLContextImpl");
+        put("SSLContext.TLSv1.2",
+            "sun.security.ssl.SSLContextImpl");
         put("SSLContext.Default",
             "sun.security.ssl.DefaultSSLContextImpl");
 
--- a/jdk/src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, 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
--- a/jdk/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2010, 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,8 @@
 
 import javax.net.ssl.*;
 
+import sun.security.provider.certpath.AlgorithmChecker;
+
 /**
  * The new X509 key manager implementation. The main differences to the
  * old SunX509 key manager are:
@@ -111,36 +113,98 @@
 
     public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
             Socket socket) {
-        return chooseAlias(getKeyTypes(keyTypes), issuers, CheckType.CLIENT);
+        return chooseAlias(getKeyTypes(keyTypes), issuers, CheckType.CLIENT,
+                        getAlgorithmConstraints(socket));
     }
 
     public String chooseEngineClientAlias(String[] keyTypes,
             Principal[] issuers, SSLEngine engine) {
-        return chooseAlias(getKeyTypes(keyTypes), issuers, CheckType.CLIENT);
+        return chooseAlias(getKeyTypes(keyTypes), issuers, CheckType.CLIENT,
+                        getAlgorithmConstraints(engine));
     }
 
     public String chooseServerAlias(String keyType,
             Principal[] issuers, Socket socket) {
-        return chooseAlias(getKeyTypes(keyType), issuers, CheckType.SERVER);
+        return chooseAlias(getKeyTypes(keyType), issuers, CheckType.SERVER,
+                        getAlgorithmConstraints(socket));
     }
 
     public String chooseEngineServerAlias(String keyType,
             Principal[] issuers, SSLEngine engine) {
-        return chooseAlias(getKeyTypes(keyType), issuers, CheckType.SERVER);
+        return chooseAlias(getKeyTypes(keyType), issuers, CheckType.SERVER,
+                        getAlgorithmConstraints(engine));
     }
 
     public String[] getClientAliases(String keyType, Principal[] issuers) {
-        return getAliases(keyType, issuers, CheckType.CLIENT);
+        return getAliases(keyType, issuers, CheckType.CLIENT, null);
     }
 
     public String[] getServerAliases(String keyType, Principal[] issuers) {
-        return getAliases(keyType, issuers, CheckType.SERVER);
+        return getAliases(keyType, issuers, CheckType.SERVER, null);
     }
 
     //
     // implementation private methods
     //
 
+    // Gets algorithm constraints of the socket.
+    private AlgorithmConstraints getAlgorithmConstraints(Socket socket) {
+        if (socket != null && socket.isConnected() &&
+                                        socket instanceof SSLSocket) {
+
+            SSLSocket sslSocket = (SSLSocket)socket;
+            SSLSession session = sslSocket.getHandshakeSession();
+
+            if (session != null) {
+                ProtocolVersion protocolVersion =
+                    ProtocolVersion.valueOf(session.getProtocol());
+                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                    String[] peerSupportedSignAlgs = null;
+
+                    if (session instanceof ExtendedSSLSession) {
+                        ExtendedSSLSession extSession =
+                            (ExtendedSSLSession)session;
+                        peerSupportedSignAlgs =
+                            extSession.getPeerSupportedSignatureAlgorithms();
+                    }
+
+                    return new SSLAlgorithmConstraints(
+                        sslSocket, peerSupportedSignAlgs, true);
+                }
+            }
+
+            return new SSLAlgorithmConstraints(sslSocket, true);
+        }
+
+        return new SSLAlgorithmConstraints((SSLSocket)null, true);
+    }
+
+    // Gets algorithm constraints of the engine.
+    private AlgorithmConstraints getAlgorithmConstraints(SSLEngine engine) {
+        if (engine != null) {
+            SSLSession session = engine.getHandshakeSession();
+            if (session != null) {
+                ProtocolVersion protocolVersion =
+                    ProtocolVersion.valueOf(session.getProtocol());
+                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                    String[] peerSupportedSignAlgs = null;
+
+                    if (session instanceof ExtendedSSLSession) {
+                        ExtendedSSLSession extSession =
+                            (ExtendedSSLSession)session;
+                        peerSupportedSignAlgs =
+                            extSession.getPeerSupportedSignatureAlgorithms();
+                    }
+
+                    return new SSLAlgorithmConstraints(
+                        engine, peerSupportedSignAlgs, true);
+                }
+            }
+        }
+
+        return new SSLAlgorithmConstraints(engine, true);
+    }
+
     // we construct the alias we return to JSSE as seen in the code below
     // a unique id is included to allow us to reliably cache entries
     // between the calls to getCertificateChain() and getPrivateKey()
@@ -196,6 +260,13 @@
     private static class KeyType {
 
         final String keyAlgorithm;
+
+        // In TLS 1.2, the signature algorithm  has been obsoleted by the
+        // supported_signature_algorithms, and the certificate type no longer
+        // restricts the algorithm used to sign the certificate.
+        // However, because we don't support certificate type checking other
+        // than rsa_sign, dss_sign and ecdsa_sign, we don't have to check the
+        // protocol version here.
         final String sigKeyAlgorithm;
 
         KeyType(String algorithm) {
@@ -218,7 +289,8 @@
             }
             if (chain.length > 1) {
                 // if possible, check the public key in the issuer cert
-                return sigKeyAlgorithm.equals(chain[1].getPublicKey().getAlgorithm());
+                return sigKeyAlgorithm.equals(
+                        chain[1].getPublicKey().getAlgorithm());
             } else {
                 // Check the signature algorithm of the certificate itself.
                 // Look for the "withRSA" in "SHA1withRSA", etc.
@@ -231,7 +303,8 @@
     }
 
     private static List<KeyType> getKeyTypes(String ... keyTypes) {
-        if ((keyTypes == null) || (keyTypes.length == 0) || (keyTypes[0] == null)) {
+        if ((keyTypes == null) ||
+                (keyTypes.length == 0) || (keyTypes[0] == null)) {
             return null;
         }
         List<KeyType> list = new ArrayList<KeyType>(keyTypes.length);
@@ -254,8 +327,8 @@
      *     with appropriate key usage to certs with the wrong key usage.
      *     return the first one of them.
      */
-    private String chooseAlias(List<KeyType> keyTypeList,
-            Principal[] issuers, CheckType checkType) {
+    private String chooseAlias(List<KeyType> keyTypeList, Principal[] issuers,
+            CheckType checkType, AlgorithmConstraints constraints) {
         if (keyTypeList == null || keyTypeList.size() == 0) {
             return null;
         }
@@ -264,8 +337,8 @@
         List<EntryStatus> allResults = null;
         for (int i = 0, n = builders.size(); i < n; i++) {
             try {
-                List<EntryStatus> results =
-                    getAliases(i, keyTypeList, issuerSet, false, checkType);
+                List<EntryStatus> results = getAliases(i, keyTypeList,
+                                    issuerSet, false, checkType, constraints);
                 if (results != null) {
                     // the results will either be a single perfect match
                     // or 1 or more imperfect matches
@@ -308,7 +381,7 @@
      * The perfect matches will be first in the array.
      */
     public String[] getAliases(String keyType, Principal[] issuers,
-            CheckType checkType) {
+            CheckType checkType, AlgorithmConstraints constraints) {
         if (keyType == null) {
             return null;
         }
@@ -318,8 +391,8 @@
         List<EntryStatus> allResults = null;
         for (int i = 0, n = builders.size(); i < n; i++) {
             try {
-                List<EntryStatus> results =
-                        getAliases(i, keyTypeList, issuerSet, true, checkType);
+                List<EntryStatus> results = getAliases(i, keyTypeList,
+                                    issuerSet, true, checkType, constraints);
                 if (results != null) {
                     if (allResults == null) {
                         allResults = new ArrayList<EntryStatus>();
@@ -438,7 +511,8 @@
             try {
                 // check extended key usage
                 List<String> certEku = cert.getExtendedKeyUsage();
-                if ((certEku != null) && Collections.disjoint(validEku, certEku)) {
+                if ((certEku != null) &&
+                        Collections.disjoint(validEku, certEku)) {
                     // if extension present and it does not contain any of
                     // the valid EKU OIDs, return extension_mismatch
                     return CheckResult.EXTENSION_MISMATCH;
@@ -534,7 +608,8 @@
      */
     private List<EntryStatus> getAliases(int builderIndex,
             List<KeyType> keyTypes, Set<Principal> issuerSet,
-            boolean findAll, CheckType checkType) throws Exception {
+            boolean findAll, CheckType checkType,
+            AlgorithmConstraints constraints) throws Exception {
         Builder builder = builders.get(builderIndex);
         KeyStore ks = builder.getKeyStore();
         List<EntryStatus> results = null;
@@ -552,6 +627,19 @@
                 // must be secret key entry, ignore
                 continue;
             }
+
+            boolean incompatible = false;
+            for (Certificate cert : chain) {
+                if (cert instanceof X509Certificate == false) {
+                    // not an X509Certificate, ignore this alias
+                    incompatible = true;
+                    break;
+                }
+            }
+            if (incompatible) {
+                continue;
+            }
+
             // check keytype
             int keyIndex = -1;
             int j = 0;
@@ -573,10 +661,6 @@
             if (issuerSet != null) {
                 boolean found = false;
                 for (Certificate cert : chain) {
-                    if (cert instanceof X509Certificate == false) {
-                        // not an X509Certificate, ignore this entry
-                        break;
-                    }
                     X509Certificate xcert = (X509Certificate)cert;
                     if (issuerSet.contains(xcert.getIssuerX500Principal())) {
                         found = true;
@@ -591,6 +675,19 @@
                     continue;
                 }
             }
+
+            // check the algorithm constraints
+            if (constraints != null &&
+                    !conformsToAlgorithmConstraints(constraints, chain)) {
+
+                if (useDebug) {
+                    debug.println("Ignoring alias " + alias +
+                            ": certificate list does not conform to " +
+                            "algorithm constraints");
+                }
+                continue;
+            }
+
             if (date == null) {
                 date = new Date();
             }
@@ -616,4 +713,29 @@
         return results;
     }
 
+    private static boolean conformsToAlgorithmConstraints(
+            AlgorithmConstraints constraints, Certificate[] chain) {
+
+        AlgorithmChecker checker = new AlgorithmChecker(constraints);
+        try {
+            checker.init(false);
+        } catch (CertPathValidatorException cpve) {
+            // unlikely to happen
+            return false;
+        }
+
+        // It is a forward checker, so we need to check from trust to target.
+        for (int i = chain.length - 1; i >= 0; i--) {
+            Certificate cert = chain[i];
+            try {
+                // We don't care about the unresolved critical extensions.
+                checker.check(cert, Collections.<String>emptySet());
+            } catch (CertPathValidatorException cpve) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
 }
--- a/jdk/src/share/classes/sun/security/ssl/X509TrustManagerImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/X509TrustManagerImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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,14 +26,15 @@
 
 package sun.security.ssl;
 
+import java.net.Socket;
+import javax.net.ssl.SSLSession;
+
 import java.util.*;
 import java.security.*;
 import java.security.cert.*;
 
 import javax.net.ssl.*;
 
-import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
-
 import sun.security.validator.*;
 
 import sun.security.util.HostnameChecker;
@@ -41,7 +42,7 @@
 /**
  * This class implements the SunJSSE X.509 trust manager using the internal
  * validator API in J2SE core. The logic in this class is minimal.<p>
- *
+ * <p>
  * This class supports both the Simple validation algorithm from previous
  * JSSE versions and PKIX validation. Currently, it is not possible for the
  * application to specify PKIX parameters other than trust anchors. This will
@@ -50,19 +51,10 @@
  * classes.
  *
  * @author Andreas Sterbenz
- * @author Xuelei Fan
  */
 final class X509TrustManagerImpl extends X509ExtendedTrustManager
         implements X509TrustManager {
 
-    /**
-     * Flag indicating whether to enable revocation check for the PKIX trust
-     * manager. Typically, this will only work if the PKIX implementation
-     * supports CRL distribution points as we do not manually setup CertStores.
-     */
-    private final static boolean checkRevocation =
-        Debug.getBooleanProperty("com.sun.net.ssl.checkRevocation", false);
-
     private final String validatorType;
 
     /**
@@ -103,6 +95,199 @@
         showTrustedCerts();
     }
 
+    @Override
+    public void checkClientTrusted(X509Certificate chain[], String authType)
+            throws CertificateException {
+        checkTrusted(chain, authType, (Socket)null, true);
+    }
+
+    @Override
+    public void checkServerTrusted(X509Certificate chain[], String authType)
+            throws CertificateException {
+        checkTrusted(chain, authType, (Socket)null, false);
+    }
+
+    @Override
+    public X509Certificate[] getAcceptedIssuers() {
+        X509Certificate[] certsArray = new X509Certificate[trustedCerts.size()];
+        trustedCerts.toArray(certsArray);
+        return certsArray;
+    }
+
+    @Override
+    public void checkClientTrusted(X509Certificate[] chain, String authType,
+                Socket socket) throws CertificateException {
+        checkTrusted(chain, authType, socket, true);
+    }
+
+    @Override
+    public void checkServerTrusted(X509Certificate[] chain, String authType,
+            Socket socket) throws CertificateException {
+        checkTrusted(chain, authType, socket, false);
+    }
+
+    @Override
+    public void checkClientTrusted(X509Certificate[] chain, String authType,
+            SSLEngine engine) throws CertificateException {
+        checkTrusted(chain, authType, engine, true);
+    }
+
+    @Override
+    public void checkServerTrusted(X509Certificate[] chain, String authType,
+            SSLEngine engine) throws CertificateException {
+        checkTrusted(chain, authType, engine, false);
+    }
+
+    private Validator checkTrustedInit(X509Certificate[] chain,
+                                        String authType, boolean isClient) {
+        if (chain == null || chain.length == 0) {
+            throw new IllegalArgumentException(
+                "null or zero-length certificate chain");
+        }
+
+        if (authType == null || authType.length() == 0) {
+            throw new IllegalArgumentException(
+                "null or zero-length authentication type");
+        }
+
+        Validator v = null;
+        if (isClient) {
+            v = clientValidator;
+            if (v == null) {
+                synchronized (this) {
+                    v = clientValidator;
+                    if (v == null) {
+                        v = getValidator(Validator.VAR_TLS_CLIENT);
+                        clientValidator = v;
+                    }
+                }
+            }
+        } else {
+            // assume double checked locking with a volatile flag works
+            // (guaranteed under the new Tiger memory model)
+            v = serverValidator;
+            if (v == null) {
+                synchronized (this) {
+                    v = serverValidator;
+                    if (v == null) {
+                        v = getValidator(Validator.VAR_TLS_SERVER);
+                        serverValidator = v;
+                    }
+                }
+            }
+        }
+
+        return v;
+    }
+
+
+    private void checkTrusted(X509Certificate[] chain, String authType,
+                Socket socket, boolean isClient) throws CertificateException {
+        Validator v = checkTrustedInit(chain, authType, isClient);
+
+        AlgorithmConstraints constraints = null;
+        if ((socket != null) && socket.isConnected() &&
+                                        (socket instanceof SSLSocket)) {
+
+            SSLSocket sslSocket = (SSLSocket)socket;
+            SSLSession session = sslSocket.getHandshakeSession();
+            if (session == null) {
+                throw new CertificateException("No handshake session");
+            }
+
+            // check endpoint identity
+            String identityAlg = sslSocket.getSSLParameters().
+                                        getEndpointIdentificationAlgorithm();
+            if (identityAlg != null && identityAlg.length() != 0) {
+                String hostname = session.getPeerHost();
+                checkIdentity(hostname, chain[0], identityAlg);
+            }
+
+            // create the algorithm constraints
+            ProtocolVersion protocolVersion =
+                ProtocolVersion.valueOf(session.getProtocol());
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                if (session instanceof ExtendedSSLSession) {
+                    ExtendedSSLSession extSession =
+                                    (ExtendedSSLSession)session;
+                    String[] localSupportedSignAlgs =
+                            extSession.getLocalSupportedSignatureAlgorithms();
+
+                    constraints = new SSLAlgorithmConstraints(
+                                    sslSocket, localSupportedSignAlgs, false);
+                } else {
+                    constraints =
+                            new SSLAlgorithmConstraints(sslSocket, false);
+                }
+            } else {
+                constraints = new SSLAlgorithmConstraints(sslSocket, false);
+            }
+        }
+
+        X509Certificate[] trustedChain = null;
+        if (isClient) {
+            trustedChain = validate(v, chain, constraints, null);
+        } else {
+            trustedChain = validate(v, chain, constraints, authType);
+        }
+        if (debug != null && Debug.isOn("trustmanager")) {
+            System.out.println("Found trusted certificate:");
+            System.out.println(trustedChain[trustedChain.length - 1]);
+        }
+    }
+
+    private void checkTrusted(X509Certificate[] chain, String authType,
+            SSLEngine engine, boolean isClient) throws CertificateException {
+        Validator v = checkTrustedInit(chain, authType, isClient);
+
+        AlgorithmConstraints constraints = null;
+        if (engine != null) {
+            SSLSession session = engine.getHandshakeSession();
+            if (session == null) {
+                throw new CertificateException("No handshake session");
+            }
+
+            // check endpoint identity
+            String identityAlg = engine.getSSLParameters().
+                                        getEndpointIdentificationAlgorithm();
+            if (identityAlg != null && identityAlg.length() != 0) {
+                String hostname = session.getPeerHost();
+                checkIdentity(hostname, chain[0], identityAlg);
+            }
+
+            // create the algorithm constraints
+            ProtocolVersion protocolVersion =
+                ProtocolVersion.valueOf(session.getProtocol());
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                if (session instanceof ExtendedSSLSession) {
+                    ExtendedSSLSession extSession =
+                                    (ExtendedSSLSession)session;
+                    String[] localSupportedSignAlgs =
+                            extSession.getLocalSupportedSignatureAlgorithms();
+
+                    constraints = new SSLAlgorithmConstraints(
+                                    engine, localSupportedSignAlgs, false);
+                } else {
+                    constraints =
+                            new SSLAlgorithmConstraints(engine, false);
+                }
+            } else {
+                constraints = new SSLAlgorithmConstraints(engine, false);
+            }
+        }
+
+        X509Certificate[] trustedChain = null;
+        if (isClient) {
+            trustedChain = validate(v, chain, constraints, null);
+        } else {
+            trustedChain = validate(v, chain, constraints, authType);
+        }
+        if (debug != null && Debug.isOn("trustmanager")) {
+            System.out.println("Found trusted certificate:");
+            System.out.println(trustedChain[trustedChain.length - 1]);
+        }
+    }
+
     private void showTrustedCerts() {
         if (debug != null && Debug.isOn("trustmanager")) {
             for (X509Certificate cert : trustedCerts) {
@@ -127,13 +312,6 @@
         Validator v;
         if (pkixParams == null) {
             v = Validator.getInstance(validatorType, variant, trustedCerts);
-            // if the PKIX validator is created from a KeyStore,
-            // disable revocation checking
-            if (v instanceof PKIXValidator) {
-                PKIXValidator pkixValidator = (PKIXValidator)v;
-                pkixValidator.getParameters().setRevocationEnabled
-                                                            (checkRevocation);
-            }
         } else {
             v = Validator.getInstance(validatorType, variant, pkixParams);
         }
@@ -141,150 +319,35 @@
     }
 
     private static X509Certificate[] validate(Validator v,
-            X509Certificate[] chain, String authType) throws CertificateException {
+            X509Certificate[] chain, AlgorithmConstraints constraints,
+            String authType) throws CertificateException {
         Object o = JsseJce.beginFipsProvider();
         try {
-            return v.validate(chain, null, authType);
+            return v.validate(chain, null, constraints, authType);
         } finally {
             JsseJce.endFipsProvider(o);
         }
     }
 
-    /**
-     * Returns true if the client certificate can be trusted.
+    /*
+     * Identify the peer by its certificate and hostname.
      *
-     * @param chain certificates which establish an identity for the client.
-     *      Chains of arbitrary length are supported, and certificates
-     *      marked internally as trusted will short-circuit signature checks.
-     * @throws IllegalArgumentException if null or zero-length chain
-     *         is passed in for the chain parameter or if null or zero-length
-     *         string is passed in for the authType parameter.
-     * @throws CertificateException if the certificate chain is not trusted
-     *      by this TrustManager.
-     */
-    public void checkClientTrusted(X509Certificate chain[], String authType)
-            throws CertificateException {
-        if (chain == null || chain.length == 0) {
-            throw new IllegalArgumentException(
-                "null or zero-length certificate chain");
-        }
-        if (authType == null || authType.length() == 0) {
-            throw new IllegalArgumentException(
-                "null or zero-length authentication type");
-        }
-
-        // assume double checked locking with a volatile flag works
-        // (guaranteed under the new Tiger memory model)
-        Validator v = clientValidator;
-        if (v == null) {
-            synchronized (this) {
-                v = clientValidator;
-                if (v == null) {
-                    v = getValidator(Validator.VAR_TLS_CLIENT);
-                    clientValidator = v;
-                }
-            }
-        }
-        X509Certificate[] trustedChain = validate(v, chain, null);
-        if (debug != null && Debug.isOn("trustmanager")) {
-            System.out.println("Found trusted certificate:");
-            System.out.println(trustedChain[trustedChain.length - 1]);
-        }
-    }
-
-    /**
-     * Returns true if the server certifcate can be trusted.
-     *
-     * @param chain certificates which establish an identity for the server.
-     *      Chains of arbitrary length are supported, and certificates
-     *      marked internally as trusted will short-circuit signature checks.
-     * @throws IllegalArgumentException if null or zero-length chain
-     *         is passed in for the chain parameter or if null or zero-length
-     *         string is passed in for the authType parameter.
-     * @throws CertificateException if the certificate chain is not trusted
-     *      by this TrustManager.
+     * Lifted from sun.net.www.protocol.https.HttpsClient.
      */
-    public void checkServerTrusted(X509Certificate chain[], String authType)
-            throws CertificateException {
-        if (chain == null || chain.length == 0) {
-            throw new IllegalArgumentException(
-                "null or zero-length certificate chain");
-        }
-        if (authType == null || authType.length() == 0) {
-            throw new IllegalArgumentException(
-                "null or zero-length authentication type");
-        }
-
-        // assume double checked locking with a volatile flag works
-        // (guaranteed under the new Tiger memory model)
-        Validator v = serverValidator;
-        if (v == null) {
-            synchronized (this) {
-                v = serverValidator;
-                if (v == null) {
-                    v = getValidator(Validator.VAR_TLS_SERVER);
-                    serverValidator = v;
-                }
-            }
-        }
-        X509Certificate[] trustedChain = validate(v, chain, authType);
-        if (debug != null && Debug.isOn("trustmanager")) {
-            System.out.println("Found trusted certificate:");
-            System.out.println(trustedChain[trustedChain.length - 1]);
-        }
-    }
-
-    /**
-     * Returns a list of CAs accepted to authenticate entities for the
-     * specified purpose.
-     *
-     * @param purpose activity for which CAs should be trusted
-     * @return list of CAs accepted for authenticating such tasks
-     */
-    public X509Certificate[] getAcceptedIssuers() {
-        X509Certificate[] certsArray = new X509Certificate[trustedCerts.size()];
-        trustedCerts.toArray(certsArray);
-        return certsArray;
-    }
-
-    /**
-     * Given the partial or complete certificate chain provided by the
-     * peer, check its identity and build a certificate path to a trusted
-     * root, return if it can be validated and is trusted for client SSL
-     * authentication based on the authentication type.
-     */
-    public void checkClientTrusted(X509Certificate[] chain, String authType,
-        String hostname, String algorithm) throws CertificateException {
-        checkClientTrusted(chain, authType);
-        checkIdentity(hostname, chain[0], algorithm);
-    }
-
-    /**
-     * Given the partial or complete certificate chain provided by the
-     * peer, check its identity and build a certificate path to a trusted
-     * root, return if it can be validated and is trusted for server SSL
-     * authentication based on the authentication type.
-     */
-    public void checkServerTrusted(X509Certificate[] chain, String authType,
-        String hostname, String algorithm) throws CertificateException {
-        checkServerTrusted(chain, authType);
-        checkIdentity(hostname, chain[0], algorithm);
-    }
-
-    // Identify the peer by its certificate and hostname.
-    private void checkIdentity(String hostname, X509Certificate cert,
-        String algorithm) throws CertificateException {
+    static void checkIdentity(String hostname, X509Certificate cert,
+            String algorithm) throws CertificateException {
         if (algorithm != null && algorithm.length() != 0) {
             // if IPv6 strip off the "[]"
-            if (hostname != null && hostname.startsWith("[") &&
-                hostname.endsWith("]")) {
-                hostname = hostname.substring(1, hostname.length()-1);
+            if ((hostname != null) && hostname.startsWith("[") &&
+                    hostname.endsWith("]")) {
+                hostname = hostname.substring(1, hostname.length() - 1);
             }
 
             if (algorithm.equalsIgnoreCase("HTTPS")) {
                 HostnameChecker.getInstance(HostnameChecker.TYPE_TLS).match(
                         hostname, cert);
-            } else if (algorithm.equalsIgnoreCase("LDAP")) {
+            } else if (algorithm.equalsIgnoreCase("LDAP") ||
+                    algorithm.equalsIgnoreCase("LDAPS")) {
                 HostnameChecker.getInstance(HostnameChecker.TYPE_LDAP).match(
                         hostname, cert);
             } else {
--- a/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -244,7 +244,7 @@
                 clientVersion, rand, input, sessionKey);
         } else {
             // Generate bogus premaster secret
-            preMaster = new KerberosPreMasterSecret(protocolVersion, rand);
+            preMaster = new KerberosPreMasterSecret(clientVersion, rand);
         }
     }
 
--- a/jdk/src/share/classes/sun/security/ssl/krb5/KerberosPreMasterSecret.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/ssl/krb5/KerberosPreMasterSecret.java	Wed Jul 05 17:26:57 2017 +0200
@@ -176,13 +176,21 @@
         // check if the premaster secret version is ok
         // the specification says that it must be the maximum version supported
         // by the client from its ClientHello message. However, many
-        // implementations send the negotiated version, so accept both
+        // old implementations send the negotiated version, so accept both
+        // for SSL v3.0 and TLS v1.0.
         // NOTE that we may be comparing two unsupported version numbers in
         // the second case, which is why we cannot use object references
         // equality in this special case
-        boolean versionMismatch = (protocolVersion != currentVersion) &&
-                                  (protocolVersion.v != clientVersion.v);
+        boolean versionMismatch = (protocolVersion.v != clientVersion.v);
 
+        /*
+         * we never checked the client_version in server side
+         * for TLS v1.0 and SSL v3.0. For compatibility, we
+         * maintain this behavior.
+         */
+        if (versionMismatch && (clientVersion.v <= 0x0301)) {
+            versionMismatch = (protocolVersion.v != currentVersion.v);
+        }
 
         /*
          * Bogus decrypted ClientKeyExchange? If so, conjure a
@@ -203,8 +211,14 @@
                     Debug.println(System.out, "Invalid secret", preMaster);
                 }
             }
-            preMaster = generatePreMaster(generator, currentVersion);
-            protocolVersion = currentVersion;
+
+            /*
+             * Randomize the preMaster secret with the
+             * ClientHello.client_version, as will produce invalid master
+             * secret to prevent the attacks.
+             */
+            preMaster = generatePreMaster(generator, clientVersion);
+            protocolVersion = clientVersion;
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+package sun.security.util;
+
+import java.security.AlgorithmConstraints;
+import java.security.CryptoPrimitive;
+import java.security.AlgorithmParameters;
+
+import java.security.Key;
+import java.security.Security;
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+import java.security.interfaces.ECKey;
+import java.security.interfaces.RSAKey;
+import java.security.interfaces.DSAKey;
+import javax.crypto.SecretKey;
+import javax.crypto.interfaces.DHKey;
+
+import java.util.Locale;
+import java.util.Set;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+/**
+ * Algorithm constraints for disabled algorithms property
+ *
+ * See the "jdk.certpath.disabledAlgorithms" specification in java.security
+ * for the syntax of the disabled algorithm string.
+ */
+public class DisabledAlgorithmConstraints implements AlgorithmConstraints {
+
+    // the known security property, jdk.certpath.disabledAlgorithms
+    public final static String PROPERTY_CERTPATH_DISABLED_ALGS =
+            "jdk.certpath.disabledAlgorithms";
+
+    // the known security property, jdk.tls.disabledAlgorithms
+    public final static String PROPERTY_TLS_DISABLED_ALGS =
+            "jdk.tls.disabledAlgorithms";
+
+    private static Map<String, String[]> disabledAlgorithmsMap =
+            Collections.synchronizedMap(new HashMap<String, String[]>());
+    private static Map<String, KeySizeConstraints> keySizeConstraintsMap =
+        Collections.synchronizedMap(new HashMap<String, KeySizeConstraints>());
+
+    private String[] disabledAlgorithms;
+    private KeySizeConstraints keySizeConstraints;
+
+    /**
+     * Initialize algorithm constraints with the specified security property.
+     *
+     * @param propertyName the security property name that define the disabled
+     *        algorithm constraints
+     */
+    public DisabledAlgorithmConstraints(String propertyName) {
+        synchronized (disabledAlgorithmsMap) {
+            if(!disabledAlgorithmsMap.containsKey(propertyName)) {
+                loadDisabledAlgorithmsMap(propertyName);
+            }
+
+            disabledAlgorithms = disabledAlgorithmsMap.get(propertyName);
+            keySizeConstraints = keySizeConstraintsMap.get(propertyName);
+        }
+    }
+
+    @Override
+    final public boolean permits(Set<CryptoPrimitive> primitives,
+            String algorithm, AlgorithmParameters parameters) {
+
+        if (algorithm == null || algorithm.length() == 0) {
+            throw new IllegalArgumentException("No algorithm name specified");
+        }
+
+        if (primitives == null || primitives.isEmpty()) {
+            throw new IllegalArgumentException(
+                        "No cryptographic primitive specified");
+        }
+
+        Set<String> elements = null;
+        for (String disabled : disabledAlgorithms) {
+            if (disabled == null || disabled.isEmpty()) {
+                continue;
+            }
+
+            // check the full name
+            if (disabled.equalsIgnoreCase(algorithm)) {
+                return false;
+            }
+
+            // decompose the algorithm into sub-elements
+            if (elements == null) {
+                elements = decomposes(algorithm);
+            }
+
+            // check the items of the algorithm
+            for (String element : elements) {
+                if (disabled.equalsIgnoreCase(element)) {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    final public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
+        return checkConstraints(primitives, "", key, null);
+    }
+
+    @Override
+    final public boolean permits(Set<CryptoPrimitive> primitives,
+            String algorithm, Key key, AlgorithmParameters parameters) {
+
+        if (algorithm == null || algorithm.length() == 0) {
+            throw new IllegalArgumentException("No algorithm name specified");
+        }
+
+        return checkConstraints(primitives, algorithm, key, parameters);
+    }
+
+    /**
+     * Decompose the standard algorithm name into sub-elements.
+     * <p>
+     * For example, we need to decompose "SHA1WithRSA" into "SHA1" and "RSA"
+     * so that we can check the "SHA1" and "RSA" algorithm constraints
+     * separately.
+     * <p>
+     * Please override the method if need to support more name pattern.
+     */
+    protected Set<String> decomposes(String algorithm) {
+        if (algorithm == null || algorithm.length() == 0) {
+            return new HashSet<String>();
+        }
+
+        // algorithm/mode/padding
+        Pattern transPattern = Pattern.compile("/");
+        String[] transTockens = transPattern.split(algorithm);
+
+        Set<String> elements = new HashSet<String>();
+        for (String transTocken : transTockens) {
+            if (transTocken == null || transTocken.length() == 0) {
+                continue;
+            }
+
+            // PBEWith<digest>And<encryption>
+            // PBEWith<prf>And<encryption>
+            // OAEPWith<digest>And<mgf>Padding
+            // <digest>with<encryption>
+            // <digest>with<encryption>and<mgf>
+            Pattern pattern =
+                    Pattern.compile("with|and", Pattern.CASE_INSENSITIVE);
+            String[] tokens = pattern.split(transTocken);
+
+            for (String token : tokens) {
+                if (token == null || token.length() == 0) {
+                    continue;
+                }
+
+                elements.add(token);
+            }
+        }
+
+        // In Java standard algorithm name specification, for different
+        // purpose, the SHA-1 and SHA-2 algorithm names are different. For
+        // example, for MessageDigest, the standard name is "SHA-256", while
+        // for Signature, the digest algorithm component is "SHA256" for
+        // signature algorithm "SHA256withRSA". So we need to check both
+        // "SHA-256" and "SHA256" to make the right constraint checking.
+
+        // handle special name: SHA-1 and SHA1
+        if (elements.contains("SHA1") && !elements.contains("SHA-1")) {
+            elements.add("SHA-1");
+        }
+        if (elements.contains("SHA-1") && !elements.contains("SHA1")) {
+            elements.add("SHA1");
+        }
+
+        // handle special name: SHA-224 and SHA224
+        if (elements.contains("SHA224") && !elements.contains("SHA-224")) {
+            elements.add("SHA-224");
+        }
+        if (elements.contains("SHA-224") && !elements.contains("SHA224")) {
+            elements.add("SHA224");
+        }
+
+        // handle special name: SHA-256 and SHA256
+        if (elements.contains("SHA256") && !elements.contains("SHA-256")) {
+            elements.add("SHA-256");
+        }
+        if (elements.contains("SHA-256") && !elements.contains("SHA256")) {
+            elements.add("SHA256");
+        }
+
+        // handle special name: SHA-384 and SHA384
+        if (elements.contains("SHA384") && !elements.contains("SHA-384")) {
+            elements.add("SHA-384");
+        }
+        if (elements.contains("SHA-384") && !elements.contains("SHA384")) {
+            elements.add("SHA384");
+        }
+
+        // handle special name: SHA-512 and SHA512
+        if (elements.contains("SHA512") && !elements.contains("SHA-512")) {
+            elements.add("SHA-512");
+        }
+        if (elements.contains("SHA-512") && !elements.contains("SHA512")) {
+            elements.add("SHA512");
+        }
+
+        return elements;
+    }
+
+    // Check algorithm constraints
+    private boolean checkConstraints(Set<CryptoPrimitive> primitives,
+            String algorithm, Key key, AlgorithmParameters parameters) {
+
+        // check the key parameter, it cannot be null.
+        if (key == null) {
+            throw new IllegalArgumentException("The key cannot be null");
+        }
+
+        // check the target algorithm
+        if (algorithm != null && algorithm.length() != 0) {
+            if (!permits(primitives, algorithm, parameters)) {
+                return false;
+            }
+        }
+
+        // check the key algorithm
+        if (!permits(primitives, key.getAlgorithm(), null)) {
+            return false;
+        }
+
+        // check the key constraints
+        if (keySizeConstraints.disables(key)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    // Get disabled algorithm constraints from the specified security property.
+    private static void loadDisabledAlgorithmsMap(
+            final String propertyName) {
+
+        String property = AccessController.doPrivileged(
+            new PrivilegedAction<String>() {
+                public String run() {
+                    return Security.getProperty(propertyName);
+                }
+            });
+
+        String[] algorithmsInProperty = null;
+
+        if (property != null && !property.isEmpty()) {
+
+            // remove double quote marks from beginning/end of the property
+            if (property.charAt(0) == '"' &&
+                    property.charAt(property.length() - 1) == '"') {
+                property = property.substring(1, property.length() - 1);
+            }
+
+            algorithmsInProperty = property.split(",");
+            for (int i = 0; i < algorithmsInProperty.length; i++) {
+                algorithmsInProperty[i] = algorithmsInProperty[i].trim();
+            }
+        }
+
+        // map the disabled algorithms
+        if (algorithmsInProperty == null) {
+            algorithmsInProperty = new String[0];
+        }
+        disabledAlgorithmsMap.put(propertyName, algorithmsInProperty);
+
+        // map the key constraints
+        KeySizeConstraints keySizeConstraints =
+            new KeySizeConstraints(algorithmsInProperty);
+        keySizeConstraintsMap.put(propertyName, keySizeConstraints);
+    }
+
+    /**
+     * key constraints
+     */
+    private static class KeySizeConstraints {
+        private static final Pattern pattern = Pattern.compile(
+                "(\\S+)\\s+keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)");
+
+        private Map<String, Set<KeySizeConstraint>> constraintsMap =
+            Collections.synchronizedMap(
+                        new HashMap<String, Set<KeySizeConstraint>>());
+
+        public KeySizeConstraints(String[] restrictions) {
+            for (String restriction : restrictions) {
+                if (restriction == null || restriction.isEmpty()) {
+                    continue;
+                }
+
+                Matcher matcher = pattern.matcher(restriction);
+                if (matcher.matches()) {
+                    String algorithm = matcher.group(1);
+
+                    KeySizeConstraint.Operator operator =
+                             KeySizeConstraint.Operator.of(matcher.group(2));
+                    int length = Integer.parseInt(matcher.group(3));
+
+                    algorithm = algorithm.toLowerCase(Locale.ENGLISH);
+
+                    synchronized (constraintsMap) {
+                        if (!constraintsMap.containsKey(algorithm)) {
+                            constraintsMap.put(algorithm,
+                                new HashSet<KeySizeConstraint>());
+                        }
+
+                        Set<KeySizeConstraint> constraintSet =
+                            constraintsMap.get(algorithm);
+                        KeySizeConstraint constraint =
+                            new KeySizeConstraint(operator, length);
+                        constraintSet.add(constraint);
+                    }
+                }
+            }
+        }
+
+        // Does this KeySizeConstraints disable the specified key?
+        public boolean disables(Key key) {
+            String algorithm = key.getAlgorithm().toLowerCase(Locale.ENGLISH);
+            synchronized (constraintsMap) {
+                if (constraintsMap.containsKey(algorithm)) {
+                    Set<KeySizeConstraint> constraintSet =
+                                        constraintsMap.get(algorithm);
+                    for (KeySizeConstraint constraint : constraintSet) {
+                        if (constraint.disables(key)) {
+                            return true;
+                        }
+                    }
+                }
+            }
+
+            return false;
+        }
+    }
+
+    /**
+     * Key size constraint.
+     *
+     * e.g.  "keysize <= 1024"
+     */
+    private static class KeySizeConstraint {
+        // operator
+        static enum Operator {
+            EQ,         // "=="
+            NE,         // "!="
+            LT,         // "<"
+            LE,         // "<="
+            GT,         // ">"
+            GE;         // ">="
+
+            static Operator of(String s) {
+                switch (s) {
+                    case "==":
+                        return EQ;
+                    case "!=":
+                        return NE;
+                    case "<":
+                        return LT;
+                    case "<=":
+                        return LE;
+                    case ">":
+                        return GT;
+                    case ">=":
+                        return GE;
+                }
+
+                throw new IllegalArgumentException(
+                        s + " is not a legal Operator");
+            }
+        }
+
+        private int minSize;            // the minimal available key size
+        private int maxSize;            // the maximal available key size
+        private int prohibitedSize = -1;    // unavailable key sizes
+
+        public KeySizeConstraint(Operator operator, int length) {
+            switch (operator) {
+                case EQ:      // an unavailable key size
+                    this.minSize = 0;
+                    this.maxSize = Integer.MAX_VALUE;
+                    prohibitedSize = length;
+                    break;
+                case NE:
+                    this.minSize = length;
+                    this.maxSize = length;
+                    break;
+                case LT:
+                    this.minSize = length;
+                    this.maxSize = Integer.MAX_VALUE;
+                    break;
+                case LE:
+                    this.minSize = length + 1;
+                    this.maxSize = Integer.MAX_VALUE;
+                    break;
+                case GT:
+                    this.minSize = 0;
+                    this.maxSize = length;
+                    break;
+                case GE:
+                    this.minSize = 0;
+                    this.maxSize = length > 1 ? (length - 1) : 0;
+                    break;
+                default:
+                    // unlikely to happen
+                    this.minSize = Integer.MAX_VALUE;
+                    this.maxSize = -1;
+            }
+        }
+
+        // Does this key constraint disable the specified key?
+        public boolean disables(Key key) {
+            int size = -1;
+
+            // it is a SecretKey
+            if (key instanceof SecretKey) {
+                SecretKey sk = (SecretKey)key;
+                if (sk.getFormat().equals("RAW") && sk.getEncoded() != null) {
+                    size = sk.getEncoded().length * 8;
+
+                }
+            }
+
+            // it is an asymmetric key
+            if (key instanceof RSAKey) {
+                RSAKey pubk = (RSAKey)key;
+                size = pubk.getModulus().bitLength();
+            } else if (key instanceof ECKey) {
+                ECKey pubk = (ECKey)key;
+                size = pubk.getParams().getOrder().bitLength();
+            } else if (key instanceof DSAKey) {
+                DSAKey pubk = (DSAKey)key;
+                size = pubk.getParams().getP().bitLength();
+            } else if (key instanceof DHKey) {
+                DHKey pubk = (DHKey)key;
+                size = pubk.getParams().getP().bitLength();
+            } // else, it is not a key we know.
+
+            if (size == 0) {
+                return true;    // we don't allow any key of size 0.
+            }
+
+            if (size >= 0) {
+                return ((size < minSize) || (size > maxSize) ||
+                    (prohibitedSize == size));
+            }
+
+            return false;
+        }
+    }
+
+}
+
--- a/jdk/src/share/classes/sun/security/validator/PKIXValidator.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/validator/PKIXValidator.java	Wed Jul 05 17:26:57 2017 +0200
@@ -31,20 +31,35 @@
 import java.security.cert.*;
 
 import javax.security.auth.x500.X500Principal;
+import sun.security.action.GetBooleanAction;
+import sun.security.provider.certpath.AlgorithmChecker;
 
 /**
  * Validator implementation built on the PKIX CertPath API. This
  * implementation will be emphasized going forward.<p>
- *
+ * <p>
  * Note that the validate() implementation tries to use a PKIX validator
  * if that appears possible and a PKIX builder otherwise. This increases
  * performance and currently also leads to better exception messages
  * in case of failures.
+ * <p>
+ * {@code PKIXValidator} objects are immutable once they have been created.
+ * Please DO NOT add methods that can change the state of an instance once
+ * it has been created.
  *
  * @author Andreas Sterbenz
  */
 public final class PKIXValidator extends Validator {
 
+    /**
+     * Flag indicating whether to enable revocation check for the PKIX trust
+     * manager. Typically, this will only work if the PKIX implementation
+     * supports CRL distribution points as we do not manually setup CertStores.
+     */
+    private final static boolean checkTLSRevocation =
+        AccessController.doPrivileged
+            (new GetBooleanAction("com.sun.net.ssl.checkRevocation"));
+
     // enable use of the validator if possible
     private final static boolean TRY_VALIDATOR = true;
 
@@ -53,10 +68,10 @@
     private int certPathLength = -1;
 
     // needed only for the validator
-    private Map<X500Principal, List<PublicKey>> trustedSubjects;
-    private CertificateFactory factory;
+    private final Map<X500Principal, List<PublicKey>> trustedSubjects;
+    private final CertificateFactory factory;
 
-    private boolean plugin = false;
+    private final boolean plugin;
 
     PKIXValidator(String variant, Collection<X509Certificate> trustedCerts) {
         super(TYPE_PKIX, variant);
@@ -75,7 +90,33 @@
             throw new RuntimeException("Unexpected error: " + e.toString(), e);
         }
         setDefaultParameters(variant);
-        initCommon();
+
+        // initCommon();
+        if (TRY_VALIDATOR) {
+            if (TRY_VALIDATOR == false) {
+                return;
+            }
+            trustedSubjects = new HashMap<X500Principal, List<PublicKey>>();
+            for (X509Certificate cert : trustedCerts) {
+                X500Principal dn = cert.getSubjectX500Principal();
+                List<PublicKey> keys;
+                if (trustedSubjects.containsKey(dn)) {
+                    keys = trustedSubjects.get(dn);
+                } else {
+                    keys = new ArrayList<PublicKey>();
+                    trustedSubjects.put(dn, keys);
+                }
+                keys.add(cert.getPublicKey());
+            }
+            try {
+                factory = CertificateFactory.getInstance("X.509");
+            } catch (CertificateException e) {
+                throw new RuntimeException("Internal error", e);
+            }
+            plugin = variant.equals(VAR_PLUGIN_CODE_SIGNING);
+        } else {
+            plugin = false;
+        }
     }
 
     PKIXValidator(String variant, PKIXBuilderParameters params) {
@@ -88,31 +129,33 @@
             }
         }
         parameterTemplate = params;
-        initCommon();
-    }
 
-    private void initCommon() {
-        if (TRY_VALIDATOR == false) {
-            return;
+        // initCommon();
+        if (TRY_VALIDATOR) {
+            if (TRY_VALIDATOR == false) {
+                return;
+            }
+            trustedSubjects = new HashMap<X500Principal, List<PublicKey>>();
+            for (X509Certificate cert : trustedCerts) {
+                X500Principal dn = cert.getSubjectX500Principal();
+                List<PublicKey> keys;
+                if (trustedSubjects.containsKey(dn)) {
+                    keys = trustedSubjects.get(dn);
+                } else {
+                    keys = new ArrayList<PublicKey>();
+                    trustedSubjects.put(dn, keys);
+                }
+                keys.add(cert.getPublicKey());
+            }
+            try {
+                factory = CertificateFactory.getInstance("X.509");
+            } catch (CertificateException e) {
+                throw new RuntimeException("Internal error", e);
+            }
+            plugin = variant.equals(VAR_PLUGIN_CODE_SIGNING);
+        } else {
+            plugin = false;
         }
-        trustedSubjects = new HashMap<X500Principal, List<PublicKey>>();
-        for (X509Certificate cert : trustedCerts) {
-            X500Principal dn = cert.getSubjectX500Principal();
-            List<PublicKey> keys;
-            if (trustedSubjects.containsKey(dn)) {
-                keys = trustedSubjects.get(dn);
-            } else {
-                keys = new ArrayList<PublicKey>();
-                trustedSubjects.put(dn, keys);
-            }
-            keys.add(cert.getPublicKey());
-        }
-        try {
-            factory = CertificateFactory.getInstance("X.509");
-        } catch (CertificateException e) {
-            throw new RuntimeException("Internal error", e);
-        }
-        plugin = variant.equals(VAR_PLUGIN_CODE_SIGNING);
     }
 
     public Collection<X509Certificate> getTrustedCertificates() {
@@ -129,7 +172,7 @@
      * @return the length of the last certification path passed to
      *   CertPathValidator.validate, or -1 if it has not been invoked yet
      */
-    public int getCertPathLength() {
+    public int getCertPathLength() { // mutable, should be private
         return certPathLength;
     }
 
@@ -138,7 +181,12 @@
      * revocation checking. In the future, this should be configurable.
      */
     private void setDefaultParameters(String variant) {
-        parameterTemplate.setRevocationEnabled(false);
+        if ((variant == Validator.VAR_TLS_SERVER) ||
+                (variant == Validator.VAR_TLS_CLIENT)) {
+            parameterTemplate.setRevocationEnabled(checkTLSRevocation);
+        } else {
+            parameterTemplate.setRevocationEnabled(false);
+        }
     }
 
     /**
@@ -146,17 +194,29 @@
      * modify the parameters but must make sure not to perform any concurrent
      * validations.
      */
-    public PKIXBuilderParameters getParameters() {
+    public PKIXBuilderParameters getParameters() { // mutable, should be private
         return parameterTemplate;
     }
 
+    @Override
     X509Certificate[] engineValidate(X509Certificate[] chain,
-            Collection<X509Certificate> otherCerts, Object parameter)
-            throws CertificateException {
+            Collection<X509Certificate> otherCerts,
+            AlgorithmConstraints constraints,
+            Object parameter) throws CertificateException {
         if ((chain == null) || (chain.length == 0)) {
             throw new CertificateException
                 ("null or zero-length certificate chain");
         }
+
+        // add  new algorithm constraints checker
+        PKIXBuilderParameters pkixParameters =
+                    (PKIXBuilderParameters) parameterTemplate.clone();
+        AlgorithmChecker algorithmChecker = null;
+        if (constraints != null) {
+            algorithmChecker = new AlgorithmChecker(constraints);
+            pkixParameters.addCertPathChecker(algorithmChecker);
+        }
+
         if (TRY_VALIDATOR) {
             // check that chain is in correct order and check if chain contains
             // trust anchor
@@ -167,7 +227,7 @@
                 if (i != 0 &&
                     !dn.equals(prevIssuer)) {
                     // chain is not ordered correctly, call builder instead
-                    return doBuild(chain, otherCerts);
+                    return doBuild(chain, otherCerts, pkixParameters);
                 }
 
                 // Check if chain[i] is already trusted. It may be inside
@@ -186,7 +246,7 @@
                     // Remove and call validator on partial chain [0 .. i-1]
                     X509Certificate[] newChain = new X509Certificate[i];
                     System.arraycopy(chain, 0, newChain, 0, i);
-                    return doValidate(newChain);
+                    return doValidate(newChain, pkixParameters);
                 }
                 prevIssuer = cert.getIssuerX500Principal();
             }
@@ -197,7 +257,7 @@
             X500Principal subject = last.getSubjectX500Principal();
             if (trustedSubjects.containsKey(issuer) &&
                     isSignatureValid(trustedSubjects.get(issuer), last)) {
-                return doValidate(chain);
+                return doValidate(chain, pkixParameters);
             }
 
             // don't fallback to builder if called from plugin/webstart
@@ -209,18 +269,17 @@
                     X509Certificate[] newChain =
                         new X509Certificate[chain.length-1];
                     System.arraycopy(chain, 0, newChain, 0, newChain.length);
+
                     // temporarily set last cert as sole trust anchor
-                    PKIXBuilderParameters params =
-                        (PKIXBuilderParameters) parameterTemplate.clone();
                     try {
-                        params.setTrustAnchors
+                        pkixParameters.setTrustAnchors
                             (Collections.singleton(new TrustAnchor
                                 (chain[chain.length-1], null)));
                     } catch (InvalidAlgorithmParameterException iape) {
                         // should never occur, but ...
                         throw new CertificateException(iape);
                     }
-                    doValidate(newChain, params);
+                    doValidate(newChain, pkixParameters);
                 }
                 // if the rest of the chain is valid, throw exception
                 // indicating no trust anchor was found
@@ -230,10 +289,11 @@
             // otherwise, fall back to builder
         }
 
-        return doBuild(chain, otherCerts);
+        return doBuild(chain, otherCerts, pkixParameters);
     }
 
-    private boolean isSignatureValid(List<PublicKey> keys, X509Certificate sub) {
+    private boolean isSignatureValid(List<PublicKey> keys,
+            X509Certificate sub) {
         if (plugin) {
             for (PublicKey key: keys) {
                 try {
@@ -273,13 +333,6 @@
         }
     }
 
-    private X509Certificate[] doValidate(X509Certificate[] chain)
-            throws CertificateException {
-        PKIXBuilderParameters params =
-            (PKIXBuilderParameters)parameterTemplate.clone();
-        return doValidate(chain, params);
-    }
-
     private X509Certificate[] doValidate(X509Certificate[] chain,
             PKIXBuilderParameters params) throws CertificateException {
         try {
@@ -300,11 +353,10 @@
     }
 
     private X509Certificate[] doBuild(X509Certificate[] chain,
-        Collection<X509Certificate> otherCerts) throws CertificateException {
+        Collection<X509Certificate> otherCerts,
+        PKIXBuilderParameters params) throws CertificateException {
 
         try {
-            PKIXBuilderParameters params =
-                (PKIXBuilderParameters)parameterTemplate.clone();
             setDate(params);
 
             // setup target constraints
--- a/jdk/src/share/classes/sun/security/validator/SimpleValidator.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/validator/SimpleValidator.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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
@@ -48,6 +48,10 @@
  * deployed certificates and previous J2SE versions. It will never support
  * more advanced features and will be deemphasized in favor of the PKIX
  * validator going forward.
+ * <p>
+ * {@code SimpleValidator} objects are immutable once they have been created.
+ * Please DO NOT add methods that can change the state of an instance once
+ * it has been created.
  *
  * @author Andreas Sterbenz
  */
@@ -80,13 +84,14 @@
      * The list is used because there may be multiple certificates
      * with an identical subject DN.
      */
-    private Map<X500Principal, List<X509Certificate>> trustedX500Principals;
+    private final Map<X500Principal, List<X509Certificate>>
+                                            trustedX500Principals;
 
     /**
      * Set of the trusted certificates. Present only for
      * getTrustedCertificates().
      */
-    private Collection<X509Certificate> trustedCerts;
+    private final Collection<X509Certificate> trustedCerts;
 
     SimpleValidator(String variant, Collection<X509Certificate> trustedCerts) {
         super(TYPE_SIMPLE, variant);
@@ -114,9 +119,11 @@
      * Perform simple validation of chain. The arguments otherCerts and
      * parameter are ignored.
      */
+    @Override
     X509Certificate[] engineValidate(X509Certificate[] chain,
-            Collection<X509Certificate> otherCerts, Object parameter)
-            throws CertificateException {
+            Collection<X509Certificate> otherCerts,
+            AlgorithmConstraints constraints,
+            Object parameter) throws CertificateException {
         if ((chain == null) || (chain.length == 0)) {
             throw new CertificateException
                 ("null or zero-length certificate chain");
@@ -129,6 +136,17 @@
         if (date == null) {
             date = new Date();
         }
+
+        // create default algorithm constraints checker
+        TrustAnchor anchor = new TrustAnchor(chain[chain.length - 1], null);
+        AlgorithmChecker defaultAlgChecker = new AlgorithmChecker(anchor);
+
+        // create application level algorithm constraints checker
+        AlgorithmChecker appAlgChecker = null;
+        if (constraints != null) {
+            appAlgChecker = new AlgorithmChecker(anchor, constraints);
+        }
+
         // verify top down, starting at the certificate issued by
         // the trust anchor
         int maxPathLength = chain.length - 1;
@@ -138,7 +156,12 @@
 
             // check certificate algorithm
             try {
-                AlgorithmChecker.check(cert);
+                // Algorithm checker don't care about the unresolved critical
+                // extensions.
+                defaultAlgChecker.check(cert, Collections.<String>emptySet());
+                if (appAlgChecker != null) {
+                    appAlgChecker.check(cert, Collections.<String>emptySet());
+                }
             } catch (CertPathValidatorException cpve) {
                 throw new ValidatorException
                         (ValidatorException.T_ALGORITHM_DISABLED, cert, cpve);
--- a/jdk/src/share/classes/sun/security/validator/Validator.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/validator/Validator.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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
@@ -27,6 +27,7 @@
 
 import java.util.*;
 
+import java.security.AlgorithmConstraints;
 import java.security.KeyStore;
 import java.security.cert.*;
 
@@ -232,16 +233,44 @@
     public final X509Certificate[] validate(X509Certificate[] chain,
             Collection<X509Certificate> otherCerts, Object parameter)
             throws CertificateException {
-        chain = engineValidate(chain, otherCerts, parameter);
+        return validate(chain, otherCerts, null, parameter);
+    }
+
+    /**
+     * Validate the given certificate chain.
+     *
+     * @param chain the target certificate chain
+     * @param otherCerts a Collection of additional X509Certificates that
+     *        could be helpful for path building (or null)
+     * @param constraints algorithm constraints for certification path
+     *        processing
+     * @param parameter an additional parameter with variant specific meaning.
+     *        Currently, it is only defined for TLS_SERVER variant validators,
+     *        where it must be non null and the name of the TLS key exchange
+     *        algorithm being used (see JSSE X509TrustManager specification).
+     *        In the future, it could be used to pass in a PKCS#7 object for
+     *        code signing to check time stamps.
+     * @return a non-empty chain that was used to validate the path. The
+     *        end entity cert is at index 0, the trust anchor at index n-1.
+     */
+    public final X509Certificate[] validate(X509Certificate[] chain,
+                Collection<X509Certificate> otherCerts,
+                AlgorithmConstraints constraints,
+                Object parameter) throws CertificateException {
+        chain = engineValidate(chain, otherCerts, constraints, parameter);
+
         // omit EE extension check if EE cert is also trust anchor
         if (chain.length > 1) {
             endEntityChecker.check(chain[0], parameter);
         }
+
         return chain;
     }
 
     abstract X509Certificate[] engineValidate(X509Certificate[] chain,
-        Collection<X509Certificate> otherCerts, Object parameter) throws CertificateException;
+                Collection<X509Certificate> otherCerts,
+                AlgorithmConstraints constraints,
+                Object parameter) throws CertificateException;
 
     /**
      * Returns an immutable Collection of the X509Certificates this instance
--- a/jdk/src/share/classes/sun/security/x509/X509CRLImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/security/x509/X509CRLImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -764,6 +764,15 @@
     }
 
     /**
+     * Gets the signature AlgorithmId from the CRL.
+     *
+     * @return the signature AlgorithmId
+     */
+    public AlgorithmId getSigAlgId() {
+        return sigAlgId;
+    }
+
+    /**
      * return the AuthorityKeyIdentifier, if any.
      *
      * @returns AuthorityKeyIdentifier or null
--- a/jdk/src/share/classes/sun/text/resources/FormatData_fr.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/text/resources/FormatData_fr.java	Wed Jul 05 17:26:57 2017 +0200
@@ -145,7 +145,7 @@
                     "{1} {0}" // date-time pattern
                 }
             },
-            { "DateTimePatternChars", "GaMjkHmsSEDFwWahKzZ" },
+            { "DateTimePatternChars", "GaMjkHmsSEDFwWxhKzZ" },
         };
     }
 }
--- a/jdk/src/share/classes/sun/text/resources/FormatData_fr_BE.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/text/resources/FormatData_fr_BE.java	Wed Jul 05 17:26:57 2017 +0200
@@ -76,7 +76,7 @@
                     "{1} {0}" // date-time pattern
                 }
             },
-            { "DateTimePatternChars", "GaMjkHmsSEDFwWahKzZ" },
+            { "DateTimePatternChars", "GaMjkHmsSEDFwWxhKzZ" },
         };
     }
 }
--- a/jdk/src/share/classes/sun/text/resources/FormatData_fr_CA.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/text/resources/FormatData_fr_CA.java	Wed Jul 05 17:26:57 2017 +0200
@@ -68,7 +68,7 @@
                     "{1} {0}" // date-time pattern
                 }
             },
-            { "DateTimePatternChars", "GaMjkHmsSEDFwWahKzZ" },
+            { "DateTimePatternChars", "GaMjkHmsSEDFwWxhKzZ" },
         };
     }
 }
--- a/jdk/src/share/classes/sun/text/resources/FormatData_fr_CH.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/text/resources/FormatData_fr_CH.java	Wed Jul 05 17:26:57 2017 +0200
@@ -83,7 +83,7 @@
                     "{1} {0}" // date-time pattern
                 }
             },
-            { "DateTimePatternChars", "GaMjkHmsSEDFwWahKzZ" },
+            { "DateTimePatternChars", "GaMjkHmsSEDFwWxhKzZ" },
         };
     }
 }
--- a/jdk/src/share/classes/sun/util/logging/PlatformLogger.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/util/logging/PlatformLogger.java	Wed Jul 05 17:26:57 2017 +0200
@@ -535,10 +535,6 @@
         }
 
         void doLog(int level, String msg, Object... params) {
-            int paramsNumber = (params != null) ? params.length : 0;
-            for (int i = 0; i < paramsNumber; i++) {
-                params[i] = String.valueOf(params[i]);
-            }
             LoggingSupport.log(javaLogger, levelObjects.get(level), msg, params);
         }
 
--- a/jdk/src/share/classes/sun/util/resources/LocaleNames.properties	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/classes/sun/util/resources/LocaleNames.properties	Wed Jul 05 17:26:57 2017 +0200
@@ -1,4 +1,4 @@
-# 
+#
 # Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
@@ -21,7 +21,7 @@
 # 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.
-# 
+#
 
 # (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
 # (C) Copyright IBM Corp. 1996 - 1999 - All Rights Reserved
@@ -228,6 +228,492 @@
 zh=Chinese
 zu=Zulu
 
+# key is ISO 639.2 language code
+aar=Afar
+abk=Abkhazian
+ace=Achinese
+ach=Acoli
+ada=Adangme
+ady=Adyghe
+afa=Afro-Asiatic
+afh=Afrihili
+afr=Afrikaans
+ain=Ainu
+aka=Akan
+akk=Akkadian
+alb=Albanian
+ale=Aleut
+alg=Algonquian
+alt=Southern Altai
+amh=Amharic
+ang=English, Old (ca.450-1100)
+anp=Angika
+apa=Apache
+ara=Arabic
+arc=Official Aramaic (700-300 BCE)
+arg=Aragonese
+arm=Armenian
+arn=Mapudungun
+arp=Arapaho
+art=Artificial
+arw=Arawak
+asm=Assamese
+ast=Asturian
+ath=Athapascan
+aus=Australian
+ava=Avaric
+ave=Avestan
+awa=Awadhi
+aym=Aymara
+aze=Azerbaijani
+bad=Banda
+bai=Bamileke
+bak=Bashkir
+bal=Baluchi
+bam=Bambara
+ban=Balinese
+baq=Basque
+bas=Basa
+bat=Baltic
+bej=Beja
+bel=Belarusian
+bem=Bemba
+ben=Bengali
+ber=Berber
+bho=Bhojpuri
+bih=Bihari
+bik=Bikol
+bin=Bini
+bis=Bislama
+bla=Siksika
+bnt=Bantu
+bos=Bosnian
+bra=Braj
+bre=Breton
+btk=Batak
+bua=Buriat
+bug=Buginese
+bul=Bulgarian
+bur=Burmese
+byn=Blin
+cad=Caddo
+cai=Central American Indian
+car=Galibi Carib
+cat=Catalan
+cau=Caucasian
+ceb=Cebuano
+cel=Celtic
+cha=Chamorro
+chb=Chibcha
+che=Chechen
+chg=Chagatai
+chi=Chinese
+chk=Chuukese
+chm=Mari
+chn=Chinook jargon
+cho=Choctaw
+chp=Chipewyan
+chr=Cherokee
+chu=Church Slavic
+chv=Chuvash
+chy=Cheyenne
+cmc=Chamic
+cop=Coptic
+cor=Cornish
+cos=Corsican
+cpe=Creoles and pidgins, English based
+cpf=Creoles and pidgins, French-based
+cpp=Creoles and pidgins, Portuguese-based
+cre=Cree
+crh=Crimean Tatar
+crp=Creoles and pidgins
+csb=Kashubian
+cus=Cushitic
+cze=Czech
+dak=Dakota
+dan=Danish
+dar=Dargwa
+day=Land Dayak
+del=Delaware
+den=Slave (Athapascan)
+dgr=Dogrib
+din=Dinka
+div=Divehi
+doi=Dogri
+dra=Dravidian
+dsb=Lower Sorbian
+dua=Duala
+dum=Dutch, Middle (ca.1050-1350)
+dut=Dutch
+dyu=Dyula
+dzo=Dzongkha
+efi=Efik
+egy=Egyptian (Ancient)
+eka=Ekajuk
+elx=Elamite
+eng=English
+enm=English, Middle (1100-1500)
+epo=Esperanto
+est=Estonian
+ewe=Ewe
+ewo=Ewondo
+fan=Fang
+fao=Faroese
+fat=Fanti
+fij=Fijian
+fil=Filipino
+fin=Finnish
+fiu=Finno-Ugrian
+fon=Fon
+fre=French
+frm=French, Middle (ca.1400-1600)
+fro=French, Old (842-ca.1400)
+frr=Northern Frisian
+frs=Eastern Frisian
+fry=Western Frisian
+ful=Fulah
+fur=Friulian
+gaa=Ga
+gay=Gayo
+gba=Gbaya
+gem=Germanic
+geo=Georgian
+ger=German
+gez=Geez
+gil=Gilbertese
+gla=Gaelic
+gle=Irish
+glg=Galician
+glv=Manx
+gmh=German, Middle High (ca.1050-1500)
+goh=German, Old High (ca.750-1050)
+gon=Gondi
+gor=Gorontalo
+got=Gothic
+grb=Grebo
+grc=Greek, Ancient (to 1453)
+gre=Greek, Modern (1453-)
+grn=Guarani
+gsw=Swiss German
+guj=Gujarati
+gwi=Gwich'in
+hai=Haida
+hat=Haitian
+hau=Hausa
+haw=Hawaiian
+heb=Hebrew
+her=Herero
+hil=Hiligaynon
+him=Himachali
+hin=Hindi
+hit=Hittite
+hmn=Hmong
+hmo=Hiri Motu
+hrv=Croatian
+hsb=Upper Sorbian
+hun=Hungarian
+hup=Hupa
+iba=Iban
+ibo=Igbo
+ice=Icelandic
+ido=Ido
+iii=Sichuan Yi
+ijo=Ijo
+iku=Inuktitut
+ile=Interlingue
+ilo=Iloko
+ina=Interlingua (International Auxiliary Language Association)
+inc=Indic
+ind=Indonesian
+ine=Indo-European
+inh=Ingush
+ipk=Inupiaq
+ira=Iranian
+iro=Iroquoian
+ita=Italian
+jav=Javanese
+jbo=Lojban
+jpn=Japanese
+jpr=Judeo-Persian
+jrb=Judeo-Arabic
+kaa=Kara-Kalpak
+kab=Kabyle
+kac=Kachin
+kal=Kalaallisut
+kam=Kamba
+kan=Kannada
+kar=Karen
+kas=Kashmiri
+kau=Kanuri
+kaw=Kawi
+kaz=Kazakh
+kbd=Kabardian
+kha=Khasi
+khi=Khoisan
+khm=Central Khmer
+kho=Khotanese
+kik=Kikuyu
+kin=Kinyarwanda
+kir=Kirghiz
+kmb=Kimbundu
+kok=Konkani
+kom=Komi
+kon=Kongo
+kor=Korean
+kos=Kosraean
+kpe=Kpelle
+krc=Karachay-Balkar
+krl=Karelian
+kro=Kru
+kru=Kurukh
+kua=Kuanyama
+kum=Kumyk
+kur=Kurdish
+kut=Kutenai
+lad=Ladino
+lah=Lahnda
+lam=Lamba
+lao=Lao
+lat=Latin
+lav=Latvian
+lez=Lezghian
+lim=Limburgan
+lin=Lingala
+lit=Lithuanian
+lol=Mongo
+loz=Lozi
+ltz=Luxembourgish
+lua=Luba-Lulua
+lub=Luba-Katanga
+lug=Ganda
+lui=Luiseno
+lun=Lunda
+luo=Luo (Kenya and Tanzania)
+lus=Lushai
+mac=Macedonian
+mad=Madurese
+mag=Magahi
+mah=Marshallese
+mai=Maithili
+mak=Makasar
+mal=Malayalam
+man=Mandingo
+mao=Maori
+map=Austronesian
+mar=Marathi
+mas=Masai
+may=Malay
+mdf=Moksha
+mdr=Mandar
+men=Mende
+mga=Irish, Middle (900-1200)
+mic=Mi'kmaq
+min=Minangkabau
+mis=Uncoded
+mkh=Mon-Khmer
+mlg=Malagasy
+mlt=Maltese
+mnc=Manchu
+mni=Manipuri
+mno=Manobo
+moh=Mohawk
+mon=Mongolian
+mos=Mossi
+mul=Multiple
+mun=Munda
+mus=Creek
+mwl=Mirandese
+mwr=Marwari
+myn=Mayan
+myv=Erzya
+nah=Nahuatl
+nai=North American Indian
+nap=Neapolitan
+nau=Nauru
+nav=Navajo
+nbl=Ndebele, South
+nde=Ndebele, North
+ndo=Ndonga
+nds=Low German
+nep=Nepali
+new=Nepal Bhasa
+nia=Nias
+nic=Niger-Kordofanian
+niu=Niuean
+nno=Norwegian Nynorsk
+nob=Bokm\u00e5l, Norwegian
+nog=Nogai
+non=Norse, Old
+nor=Norwegian
+nqo=N'Ko
+nso=Pedi
+nub=Nubian
+nwc=Classical Newari
+nya=Chichewa
+nym=Nyamwezi
+nyn=Nyankole
+nyo=Nyoro
+nzi=Nzima
+oci=Occitan (post 1500)
+oji=Ojibwa
+ori=Oriya
+orm=Oromo
+osa=Osage
+oss=Ossetian
+ota=Turkish, Ottoman (1500-1928)
+oto=Otomian
+paa=Papuan
+pag=Pangasinan
+pal=Pahlavi
+pam=Pampanga
+pan=Panjabi
+pap=Papiamento
+pau=Palauan
+peo=Persian, Old (ca.600-400 B.C.)
+per=Persian
+phi=Philippine
+phn=Phoenician
+pli=Pali
+pol=Polish
+pon=Pohnpeian
+por=Portuguese
+pra=Prakrit
+pro=Proven\u00e7al, Old (to 1500)
+pus=Pushto; Pashto
+que=Quechua
+raj=Rajasthani
+rap=Rapanui
+rar=Rarotongan
+roa=Romance
+roh=Romansh
+rom=Romany
+rum=Romanian
+run=Rundi
+rup=Aromanian
+rus=Russian
+sad=Sandawe
+sag=Sango
+sah=Yakut
+sai=South American Indian
+sal=Salishan
+sam=Samaritan Aramaic
+san=Sanskrit
+sas=Sasak
+sat=Santali
+scn=Sicilian
+sco=Scots
+sel=Selkup
+sem=Semitic
+sga=Irish, Old (to 900)
+sgn=Sign
+shn=Shan
+sid=Sidamo
+sin=Sinhala
+sio=Siouan
+sit=Sino-Tibetan
+sla=Slavic
+slo=Slovak
+slv=Slovenian
+sma=Southern Sami
+sme=Northern Sami
+smi=Sami
+smj=Lule Sami
+smn=Inari Sami
+smo=Samoan
+sms=Skolt Sami
+sna=Shona
+snd=Sindhi
+snk=Soninke
+sog=Sogdian
+som=Somali
+son=Songhai
+sot=Sotho, Southern
+spa=Spanish
+srd=Sardinian
+srn=Sranan Tongo
+srp=Serbian
+srr=Serer
+ssa=Nilo-Saharan
+ssw=Swati
+suk=Sukuma
+sun=Sundanese
+sus=Susu
+sux=Sumerian
+swa=Swahili
+swe=Swedish
+syc=Classical Syriac
+syr=Syriac
+tah=Tahitian
+tai=Tai
+tam=Tamil
+tat=Tatar
+tel=Telugu
+tem=Timne
+ter=Tereno
+tet=Tetum
+tgk=Tajik
+tgl=Tagalog
+tha=Thai
+tib=Tibetan
+tig=Tigre
+tir=Tigrinya
+tiv=Tiv
+tkl=Tokelau
+tlh=Klingon
+tli=Tlingit
+tmh=Tamashek
+tog=Tonga (Nyasa)
+ton=Tonga (Tonga Islands)
+tpi=Tok Pisin
+tsi=Tsimshian
+tsn=Tswana
+tso=Tsonga
+tuk=Turkmen
+tum=Tumbuka
+tup=Tupi
+tur=Turkish
+tut=Altaic
+tvl=Tuvalu
+twi=Twi
+tyv=Tuvinian
+udm=Udmurt
+uga=Ugaritic
+uig=Uighur
+ukr=Ukrainian
+umb=Umbundu
+und=Undetermined
+urd=Urdu
+uzb=Uzbek
+vai=Vai
+ven=Venda
+vie=Vietnamese
+vol=Volap\u00fck
+vot=Votic
+wak=Wakashan
+wal=Wolaitta
+war=Waray
+was=Washo
+wel=Welsh
+wen=Sorbian
+wln=Walloon
+wol=Wolof
+xal=Kalmyk
+xho=Xhosa
+yao=Yao
+yap=Yapese
+yid=Yiddish
+yor=Yoruba
+ypk=Yupik
+zap=Zapotec
+zbl=Blissymbols
+zen=Zenaga
+zha=Zhuang
+znd=Zande
+zul=Zulu
+zun=Zuni
+zxx=No linguistic content
+zza=Zaza
+
 # script names
 # key is ISO 15924 script code
 
--- a/jdk/src/share/lib/security/java.security	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/lib/security/java.security	Wed Jul 05 17:26:57 2017 +0200
@@ -282,3 +282,95 @@
 #   krb5.kdc.bad.policy = tryLess:2,2000
 krb5.kdc.bad.policy = tryLast
 
+# Algorithm restrictions for certification path (CertPath) processing
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for certification path building and validation.  For example, "MD2" is
+# generally no longer considered to be a secure hash algorithm.  This section
+# describes the mechanism for disabling algorithms based on algorithm name
+# and/or key length.  This includes algorithms used in certificates, as well
+# as revocation information such as CRLs and signed OCSP Responses.
+#
+# The syntax of the disabled algorithm string is described as this Java
+# BNF-style:
+#   DisabledAlgorithms:
+#       " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+#   DisabledAlgorithm:
+#       AlgorithmName [Constraint]
+#
+#   AlgorithmName:
+#       (see below)
+#
+#   Constraint:
+#       KeySizeConstraint
+#
+#   KeySizeConstraint:
+#       keySize Operator DecimalInteger
+#
+#   Operator:
+#       <= | < | == | != | >= | >
+#
+#   DecimalInteger:
+#       DecimalDigits
+#
+#   DecimalDigits:
+#       DecimalDigit {DecimalDigit}
+#
+#   DecimalDigit: one of
+#       1 2 3 4 5 6 7 8 9 0
+#
+# The "AlgorithmName" is the standard algorithm name of the disabled
+# algorithm. See "Java Cryptography Architecture Standard Algorithm Name
+# Documentation" for information about Standard Algorithm Names.  Matching
+# is performed using a case-insensitive sub-element matching rule.  (For
+# example, in "SHA1withECDSA" the sub-elements are "SHA1" for hashing and
+# "ECDSA" for signatures.)  If the assertion "AlgorithmName" is a
+# sub-element of the certificate algorithm name, the algorithm will be
+# rejected during certification path building and validation.  For example,
+# the assertion algorithm name "DSA" will disable all certificate algorithms
+# that rely on DSA, such as NONEwithDSA, SHA1withDSA.  However, the assertion
+# will not disable algorithms related to "ECDSA".
+#
+# A "Constraint" provides further guidance for the algorithm being specified.
+# The "KeySizeConstraint" requires a key of a valid size range if the
+# "AlgorithmName" is of a key algorithm.  The "DecimalInteger" indicates the
+# key size specified in number of bits.  For example, "RSA keySize <= 1024"
+# indicates that any RSA key with key size less than or equal to 1024 bits
+# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates
+# that any RSA key with key size less than 1024 or greater than 2048 should
+# be disabled. Note that the "KeySizeConstraint" only makes sense to key
+# algorithms.
+#
+# Note: This property is currently used by Oracle's PKIX implementation. It
+# is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
+#
+#
+jdk.certpath.disabledAlgorithms=MD2
+
+# Algorithm restrictions for Secure Socket Layer/Transport Layer Security
+# (SSL/TLS) processing
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# when using SSL/TLS.  This section describes the mechanism for disabling
+# algorithms during SSL/TLS security parameters negotiation, including cipher
+# suites selection, peer authentication and key exchange mechanisms.
+#
+# For PKI-based peer authentication and key exchange mechanisms, this list
+# of disabled algorithms will also be checked during certification path
+# building and validation, including algorithms used in certificates, as
+# well as revocation information such as CRLs and signed OCSP Responses.
+# This is in addition to the jdk.certpath.disabledAlgorithms property above.
+#
+# See the specification of "jdk.certpath.disabledAlgorithms" for the
+# syntax of the disabled algorithm string.
+#
+# Note: This property is currently used by Oracle's JSSE implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.tls.disabledAlgorithms=MD5, SHA1, DSA, RSA keySize < 2048
+
--- a/jdk/src/share/lib/security/java.security-solaris	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/lib/security/java.security-solaris	Wed Jul 05 17:26:57 2017 +0200
@@ -56,10 +56,10 @@
 
 #
 # Select the source of seed data for SecureRandom. By default an
-# attempt is made to use the entropy gathering device specified by 
+# attempt is made to use the entropy gathering device specified by
 # the securerandom.source property. If an exception occurs when
-# accessing the URL then the traditional system/thread activity 
-# algorithm is used. 
+# accessing the URL then the traditional system/thread activity
+# algorithm is used.
 #
 # On Solaris and Linux systems, if file:/dev/urandom is specified and it
 # exists, a special SecureRandom implementation is activated by default.
@@ -73,7 +73,7 @@
 # The entropy gathering device is described as a URL and can also
 # be specified with the system property "java.security.egd". For example,
 #   -Djava.security.egd=file:/dev/urandom
-# Specifying this system property will override the securerandom.source 
+# Specifying this system property will override the securerandom.source
 # setting.
 
 #
@@ -119,11 +119,6 @@
 keystore.type=jks
 
 #
-# Class to instantiate as the system scope:
-#
-system.scope=sun.security.provider.IdentityDatabase
-
-#
 # List of comma-separated packages that start with or equal this string
 # will cause a security exception to be thrown when
 # passed to checkPackageAccess unless the
@@ -150,7 +145,7 @@
 security.overridePropertiesFile=true
 
 #
-# Determines the default key and trust manager factory algorithms for 
+# Determines the default key and trust manager factory algorithms for
 # the javax.net.ssl package.
 #
 ssl.KeyManagerFactory.algorithm=SunX509
@@ -165,13 +160,14 @@
 #
 # default value is forever (FOREVER). For security reasons, this
 # caching is made forever when a security manager is set. When a security
-# manager is not set, the default behavior is to cache for 30 seconds.
+# manager is not set, the default behavior in this implementation
+# is to cache for 30 seconds.
 #
 # NOTE: setting this to anything other than the default value can have
-#       serious security implications. Do not set it unless 
+#       serious security implications. Do not set it unless
 #       you are sure you are not exposed to DNS spoofing attack.
 #
-#networkaddress.cache.ttl=-1 
+#networkaddress.cache.ttl=-1
 
 # The Java-level namelookup cache policy for failed lookups:
 #
@@ -183,7 +179,7 @@
 # the WINS name service in addition to DNS, name service lookups
 # that fail may take a noticeably long time to return (approx. 5 seconds).
 # For this reason the default caching policy is to maintain these
-# results for 10 seconds. 
+# results for 10 seconds.
 #
 #
 networkaddress.cache.negative.ttl=10
@@ -192,7 +188,7 @@
 # Properties to configure OCSP for certificate revocation checking
 #
 
-# Enable OCSP 
+# Enable OCSP
 #
 # By default, OCSP is not used for certificate revocation checking.
 # This property enables the use of OCSP when set to the value "true".
@@ -201,7 +197,7 @@
 #
 # Example,
 #   ocsp.enable=true
- 
+
 #
 # Location of the OCSP responder
 #
@@ -213,15 +209,15 @@
 #
 # Example,
 #   ocsp.responderURL=http://ocsp.example.net:80
- 
+
 #
 # Subject name of the OCSP responder's certificate
 #
 # By default, the certificate of the OCSP responder is that of the issuer
 # of the certificate being validated. This property identifies the certificate
-# of the OCSP responder when the default does not apply. Its value is a string 
-# distinguished name (defined in RFC 2253) which identifies a certificate in 
-# the set of certificates supplied during cert path validation. In cases where 
+# of the OCSP responder when the default does not apply. Its value is a string
+# distinguished name (defined in RFC 2253) which identifies a certificate in
+# the set of certificates supplied during cert path validation. In cases where
 # the subject name alone is not sufficient to uniquely identify the certificate
 # then both the "ocsp.responderCertIssuerName" and
 # "ocsp.responderCertSerialNumber" properties must be used instead. When this
@@ -237,14 +233,14 @@
 # of the certificate being validated. This property identifies the certificate
 # of the OCSP responder when the default does not apply. Its value is a string
 # distinguished name (defined in RFC 2253) which identifies a certificate in
-# the set of certificates supplied during cert path validation. When this 
-# property is set then the "ocsp.responderCertSerialNumber" property must also 
-# be set. When the "ocsp.responderCertSubjectName" property is set then this 
+# the set of certificates supplied during cert path validation. When this
+# property is set then the "ocsp.responderCertSerialNumber" property must also
+# be set. When the "ocsp.responderCertSubjectName" property is set then this
 # property is ignored.
 #
 # Example,
 #   ocsp.responderCertIssuerName="CN=Enterprise CA, O=XYZ Corp"
- 
+
 #
 # Serial number of the OCSP responder's certificate
 #
@@ -259,7 +255,7 @@
 #
 # Example,
 #   ocsp.responderCertSerialNumber=2A:FF:00
- 
+
 #
 # Policy for failed Kerberos KDC lookups:
 #
@@ -287,3 +283,95 @@
 #   krb5.kdc.bad.policy = tryLess:2,2000
 krb5.kdc.bad.policy = tryLast
 
+# Algorithm restrictions for certification path (CertPath) processing
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for certification path building and validation.  For example, "MD2" is
+# generally no longer considered to be a secure hash algorithm.  This section
+# describes the mechanism for disabling algorithms based on algorithm name
+# and/or key length.  This includes algorithms used in certificates, as well
+# as revocation information such as CRLs and signed OCSP Responses.
+#
+# The syntax of the disabled algorithm string is described as this Java
+# BNF-style:
+#   DisabledAlgorithms:
+#       " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+#   DisabledAlgorithm:
+#       AlgorithmName [Constraint]
+#
+#   AlgorithmName:
+#       (see below)
+#
+#   Constraint:
+#       KeySizeConstraint
+#
+#   KeySizeConstraint:
+#       keySize Operator DecimalInteger
+#
+#   Operator:
+#       <= | < | == | != | >= | >
+#
+#   DecimalInteger:
+#       DecimalDigits
+#
+#   DecimalDigits:
+#       DecimalDigit {DecimalDigit}
+#
+#   DecimalDigit: one of
+#       1 2 3 4 5 6 7 8 9 0
+#
+# The "AlgorithmName" is the standard algorithm name of the disabled
+# algorithm. See "Java Cryptography Architecture Standard Algorithm Name
+# Documentation" for information about Standard Algorithm Names.  Matching
+# is performed using a case-insensitive sub-element matching rule.  (For
+# example, in "SHA1withECDSA" the sub-elements are "SHA1" for hashing and
+# "ECDSA" for signatures.)  If the assertion "AlgorithmName" is a
+# sub-element of the certificate algorithm name, the algorithm will be
+# rejected during certification path building and validation.  For example,
+# the assertion algorithm name "DSA" will disable all certificate algorithms
+# that rely on DSA, such as NONEwithDSA, SHA1withDSA.  However, the assertion
+# will not disable algorithms related to "ECDSA".
+#
+# A "Constraint" provides further guidance for the algorithm being specified.
+# The "KeySizeConstraint" requires a key of a valid size range if the
+# "AlgorithmName" is of a key algorithm.  The "DecimalInteger" indicates the
+# key size specified in number of bits.  For example, "RSA keySize <= 1024"
+# indicates that any RSA key with key size less than or equal to 1024 bits
+# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates
+# that any RSA key with key size less than 1024 or greater than 2048 should
+# be disabled. Note that the "KeySizeConstraint" only makes sense to key
+# algorithms.
+#
+# Note: This property is currently used by Oracle's PKIX implementation. It
+# is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
+#
+#
+jdk.certpath.disabledAlgorithms=MD2
+
+# Algorithm restrictions for Secure Socket Layer/Transport Layer Security
+# (SSL/TLS) processing
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# when using SSL/TLS.  This section describes the mechanism for disabling
+# algorithms during SSL/TLS security parameters negotiation, including cipher
+# suites selection, peer authentication and key exchange mechanisms.
+#
+# For PKI-based peer authentication and key exchange mechanisms, this list
+# of disabled algorithms will also be checked during certification path
+# building and validation, including algorithms used in certificates, as
+# well as revocation information such as CRLs and signed OCSP Responses.
+# This is in addition to the jdk.certpath.disabledAlgorithms property above.
+#
+# See the specification of "jdk.certpath.disabledAlgorithms" for the
+# syntax of the disabled algorithm string.
+#
+# Note: This property is currently used by Oracle's JSSE implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.tls.disabledAlgorithms=MD5, SHA1, DSA, RSA keySize < 2048
+i
--- a/jdk/src/share/lib/security/java.security-windows	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/lib/security/java.security-windows	Wed Jul 05 17:26:57 2017 +0200
@@ -56,10 +56,10 @@
 
 #
 # Select the source of seed data for SecureRandom. By default an
-# attempt is made to use the entropy gathering device specified by 
+# attempt is made to use the entropy gathering device specified by
 # the securerandom.source property. If an exception occurs when
-# accessing the URL then the traditional system/thread activity 
-# algorithm is used. 
+# accessing the URL then the traditional system/thread activity
+# algorithm is used.
 #
 # On Solaris and Linux systems, if file:/dev/urandom is specified and it
 # exists, a special SecureRandom implementation is activated by default.
@@ -73,7 +73,7 @@
 # The entropy gathering device is described as a URL and can also
 # be specified with the system property "java.security.egd". For example,
 #   -Djava.security.egd=file:/dev/urandom
-# Specifying this system property will override the securerandom.source 
+# Specifying this system property will override the securerandom.source
 # setting.
 
 #
@@ -119,11 +119,6 @@
 keystore.type=jks
 
 #
-# Class to instantiate as the system scope:
-#
-system.scope=sun.security.provider.IdentityDatabase
-
-#
 # List of comma-separated packages that start with or equal this string
 # will cause a security exception to be thrown when
 # passed to checkPackageAccess unless the
@@ -150,7 +145,7 @@
 security.overridePropertiesFile=true
 
 #
-# Determines the default key and trust manager factory algorithms for 
+# Determines the default key and trust manager factory algorithms for
 # the javax.net.ssl package.
 #
 ssl.KeyManagerFactory.algorithm=SunX509
@@ -165,13 +160,14 @@
 #
 # default value is forever (FOREVER). For security reasons, this
 # caching is made forever when a security manager is set. When a security
-# manager is not set, the default behavior is to cache for 30 seconds.
+# manager is not set, the default behavior in this implementation
+# is to cache for 30 seconds.
 #
 # NOTE: setting this to anything other than the default value can have
-#       serious security implications. Do not set it unless 
+#       serious security implications. Do not set it unless
 #       you are sure you are not exposed to DNS spoofing attack.
 #
-#networkaddress.cache.ttl=-1 
+#networkaddress.cache.ttl=-1
 
 # The Java-level namelookup cache policy for failed lookups:
 #
@@ -183,7 +179,7 @@
 # the WINS name service in addition to DNS, name service lookups
 # that fail may take a noticeably long time to return (approx. 5 seconds).
 # For this reason the default caching policy is to maintain these
-# results for 10 seconds. 
+# results for 10 seconds.
 #
 #
 networkaddress.cache.negative.ttl=10
@@ -192,7 +188,7 @@
 # Properties to configure OCSP for certificate revocation checking
 #
 
-# Enable OCSP 
+# Enable OCSP
 #
 # By default, OCSP is not used for certificate revocation checking.
 # This property enables the use of OCSP when set to the value "true".
@@ -201,7 +197,7 @@
 #
 # Example,
 #   ocsp.enable=true
- 
+
 #
 # Location of the OCSP responder
 #
@@ -213,15 +209,15 @@
 #
 # Example,
 #   ocsp.responderURL=http://ocsp.example.net:80
- 
+
 #
 # Subject name of the OCSP responder's certificate
 #
 # By default, the certificate of the OCSP responder is that of the issuer
 # of the certificate being validated. This property identifies the certificate
-# of the OCSP responder when the default does not apply. Its value is a string 
-# distinguished name (defined in RFC 2253) which identifies a certificate in 
-# the set of certificates supplied during cert path validation. In cases where 
+# of the OCSP responder when the default does not apply. Its value is a string
+# distinguished name (defined in RFC 2253) which identifies a certificate in
+# the set of certificates supplied during cert path validation. In cases where
 # the subject name alone is not sufficient to uniquely identify the certificate
 # then both the "ocsp.responderCertIssuerName" and
 # "ocsp.responderCertSerialNumber" properties must be used instead. When this
@@ -237,14 +233,14 @@
 # of the certificate being validated. This property identifies the certificate
 # of the OCSP responder when the default does not apply. Its value is a string
 # distinguished name (defined in RFC 2253) which identifies a certificate in
-# the set of certificates supplied during cert path validation. When this 
-# property is set then the "ocsp.responderCertSerialNumber" property must also 
-# be set. When the "ocsp.responderCertSubjectName" property is set then this 
+# the set of certificates supplied during cert path validation. When this
+# property is set then the "ocsp.responderCertSerialNumber" property must also
+# be set. When the "ocsp.responderCertSubjectName" property is set then this
 # property is ignored.
 #
 # Example,
 #   ocsp.responderCertIssuerName="CN=Enterprise CA, O=XYZ Corp"
- 
+
 #
 # Serial number of the OCSP responder's certificate
 #
@@ -259,7 +255,7 @@
 #
 # Example,
 #   ocsp.responderCertSerialNumber=2A:FF:00
- 
+
 #
 # Policy for failed Kerberos KDC lookups:
 #
@@ -287,3 +283,95 @@
 #   krb5.kdc.bad.policy = tryLess:2,2000
 krb5.kdc.bad.policy = tryLast
 
+# Algorithm restrictions for certification path (CertPath) processing
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for certification path building and validation.  For example, "MD2" is
+# generally no longer considered to be a secure hash algorithm.  This section
+# describes the mechanism for disabling algorithms based on algorithm name
+# and/or key length.  This includes algorithms used in certificates, as well
+# as revocation information such as CRLs and signed OCSP Responses.
+#
+# The syntax of the disabled algorithm string is described as this Java
+# BNF-style:
+#   DisabledAlgorithms:
+#       " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+#   DisabledAlgorithm:
+#       AlgorithmName [Constraint]
+#
+#   AlgorithmName:
+#       (see below)
+#
+#   Constraint:
+#       KeySizeConstraint
+#
+#   KeySizeConstraint:
+#       keySize Operator DecimalInteger
+#
+#   Operator:
+#       <= | < | == | != | >= | >
+#
+#   DecimalInteger:
+#       DecimalDigits
+#
+#   DecimalDigits:
+#       DecimalDigit {DecimalDigit}
+#
+#   DecimalDigit: one of
+#       1 2 3 4 5 6 7 8 9 0
+#
+# The "AlgorithmName" is the standard algorithm name of the disabled
+# algorithm. See "Java Cryptography Architecture Standard Algorithm Name
+# Documentation" for information about Standard Algorithm Names.  Matching
+# is performed using a case-insensitive sub-element matching rule.  (For
+# example, in "SHA1withECDSA" the sub-elements are "SHA1" for hashing and
+# "ECDSA" for signatures.)  If the assertion "AlgorithmName" is a
+# sub-element of the certificate algorithm name, the algorithm will be
+# rejected during certification path building and validation.  For example,
+# the assertion algorithm name "DSA" will disable all certificate algorithms
+# that rely on DSA, such as NONEwithDSA, SHA1withDSA.  However, the assertion
+# will not disable algorithms related to "ECDSA".
+#
+# A "Constraint" provides further guidance for the algorithm being specified.
+# The "KeySizeConstraint" requires a key of a valid size range if the
+# "AlgorithmName" is of a key algorithm.  The "DecimalInteger" indicates the
+# key size specified in number of bits.  For example, "RSA keySize <= 1024"
+# indicates that any RSA key with key size less than or equal to 1024 bits
+# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates
+# that any RSA key with key size less than 1024 or greater than 2048 should
+# be disabled. Note that the "KeySizeConstraint" only makes sense to key
+# algorithms.
+#
+# Note: This property is currently used by Oracle's PKIX implementation. It
+# is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
+#
+#
+jdk.certpath.disabledAlgorithms=MD2
+
+# Algorithm restrictions for Secure Socket Layer/Transport Layer Security
+# (SSL/TLS) processing
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# when using SSL/TLS.  This section describes the mechanism for disabling
+# algorithms during SSL/TLS security parameters negotiation, including cipher
+# suites selection, peer authentication and key exchange mechanisms.
+#
+# For PKI-based peer authentication and key exchange mechanisms, this list
+# of disabled algorithms will also be checked during certification path
+# building and validation, including algorithms used in certificates, as
+# well as revocation information such as CRLs and signed OCSP Responses.
+# This is in addition to the jdk.certpath.disabledAlgorithms property above.
+#
+# See the specification of "jdk.certpath.disabledAlgorithms" for the
+# syntax of the disabled algorithm string.
+#
+# Note: This property is currently used by Oracle's JSSE implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.tls.disabledAlgorithms=MD5, SHA1, DSA, RSA keySize < 2048
+
--- a/jdk/src/share/native/common/jdk_util.c	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/native/common/jdk_util.c	Wed Jul 05 17:26:57 2017 +0200
@@ -25,6 +25,8 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
+#include <assert.h>
 
 #include "jvm.h"
 #include "jdk_util.h"
@@ -45,6 +47,7 @@
         (unsigned int) atoi(JDK_MICRO_VERSION);
 
     const char* jdk_build_string = JDK_BUILD_NUMBER;
+    char build_number[4];
     unsigned int jdk_build_number = 0;
 
     const char* jdk_update_string = JDK_UPDATE_VERSION;
@@ -55,16 +58,28 @@
     /* If the JDK_BUILD_NUMBER is of format bXX and XX is an integer
      * XX is the jdk_build_number.
      */
-    if (strlen(jdk_build_string) == 3) {
-        if (jdk_build_string[0] == 'b' &&
-            jdk_build_string[1] >= '0' && jdk_build_string[1] <= '9' &&
-            jdk_build_string[2] >= '0' && jdk_build_string[2] <= '9') {
-            jdk_build_number = (unsigned int) atoi(&jdk_build_string[1]);
+    int len = strlen(jdk_build_string);
+    if (jdk_build_string[0] == 'b' && len >= 2) {
+        int i = 0;
+        for (i = 1; i < len; i++) {
+            if (isdigit(jdk_build_string[i])) {
+                build_number[i-1] = jdk_build_string[i];
+            } else {
+                // invalid build number
+                i = -1;
+                break;
+            }
+        }
+        if (i == len) {
+            build_number[len-1] = '\0';
+            jdk_build_number = (unsigned int) atoi(build_number) ;
         }
     }
+
+    assert(jdk_build_number >= 0 && jdk_build_number <= 255);
+
     if (strlen(jdk_update_string) == 2 || strlen(jdk_update_string) == 3) {
-        if (jdk_update_string[0] >= '0' && jdk_update_string[0] <= '9' &&
-            jdk_update_string[1] >= '0' && jdk_update_string[1] <= '9') {
+        if (isdigit(jdk_update_string[0]) && isdigit(jdk_update_string[1])) {
             update_ver[0] = jdk_update_string[0];
             update_ver[1] = jdk_update_string[1];
             update_ver[2] = '\0';
@@ -75,7 +90,6 @@
         }
     }
 
-
     memset(info, 0, info_size);
     info->jdk_version = ((jdk_major_version & 0xFF) << 24) |
                         ((jdk_minor_version & 0xFF) << 16) |
--- a/jdk/src/share/native/java/lang/System.c	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/native/java/lang/System.c	Wed Jul 05 17:26:57 2017 +0200
@@ -219,11 +219,14 @@
 
     /*
      *  user.language
-     *  user.country, user.variant (if user's environment specifies them)
+     *  user.script, user.country, user.variant (if user's environment specifies them)
      *  file.encoding
      *  file.encoding.pkg
      */
     PUTPROP(props, "user.language", sprops->language);
+    if (sprops->script) {
+        PUTPROP(props, "user.script", sprops->script);
+    }
     if (sprops->country) {
         PUTPROP(props, "user.country", sprops->country);
     }
@@ -305,11 +308,12 @@
     }
 
     /*
-     * unset "user.language", "user.country", and "user.variant"
+     * unset "user.language", "user.script", "user.country", and "user.variant"
      * in order to tell whether the command line option "-DXXXX=YYYY" is
      * specified or not.  They will be reset in fillI18nProps() below.
      */
     REMOVEPROP(props, "user.language");
+    REMOVEPROP(props, "user.script");
     REMOVEPROP(props, "user.country");
     REMOVEPROP(props, "user.variant");
     REMOVEPROP(props, "file.encoding");
@@ -328,6 +332,8 @@
     /* reconstruct i18n related properties */
     fillI18nProps(env, props, "user.language", sprops->display_language,
         sprops->format_language, putID, getPropID);
+    fillI18nProps(env, props, "user.script",
+        sprops->display_script, sprops->format_script, putID, getPropID);
     fillI18nProps(env, props, "user.country",
         sprops->display_country, sprops->format_country, putID, getPropID);
     fillI18nProps(env, props, "user.variant",
--- a/jdk/src/share/native/java/lang/java_props.h	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/native/java/lang/java_props.h	Wed Jul 05 17:26:57 2017 +0200
@@ -55,6 +55,9 @@
     char *language;
     char *format_language;
     char *display_language;
+    char *script;
+    char *format_script;
+    char *display_script;
     char *country;
     char *format_country;
     char *display_country;
--- a/jdk/src/share/native/java/util/zip/zlib-1.2.3/zcrc32.c	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/native/java/util/zip/zlib-1.2.3/zcrc32.c	Wed Jul 05 17:26:57 2017 +0200
@@ -406,7 +406,7 @@
         return crc1;
 
     /* put operator for one zero bit in odd */
-    odd[0] = 0xedb88320L;           /* CRC-32 polynomial */
+    odd[0] = 0xedb88320UL;           /* CRC-32 polynomial */
     row = 1;
     for (n = 1; n < GF2_DIM; n++) {
         odd[n] = row;
--- a/jdk/src/share/native/sun/java2d/loops/ProcessPath.c	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/share/native/sun/java2d/loops/ProcessPath.c	Wed Jul 05 17:26:57 2017 +0200
@@ -116,14 +116,26 @@
         jint Y0 = (fY0) >> MDP_PREC;                                        \
         jint X1 = (fX1) >> MDP_PREC;                                        \
         jint Y1 = (fY1) >> MDP_PREC;                                        \
-        /* Handling lines having just one pixel                           */\
+        jint res;                                                           \
+                                                                            \
+        /* Checking bounds and clipping if necessary */                     \
+        if (checkBounds) {                                                  \
+            TESTANDCLIP(hnd->dhnd->yMin, hnd->dhnd->yMax, Y0, X0, Y1, X1,   \
+                        jint, res);                                         \
+            if (res == CRES_INVISIBLE) break;                               \
+            TESTANDCLIP(hnd->dhnd->yMin, hnd->dhnd->yMax, Y1, X1, Y0, X0,   \
+                        jint, res);                                         \
+            if (res == CRES_INVISIBLE) break;                               \
+            TESTANDCLIP(hnd->dhnd->xMin, hnd->dhnd->xMax, X0, Y0, X1, Y1,   \
+                        jint, res);                                         \
+            if (res == CRES_INVISIBLE) break;                               \
+            TESTANDCLIP(hnd->dhnd->xMin, hnd->dhnd->xMax, X1, Y1, X0, Y0,   \
+                        jint, res);                                         \
+            if (res == CRES_INVISIBLE) break;                               \
+        }                                                                   \
+                                                                            \
+        /* Handling lines having just one pixel      */                     \
         if (((X0^X1) | (Y0^Y1)) == 0) {                                     \
-            if (checkBounds &&                                              \
-                (hnd->dhnd->yMin > Y0  ||                                   \
-                 hnd->dhnd->yMax <= Y0 ||                                   \
-                 hnd->dhnd->xMin > X0  ||                                   \
-                 hnd->dhnd->xMax <= X0)) break;                             \
-                                                                            \
             if (pixelInfo[0] == 0) {                                        \
                 pixelInfo[0] = 1;                                           \
                 pixelInfo[1] = X0;                                          \
@@ -140,18 +152,11 @@
             break;                                                          \
         }                                                                   \
                                                                             \
-        if (!checkBounds ||                                                 \
-            (hnd->dhnd->yMin <= Y0  &&                                      \
-             hnd->dhnd->yMax > Y0 &&                                        \
-             hnd->dhnd->xMin <= X0  &&                                      \
-             hnd->dhnd->xMax > X0))                                         \
+        if (pixelInfo[0] &&                                                 \
+            ((pixelInfo[1] == X0 && pixelInfo[2] == Y0) ||                  \
+            (pixelInfo[3] == X0 && pixelInfo[4] == Y0)))                    \
         {                                                                   \
-                if (pixelInfo[0] &&                                         \
-                    ((pixelInfo[1] == X0 && pixelInfo[2] == Y0) ||          \
-                     (pixelInfo[3] == X0 && pixelInfo[4] == Y0)))           \
-                {                                                           \
-                    hnd->dhnd->pDrawPixel(hnd->dhnd, X0, Y0);               \
-                }                                                           \
+            hnd->dhnd->pDrawPixel(hnd->dhnd, X0, Y0);                       \
         }                                                                   \
                                                                             \
         hnd->dhnd->pDrawLine(hnd->dhnd, X0, Y0, X1, Y1);                    \
@@ -170,14 +175,6 @@
         if ((pixelInfo[1] == X1 && pixelInfo[2] == Y1) ||                   \
             (pixelInfo[3] == X1 && pixelInfo[4] == Y1))                     \
         {                                                                   \
-            if (checkBounds &&                                              \
-                (hnd->dhnd->yMin > Y1  ||                                   \
-                 hnd->dhnd->yMax <= Y1 ||                                   \
-                 hnd->dhnd->xMin > X1  ||                                   \
-                 hnd->dhnd->xMax <= X1)) {                                  \
-                break;                                                      \
-            }                                                               \
-                                                                            \
             hnd->dhnd->pDrawPixel(hnd->dhnd, X1, Y1);                       \
         }                                                                   \
         pixelInfo[3] = X1;                                                  \
--- a/jdk/src/solaris/bin/java_md.c	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/solaris/bin/java_md.c	Wed Jul 05 17:26:57 2017 +0200
@@ -868,7 +868,7 @@
     while (dp != NULL) {
         cp = JLI_StrChr(dp, (int)':');
         if (cp != NULL)
-            *cp = (char)NULL;
+            *cp = '\0';
         if ((target = ProcessDir(info, dp)) != NULL)
             break;
         dp = cp;
--- a/jdk/src/solaris/bin/jexec.c	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/solaris/bin/jexec.c	Wed Jul 05 17:26:57 2017 +0200
@@ -221,6 +221,7 @@
      * implies an error in the exec. */
     free(nargv);
     errorExit(errno, BAD_EXEC_MSG);
+    return 0; // keep the compiler happy
 }
 
 
--- a/jdk/src/solaris/classes/sun/nio/ch/FileDispatcherImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/solaris/classes/sun/nio/ch/FileDispatcherImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -94,6 +94,12 @@
         preClose0(fd);
     }
 
+    FileDescriptor duplicateForMapping(FileDescriptor fd) {
+        // file descriptor not required for mapping operations; okay
+        // to return invalid file descriptor.
+        return new FileDescriptor();
+    }
+
     // -- Native methods --
 
     static native int read0(FileDescriptor fd, long address, int len)
--- a/jdk/src/solaris/classes/sun/nio/ch/LinuxAsynchronousChannelProvider.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/solaris/classes/sun/nio/ch/LinuxAsynchronousChannelProvider.java	Wed Jul 05 17:26:57 2017 +0200
@@ -29,7 +29,6 @@
 import java.nio.channels.spi.AsynchronousChannelProvider;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ThreadFactory;
-import java.net.ProtocolFamily;
 import java.io.IOException;
 
 public class LinuxAsynchronousChannelProvider
@@ -88,12 +87,4 @@
     {
         return new UnixAsynchronousSocketChannelImpl(toPort(group));
     }
-
-    @Override
-    public AsynchronousDatagramChannel openAsynchronousDatagramChannel(ProtocolFamily family,
-                                                                       AsynchronousChannelGroup group)
-        throws IOException
-    {
-        return new SimpleAsynchronousDatagramChannelImpl(family, toPort(group));
-    }
 }
--- a/jdk/src/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java	Wed Jul 05 17:26:57 2017 +0200
@@ -29,7 +29,6 @@
 import java.nio.channels.spi.AsynchronousChannelProvider;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ThreadFactory;
-import java.net.ProtocolFamily;
 import java.io.IOException;
 
 public class SolarisAsynchronousChannelProvider
@@ -91,12 +90,4 @@
     {
         return new UnixAsynchronousSocketChannelImpl(toEventPort(group));
     }
-
-    @Override
-    public AsynchronousDatagramChannel openAsynchronousDatagramChannel(ProtocolFamily family,
-                                                                       AsynchronousChannelGroup group)
-        throws IOException
-    {
-        return new SimpleAsynchronousDatagramChannelImpl(family, toEventPort(group));
-    }
 }
--- a/jdk/src/solaris/native/java/lang/java_props_md.c	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/solaris/native/java/lang/java_props_md.c	Wed Jul 05 17:26:57 2017 +0200
@@ -117,7 +117,8 @@
 #define P_tmpdir "/var/tmp"
 #endif
 
-static int ParseLocale(int cat, char ** std_language, char ** std_country, char ** std_variant, char ** std_encoding) {
+static int ParseLocale(int cat, char ** std_language, char ** std_script,
+                       char ** std_country, char ** std_variant, char ** std_encoding) {
     char temp[64];
     char *language = NULL, *country = NULL, *variant = NULL,
          *encoding = NULL;
@@ -181,14 +182,22 @@
         strcpy(encoding_variant, p); /* Copy the leading '.' */
         *p = '\0';
     } else if ((p = strchr(temp, '@')) != NULL) {
-         strcpy(encoding_variant, p); /* Copy the leading '@' */
-         *p = '\0';
+        strcpy(encoding_variant, p); /* Copy the leading '@' */
+        *p = '\0';
     } else {
         *encoding_variant = '\0';
     }
 
     if (mapLookup(locale_aliases, temp, &p)) {
         strcpy(temp, p);
+        // check the "encoding_variant" again, if any.
+        if ((p = strchr(temp, '.')) != NULL) {
+            strcpy(encoding_variant, p); /* Copy the leading '.' */
+            *p = '\0';
+        } else if ((p = strchr(temp, '@')) != NULL) {
+            strcpy(encoding_variant, p); /* Copy the leading '@' */
+            *p = '\0';
+        }
     }
 
     language = temp;
@@ -219,10 +228,17 @@
         mapLookup(country_names, country, std_country);
     }
 
-    /* Normalize the variant name.  Note that we only use
-     * variants listed in the mapping array; others are ignored. */
-    if (std_variant != NULL && variant != NULL) {
-        mapLookup(variant_names, variant, std_variant);
+    /* Normalize the script and variant name.  Note that we only use
+     * variants listed in the mapping array; others are ignored.
+     */
+    if (variant != NULL) {
+        if (std_script != NULL) {
+            mapLookup(script_names, variant, std_script);
+        }
+
+        if (std_variant != NULL) {
+            mapLookup(variant_names, variant, std_variant);
+        }
     }
 
     /* Normalize the encoding name.  Note that we IGNORE the string
@@ -358,11 +374,13 @@
     setlocale(LC_ALL, "");
     if (ParseLocale(LC_CTYPE,
                     &(sprops.format_language),
+                    &(sprops.format_script),
                     &(sprops.format_country),
                     &(sprops.format_variant),
                     &(sprops.encoding))) {
         ParseLocale(LC_MESSAGES,
                     &(sprops.language),
+                    &(sprops.script),
                     &(sprops.country),
                     &(sprops.variant),
                     NULL);
@@ -371,6 +389,7 @@
         sprops.encoding = "ISO8859-1";
     }
     sprops.display_language = sprops.language;
+    sprops.display_script = sprops.script;
     sprops.display_country = sprops.country;
     sprops.display_variant = sprops.variant;
     sprops.sun_jnu_encoding = sprops.encoding;
--- a/jdk/src/solaris/native/java/lang/locale_str.h	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/solaris/native/java/lang/locale_str.h	Wed Jul 05 17:26:57 2017 +0200
@@ -86,6 +86,8 @@
     "wa", "wa_BE",
     "zh", "zh_CN",
 #ifdef __linux__
+    "bokmal", "nb_NO",
+    "bokm\u00e5l", "nb_NO",
     "catalan", "ca_ES",
     "croatian", "hr_HR",
     "czech", "cs_CZ",
@@ -93,9 +95,13 @@
     "dansk", "da_DK",
     "deutsch", "de_DE",
     "dutch", "nl_NL",
+    "eesti", "et_EE",
+    "estonian", "et_EE",
     "finnish", "fi_FI",
     "fran\xE7\x61is", "fr_FR",
     "french", "fr_FR",
+    "galego", "gl_ES",
+    "galician", "gl_ES",
     "german", "de_DE",
     "greek", "el_GR",
     "hebrew", "iw_IL",
@@ -104,7 +110,10 @@
     "icelandic", "is_IS",
     "italian", "it_IT",
     "japanese", "ja_JP",
+    "korean", "ko_KR",
+    "lithuanian", "lt_LT",
     "norwegian", "no_NO",
+    "nynorsk", "nn_NO",
     "polish", "pl_PL",
     "portuguese", "pt_PT",
     "romanian", "ro_RO",
@@ -114,11 +123,16 @@
     "slovenian", "sl_SI",
     "spanish", "es_ES",
     "swedish", "sv_SE",
+    "thai", "th_TH",
     "turkish", "tr_TR",
 #else
     "big5", "zh_TW.Big5",
     "chinese", "zh_CN",
+    "iso_8859_1", "en_US.ISO8859-1",
+    "iso_8859_15", "en_US.ISO8859-15",
     "japanese", "ja_JP",
+    "no_NY", "no_NO@nynorsk",
+    "sr_SP", "sr_YU",
     "tchinese", "zh_TW",
 #endif
     ""
@@ -361,6 +375,506 @@
     "japanese", "ja",
     "korean", "ko",
 #endif
+
+    /* ISO 639.2 codes */
+    "aar", "aar",
+    "abk", "abk",
+    "ace", "ace",
+    "ach", "ach",
+    "ada", "ada",
+    "ady", "ady",
+    "afa", "afa",
+    "afh", "afh",
+    "afr", "afr",
+    "ain", "ain",
+    "aka", "aka",
+    "akk", "akk",
+    "alb", "alb",
+    "ale", "ale",
+    "alg", "alg",
+    "alt", "alt",
+    "amh", "amh",
+    "ang", "ang",
+    "anp", "anp",
+    "apa", "apa",
+    "ara", "ara",
+    "arc", "arc",
+    "arg", "arg",
+    "arm", "arm",
+    "arn", "arn",
+    "arp", "arp",
+    "art", "art",
+    "arw", "arw",
+    "asm", "asm",
+    "ast", "ast",
+    "ath", "ath",
+    "aus", "aus",
+    "ava", "ava",
+    "ave", "ave",
+    "awa", "awa",
+    "aym", "aym",
+    "aze", "aze",
+    "bad", "bad",
+    "bai", "bai",
+    "bak", "bak",
+    "bal", "bal",
+    "bam", "bam",
+    "ban", "ban",
+    "baq", "baq",
+    "bas", "bas",
+    "bat", "bat",
+    "bej", "bej",
+    "bel", "bel",
+    "bem", "bem",
+    "ben", "ben",
+    "ber", "ber",
+    "bho", "bho",
+    "bih", "bih",
+    "bik", "bik",
+    "bin", "bin",
+    "bis", "bis",
+    "bla", "bla",
+    "bnt", "bnt",
+    "bos", "bos",
+    "bra", "bra",
+    "bre", "bre",
+    "btk", "btk",
+    "bua", "bua",
+    "bug", "bug",
+    "bul", "bul",
+    "bur", "bur",
+    "byn", "byn",
+    "cad", "cad",
+    "cai", "cai",
+    "car", "car",
+    "cat", "cat",
+    "cau", "cau",
+    "ceb", "ceb",
+    "cel", "cel",
+    "cha", "cha",
+    "chb", "chb",
+    "che", "che",
+    "chg", "chg",
+    "chi", "chi",
+    "chk", "chk",
+    "chm", "chm",
+    "chn", "chn",
+    "cho", "cho",
+    "chp", "chp",
+    "chr", "chr",
+    "chu", "chu",
+    "chv", "chv",
+    "chy", "chy",
+    "cmc", "cmc",
+    "cop", "cop",
+    "cor", "cor",
+    "cos", "cos",
+    "cpe", "cpe",
+    "cpf", "cpf",
+    "cpp", "cpp",
+    "cre", "cre",
+    "crh", "crh",
+    "crp", "crp",
+    "csb", "csb",
+    "cus", "cus",
+    "cze", "cze",
+    "dak", "dak",
+    "dan", "dan",
+    "dar", "dar",
+    "day", "day",
+    "del", "del",
+    "den", "den",
+    "dgr", "dgr",
+    "din", "din",
+    "div", "div",
+    "doi", "doi",
+    "dra", "dra",
+    "dsb", "dsb",
+    "dua", "dua",
+    "dum", "dum",
+    "dut", "dut",
+    "dyu", "dyu",
+    "dzo", "dzo",
+    "efi", "efi",
+    "egy", "egy",
+    "eka", "eka",
+    "elx", "elx",
+    "eng", "eng",
+    "enm", "enm",
+    "epo", "epo",
+    "est", "est",
+    "ewe", "ewe",
+    "ewo", "ewo",
+    "fan", "fan",
+    "fao", "fao",
+    "fat", "fat",
+    "fij", "fij",
+    "fil", "fil",
+    "fin", "fin",
+    "fiu", "fiu",
+    "fon", "fon",
+    "fre", "fre",
+    "frm", "frm",
+    "fro", "fro",
+    "frr", "frr",
+    "frs", "frs",
+    "fry", "fry",
+    "ful", "ful",
+    "fur", "fur",
+    "gaa", "gaa",
+    "gay", "gay",
+    "gba", "gba",
+    "gem", "gem",
+    "geo", "geo",
+    "ger", "ger",
+    "gez", "gez",
+    "gil", "gil",
+    "gla", "gla",
+    "gle", "gle",
+    "glg", "glg",
+    "glv", "glv",
+    "gmh", "gmh",
+    "goh", "goh",
+    "gon", "gon",
+    "gor", "gor",
+    "got", "got",
+    "grb", "grb",
+    "grc", "grc",
+    "gre", "gre",
+    "grn", "grn",
+    "gsw", "gsw",
+    "guj", "guj",
+    "gwi", "gwi",
+    "hai", "hai",
+    "hat", "hat",
+    "hau", "hau",
+    "haw", "haw",
+    "heb", "heb",
+    "her", "her",
+    "hil", "hil",
+    "him", "him",
+    "hin", "hin",
+    "hit", "hit",
+    "hmn", "hmn",
+    "hmo", "hmo",
+    "hrv", "hrv",
+    "hsb", "hsb",
+    "hun", "hun",
+    "hup", "hup",
+    "iba", "iba",
+    "ibo", "ibo",
+    "ice", "ice",
+    "ido", "ido",
+    "iii", "iii",
+    "ijo", "ijo",
+    "iku", "iku",
+    "ile", "ile",
+    "ilo", "ilo",
+    "ina", "ina",
+    "inc", "inc",
+    "ind", "ind",
+    "ine", "ine",
+    "inh", "inh",
+    "ipk", "ipk",
+    "ira", "ira",
+    "iro", "iro",
+    "ita", "ita",
+    "jav", "jav",
+    "jbo", "jbo",
+    "jpn", "jpn",
+    "jpr", "jpr",
+    "jrb", "jrb",
+    "kaa", "kaa",
+    "kab", "kab",
+    "kac", "kac",
+    "kal", "kal",
+    "kam", "kam",
+    "kan", "kan",
+    "kar", "kar",
+    "kas", "kas",
+    "kau", "kau",
+    "kaw", "kaw",
+    "kaz", "kaz",
+    "kbd", "kbd",
+    "kha", "kha",
+    "khi", "khi",
+    "khm", "khm",
+    "kho", "kho",
+    "kik", "kik",
+    "kin", "kin",
+    "kir", "kir",
+    "kmb", "kmb",
+    "kok", "kok",
+    "kom", "kom",
+    "kon", "kon",
+    "kor", "kor",
+    "kos", "kos",
+    "kpe", "kpe",
+    "krc", "krc",
+    "krl", "krl",
+    "kro", "kro",
+    "kru", "kru",
+    "kua", "kua",
+    "kum", "kum",
+    "kur", "kur",
+    "kut", "kut",
+    "lad", "lad",
+    "lah", "lah",
+    "lam", "lam",
+    "lao", "lao",
+    "lat", "lat",
+    "lav", "lav",
+    "lez", "lez",
+    "lim", "lim",
+    "lin", "lin",
+    "lit", "lit",
+    "lol", "lol",
+    "loz", "loz",
+    "ltz", "ltz",
+    "lua", "lua",
+    "lub", "lub",
+    "lug", "lug",
+    "lui", "lui",
+    "lun", "lun",
+    "luo", "luo",
+    "lus", "lus",
+    "mac", "mac",
+    "mad", "mad",
+    "mag", "mag",
+    "mah", "mah",
+    "mai", "mai",
+    "mak", "mak",
+    "mal", "mal",
+    "man", "man",
+    "mao", "mao",
+    "map", "map",
+    "mar", "mar",
+    "mas", "mas",
+    "may", "may",
+    "mdf", "mdf",
+    "mdr", "mdr",
+    "men", "men",
+    "mga", "mga",
+    "mic", "mic",
+    "min", "min",
+    "mis", "mis",
+    "mkh", "mkh",
+    "mlg", "mlg",
+    "mlt", "mlt",
+    "mnc", "mnc",
+    "mni", "mni",
+    "mno", "mno",
+    "moh", "moh",
+    "mon", "mon",
+    "mos", "mos",
+    "mul", "mul",
+    "mun", "mun",
+    "mus", "mus",
+    "mwl", "mwl",
+    "mwr", "mwr",
+    "myn", "myn",
+    "myv", "myv",
+    "nah", "nah",
+    "nai", "nai",
+    "nap", "nap",
+    "nau", "nau",
+    "nav", "nav",
+    "nbl", "nbl",
+    "nde", "nde",
+    "ndo", "ndo",
+    "nds", "nds",
+    "nep", "nep",
+    "new", "new",
+    "nia", "nia",
+    "nic", "nic",
+    "niu", "niu",
+    "nno", "nno",
+    "nob", "nob",
+    "nog", "nog",
+    "non", "non",
+    "nor", "nor",
+    "nqo", "nqo",
+    "nso", "nso",
+    "nub", "nub",
+    "nwc", "nwc",
+    "nya", "nya",
+    "nym", "nym",
+    "nyn", "nyn",
+    "nyo", "nyo",
+    "nzi", "nzi",
+    "oci", "oci",
+    "oji", "oji",
+    "ori", "ori",
+    "orm", "orm",
+    "osa", "osa",
+    "oss", "oss",
+    "ota", "ota",
+    "oto", "oto",
+    "paa", "paa",
+    "pag", "pag",
+    "pal", "pal",
+    "pam", "pam",
+    "pan", "pan",
+    "pap", "pap",
+    "pau", "pau",
+    "peo", "peo",
+    "per", "per",
+    "phi", "phi",
+    "phn", "phn",
+    "pli", "pli",
+    "pol", "pol",
+    "pon", "pon",
+    "por", "por",
+    "pra", "pra",
+    "pro", "pro",
+    "pus", "pus",
+    "que", "que",
+    "raj", "raj",
+    "rap", "rap",
+    "rar", "rar",
+    "roa", "roa",
+    "roh", "roh",
+    "rom", "rom",
+    "rum", "rum",
+    "run", "run",
+    "rup", "rup",
+    "rus", "rus",
+    "sad", "sad",
+    "sag", "sag",
+    "sah", "sah",
+    "sai", "sai",
+    "sal", "sal",
+    "sam", "sam",
+    "san", "san",
+    "sas", "sas",
+    "sat", "sat",
+    "scn", "scn",
+    "sco", "sco",
+    "sel", "sel",
+    "sem", "sem",
+    "sga", "sga",
+    "sgn", "sgn",
+    "shn", "shn",
+    "sid", "sid",
+    "sin", "sin",
+    "sio", "sio",
+    "sit", "sit",
+    "sla", "sla",
+    "slo", "slo",
+    "slv", "slv",
+    "sma", "sma",
+    "sme", "sme",
+    "smi", "smi",
+    "smj", "smj",
+    "smn", "smn",
+    "smo", "smo",
+    "sms", "sms",
+    "sna", "sna",
+    "snd", "snd",
+    "snk", "snk",
+    "sog", "sog",
+    "som", "som",
+    "son", "son",
+    "sot", "sot",
+    "spa", "spa",
+    "srd", "srd",
+    "srn", "srn",
+    "srp", "srp",
+    "srr", "srr",
+    "ssa", "ssa",
+    "ssw", "ssw",
+    "suk", "suk",
+    "sun", "sun",
+    "sus", "sus",
+    "sux", "sux",
+    "swa", "swa",
+    "swe", "swe",
+    "syc", "syc",
+    "syr", "syr",
+    "tah", "tah",
+    "tai", "tai",
+    "tam", "tam",
+    "tat", "tat",
+    "tel", "tel",
+    "tem", "tem",
+    "ter", "ter",
+    "tet", "tet",
+    "tgk", "tgk",
+    "tgl", "tgl",
+    "tha", "tha",
+    "tib", "tib",
+    "tig", "tig",
+    "tir", "tir",
+    "tiv", "tiv",
+    "tkl", "tkl",
+    "tlh", "tlh",
+    "tli", "tli",
+    "tmh", "tmh",
+    "tog", "tog",
+    "ton", "ton",
+    "tpi", "tpi",
+    "tsi", "tsi",
+    "tsn", "tsn",
+    "tso", "tso",
+    "tuk", "tuk",
+    "tum", "tum",
+    "tup", "tup",
+    "tur", "tur",
+    "tut", "tut",
+    "tvl", "tvl",
+    "twi", "twi",
+    "tyv", "tyv",
+    "udm", "udm",
+    "uga", "uga",
+    "uig", "uig",
+    "ukr", "ukr",
+    "umb", "umb",
+    "und", "und",
+    "urd", "urd",
+    "uzb", "uzb",
+    "vai", "vai",
+    "ven", "ven",
+    "vie", "vie",
+    "vol", "vol",
+    "vot", "vot",
+    "wak", "wak",
+    "wal", "wal",
+    "war", "war",
+    "was", "was",
+    "wel", "wel",
+    "wen", "wen",
+    "wln", "wln",
+    "wol", "wol",
+    "xal", "xal",
+    "xho", "xho",
+    "yao", "yao",
+    "yap", "yap",
+    "yid", "yid",
+    "yor", "yor",
+    "ypk", "ypk",
+    "zap", "zap",
+    "zbl", "zbl",
+    "zen", "zen",
+    "zha", "zha",
+    "znd", "znd",
+    "zul", "zul",
+    "zun", "zun",
+    "zxx", "zxx",
+    "zza", "zza",
+
+    "",
+};
+
+/*
+ * Linux/Solaris script string to Java script name mapping table.
+ */
+static char *script_names[] = {
+#ifdef __linux__
+    "cyrillic", "Cyrl",
+    "devanagari", "Deva",
+    "iqtelif", "Latn",
+    "latin", "Latn",
+#endif
     "",
 };
 
@@ -503,6 +1017,7 @@
     "MA", "MA",
     "MC", "MC",
     "MD", "MD",
+    "ME", "ME",
     "MG", "MG",
     "MH", "MH",
     "MK", "MK",
@@ -554,6 +1069,7 @@
     "RN", "US", // used on Linux, not clear what it stands for
 #endif
     "RO", "RO",
+    "RS", "RS",
     "RU", "RU",
     "RW", "RW",
     "SA", "SA",
--- a/jdk/src/solaris/native/java/net/Inet4AddressImpl.c	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/solaris/native/java/net/Inet4AddressImpl.c	Wed Jul 05 17:26:57 2017 +0200
@@ -381,7 +381,15 @@
       n = sendto(fd, sendbuf, plen, 0, (struct sockaddr *)him,
                  sizeof(struct sockaddr));
       if (n < 0 && errno != EINPROGRESS ) {
-        NET_ThrowNew(env, errno, "Can't send ICMP packet");
+#ifdef __linux__
+        if (errno != EINVAL)
+          /*
+           * On some Linuxes, when bound to the loopback interface, sendto
+           * will fail and errno will be set to EINVAL. When that happens,
+           * don't throw an exception, just return false.
+           */
+#endif /*__linux__ */
+          NET_ThrowNew(env, errno, "Can't send ICMP packet");
         close(fd);
         return JNI_FALSE;
       }
--- a/jdk/src/solaris/native/java/net/Inet6AddressImpl.c	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/solaris/native/java/net/Inet6AddressImpl.c	Wed Jul 05 17:26:57 2017 +0200
@@ -506,7 +506,16 @@
       plen = sizeof(struct icmp6_hdr) + sizeof(tv);
       n = sendto(fd, sendbuf, plen, 0, (struct sockaddr*) him, sizeof(struct sockaddr_in6));
       if (n < 0 && errno != EINPROGRESS) {
+#ifdef __linux__
+        if (errno != EINVAL)
+          /*
+           * On some Linuxes, when bound to the loopback interface, sendto
+           * will fail and errno will be set to EINVAL. When that happens,
+           * don't throw an exception, just return false.
+           */
+#endif /*__linux__ */
         NET_ThrowNew(env, errno, "Can't send ICMP packet");
+        close(fd);
         return JNI_FALSE;
       }
 
--- a/jdk/src/solaris/native/java/nio/MappedByteBuffer.c	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/solaris/native/java/nio/MappedByteBuffer.c	Wed Jul 05 17:26:57 2017 +0200
@@ -82,8 +82,8 @@
 
 
 JNIEXPORT void JNICALL
-Java_java_nio_MappedByteBuffer_force0(JNIEnv *env, jobject obj, jlong address,
-                                      jlong len)
+Java_java_nio_MappedByteBuffer_force0(JNIEnv *env, jobject obj, jobject fdo,
+                                      jlong address, jlong len)
 {
     void* a = (void *)jlong_to_ptr(address);
     int result = msync(a, (size_t)len, MS_SYNC);
--- a/jdk/src/windows/bin/java_md.c	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/windows/bin/java_md.c	Wed Jul 05 17:26:57 2017 +0200
@@ -51,6 +51,92 @@
 static jboolean GetJREPath(char *path, jint pathsize);
 static void EnsureJreInstallation(const char *jrepath);
 
+/* We supports warmup for UI stack that is performed in parallel
+ * to VM initialization.
+ * This helps to improve startup of UI application as warmup phase
+ * might be long due to initialization of OS or hardware resources.
+ * It is not CPU bound and therefore it does not interfere with VM init.
+ * Obviously such warmup only has sense for UI apps and therefore it needs
+ * to be explicitly requested by passing -Dsun.awt.warmup=true property
+ * (this is always the case for plugin/javaws).
+ *
+ * Implementation launches new thread after VM starts and use it to perform
+ * warmup code (platform dependent).
+ * This thread is later reused as AWT toolkit thread as graphics toolkit
+ * often assume that they are used from the same thread they were launched on.
+ *
+ * At the moment we only support warmup for D3D. It only possible on windows
+ * and only if other flags do not prohibit this (e.g. OpenGL support requested).
+ */
+#undef ENABLE_AWT_PRELOAD
+#ifndef JAVA_ARGS /* turn off AWT preloading for javac, jar, etc */
+    #define ENABLE_AWT_PRELOAD
+#endif
+
+#ifdef ENABLE_AWT_PRELOAD
+/* "AWT was preloaded" flag;
+ * turned on by AWTPreload().
+ */
+int awtPreloaded = 0;
+
+/* Calls a function with the name specified
+ * the function must be int(*fn)(void).
+ */
+int AWTPreload(const char *funcName);
+/* stops AWT preloading */
+void AWTPreloadStop();
+
+/* D3D preloading */
+/* -1: not initialized; 0: OFF, 1: ON */
+int awtPreloadD3D = -1;
+/* command line parameter to swith D3D preloading on */
+#define PARAM_PRELOAD_D3D "-Dsun.awt.warmup"
+/* D3D/OpenGL management parameters */
+#define PARAM_NODDRAW "-Dsun.java2d.noddraw"
+#define PARAM_D3D "-Dsun.java2d.d3d"
+#define PARAM_OPENGL "-Dsun.java2d.opengl"
+/* funtion in awt.dll (src/windows/native/sun/java2d/d3d/D3DPipelineManager.cpp) */
+#define D3D_PRELOAD_FUNC "preloadD3D"
+
+
+/* Extracts value of a parameter with the specified name
+ * from command line argument (returns pointer in the argument).
+ * Returns NULL if the argument does not contains the parameter.
+ * e.g.:
+ * GetParamValue("theParam", "theParam=value") returns pointer to "value".
+ */
+const char * GetParamValue(const char *paramName, const char *arg) {
+    int nameLen = JLI_StrLen(paramName);
+    if (JLI_StrNCmp(paramName, arg, nameLen) == 0) {
+        /* arg[nameLen] is valid (may contain final NULL) */
+        if (arg[nameLen] == '=') {
+            return arg + nameLen + 1;
+        }
+    }
+    return NULL;
+}
+
+/* Checks if commandline argument contains property specified
+ * and analyze it as boolean property (true/false).
+ * Returns -1 if the argument does not contain the parameter;
+ * Returns 1 if the argument contains the parameter and its value is "true";
+ * Returns 0 if the argument contains the parameter and its value is "false".
+ */
+int GetBoolParamValue(const char *paramName, const char *arg) {
+    const char * paramValue = GetParamValue(paramName, arg);
+    if (paramValue != NULL) {
+        if (JLI_StrCaseCmp(paramValue, "true") == 0) {
+            return 1;
+        }
+        if (JLI_StrCaseCmp(paramValue, "false") == 0) {
+            return 0;
+        }
+    }
+    return -1;
+}
+#endif /* ENABLE_AWT_PRELOAD */
+
+
 static jboolean _isjavaw = JNI_FALSE;
 
 
@@ -132,6 +218,30 @@
         exit(4);
     }
     /* If we got here, jvmpath has been correctly initialized. */
+
+    /* Check if we need preload AWT */
+#ifdef ENABLE_AWT_PRELOAD
+    argv = *pargv;
+    for (i = 0; i < *pargc ; i++) {
+        /* Tests the "turn on" parameter only if not set yet. */
+        if (awtPreloadD3D < 0) {
+            if (GetBoolParamValue(PARAM_PRELOAD_D3D, argv[i]) == 1) {
+                awtPreloadD3D = 1;
+            }
+        }
+        /* Test parameters which can disable preloading if not already disabled. */
+        if (awtPreloadD3D != 0) {
+            if (GetBoolParamValue(PARAM_NODDRAW, argv[i]) == 1
+                || GetBoolParamValue(PARAM_D3D, argv[i]) == 0
+                || GetBoolParamValue(PARAM_OPENGL, argv[i]) == 1)
+            {
+                awtPreloadD3D = 0;
+                /* no need to test the rest of the parameters */
+                break;
+            }
+        }
+    }
+#endif /* ENABLE_AWT_PRELOAD */
 }
 
 
@@ -208,7 +318,7 @@
     struct stat s;
 
     /* Make sure the jrepath contains something */
-    if (jrepath[0] == NULL) {
+    if ((void*)jrepath[0] == NULL) {
         return;
     }
     /* 32 bit windows only please */
@@ -540,7 +650,7 @@
         /* get the length of the string we need */
         int len = mlen =  _vscprintf(fmt, vl) + 1;
         if (freeit) {
-           mlen += JLI_StrLen(errtext);
+           mlen += (int)JLI_StrLen(errtext);
         }
 
         message = (char *)JLI_MemAlloc(mlen);
@@ -997,7 +1107,6 @@
 
         exit(exitCode);
     }
-
 }
 
 /*
@@ -1087,6 +1196,40 @@
                              0,
                              &thread_id);
     }
+
+    /* AWT preloading (AFTER main thread start) */
+#ifdef ENABLE_AWT_PRELOAD
+    /* D3D preloading */
+    if (awtPreloadD3D != 0) {
+        char *envValue;
+        /* D3D routines checks env.var J2D_D3D if no appropriate
+         * command line params was specified
+         */
+        envValue = getenv("J2D_D3D");
+        if (envValue != NULL && JLI_StrCaseCmp(envValue, "false") == 0) {
+            awtPreloadD3D = 0;
+        }
+        /* Test that AWT preloading isn't disabled by J2D_D3D_PRELOAD env.var */
+        envValue = getenv("J2D_D3D_PRELOAD");
+        if (envValue != NULL && JLI_StrCaseCmp(envValue, "false") == 0) {
+            awtPreloadD3D = 0;
+        }
+        if (awtPreloadD3D < 0) {
+            /* If awtPreloadD3D is still undefined (-1), test
+             * if it is turned on by J2D_D3D_PRELOAD env.var.
+             * By default it's turned OFF.
+             */
+            awtPreloadD3D = 0;
+            if (envValue != NULL && JLI_StrCaseCmp(envValue, "true") == 0) {
+                awtPreloadD3D = 1;
+            }
+         }
+    }
+    if (awtPreloadD3D) {
+        AWTPreload(D3D_PRELOAD_FUNC);
+    }
+#endif /* ENABLE_AWT_PRELOAD */
+
     if (thread_handle) {
       WaitForSingleObject(thread_handle, INFINITE);
       GetExitCodeThread(thread_handle, &rslt);
@@ -1094,6 +1237,13 @@
     } else {
       rslt = continuation(args);
     }
+
+#ifdef ENABLE_AWT_PRELOAD
+    if (awtPreloaded) {
+        AWTPreloadStop();
+    }
+#endif /* ENABLE_AWT_PRELOAD */
+
     return rslt;
 }
 
@@ -1140,3 +1290,98 @@
     _isjavaw = javaw;
     JLI_SetTraceLauncher();
 }
+
+
+/* ============================== */
+/* AWT preloading */
+#ifdef ENABLE_AWT_PRELOAD
+
+typedef int FnPreloadStart(void);
+typedef void FnPreloadStop(void);
+static FnPreloadStop *fnPreloadStop = NULL;
+static HMODULE hPreloadAwt = NULL;
+
+/*
+ * Starts AWT preloading
+ */
+int AWTPreload(const char *funcName)
+{
+    int result = -1;
+    /* load AWT library once (if several preload function should be called) */
+    if (hPreloadAwt == NULL) {
+        /* awt.dll is not loaded yet */
+        char libraryPath[MAXPATHLEN];
+        int jrePathLen = 0;
+        HMODULE hJava = NULL;
+        HMODULE hVerify = NULL;
+
+        while (1) {
+            /* awt.dll depends on jvm.dll & java.dll;
+             * jvm.dll is already loaded, so we need only java.dll;
+             * java.dll depends on MSVCRT lib & verify.dll.
+             */
+            if (!GetJREPath(libraryPath, MAXPATHLEN)) {
+                break;
+            }
+
+            /* save path length */
+            jrePathLen = JLI_StrLen(libraryPath);
+
+            /* load msvcrt 1st */
+            LoadMSVCRT();
+
+            /* load verify.dll */
+            JLI_StrCat(libraryPath, "\\bin\\verify.dll");
+            hVerify = LoadLibrary(libraryPath);
+            if (hVerify == NULL) {
+                break;
+            }
+
+            /* restore jrePath */
+            libraryPath[jrePathLen] = 0;
+            /* load java.dll */
+            JLI_StrCat(libraryPath, "\\bin\\" JAVA_DLL);
+            hJava = LoadLibrary(libraryPath);
+            if (hJava == NULL) {
+                break;
+            }
+
+            /* restore jrePath */
+            libraryPath[jrePathLen] = 0;
+            /* load awt.dll */
+            JLI_StrCat(libraryPath, "\\bin\\awt.dll");
+            hPreloadAwt = LoadLibrary(libraryPath);
+            if (hPreloadAwt == NULL) {
+                break;
+            }
+
+            /* get "preloadStop" func ptr */
+            fnPreloadStop = (FnPreloadStop *)GetProcAddress(hPreloadAwt, "preloadStop");
+
+            break;
+        }
+    }
+
+    if (hPreloadAwt != NULL) {
+        FnPreloadStart *fnInit = (FnPreloadStart *)GetProcAddress(hPreloadAwt, funcName);
+        if (fnInit != NULL) {
+            /* don't forget to stop preloading */
+            awtPreloaded = 1;
+
+            result = fnInit();
+        }
+    }
+
+    return result;
+}
+
+/*
+ * Terminates AWT preloading
+ */
+void AWTPreloadStop() {
+    if (fnPreloadStop != NULL) {
+        fnPreloadStop();
+    }
+}
+
+#endif /* ENABLE_AWT_PRELOAD */
--- a/jdk/src/windows/classes/sun/awt/windows/WInputMethod.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/windows/classes/sun/awt/windows/WInputMethod.java	Wed Jul 05 17:26:57 2017 +0200
@@ -169,7 +169,7 @@
                     locale.equals(Locale.JAPAN) && lang.equals(Locale.JAPANESE) ||
                     locale.equals(Locale.KOREA) && lang.equals(Locale.KOREAN)) {
                 if (isActive) {
-                    setNativeLocale(locale.toString(), onActivate);
+                    setNativeLocale(locale.toLanguageTag(), onActivate);
                 }
                 currentLocale = locale;
                 return true;
--- a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java	Wed Jul 05 17:26:57 2017 +0200
@@ -218,6 +218,8 @@
 
     private static native void postDispose();
 
+    private static native boolean startToolkitThread(Runnable thread);
+
     public WToolkit() {
         // Startup toolkit threads
         if (PerformanceLogger.loggingEnabled()) {
@@ -231,9 +233,6 @@
             // where notifyAll can be called before
             // the "AWT-Windows" thread's parent thread is
             // waiting, resulting in a deadlock on startup.
-            Thread toolkitThread = new Thread(this, "AWT-Windows");
-            toolkitThread.setDaemon(true);
-            toolkitThread.setPriority(Thread.NORM_PRIORITY+1);
 
             /*
              * Fix for 4701990.
@@ -242,7 +241,11 @@
              */
             AWTAutoShutdown.notifyToolkitThreadBusy();
 
-            toolkitThread.start();
+            if (!startToolkitThread(this)) {
+                Thread toolkitThread = new Thread(this, "AWT-Windows");
+                toolkitThread.setDaemon(true);
+                toolkitThread.start();
+            }
 
             try {
                 wait();
@@ -263,6 +266,7 @@
     }
 
     public void run() {
+        Thread.currentThread().setPriority(Thread.NORM_PRIORITY+1);
         boolean startPump = init();
 
         if (startPump) {
--- a/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java	Wed Jul 05 17:26:57 2017 +0200
@@ -600,6 +600,7 @@
     }
 
     private native void setOpacity(int iOpacity);
+    private float opacity = 1.0f;
 
     public void setOpacity(float opacity) {
         if (!((SunToolkit)((Window)target).getToolkit()).
@@ -608,7 +609,21 @@
             return;
         }
 
-        replaceSurfaceDataRecursively((Component)getTarget());
+        if (opacity < 0.0f || opacity > 1.0f) {
+            throw new IllegalArgumentException(
+                "The value of opacity should be in the range [0.0f .. 1.0f].");
+        }
+
+        if (((this.opacity == 1.0f && opacity <  1.0f) ||
+             (this.opacity <  1.0f && opacity == 1.0f)) &&
+            !Win32GraphicsEnvironment.isVistaOS())
+        {
+            // non-Vista OS: only replace the surface data if opacity status
+            // changed (see WComponentPeer.isAccelCapable() for more)
+            replaceSurfaceDataRecursively((Component)getTarget());
+        }
+
+        this.opacity = opacity;
 
         final int maxOpacity = 0xff;
         int iOpacity = (int)(opacity * maxOpacity);
@@ -650,7 +665,7 @@
 
         boolean isVistaOS = Win32GraphicsEnvironment.isVistaOS();
 
-        if (!isVistaOS) {
+        if (this.isOpaque != isOpaque && !isVistaOS) {
             // non-Vista OS: only replace the surface data if the opacity
             // status changed (see WComponentPeer.isAccelCapable() for more)
             replaceSurfaceDataRecursively(target);
--- a/jdk/src/windows/classes/sun/nio/ch/FileDispatcherImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/windows/classes/sun/nio/ch/FileDispatcherImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -26,10 +26,11 @@
 package sun.nio.ch;
 
 import java.io.*;
+import sun.misc.SharedSecrets;
+import sun.misc.JavaIOFileDescriptorAccess;
 
 class FileDispatcherImpl extends FileDispatcher
 {
-
     static {
         Util.load();
     }
@@ -94,6 +95,16 @@
         close0(fd);
     }
 
+    FileDescriptor duplicateForMapping(FileDescriptor fd) throws IOException {
+        // on Windows we need to keep a handle to the file
+        JavaIOFileDescriptorAccess fdAccess =
+            SharedSecrets.getJavaIOFileDescriptorAccess();
+        FileDescriptor result = new FileDescriptor();
+        long handle = duplicateHandle(fdAccess.getHandle(fd));
+        fdAccess.setHandle(result, handle);
+        return result;
+    }
+
     //-- Native methods
 
     static native int read0(FileDescriptor fd, long address, int len)
@@ -132,4 +143,5 @@
 
     static native void closeByHandle(long fd) throws IOException;
 
+    static native long duplicateHandle(long fd) throws IOException;
 }
--- a/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousChannelProvider.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousChannelProvider.java	Wed Jul 05 17:26:57 2017 +0200
@@ -29,7 +29,6 @@
 import java.nio.channels.spi.AsynchronousChannelProvider;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ThreadFactory;
-import java.net.ProtocolFamily;
 import java.io.IOException;
 
 public class WindowsAsynchronousChannelProvider
@@ -90,12 +89,4 @@
     {
         return new WindowsAsynchronousSocketChannelImpl(toIocp(group));
     }
-
-    @Override
-    public AsynchronousDatagramChannel openAsynchronousDatagramChannel(ProtocolFamily family,
-                                                                       AsynchronousChannelGroup group)
-        throws IOException
-    {
-        return new SimpleAsynchronousDatagramChannelImpl(family, toIocp(group));
-    }
 }
--- a/jdk/src/windows/classes/sun/security/krb5/internal/tools/Ktab.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/windows/classes/sun/security/krb5/internal/tools/Ktab.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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,10 +39,11 @@
 import java.text.DateFormat;
 import java.util.Arrays;
 import java.util.Date;
+import java.util.Locale;
 import sun.security.krb5.internal.crypto.EType;
 /**
  * This class can execute as a command-line tool to help the user manage
- * entires in the key table.
+ * entries in the key table.
  * Available functions include list/add/update/delete service key(s).
  *
  * @author Yanni Zhang
@@ -60,30 +61,20 @@
     int etype = -1;
     char[] password = null;
 
+    boolean forced = false; // true if delete without prompt. Default false
+    boolean append = false; // true if new keys are appended. Default false
+    int vDel = -1;          // kvno to delete, -1 all, -2 old. Default -1
+    int vAdd = -1;          // kvno to add. Default -1, means auto incremented
+
     /**
      * The main program that can be invoked at command line.
-     * <br>Usage: ktab <options>
-     * <br>available options to Ktab:
-     * <ul>
-     * <li><b>-l [-e] [-t]</b>  list the keytab name and entries, -e show
-     * encryption etypes, -t show timestamps.
-     * <li><b>-a</b>  &lt;<i>principal name</i>&gt;
-     * (&lt;<i>password</i>&gt;)  add an entry to the keytab.
-     * The entry is added only to the keytab. No changes are made to the
-     * Kerberos database.
-     * <li><b>-d</b>  &lt;<i>principal name</i>&gt; [&lt;<i>etype</i>&gt;]
-     * delete an entry from the keytab.
-     * The entry is deleted only from the keytab. No changes are made to the
-     * Kerberos database.
-     * <li><b>-k</b>  &lt;<i>keytab name</i> &gt;
-     * specify keytab name and path with prefix FILE:
-     * <li><b>-help</b> display instructions.
+     * See {@link #printHelp} for usages.
      */
     public static void main(String[] args) {
         Ktab ktab = new Ktab();
         if ((args.length == 1) && (args[0].equalsIgnoreCase("-help"))) {
             ktab.printHelp();
-            System.exit(0);
+            return;
         } else if ((args == null) || (args.length == 0)) {
             ktab.action = 'l';
         } else {
@@ -139,7 +130,6 @@
             break;
         default:
             ktab.printHelp();
-            System.exit(-1);
         }
     }
 
@@ -147,84 +137,129 @@
      * Parses the command line arguments.
      */
     void processArgs(String[] args) {
-        Character arg = null;
+
+        // Commands (should appear before options):
+        //   -l
+        //   -a <princ>
+        //   -d <princ>
+        // Options:
+        //   -e <etype> (for -d)
+        //   -e (for -l)
+        //   -n <kvno>
+        //   -k <keytab>
+        //   -t
+        //   -f
+        //   -append
+        // Optional extra arguments:
+        //   password for -a
+        //   [kvno|all|old] for -d
+
+        boolean argAlreadyAppeared = false;
         for (int i = 0; i < args.length; i++) {
-            if ((args[i].length() == 2) && (args[i].startsWith("-"))) {
-                arg = new Character(args[i].charAt(1));
-            } else {
-                printHelp();
-                System.exit(-1);
-            }
-            switch (arg.charValue()) {
-            case 'l':
-            case 'L':
-                action = 'l';    // list keytab location, name and entries
-                break;
-            case 'a':
-            case 'A':
-                action = 'a'; // add a new entry to keytab.
-                i++;
-                if ((i < args.length) && (!args[i].startsWith("-"))) {
-                    principal = args[i];
-                } else {
-                    System.out.println("Please specify the principal name"+
-                                       " after -a option.");
-                    printHelp();
-                    System.exit(-1);
+            if (args[i].startsWith("-")) {
+                switch (args[i].toLowerCase(Locale.US)) {
+
+                    // Commands
+                    case "-l":   // list
+                        action = 'l';
+                        break;
+                    case "-a":   // add a new entry to keytab.
+                        action = 'a';
+                        if (++i >= args.length || args[i].startsWith("-")) {
+                            error("A principal name must be specified after -a");
+                        }
+                        principal = args[i];
+                        break;
+                    case "-d":   // delete entries
+                        action = 'd';
+                        if (++i >= args.length || args[i].startsWith("-")) {
+                            error("A principal name must be specified after -d");
+                        }
+                        principal = args[i];
+                        break;
+
+                        // Options
+                    case "-e":
+                        if (action == 'l') {    // list etypes
+                            showEType = true;
+                        } else if (action == 'd') { // delete etypes
+                            if (++i >= args.length || args[i].startsWith("-")) {
+                                error("An etype must be specified after -e");
+                            }
+                            try {
+                                etype = Integer.parseInt(args[i]);
+                                if (etype <= 0) {
+                                    throw new NumberFormatException();
+                                }
+                            } catch (NumberFormatException nfe) {
+                                error(args[i] + " is not a valid etype");
+                            }
+                        } else {
+                            error(args[i] + " is not valid after -" + action);
+                        }
+                        break;
+                    case "-n":   // kvno for -a
+                        if (++i >= args.length || args[i].startsWith("-")) {
+                            error("A KVNO must be specified after -n");
+                        }
+                        try {
+                            vAdd = Integer.parseInt(args[i]);
+                            if (vAdd < 0) {
+                                throw new NumberFormatException();
+                            }
+                        } catch (NumberFormatException nfe) {
+                            error(args[i] + " is not a valid KVNO");
+                        }
+                        break;
+                    case "-k":  // specify keytab to use
+                        if (++i >= args.length || args[i].startsWith("-")) {
+                            error("A keytab name must be specified after -k");
+                        }
+                        if (args[i].length() >= 5 &&
+                            args[i].substring(0, 5).equalsIgnoreCase("FILE:")) {
+                            name = args[i].substring(5);
+                        } else {
+                            name = args[i];
+                        }
+                        break;
+                    case "-t":   // list timestamps
+                        showTime = true;
+                        break;
+                    case "-f":   // force delete, no prompt
+                        forced = true;
+                        break;
+                    case "-append": // -a, new keys append to file
+                        append = true;
+                        break;
+                    default:
+                        printHelp();
+                        break;
                 }
-                if ((i + 1 < args.length) &&
-                    (!args[i + 1].startsWith("-"))) {
-                    password = args[i + 1].toCharArray();
-                    i++;
-                } else {
-                    password = null; // prompt user for password later.
+            } else {    // optional standalone arguments
+                if (argAlreadyAppeared) {
+                    error("Useless extra argument " + args[i]);
                 }
-                break;
-            case 'd':
-            case 'D':
-                action = 'd'; // delete an entry.
-                i++;
-                if ((i < args.length) && (!args[i].startsWith("-"))) {
-                    principal = args[i];
-                    int j = i + 1;
-                    if ((j < args.length) && (!args[j].startsWith("-"))) {
-                        etype = Integer.parseInt(args[j]);
-                        i = j;
+                if (action == 'a') {
+                    password = args[i].toCharArray();
+                } else if (action == 'd') {
+                    switch (args[i]) {
+                        case "all": vDel = -1; break;
+                        case "old": vDel = -2; break;
+                        default: {
+                            try {
+                                vDel = Integer.parseInt(args[i]);
+                                if (vDel < 0) {
+                                    throw new NumberFormatException();
+                                }
+                            } catch (NumberFormatException nfe) {
+                                error(args[i] + " is not a valid KVNO");
+                            }
+                        }
                     }
                 } else {
-                    System.out.println("Please specify the principal" +
-                                       "name of the entry you want to " +
-                                       " delete after -d option.");
-                    printHelp();
-                    System.exit(-1);
+                    error("Useless extra argument " + args[i]);
                 }
-                break;
-            case 'k':
-            case 'K':
-                i++;
-                if ((i < args.length) && (!args[i].startsWith("-"))) {
-                    if (args[i].length() >= 5 &&
-                        args[i].substring(0, 5).equalsIgnoreCase("FILE:")) {
-                        name = args[i].substring(5);
-                    } else
-                        name = args[i];
-                } else {
-                    System.out.println("Please specify the keytab "+
-                                       "file name and location " +
-                                       "after -k option");
-                    printHelp();
-                    System.exit(-1);
-                }
-                break;
-            case 'e':
-                showEType = true;
-                break;
-            case 't':
-                showTime = true;
-                break;
-            default:
-                printHelp();
-                System.exit(-1);
+                argAlreadyAppeared = true;
             }
         }
     }
@@ -263,7 +298,7 @@
         }
         try {
             // admin.addEntry(pname, password);
-            table.addEntry(pname, password);
+            table.addEntry(pname, password, vAdd, append);
             Arrays.fill(password, '0');  // clear password
             // admin.save();
             table.save();
@@ -350,23 +385,25 @@
             if (pname.getRealm() == null) {
                 pname.setRealm(Config.getInstance().getDefaultRealm());
             }
-            String answer;
-            BufferedReader cis =
-                new BufferedReader(new InputStreamReader(System.in));
-            System.out.print("Are you sure you want to"+
-                             " delete service key for " + pname.toString() +
-                             " (" + (etype==-1?"all etypes":("etype = "+etype)) +
-                             ") in " + table.tabName() + "?(Y/N): ");
+            if (!forced) {
+                String answer;
+                BufferedReader cis =
+                    new BufferedReader(new InputStreamReader(System.in));
+                System.out.print("Are you sure you want to delete "+
+                        "service key(s) for " + pname.toString() +
+                        " (" + (etype==-1?"all etypes":("etype="+etype)) + ", " +
+                        (vDel==-1?"all kvno":(vDel==-2?"old kvno":("kvno=" + vDel))) +
+                        ") in " + table.tabName() + "? (Y/[N]): ");
 
-            System.out.flush();
-            answer = cis.readLine();
-            if (answer.equalsIgnoreCase("Y") ||
-                answer.equalsIgnoreCase("Yes"));
-            else {
-                // no error, the user did not want to delete the entry
-                System.exit(0);
+                System.out.flush();
+                answer = cis.readLine();
+                if (answer.equalsIgnoreCase("Y") ||
+                    answer.equalsIgnoreCase("Yes"));
+                else {
+                    // no error, the user did not want to delete the entry
+                    System.exit(0);
+                }
             }
-
         } catch (KrbException e) {
             System.err.println("Error occured while deleting the entry. "+
                                "Deletion failed.");
@@ -379,9 +416,7 @@
             System.exit(-1);
         }
 
-        int count;
-        if (etype == -1) count = table.deleteEntry(pname);
-        else count = table.deleteEntry(pname, etype);
+        int count = table.deleteEntries(pname, etype, vDel);
 
         if (count == 0) {
             System.err.println("No matched entry in the keytab. " +
@@ -396,23 +431,47 @@
                 e.printStackTrace();
                 System.exit(-1);
             }
-            System.out.println("Done!");
+            System.out.println("Done! " + count + " entries removed.");
         }
     }
 
+    void error(String... errors) {
+        for (String error: errors) {
+            System.out.println("Error: " + error + ".");
+        }
+        printHelp();
+        System.exit(-1);
+    }
     /**
      * Prints out the help information.
      */
     void printHelp() {
-        System.out.println("\nUsage: ktab " +
-                           "<options>");
-        System.out.println("available options to Ktab:");
-        System.out.println("-l [-e] [-t]\t\t\tlist the keytab name and entries,\n\t\t\t\t-e with etype, -t with timestamp");
-        System.out.println("-a <principal name> (<password>)add an entry " +
-                           "to the keytab");
-        System.out.println("-d <principal name> [<etype>]\tdelete an "+
-                           "entry from the keytab");
-        System.out.println("-k <keytab name>\t\tspecify keytab name and "+
-                           "path with prefix FILE:");
+        System.out.println("\nUsage: ktab <commands> <options>");
+        System.out.println();
+        System.out.println("Available commands:");
+        System.out.println();
+        System.out.println("-l [-e] [-t]\n"
+                + "    list the keytab name and entries. -e with etype, -t with timestamp.");
+        System.out.println("-a <principal name> [<password>] [-n <kvno>] [-append]\n"
+                + "    add new key entries to the keytab for the given principal name with\n"
+                + "    optional <password>. If a <kvno> is specified, new keys' Key Version\n"
+                + "    Numbers equal to the value, otherwise, automatically incrementing\n"
+                + "    the Key Version Numbers. If -append is specified, new keys are\n"
+                + "    appended to the keytab, otherwise, old keys for the\n"
+                + "    same principal are removed.");
+        System.out.println("-d <principal name> [-f] [-e <etype>] [<kvno> | all | old]\n"
+                + "    delete key entries from the keytab for the specified principal. If\n"
+                + "    <kvno> is specified, delete keys whose Key Version Numbers match\n"
+                + "    kvno. If \"all\" is specified, delete all keys. If \"old\" is specified,\n"
+                + "    delete all keys except those with the highest kvno. Default action\n"
+                + "    is \"all\". If <etype> is specified, only keys of this encryption type\n"
+                + "    are deleted. <etype> should be specified as the numberic value etype\n"
+                + "    defined in RFC 3961, section 8. A prompt to confirm the deletion is\n"
+                + "    displayed unless -f is specified.");
+        System.out.println();
+        System.out.println("Common option(s):");
+        System.out.println();
+        System.out.println("-k <keytab name>\n"
+                + "    specify keytab name and path with prefix FILE:");
     }
 }
--- a/jdk/src/windows/native/com/sun/media/sound/PLATFORM_API_WinOS_DirectSound.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/windows/native/com/sun/media/sound/PLATFORM_API_WinOS_DirectSound.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -476,6 +476,7 @@
 
 DWORD WINAPI __stdcall DS_StartBufferHelper::ThreadProc(void *param)
 {
+    ::CoInitialize(NULL);
     while (1) {
         // wait for something to do
         ::WaitForSingleObject(data.startEvent, INFINITE);
@@ -492,6 +493,7 @@
         }
         ::SetEvent(data.startedEvent);
     }
+    ::CoUninitialize();
     return 0;
 }
 
--- a/jdk/src/windows/native/java/lang/java_props_md.c	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/windows/native/java/lang/java_props_md.c	Wed Jul 05 17:26:57 2017 +0200
@@ -43,11 +43,14 @@
 #endif
 
 typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
-static void SetupI18nProps(LCID lcid, char** language, char** country,
+static void SetupI18nProps(LCID lcid, char** language, char** script, char** country,
                char** variant, char** encoding);
 
 #define SHELL_KEY "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
 
+#define PROPSIZE 9      // eight-letter + null terminator
+#define SNAMESIZE 86    // max number of chars for LOCALE_SNAME is 85
+
 static char *
 getEncodingInternal(LCID lcid)
 {
@@ -127,30 +130,31 @@
     return getEncodingInternal(MAKELCID(langID, SORT_DEFAULT));
 }
 
+// Returns BCP47 Language Tag
 DllExport const char *
 getJavaIDFromLangID(LANGID langID)
 {
-    char * lang;
-    char * ctry;
-    char * vrnt;
-    char * enc;
-    char * ret = malloc(16);
+    char * elems[5]; // lang, script, ctry, variant, encoding
+    char * ret = malloc(SNAMESIZE);
+    int index;
+
+    SetupI18nProps(MAKELCID(langID, SORT_DEFAULT),
+                   &(elems[0]), &(elems[1]), &(elems[2]), &(elems[3]), &(elems[4]));
 
-    SetupI18nProps(MAKELCID(langID, SORT_DEFAULT), &lang, &ctry, &vrnt, &enc);
-    if (ctry[0] != '\0') {
-        if (vrnt[0] != '\0') {
-            sprintf(ret, "%s_%s_%s", lang, ctry, vrnt);
-        } else {
-            sprintf(ret, "%s_%s", lang, ctry);
+    // there always is the "language" tag
+    strcpy(ret, elems[0]);
+
+    // append other elements, if any
+    for (index = 1; index < 4; index++) {
+        if ((elems[index])[0] != '\0') {
+            strcat(ret, "-");
+            strcat(ret, elems[index]);
         }
-    } else {
-        strcpy(ret, lang);
     }
 
-    free(lang);
-    free(ctry);
-    free(vrnt);
-    free(enc);
+    for (index = 0; index < 5; index++) {
+        free(elems[index]);
+    }
 
     return ret;
 }
@@ -289,39 +293,38 @@
     return NULL;
 }
 
-#define PROPSIZE 3      // two-letter + null terminator
 static void
-SetupI18nProps(LCID lcid, char** language, char** country,
+SetupI18nProps(LCID lcid, char** language, char** script, char** country,
                char** variant, char** encoding) {
+    /* script */
+    char tmp[SNAMESIZE];
+    *script = malloc(PROPSIZE);
+    if (GetLocaleInfo(lcid,
+                      LOCALE_SNAME, tmp, SNAMESIZE) == 0 ||
+        sscanf(tmp, "%*[a-z\\-]%1[A-Z]%[a-z]", *script, &((*script)[1])) == 0 ||
+        strlen(*script) != 4) {
+        (*script)[0] = '\0';
+    }
+
     /* country */
     *country = malloc(PROPSIZE);
     if (GetLocaleInfo(lcid,
-                      LOCALE_SISO3166CTRYNAME, *country, PROPSIZE) == 0) {
+                      LOCALE_SISO3166CTRYNAME, *country, PROPSIZE) == 0 &&
+        GetLocaleInfo(lcid,
+                      LOCALE_SISO3166CTRYNAME2, *country, PROPSIZE) == 0) {
         (*country)[0] = '\0';
     }
 
     /* language */
     *language = malloc(PROPSIZE);
-    if (lcid == 0x46c) {
-        /* Windows returns non-existent language code "ns" for Northern Sotho.
-         * Defaults to en_US
-         */
-        strcpy(*language, "en");
-        strcpy(*country, "US");
-    } else if (GetLocaleInfo(lcid,
-                      LOCALE_SISO639LANGNAME, *language, PROPSIZE) == 0) {
-        if (lcid == 0x465) {
-            /* for some reason, Windows returns "div" for this Divehi LCID, even though
-             * there is a two letter language code "dv".  Tweak it here.
-             */
-            strcpy(*language, "dv");
-            strcpy(*country, "MV");
-        } else {
+    if (GetLocaleInfo(lcid,
+                      LOCALE_SISO639LANGNAME, *language, PROPSIZE) == 0 &&
+        GetLocaleInfo(lcid,
+                      LOCALE_SISO639LANGNAME2, *language, PROPSIZE) == 0) {
             /* defaults to en_US */
             strcpy(*language, "en");
             strcpy(*country, "US");
         }
-    }
 
     /* variant */
     *variant = malloc(PROPSIZE);
@@ -564,7 +567,7 @@
 
     /*
      *  user.language
-     *  user.country, user.variant (if user's environment specifies them)
+     *  user.script, user.country, user.variant (if user's environment specifies them)
      *  file.encoding
      *  file.encoding.pkg
      */
@@ -582,16 +585,19 @@
 
             SetupI18nProps(userDefaultUILang,
                            &sprops.language,
+                           &sprops.script,
                            &sprops.country,
                            &sprops.variant,
                            &display_encoding);
             SetupI18nProps(userDefaultLCID,
                            &sprops.format_language,
+                           &sprops.format_script,
                            &sprops.format_country,
                            &sprops.format_variant,
                            &sprops.encoding);
             SetupI18nProps(userDefaultUILang,
                            &sprops.display_language,
+                           &sprops.display_script,
                            &sprops.display_country,
                            &sprops.display_variant,
                            &display_encoding);
--- a/jdk/src/windows/native/java/nio/MappedByteBuffer.c	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/windows/native/java/nio/MappedByteBuffer.c	Wed Jul 05 17:26:57 2017 +0200
@@ -51,11 +51,11 @@
 }
 
 JNIEXPORT void JNICALL
-Java_java_nio_MappedByteBuffer_force0(JNIEnv *env, jobject obj, jlong address,
-                                      jlong len)
+Java_java_nio_MappedByteBuffer_force0(JNIEnv *env, jobject obj, jobject fdo,
+                                      jlong address, jlong len)
 {
     void *a = (void *) jlong_to_ptr(address);
-    int result;
+    BOOL result;
     int retry;
 
     /*
@@ -71,6 +71,30 @@
         retry++;
     } while (retry < 3);
 
+    /**
+     * FlushViewOfFile only initiates the writing of dirty pages to disk
+     * so we have to call FlushFileBuffers to and ensure they are written.
+     */
+    if (result != 0) {
+        // by right, the jfieldID initialization should be in a static
+        // initializer but we do it here instead to avoiding needing to
+        // load nio.dll during startup.
+        static jfieldID handle_fdID;
+        HANDLE h;
+        if (handle_fdID == NULL) {
+            jclass clazz = (*env)->FindClass(env, "java/io/FileDescriptor");
+            if (clazz == NULL)
+                return; // exception thrown
+            handle_fdID = (*env)->GetFieldID(env, clazz, "handle", "J");
+        }
+        h = jlong_to_ptr((*env)->GetLongField(env, fdo, handle_fdID));
+        result = FlushFileBuffers(h);
+        if (result == 0 && GetLastError() == ERROR_ACCESS_DENIED) {
+            // read-only mapping
+            result = 1;
+        }
+    }
+
     if (result == 0) {
         JNU_ThrowIOExceptionWithLastError(env, "Flush failed");
     }
--- a/jdk/src/windows/native/sun/java2d/d3d/D3DGraphicsDevice.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/windows/native/sun/java2d/d3d/D3DGraphicsDevice.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -36,22 +36,6 @@
 extern void addDisplayMode(JNIEnv* env, jobject arrayList, jint width,
                            jint height, jint bitDepth, jint refreshRate);
 
-void InitD3D(void *pReturn)
-{
-    J2dTraceLn(J2D_TRACE_INFO, "InitD3D");
-
-    jboolean *pRet = (jboolean *)pReturn;
-
-    D3DPipelineManager *pMgr = D3DPipelineManager::CreateInstance();
-    if (pMgr == NULL) {
-        J2dTraceLn(J2D_TRACE_ERROR, "InitD3D: could not create or init d3d");
-        *pRet = JNI_FALSE;
-    } else {
-        J2dTraceLn(J2D_TRACE_INFO, "InitD3D: successfully initialized d3d");
-        *pRet = JNI_TRUE;
-    }
-}
-
 extern "C" {
 /*
  * Class:     sun_java2d_d3d_D3DGraphicsDevice
@@ -63,8 +47,8 @@
 {
     J2dTraceLn(J2D_TRACE_INFO, "D3DGD_initD3D");
 
-    jboolean result = JNI_FALSE;
-    AwtToolkit::GetInstance().InvokeFunction(InitD3D, &result);
+    jboolean result = D3DInitializer::GetInstance().EnsureInited()
+                      ? JNI_TRUE : JNI_FALSE;
     J2dTraceLn1(J2D_TRACE_INFO, "D3DGD_initD3D: result=%x", result);
     return result;
 }
--- a/jdk/src/windows/native/sun/java2d/d3d/D3DPipelineManager.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/windows/native/sun/java2d/d3d/D3DPipelineManager.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -40,6 +40,7 @@
 
 D3DPipelineManager *D3DPipelineManager::pMgr = NULL;
 
+
 D3DPipelineManager * D3DPipelineManager::CreateInstance(void)
 {
     if (!IsD3DEnabled() ||
@@ -179,6 +180,12 @@
     HMONITOR hMon;
     int gdiScreen;
     D3DPipelineManager *pMgr;
+
+    // fix for 6946559: if d3d preloading fails jmv may be NULL
+    if (jvm == NULL) {
+        return;
+    }
+
     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 
     pMgr = D3DPipelineManager::GetInstance();
@@ -934,3 +941,87 @@
     *ppd3dContext = pAdapters[adapterOrdinal].pd3dContext;
     return res;
 }
+
+
+//==============================================================
+// D3DInitializer
+//==============================================================
+
+D3DInitializer D3DInitializer::theInstance;
+
+D3DInitializer::D3DInitializer()
+    : bComInitialized(false), pAdapterIniters(NULL)
+{
+}
+
+D3DInitializer::~D3DInitializer()
+{
+    if (pAdapterIniters) {
+        delete[] pAdapterIniters;
+    }
+}
+
+void D3DInitializer::InitImpl()
+{
+    J2dRlsTraceLn(J2D_TRACE_INFO, "D3DInitializer::InitImpl");
+    if (SUCCEEDED(::CoInitialize(NULL))) {
+        bComInitialized = true;
+    }
+    D3DPipelineManager *pMgr = D3DPipelineManager::CreateInstance();
+    if (pMgr != NULL) {
+        UINT adapterCount = pMgr->adapterCount;
+
+        pAdapterIniters = new D3DAdapterInitializer[adapterCount];
+        for (UINT i=0; i<adapterCount; i++) {
+            pAdapterIniters[i].setAdapter(i);
+            AwtToolkit::GetInstance().GetPreloadThread().AddAction(&pAdapterIniters[i]);
+        }
+    }
+}
+
+void D3DInitializer::CleanImpl(bool reInit)
+{
+    J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DInitializer::CleanImpl (%s)",
+                                    reInit ? "RELAUNCH" : "normal");
+    D3DPipelineManager::DeleteInstance();
+    if (bComInitialized) {
+        CoUninitialize();
+    }
+}
+
+
+void D3DInitializer::D3DAdapterInitializer::InitImpl()
+{
+    J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DAdapterInitializer::InitImpl(%d) started", adapter);
+
+    D3DPipelineManager *pMgr = D3DPipelineManager::GetInstance();
+    if (pMgr == NULL) {
+        return;
+    }
+
+    D3DContext *pd3dContext;
+    pMgr->GetD3DContext(adapter, &pd3dContext);
+
+    J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DAdapterInitializer::InitImpl(%d) finished", adapter);
+}
+
+void D3DInitializer::D3DAdapterInitializer::CleanImpl(bool reInit)
+{
+    // nothing to do - D3DPipelineManager cleans adapters
+}
+
+
+extern "C" {
+/*
+ * Export function to start D3D preloading
+ * (called from java/javaw - see src/windows/bin/java-md.c)
+ */
+__declspec(dllexport) int preloadD3D()
+{
+    J2dRlsTraceLn(J2D_TRACE_INFO, "AWT warmup: preloadD3D");
+    AwtToolkit::GetInstance().GetPreloadThread().AddAction(&D3DInitializer::GetInstance());
+    return 1;
+}
+
+}
+
--- a/jdk/src/windows/native/sun/java2d/d3d/D3DPipelineManager.h	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/windows/native/sun/java2d/d3d/D3DPipelineManager.h	Wed Jul 05 17:26:57 2017 +0200
@@ -26,6 +26,7 @@
 
 #include "D3DPipeline.h"
 #include "D3DContext.h"
+#include "awt_Toolkit.h"
 
 typedef class D3DPipelineManager *LPD3DPIPELINEMANAGER;
 
@@ -38,11 +39,15 @@
 
 class D3DPIPELINE_API D3DPipelineManager
 {
-public:
+    friend class D3DInitializer;
+private:
     // creates and initializes instance of D3DPipelineManager, may return NULL
     static D3DPipelineManager* CreateInstance(void);
+
     // deletes the single instance of the manager
     static void DeleteInstance();
+
+public:
     // returns the single instance of the manager, may return NULL
     static D3DPipelineManager* GetInstance(void);
 
@@ -143,3 +148,40 @@
 #define OS_ALL (OS_VISTA|OS_WINSERV_2008|OS_WINXP|OS_WINXP_64|OS_WINSERV_2003)
 #define OS_UNKNOWN      (~OS_ALL)
 BOOL D3DPPLM_OsVersionMatches(USHORT osInfo);
+
+
+class D3DInitializer : public AwtToolkit::PreloadAction {
+private:
+    D3DInitializer();
+    ~D3DInitializer();
+
+protected:
+    // PreloadAction overrides
+    virtual void InitImpl();
+    virtual void CleanImpl(bool reInit);
+
+public:
+    static D3DInitializer& GetInstance() { return theInstance; }
+
+private:
+    // single instance
+    static D3DInitializer theInstance;
+
+    // adapter initializer class
+    class D3DAdapterInitializer : public AwtToolkit::PreloadAction {
+    public:
+        void setAdapter(UINT adapter) { this->adapter = adapter; }
+    protected:
+        // PreloadAction overrides
+        virtual void InitImpl();
+        virtual void CleanImpl(bool reInit);
+    private:
+        UINT adapter;
+    };
+
+    // the flag indicates success of COM initialization
+    bool bComInitialized;
+    D3DAdapterInitializer *pAdapterIniters;
+
+};
+
--- a/jdk/src/windows/native/sun/java2d/windows/WindowsFlags.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/windows/native/sun/java2d/windows/WindowsFlags.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -28,7 +28,8 @@
 #include "WindowsFlags.h"
 
 BOOL      accelReset;         // reset registry 2d acceleration settings
-BOOL      useD3D;             // d3d enabled flag
+BOOL      useD3D = TRUE;      // d3d enabled flag
+                              // initially is TRUE to allow D3D preloading
 BOOL      forceD3DUsage;      // force d3d on or off
 jboolean  g_offscreenSharing; // JAWT accelerated surface sharing
 BOOL      checkRegistry;      // Diagnostic tool: outputs 2d registry settings
--- a/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c	Wed Jul 05 17:26:57 2017 +0200
@@ -32,6 +32,7 @@
 #include <io.h>
 #include "nio.h"
 #include "nio_util.h"
+#include "jlong.h"
 
 
 /**************************************************************
@@ -441,3 +442,15 @@
 {
     closeFile(env, fd);
 }
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_duplicateHandle(JNIEnv *env, jclass this, jlong hFile)
+{
+    HANDLE hProcess = GetCurrentProcess();
+    HANDLE hResult;
+    BOOL res = DuplicateHandle(hProcess, hFile, hProcess, &hResult, 0, FALSE,
+                               DUPLICATE_SAME_ACCESS);
+    if (res == 0)
+       JNU_ThrowIOExceptionWithLastError(env, "DuplicateHandle failed");
+    return ptr_to_jlong(hResult);
+}
--- a/jdk/src/windows/native/sun/windows/awt_InputMethod.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/windows/native/sun/windows/awt_InputMethod.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -540,34 +540,15 @@
 {
     TRY;
 
-    // get language, country, variant information
-    char * language = (char *)safe_Malloc(strlen(name) + 1);
-    char * country;
-    char * variant;
-    DASSERT(!safe_ExceptionOccurred(env));
-    strcpy(language, name);
-    for (country = language; *country != '_' && *country != '\0'; country++);
-    if (*country == '_') {
-        *country++ = '\0';
-        for (variant = country; *variant != '_' && *variant != '\0'; variant++);
-        if (*variant == '_') {
-            *variant++ = '\0';
-        }
-    } else {
-        variant = country;
-    }
-
     // create Locale object
-    jobject langObj = env->NewStringUTF(language);
-    jobject ctryObj = env->NewStringUTF(country);
-    jobject vrntObj = env->NewStringUTF(variant);
-    jobject localeObj = JNU_NewObjectByName(env, "java/util/Locale",
-                                            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
-                                            langObj, ctryObj, vrntObj);
-    free(language);
-    env->DeleteLocalRef(langObj);
-    env->DeleteLocalRef(ctryObj);
-    env->DeleteLocalRef(vrntObj);
+    jobject langtagObj = env->NewStringUTF(name);
+    jobject localeObj = JNU_CallStaticMethodByName(env,
+                                                   NULL,
+                                                   "java/util/Locale",
+                                                   "forLanguageTag",
+                                                   "(Ljava/lang/String;)Ljava/util/Locale;",
+                                                   langtagObj).l;
+    env->DeleteLocalRef(langtagObj);
 
     return localeObj;
 
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp	Wed Jul 05 17:26:57 2017 +0200
@@ -28,6 +28,7 @@
 #include "awt.h"
 #include <signal.h>
 #include <windowsx.h>
+#include <process.h>
 
 #include "awt_DrawingSurface.h"
 #include "awt_AWTEvent.h"
@@ -88,7 +89,7 @@
 
 /* Initialize the Java VM instance variable when the library is
    first loaded */
-JavaVM *jvm;
+JavaVM *jvm = NULL;
 
 JNIEXPORT jint JNICALL
 JNI_OnLoad(JavaVM *vm, void *reserved)
@@ -358,6 +359,95 @@
     return hwnd;
 }
 
+
+struct ToolkitThreadProc_Data {
+    bool result;
+    HANDLE hCompleted;
+
+    jobject thread;
+};
+
+void ToolkitThreadProc(void *param)
+{
+    ToolkitThreadProc_Data *data = (ToolkitThreadProc_Data *)param;
+
+    bool bNotified = false;
+
+    JNIEnv *env;
+    JavaVMAttachArgs attachArgs;
+    attachArgs.version  = JNI_VERSION_1_2;
+    attachArgs.name     = "AWT-Windows";
+    attachArgs.group    = NULL;
+
+    jint res = jvm->AttachCurrentThreadAsDaemon((void **)&env, &attachArgs);
+    if (res < 0) {
+        return;
+    }
+
+    jobject thread = env->NewGlobalRef(data->thread);
+    if (thread != NULL) {
+        jclass cls = env->GetObjectClass(thread);
+        if (cls != NULL) {
+            jmethodID runId = env->GetMethodID(cls, "run", "()V");
+            if (runId != NULL) {
+                data->result = true;
+                ::SetEvent(data->hCompleted);
+                bNotified = true;
+
+                env->CallVoidMethod(thread, runId);
+
+                if (env->ExceptionCheck()) {
+                    env->ExceptionDescribe();
+                    env->ExceptionClear();
+                    // TODO: handle
+                }
+            }
+            env->DeleteLocalRef(cls);
+        }
+        env->DeleteGlobalRef(thread);
+    }
+    if (!bNotified) {
+        ::SetEvent(data->hCompleted);
+    }
+
+    jvm->DetachCurrentThread();
+}
+
+/*
+ * Class:     sun_awt_windows_WToolkit
+ * Method:    startToolkitThread
+ * Signature: (Ljava/lang/Runnable;)Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_sun_awt_windows_WToolkit_startToolkitThread(JNIEnv *env, jclass cls, jobject thread)
+{
+    AwtToolkit& tk = AwtToolkit::GetInstance();
+
+    ToolkitThreadProc_Data data;
+    data.result = false;
+    data.thread = env->NewGlobalRef(thread);
+    if (data.thread == NULL) {
+        return JNI_FALSE;
+    }
+    data.hCompleted = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+
+    bool result = tk.GetPreloadThread()
+                    .InvokeAndTerminate(ToolkitThreadProc, &data);
+
+    if (result) {
+        ::WaitForSingleObject(data.hCompleted, INFINITE);
+        result = data.result;
+    } else {
+        // no awt preloading
+        // return back to the usual toolkit way
+    }
+    ::CloseHandle(data.hCompleted);
+
+    env->DeleteGlobalRef(data.thread);
+
+    return result ? JNI_TRUE : JNI_FALSE;
+}
+
 BOOL AwtToolkit::Initialize(BOOL localPump) {
     AwtToolkit& tk = AwtToolkit::GetInstance();
 
@@ -371,6 +461,11 @@
     // ComCtl32Util was constructed but not disposed
     ComCtl32Util::GetInstance().InitLibraries();
 
+    if (!localPump) {
+        // if preload thread was run, terminate it
+        preloadThread.Terminate(true);
+    }
+
     /* Register this toolkit's helper window */
     VERIFY(tk.RegisterClass() != NULL);
 
@@ -439,7 +534,7 @@
     // dispose Direct3D-related resources. This should be done
     // before AwtObjectList::Cleanup() as the d3d will attempt to
     // shutdown when the last of its windows is disposed of
-    D3DPipelineManager::DeleteInstance();
+    D3DInitializer::GetInstance().Clean();
 
     AwtObjectList::Cleanup();
     AwtFont::Cleanup();
@@ -1635,6 +1730,270 @@
     ::GetWindowRect(hWnd, lpRect);
 }
 
+
+/************************************************************************
+ * AWT preloading support
+ */
+bool AwtToolkit::PreloadAction::EnsureInited()
+{
+    DWORD _initThreadId = GetInitThreadID();
+    if (_initThreadId != 0) {
+        // already inited
+        // ensure the action is inited on correct thread
+        PreloadThread &preloadThread
+            = AwtToolkit::GetInstance().GetPreloadThread();
+        if (_initThreadId == preloadThread.GetThreadId()) {
+            if (!preloadThread.IsWrongThread()) {
+                return true;
+            }
+            // inited on preloadThread (wrongThread), not cleaned yet
+            // have to wait cleanup completion
+            preloadThread.Wait4Finish();
+        } else {
+            // inited on other thread (Toolkit thread?)
+            // consider as correctly inited
+            return true;
+        }
+    }
+
+    // init on Toolkit thread
+    AwtToolkit::GetInstance().InvokeFunction(InitWrapper, this);
+
+    return true;
+}
+
+DWORD AwtToolkit::PreloadAction::GetInitThreadID()
+{
+    CriticalSection::Lock lock(initLock);
+    return initThreadId;
+}
+
+bool AwtToolkit::PreloadAction::Clean()
+{
+    DWORD _initThreadId = GetInitThreadID();
+    if (_initThreadId == ::GetCurrentThreadId()) {
+        // inited on this thread
+        Clean(false);
+        return true;
+    }
+    return false;
+}
+
+/*static*/
+void AwtToolkit::PreloadAction::InitWrapper(void *param)
+{
+    PreloadAction *pThis = (PreloadAction *)param;
+    pThis->Init();
+}
+
+void AwtToolkit::PreloadAction::Init()
+{
+    CriticalSection::Lock lock(initLock);
+    if (initThreadId == 0) {
+        initThreadId = ::GetCurrentThreadId();
+        InitImpl();
+    }
+}
+
+void AwtToolkit::PreloadAction::Clean(bool reInit) {
+    CriticalSection::Lock lock(initLock);
+    if (initThreadId != 0) {
+        //ASSERT(initThreadId == ::GetCurrentThreadId());
+        CleanImpl(reInit);
+        initThreadId = 0;
+    }
+}
+
+// PreloadThread implementation
+AwtToolkit::PreloadThread::PreloadThread()
+    : status(None), wrongThread(false), threadId(0),
+    pActionChain(NULL), pLastProcessedAction(NULL),
+    execFunc(NULL), execParam(NULL)
+{
+    hFinished = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+    hAwake = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+}
+
+AwtToolkit::PreloadThread::~PreloadThread()
+{
+    //Terminate(false);
+    ::CloseHandle(hFinished);
+    ::CloseHandle(hAwake);
+}
+
+bool AwtToolkit::PreloadThread::AddAction(AwtToolkit::PreloadAction *pAction)
+{
+    CriticalSection::Lock lock(threadLock);
+
+    if (status > Preloading) {
+        // too late - the thread already terminated or run as toolkit thread
+        return false;
+    }
+
+    if (pActionChain == NULL) {
+        // 1st action
+        pActionChain = pAction;
+    } else {
+        // add the action to the chain
+        PreloadAction *pChain = pActionChain;
+        while (true) {
+            PreloadAction *pNext = pChain->GetNext();
+            if (pNext == NULL) {
+                break;
+            }
+            pChain = pNext;
+        }
+        pChain->SetNext(pAction);
+    }
+
+    if (status > None) {
+        // the thread is already running (status == Preloading)
+        AwakeThread();
+        return true;
+    }
+
+    // need to start thread
+    ::ResetEvent(hAwake);
+    ::ResetEvent(hFinished);
+
+    HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0x100000, StaticThreadProc,
+                                            this, 0, &threadId);
+
+    if (hThread == 0) {
+        threadId = 0;
+        return false;
+    }
+
+    status = Preloading;
+
+    ::CloseHandle(hThread);
+
+    return true;
+}
+
+bool AwtToolkit::PreloadThread::Terminate(bool wrongThread)
+{
+    CriticalSection::Lock lock(threadLock);
+
+    if (status != Preloading) {
+        return false;
+    }
+
+    execFunc = NULL;
+    execParam = NULL;
+    this->wrongThread = wrongThread;
+    status = Cleaning;
+    AwakeThread();
+
+    return true;
+}
+
+bool AwtToolkit::PreloadThread::InvokeAndTerminate(void(_cdecl *fn)(void *), void *param)
+{
+    CriticalSection::Lock lock(threadLock);
+
+    if (status != Preloading) {
+        return false;
+    }
+
+    execFunc = fn;
+    execParam = param;
+    status = fn == NULL ? Cleaning : RunningToolkit;
+    AwakeThread();
+
+    return true;
+}
+
+/*static*/
+unsigned WINAPI AwtToolkit::PreloadThread::StaticThreadProc(void *param)
+{
+    AwtToolkit::PreloadThread *pThis = (AwtToolkit::PreloadThread *)param;
+    return pThis->ThreadProc();
+}
+
+unsigned AwtToolkit::PreloadThread::ThreadProc()
+{
+    void(_cdecl *_execFunc)(void *) = NULL;
+    void *_execParam = NULL;
+    bool _wrongThread = false;
+
+    // initialization
+    while (true) {
+        PreloadAction *pAction;
+        {
+            CriticalSection::Lock lock(threadLock);
+            if (status != Preloading) {
+                // get invoke parameters
+                _execFunc = execFunc;
+                _execParam = execParam;
+                _wrongThread = wrongThread;
+                break;
+            }
+            pAction = GetNextAction();
+        }
+        if (pAction != NULL) {
+            pAction->Init();
+        } else {
+            ::WaitForSingleObject(hAwake, INFINITE);
+        }
+    }
+
+    // call a function from InvokeAndTerminate
+    if (_execFunc != NULL) {
+        _execFunc(_execParam);
+    } else {
+        // time to terminate..
+    }
+
+    // cleanup
+    {
+        CriticalSection::Lock lock(threadLock);
+        pLastProcessedAction = NULL; // goto 1st action in the chain
+        status = Cleaning;
+    }
+    for (PreloadAction *pAction = GetNextAction(); pAction != NULL;
+            pAction = GetNextAction()) {
+        pAction->Clean(_wrongThread);
+    }
+
+    // don't clear threadId! it is used by PreloadAction::EnsureInited
+
+    {
+        CriticalSection::Lock lock(threadLock);
+        status = Finished;
+    }
+    ::SetEvent(hFinished);
+    return 0;
+}
+
+AwtToolkit::PreloadAction* AwtToolkit::PreloadThread::GetNextAction()
+{
+    CriticalSection::Lock lock(threadLock);
+    PreloadAction *pAction = (pLastProcessedAction == NULL)
+                                    ? pActionChain
+                                    : pLastProcessedAction->GetNext();
+    if (pAction != NULL) {
+        pLastProcessedAction = pAction;
+    }
+
+    return pAction;
+}
+
+
+extern "C" {
+
+/* Terminates preload thread (if it's still alive
+ * - it may occur if the application doesn't use AWT).
+ * The function is called from launcher after completion main java thread.
+ */
+__declspec(dllexport) void preloadStop()
+{
+    AwtToolkit::GetInstance().GetPreloadThread().Terminate(false);
+}
+
+}
+
+
 /************************************************************************
  * Toolkit native methods
  */
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.h	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.h	Wed Jul 05 17:26:57 2017 +0200
@@ -465,6 +465,151 @@
 
     void InstallMouseLowLevelHook();
     void UninstallMouseLowLevelHook();
+
+
+/* AWT preloading (early Toolkit thread start)
+ */
+public:
+    /* Toolkit preload action class.
+     * Preload actions should be registered with
+     * AwtToolkit::getInstance().GetPreloadThread().AddAction().
+     * AwtToolkit thread calls InitImpl method at the beghining
+     * and CleanImpl(false) before exiting for all registered actions.
+     * If an application provides own Toolkit thread
+     * (sun.awt.windows.WToolkit.embeddedInit), the thread calls Clean(true)
+     * for each action.
+     */
+    class PreloadThread;    // forward declaration
+    class PreloadAction {
+        friend class PreloadThread;
+    public:
+        PreloadAction() : initThreadId(0), pNext(NULL) {}
+        virtual ~PreloadAction() {}
+
+    protected:
+        // called by PreloadThread or as result
+        // of EnsureInited() call (on Toolkit thread!).
+        virtual void InitImpl() = 0;
+
+        // called by PreloadThread (before exiting).
+        // reInit == false: normal shutdown;
+        // reInit == true: PreloadThread is shutting down due external
+        //   Toolkit thread was provided.
+        virtual void CleanImpl(bool reInit) = 0;
+
+    public:
+        // Initialized the action on the Toolkit thread if not yet initialized.
+        bool EnsureInited();
+
+        // returns thread ID which the action was inited on (0 if not inited)
+        DWORD GetInitThreadID();
+
+        // Allows to deinitialize action earlier.
+        // The method must be called on the Toolkit thread only.
+        // returns true on success,
+        //         false if the action was inited on other thread.
+        bool Clean();
+
+    private:
+        unsigned initThreadId;
+        // lock for Init/Clean
+        CriticalSection initLock;
+
+        // Chain support (for PreloadThread)
+        PreloadAction *pNext;   // for action chain used by PreloadThread
+        void SetNext(PreloadAction *pNext) { this->pNext = pNext; }
+        PreloadAction *GetNext() { return pNext; }
+
+        // wrapper for AwtToolkit::InvokeFunction
+        static void InitWrapper(void *param);
+
+        void Init();
+        void Clean(bool reInit);
+
+    };
+
+    /** Toolkit preload thread class.
+     */
+    class PreloadThread {
+    public:
+        PreloadThread();
+        ~PreloadThread();
+
+        // adds action & start the thread if not yet started
+        bool AddAction(PreloadAction *pAction);
+
+        // sets termination flag; returns true if the thread is running.
+        // wrongThread specifies cause of the termination:
+        //   false means termination on the application shutdown;
+        // wrongThread is used as reInit parameter for action cleanup.
+        bool Terminate(bool wrongThread);
+        bool InvokeAndTerminate(void(_cdecl *fn)(void *), void *param);
+
+        // waits for the the thread completion;
+        // use the method after Terminate() only if Terminate() returned true
+        INLINE void Wait4Finish() {
+            ::WaitForSingleObject(hFinished, INFINITE);
+        }
+
+        INLINE unsigned GetThreadId() {
+            CriticalSection::Lock lock(threadLock);
+            return threadId;
+        }
+        INLINE bool IsWrongThread() {
+            CriticalSection::Lock lock(threadLock);
+            return wrongThread;
+        }
+
+    private:
+        // data access lock
+        CriticalSection threadLock;
+
+        // the thread status
+        enum Status {
+            None = -1,      // initial
+            Preloading = 0, // preloading in progress
+            RunningToolkit, // Running as Toolkit thread
+            Cleaning,       // exited from Toolkit thread proc, cleaning
+            Finished        //
+        } status;
+
+        // "wrong thread" flag
+        bool wrongThread;
+
+        // thread proc (calls (this)param->ThreadProc())
+        static unsigned WINAPI StaticThreadProc(void *param);
+        unsigned ThreadProc();
+
+        INLINE void AwakeThread() {
+            ::SetEvent(hAwake);
+        }
+
+        // if threadId != 0 -> we are running
+        unsigned threadId;
+        // ThreadProc sets the event on exit
+        HANDLE hFinished;
+        // ThreadProc waits on the event for NewAction/Terminate/InvokeAndTerminate
+        HANDLE hAwake;
+
+        // function/param to invoke (InvokeAndTerminate)
+        // if execFunc == NULL => just terminate
+        void(_cdecl *execFunc)(void *);
+        void *execParam;
+
+        // action chain
+        PreloadAction *pActionChain;
+        PreloadAction *pLastProcessedAction;
+
+        // returns next action in the list (NULL if no more actions)
+        PreloadAction* GetNextAction();
+
+    };
+
+    INLINE PreloadThread& GetPreloadThread() { return preloadThread; }
+
+private:
+    PreloadThread preloadThread;
+
 };
 
 
--- a/jdk/test/com/sun/crypto/provider/TLS/TestKeyMaterial.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/com/sun/crypto/provider/TLS/TestKeyMaterial.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -117,16 +117,23 @@
                 System.out.print(".");
                 n++;
 
-                KeyGenerator kg = KeyGenerator.getInstance("SunTlsKeyMaterial", provider);
-                SecretKey masterKey = new SecretKeySpec(master, "TlsMasterSecret");
-                TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec
-                (masterKey, major, minor, clientRandom, serverRandom, cipherAlgorithm,
-                keyLength, expandedKeyLength, ivLength, macLength);
+                KeyGenerator kg =
+                    KeyGenerator.getInstance("SunTlsKeyMaterial", provider);
+                SecretKey masterKey =
+                    new SecretKeySpec(master, "TlsMasterSecret");
+                TlsKeyMaterialParameterSpec spec =
+                    new TlsKeyMaterialParameterSpec(masterKey, major, minor,
+                        clientRandom, serverRandom, cipherAlgorithm,
+                        keyLength, expandedKeyLength, ivLength, macLength,
+                        null, -1, -1);
 
                 kg.init(spec);
-                TlsKeyMaterialSpec result = (TlsKeyMaterialSpec)kg.generateKey();
-                match(lineNumber, clientCipherBytes, result.getClientCipherKey());
-                match(lineNumber, serverCipherBytes, result.getServerCipherKey());
+                TlsKeyMaterialSpec result =
+                    (TlsKeyMaterialSpec)kg.generateKey();
+                match(lineNumber, clientCipherBytes,
+                    result.getClientCipherKey());
+                match(lineNumber, serverCipherBytes,
+                    result.getServerCipherKey());
                 match(lineNumber, clientIv, result.getClientIv());
                 match(lineNumber, serverIv, result.getServerIv());
                 match(lineNumber, clientMacBytes, result.getClientMacKey());
@@ -144,7 +151,8 @@
         System.out.println("OK: " + n + " tests");
     }
 
-    private static void match(int lineNumber, byte[] out, Object res) throws Exception {
+    private static void match(int lineNumber, byte[] out, Object res)
+            throws Exception {
         if ((out == null) || (res == null)) {
             if (out != res) {
                 throw new Exception("null mismatch line " + lineNumber);
--- a/jdk/test/com/sun/crypto/provider/TLS/TestMasterSecret.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/com/sun/crypto/provider/TLS/TestMasterSecret.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -97,17 +97,22 @@
                 System.out.print(".");
                 n++;
 
-                KeyGenerator kg = KeyGenerator.getInstance("SunTlsMasterSecret", provider);
-                SecretKey premasterKey = new SecretKeySpec(premaster, algorithm);
-                TlsMasterSecretParameterSpec spec = new TlsMasterSecretParameterSpec
-                    (premasterKey, protoMajor, protoMinor, clientRandom, serverRandom);
+                KeyGenerator kg =
+                    KeyGenerator.getInstance("SunTlsMasterSecret", provider);
+                SecretKey premasterKey =
+                    new SecretKeySpec(premaster, algorithm);
+                TlsMasterSecretParameterSpec spec =
+                    new TlsMasterSecretParameterSpec(premasterKey, protoMajor,
+                        protoMinor, clientRandom, serverRandom,
+                        null, -1, -1);
                 kg.init(spec);
                 TlsMasterSecret key = (TlsMasterSecret)kg.generateKey();
                 byte[] enc = key.getEncoded();
                 if (Arrays.equals(master, enc) == false) {
                     throw new Exception("mismatch line: " + lineNumber);
                 }
-                if ((preMajor != key.getMajorVersion()) || (preMinor != key.getMinorVersion())) {
+                if ((preMajor != key.getMajorVersion()) ||
+                        (preMinor != key.getMinorVersion())) {
                     throw new Exception("version mismatch line: " + lineNumber);
                 }
             } else {
--- a/jdk/test/com/sun/crypto/provider/TLS/TestPRF.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/com/sun/crypto/provider/TLS/TestPRF.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -85,14 +85,17 @@
                 System.out.print(".");
                 n++;
 
-                KeyGenerator kg = KeyGenerator.getInstance("SunTlsPrf", provider);
+                KeyGenerator kg =
+                    KeyGenerator.getInstance("SunTlsPrf", provider);
                 SecretKey inKey;
                 if (secret == null) {
                     inKey = null;
                 } else {
                     inKey = new SecretKeySpec(secret, "Generic");
                 }
-                TlsPrfParameterSpec spec = new TlsPrfParameterSpec(inKey, label, seed, length);
+                TlsPrfParameterSpec spec =
+                    new TlsPrfParameterSpec(inKey, label, seed, length,
+                        null, -1, -1);
                 kg.init(spec);
                 SecretKey key = kg.generateKey();
                 byte[] enc = key.getEncoded();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/TLS/TestPRF12.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2010, 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 6313661
+ * @summary Basic known-answer-test for TlsPrf 12
+ *
+ * Vector obtained from the IETF TLS working group mailing list:
+ *
+ *     http://www.ietf.org/mail-archive/web/tls/current/msg03416.html
+ */
+
+import java.io.*;
+import java.util.*;
+
+import java.security.Security;
+import java.security.Provider;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+import javax.crypto.spec.*;
+
+import sun.security.internal.spec.*;
+
+public class TestPRF12 extends Utils {
+
+    private static int PREFIX_LENGTH = "prf-output: ".length();
+
+    public static void main(String[] args) throws Exception {
+        Provider provider = Security.getProvider("SunJCE");
+
+        InputStream in = new FileInputStream(new File(BASE, "prf12data.txt"));
+        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+
+        int n = 0;
+        int lineNumber = 0;
+
+        byte[] secret = null;
+        String label = null;
+        byte[] seed = null;
+        int length = 0;
+        String prfAlg = null;
+        int prfHashLength = 0;
+        int prfBlockSize = 0;
+        byte[] output = null;
+
+        while (true) {
+            String line = reader.readLine();
+            lineNumber++;
+            if (line == null) {
+                break;
+            }
+            if (line.startsWith("prf-") == false) {
+                continue;
+            }
+
+            String data = line.substring(PREFIX_LENGTH);
+            if (line.startsWith("prf-secret:")) {
+                secret = parse(data);
+            } else if (line.startsWith("prf-label:")) {
+                label = data;
+            } else if (line.startsWith("prf-seed:")) {
+                seed = parse(data);
+            } else if (line.startsWith("prf-length:")) {
+                length = Integer.parseInt(data);
+            } else if (line.startsWith("prf-alg:")) {
+                prfAlg = data;
+                switch (prfAlg) {
+                case "SHA-224":
+                    prfHashLength = 28;
+                    prfBlockSize =  64;
+                    break;
+                case "SHA-256":
+                    prfHashLength = 32;
+                    prfBlockSize =  64;
+                    break;
+                case "SHA-384":
+                    prfHashLength = 48;
+                    prfBlockSize = 128;
+                    break;
+                case "SHA-512":
+                    prfHashLength = 64;
+                    prfBlockSize = 128;
+                    break;
+                default:
+                    throw new Exception("Unknown Alg in the data.");
+                }
+            } else if (line.startsWith("prf-output:")) {
+                output = parse(data);
+
+                System.out.print(".");
+                n++;
+
+                KeyGenerator kg =
+                    KeyGenerator.getInstance("SunTls12Prf", provider);
+                SecretKey inKey;
+                if (secret == null) {
+                    inKey = null;
+                } else {
+                    inKey = new SecretKeySpec(secret, "Generic");
+                }
+                TlsPrfParameterSpec spec =
+                    new TlsPrfParameterSpec(inKey, label, seed, length,
+                        prfAlg, prfHashLength, prfBlockSize);
+                kg.init(spec);
+                SecretKey key = kg.generateKey();
+                byte[] enc = key.getEncoded();
+                if (Arrays.equals(output, enc) == false) {
+                    throw new Exception("mismatch line: " + lineNumber);
+                }
+            } else {
+                throw new Exception("Unknown line: " + line);
+            }
+        }
+        if (n == 0) {
+            throw new Exception("no tests");
+        }
+        in.close();
+        System.out.println();
+        System.out.println("OK: " + n + " tests");
+    }
+
+}
--- a/jdk/test/com/sun/crypto/provider/TLS/TestPremaster.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/com/sun/crypto/provider/TLS/TestPremaster.java	Wed Jul 05 17:26:57 2017 +0200
@@ -60,7 +60,8 @@
         System.out.println("Done.");
     }
 
-    private static void test(KeyGenerator kg, int major, int minor) throws Exception {
+    private static void test(KeyGenerator kg, int major, int minor)
+            throws Exception {
 
         kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor));
         SecretKey key = kg.generateKey();
@@ -69,7 +70,8 @@
             throw new Exception("length: " + encoded.length);
         }
         if ((encoded[0] != major) || (encoded[1] != minor)) {
-            throw new Exception("version mismatch: "  + encoded[0] + "." + encoded[1]);
+            throw new Exception("version mismatch: "  + encoded[0] +
+                "." + encoded[1]);
         }
         System.out.println("OK: " + major + "." + minor);
     }
--- a/jdk/test/com/sun/crypto/provider/TLS/Utils.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/com/sun/crypto/provider/TLS/Utils.java	Wed Jul 05 17:26:57 2017 +0200
@@ -22,7 +22,6 @@
  */
 
 import java.io.*;
-import java.util.*;
 
 class Utils {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/TLS/prf12data.txt	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,19 @@
+prf-secret: 9b:be:43:6b:a9:40:f0:17:b1:76:52:84:9a:71:db:35
+prf-seed:   a0:ba:9f:93:6c:da:31:18:27:a6:f7:96:ff:d5:19:8c
+prf-label:  test label
+prf-length: 100
+prf-alg:    SHA-256
+prf-output: e3:f2:29:ba:72:7b:e1:7b:8d:12:26:20:55:7c:d4:53:c2:aa:b2:1d:07:c3:d4:95:32:9b:52:d4:e6:1e:db:5a:6b:30:17:91:e9:0d:35:c9:c9:a4:6b:4e:14:ba:f9:af:0f:a0:22:f7:07:7d:ef:17:ab:fd:37:97:c0:56:4b:ab:4f:bc:91:66:6e:9d:ef:9b:97:fc:e3:4f:79:67:89:ba:a4:80:82:d1:22:ee:42:c5:a7:2e:5a:51:10:ff:f7:01:87:34:7b:66
+prf-secret: b8:0b:73:3d:6c:ee:fc:dc:71:56:6e:a4:8e:55:67:df
+prf-seed:   cd:66:5c:f6:a8:44:7d:d6:ff:8b:27:55:5e:db:74:65
+prf-label:  test label
+prf-length: 148
+prf-alg:    SHA-384
+prf-output: 7b:0c:18:e9:ce:d4:10:ed:18:04:f2:cf:a3:4a:33:6a:1c:14:df:fb:49:00:bb:5f:d7:94:21:07:e8:1c:83:cd:e9:ca:0f:aa:60:be:9f:e3:4f:82:b1:23:3c:91:46:a0:e5:34:cb:40:0f:ed:27:00:88:4f:9d:c2:36:f8:0e:dd:8b:fa:96:11:44:c9:e8:d7:92:ec:a7:22:a7:b3:2f:c3:d4:16:d4:73:eb:c2:c5:fd:4a:bf:da:d0:5d:91:84:25:9b:5b:f8:cd:4d:90:fa:0d:31:e2:de:c4:79:e4:f1:a2:60:66:f2:ee:a9:a6:92:36:a3:e5:26:55:c9:e9:ae:e6:91:c8:f3:a2:68:54:30:8d:5e:aa:3b:e8:5e:09:90:70:3d:73:e5:6f
+prf-secret: b0:32:35:23:c1:85:35:99:58:4d:88:56:8b:bb:05:eb
+prf-seed:   d4:64:0e:12:e4:bc:db:fb:43:7f:03:e6:ae:41:8e:e5
+prf-label:  test label
+prf-length: 196
+prf-alg:    SHA-512
+prf-output: 12:61:f5:88:c7:98:c5:c2:01:ff:03:6e:7a:9c:b5:ed:cd:7f:e3:f9:4c:66:9a:12:2a:46:38:d7:d5:08:b2:83:04:2d:f6:78:98:75:c7:14:7e:90:6d:86:8b:c7:5c:45:e2:0e:b4:0c:1c:f4:a1:71:3b:27:37:1f:68:43:25:92:f7:dc:8e:a8:ef:22:3e:12:ea:85:07:84:13:11:bf:68:65:3d:0c:fc:40:56:d8:11:f0:25:c4:5d:df:a6:e6:fe:c7:02:f0:54:b4:09:d6:f2:8d:d0:a3:23:3e:49:8d:a4:1a:3e:75:c5:63:0e:ed:be:22:fe:25:4e:33:a1:b0:e9:f6:b9:82:66:75:be:c7:d0:1a:84:56:58:dc:9c:39:75:45:40:1d:40:b9:f4:6c:7a:40:0e:e1:b8:f8:1c:a0:a6:0d:1a:39:7a:10:28:bf:f5:d2:ef:50:66:12:68:42:fb:8d:a4:19:76:32:bd:b5:4f:f6:63:3f:86:bb:c8:36:e6:40:d4:d8:98
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/java_awt_BasicStroke.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010, 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 4358979
+ * @summary Tests BasicStroke encoding
+ * @author Sergey Malenkov
+ */
+
+import java.awt.BasicStroke;
+
+public final class java_awt_BasicStroke extends AbstractTest<BasicStroke> {
+    public static void main(String[] args) {
+        new java_awt_BasicStroke().test(true);
+    }
+
+    protected BasicStroke getObject() {
+        return new BasicStroke();
+    }
+
+    protected BasicStroke getAnotherObject() {
+        float[] f = {1.0f, 2.0f, 3.0f, 4.0f};
+        return new BasicStroke(f[1], BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, f[2], f, f[3]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/java_awt_GradientPaint.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2010, 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 4358979
+ * @summary Tests GradientPaint encoding
+ * @author Sergey Malenkov
+ */
+
+import java.awt.Color;
+import java.awt.GradientPaint;
+
+public final class java_awt_GradientPaint extends AbstractTest<GradientPaint> {
+    public static void main(String[] args) {
+        new java_awt_GradientPaint().test(true);
+    }
+
+    protected GradientPaint getObject() {
+        return new GradientPaint(0.1f, 0.2f, Color.BLACK, 0.3f, 0.4f, Color.WHITE, true);
+    }
+
+    protected GradientPaint getAnotherObject() {
+        return null; /* TODO: could not update property
+        return new GradientPaint(0.4f, 0.3f, Color.WHITE, 0.2f, 0.1f, Color.BLACK, false);*/
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/java_awt_LinearGradientPaint.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2010, 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 4358979
+ * @summary Tests LinearGradientPaint encoding
+ * @author Sergey Malenkov
+ */
+
+import java.awt.Color;
+import java.awt.LinearGradientPaint;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+
+import static java.awt.MultipleGradientPaint.ColorSpaceType.LINEAR_RGB;
+import static java.awt.MultipleGradientPaint.CycleMethod.REFLECT;
+
+public final class java_awt_LinearGradientPaint extends AbstractTest<LinearGradientPaint> {
+    public static void main(String[] args) {
+        new java_awt_LinearGradientPaint().test(true);
+    }
+
+    protected LinearGradientPaint getObject() {
+        float[] f = { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f };
+        Color[] c = { Color.BLUE, Color.GREEN, Color.RED, Color.BLUE, Color.GREEN, Color.RED };
+        return new LinearGradientPaint(f[0], f[1], f[2], f[3], f, c);
+    }
+
+    protected LinearGradientPaint getAnotherObject() {
+        return null; /* TODO: could not update property
+        float[] f = { 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f };
+        Color[] c = { Color.RED, Color.GREEN, Color.BLUE, Color.RED, Color.GREEN, Color.BLUE };
+        return new LinearGradientPaint(
+                new Point2D.Float(f[0], f[1]),
+                new Point2D.Float(f[2], f[3]),
+                f, c, REFLECT, LINEAR_RGB,
+                new AffineTransform(f));*/
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/java_awt_RadialGradientPaint.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2010, 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 4358979
+ * @summary Tests RadialGradientPaint encoding
+ * @author Sergey Malenkov
+ */
+
+import java.awt.Color;
+import java.awt.RadialGradientPaint;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+
+import static java.awt.MultipleGradientPaint.ColorSpaceType.LINEAR_RGB;
+import static java.awt.MultipleGradientPaint.CycleMethod.REFLECT;
+
+public final class java_awt_RadialGradientPaint extends AbstractTest<RadialGradientPaint> {
+    public static void main(String[] args) {
+        new java_awt_RadialGradientPaint().test(true);
+    }
+
+    protected RadialGradientPaint getObject() {
+        float[] f = { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f };
+        Color[] c = { Color.BLUE, Color.GREEN, Color.RED, Color.BLUE, Color.GREEN, Color.RED };
+        return new RadialGradientPaint(f[0], f[1], f[2], f, c);
+    }
+
+    protected RadialGradientPaint getAnotherObject() {
+        return null; /* TODO: could not update property
+        float[] f = { 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f };
+        Color[] c = { Color.RED, Color.GREEN, Color.BLUE, Color.RED, Color.GREEN, Color.BLUE };
+        return new RadialGradientPaint(
+                new Point2D.Float(f[0], f[1]), 100.0f,
+                new Point2D.Float(f[2], f[3]),
+                f, c, REFLECT, LINEAR_RGB,
+                new AffineTransform(f));*/
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/java_awt_geom_AffineTransform.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010, 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 4358979
+ * @summary Tests AffineTransform encoding
+ * @author Sergey Malenkov
+ */
+
+import java.awt.geom.AffineTransform;
+
+public final class java_awt_geom_AffineTransform extends AbstractTest<AffineTransform> {
+    public static void main(String[] args) {
+        new java_awt_geom_AffineTransform().test(true);
+    }
+
+    protected AffineTransform getObject() {
+        return new AffineTransform(0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f);
+    }
+
+    protected AffineTransform getAnotherObject() {
+        return new AffineTransform(0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/javax_swing_border_StrokeBorder.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010, 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 4358979
+ * @summary Tests StrokeBorder encoding
+ * @author Sergey Malenkov
+ */
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import javax.swing.border.StrokeBorder;
+
+public final class javax_swing_border_StrokeBorder extends AbstractTest<StrokeBorder> {
+    public static void main(String[] args) {
+        new javax_swing_border_StrokeBorder().test(true);
+    }
+
+    protected StrokeBorder getObject() {
+        return new StrokeBorder(new BasicStroke(0), Color.WHITE);
+    }
+
+    protected StrokeBorder getAnotherObject() {
+        return null; // TODO: could not update property
+        //return new StrokeBorder(new BasicStroke(1));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/dyn/ClassValueTest.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2010, 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
+ * @summary tests for class-specific values
+ * @compile ClassValueTest.java
+ * @run junit/othervm test.java.dyn.ClassValueTest
+ */
+
+/*
+  Manually:
+   $ $JAVA7X_HOME/bin/javac -d foo -cp $JUNIT4_JAR test/java/dyn/ClassValueTest.java
+   $ $JAVA7X_HOME/bin/java -cp foo:$JUNIT4_JAR org.junit.runner.JUnitCore test.java.dyn.ClassValueTest
+  Output: .testAdd => 1000 : Integer
+ */
+
+package test.java.dyn;
+
+import java.util.*;
+
+import java.dyn.*;
+
+import org.junit.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author jrose
+ */
+public class ClassValueTest {
+    static String nameForCV1(Class<?> type) {
+        return "CV1:" + type.getName();
+    }
+    static int countForCV1;
+    static final ClassValue<String> CV1 = new ClassValue<String>() {
+        protected String computeValue(Class<?> type) {
+            countForCV1++;
+            return nameForCV1(type);
+        }
+    };
+
+    static final Class[] CLASSES = {
+        String.class,
+        Integer.class,
+        int.class,
+        boolean[].class,
+        char[][].class,
+        ClassValueTest.class
+    };
+
+    @Test
+    public void testGet() {
+        countForCV1 = 0;
+        for (Class c : CLASSES) {
+            assertEquals(nameForCV1(c), CV1.get(c));
+        }
+        assertEquals(CLASSES.length, countForCV1);
+        for (Class c : CLASSES) {
+            assertEquals(nameForCV1(c), CV1.get(c));
+        }
+        assertEquals(CLASSES.length, countForCV1);
+    }
+
+    @Test
+    public void testRemove() {
+        for (Class c : CLASSES) {
+            CV1.get(c);
+        }
+        countForCV1 = 0;
+        int REMCOUNT = 3;
+        for (int i = 0; i < REMCOUNT; i++) {
+            CV1.remove(CLASSES[i]);
+        }
+        assertEquals(0, countForCV1);  // no change
+        for (Class c : CLASSES) {
+            assertEquals(nameForCV1(c), CV1.get(c));
+        }
+        assertEquals(REMCOUNT, countForCV1);
+    }
+
+    static String nameForCVN(Class<?> type, int n) {
+        return "CV[" + n + "]" + type.getName();
+    }
+    static int countForCVN;
+    static class CVN extends ClassValue<String> {
+        final int n;
+        CVN(int n) { this.n = n; }
+        protected String computeValue(Class<?> type) {
+            countForCVN++;
+            return nameForCVN(type, n);
+        }
+    };
+
+    @Test
+    public void testGetMany() {
+        int CVN_COUNT1 = 100, CVN_COUNT2 = 100;
+        CVN cvns[] = new CVN[CVN_COUNT1 * CVN_COUNT2];
+        for (int n = 0; n < cvns.length; n++) {
+            cvns[n] = new CVN(n);
+        }
+        countForCVN = 0;
+        for (int pass = 0; pass <= 2; pass++) {
+            for (int i1 = 0; i1 < CVN_COUNT1; i1++) {
+                eachClass:
+                for (Class c : CLASSES) {
+                    for (int i2 = 0; i2 < CVN_COUNT2; i2++) {
+                        int n = i1*CVN_COUNT2 + i2;
+                        assertEquals(0, countForCVN);
+                        assertEquals(nameForCVN(c, n), cvns[n].get(c));
+                        cvns[n].get(c);  //get it again
+                        //System.out.println("getting "+n+":"+cvns[n].get(c));
+                        boolean doremove = (((i1 + i2) & 3) == 0);
+                        switch (pass) {
+                        case 0:
+                            assertEquals(1, countForCVN);
+                            break;
+                        case 1:
+                            // remove on middle pass
+                            assertEquals(0, countForCVN);
+                            if (doremove) {
+                                //System.out.println("removing "+n+":"+cvns[n].get(c));
+                                cvns[n].remove(c);
+                                assertEquals(0, countForCVN);
+                            }
+                            break;
+                        case 2:
+                            assertEquals(doremove ? 1 : 0, countForCVN);
+                            break;
+                        }
+                        countForCVN = 0;
+                        if (i1 > i2 && i1 < i2+5)  continue eachClass;  // leave diagonal gap
+                    }
+                }
+            }
+        }
+        assertEquals(countForCVN, 0);
+        for (int n = 0; n < cvns.length; n++) {
+            for (Class c : CLASSES) {
+                assertEquals(nameForCVN(c, n), cvns[n].get(c));
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/dyn/JavaDocExamples.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2009, 2010, 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
+ * @summary example code used in javadoc for java.dyn API
+ * @compile -XDallowTransitionalJSR292=no JavaDocExamples.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.JavaDocExamples
+ */
+
+/*
+---- To run outside jtreg:
+$ $JAVA7X_HOME/bin/javac -cp $JUNIT4_JAR -d /tmp/Classes \
+   $DAVINCI/sources/jdk/test/java/dyn/JavaDocExamples.java
+$ $JAVA7X_HOME/bin/java   -cp $JUNIT4_JAR:/tmp/Classes \
+   -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles \
+   -Dtest.java.dyn.JavaDocExamples.verbosity=1 \
+     test.java.dyn.JavaDocExamples
+----
+*/
+
+package test.java.dyn;
+
+import java.dyn.*;
+import static java.dyn.MethodHandles.*;
+import static java.dyn.MethodType.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.junit.*;
+import static org.junit.Assert.*;
+import static org.junit.Assume.*;
+
+
+/**
+ * @author jrose
+ */
+public class JavaDocExamples {
+    /** Wrapper for running the JUnit tests in this module.
+     *  Put JUnit on the classpath!
+     */
+    public static void main(String... ignore) {
+        org.junit.runner.JUnitCore.runClasses(JavaDocExamples.class);
+    }
+    // How much output?
+    static int verbosity = Integer.getInteger("test.java.dyn.JavaDocExamples.verbosity", 0);
+
+{}
+static final private Lookup LOOKUP = lookup();
+// static final private MethodHandle CONCAT_1 = LOOKUP.findVirtual(String.class,
+//     "concat", methodType(String.class, String.class));
+// static final private MethodHandle HASHCODE_1 = LOOKUP.findVirtual(Object.class,
+//     "hashCode", methodType(int.class));
+
+// form required if NoAccessException is intercepted:
+static final private MethodHandle CONCAT_2, HASHCODE_2;
+static {
+  try {
+    CONCAT_2 = LOOKUP.findVirtual(String.class,
+      "concat", methodType(String.class, String.class));
+    HASHCODE_2 = LOOKUP.findVirtual(Object.class,
+      "hashCode", methodType(int.class));
+   } catch (NoAccessException ex) {
+     throw new RuntimeException(ex);
+   }
+}
+{}
+
+    @Test public void testFindVirtual() throws Throwable {
+{}
+MethodHandle CONCAT_3 = LOOKUP.findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+MethodHandle HASHCODE_3 = LOOKUP.findVirtual(Object.class,
+  "hashCode", methodType(int.class));
+//assertEquals("xy", (String) CONCAT_1.invokeExact("x", "y"));
+assertEquals("xy", (String) CONCAT_2.<String>invokeExact("x", "y"));
+assertEquals("xy", (String) CONCAT_3.<String>invokeExact("x", "y"));
+//assertEquals("xy".hashCode(), (int) HASHCODE_1.<int>invokeExact((Object)"xy"));
+assertEquals("xy".hashCode(), (int) HASHCODE_2.<int>invokeExact((Object)"xy"));
+assertEquals("xy".hashCode(), (int) HASHCODE_3.<int>invokeExact((Object)"xy"));
+{}
+    }
+    @Test public void testDropArguments() throws Throwable {
+        {{
+{} /// JAVADOC
+MethodHandle cat = lookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+cat = cat.asType(methodType(Object.class, String.class, String.class)); /*(String)*/
+assertEquals("xy", /*(String)*/ cat.invokeExact("x", "y"));
+MethodHandle d0 = dropArguments(cat, 0, String.class);
+assertEquals("yz", /*(String)*/ d0.invokeExact("x", "y", "z"));
+MethodHandle d1 = dropArguments(cat, 1, String.class);
+assertEquals("xz", /*(String)*/ d1.invokeExact("x", "y", "z"));
+MethodHandle d2 = dropArguments(cat, 2, String.class);
+assertEquals("xy", /*(String)*/ d2.invokeExact("x", "y", "z"));
+MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
+assertEquals("xz", /*(String)*/ d12.invokeExact("x", 12, true, "z"));
+            }}
+    }
+
+    static void assertEquals(Object exp, Object act) {
+        if (verbosity > 0)
+            System.out.println("result: "+act);
+        Assert.assertEquals(exp, act);
+    }
+}
--- a/jdk/test/java/dyn/MethodHandlesTest.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/java/dyn/MethodHandlesTest.java	Wed Jul 05 17:26:57 2017 +0200
@@ -265,6 +265,12 @@
 //            wrap = Wrapper.forWrapperType(dst);
 //        if (wrap != Wrapper.OBJECT)
 //            return wrap.wrap(nextArg++);
+        if (param.isInterface()) {
+            for (Class<?> c : param.getClasses()) {
+                if (param.isAssignableFrom(c) && !c.isInterface())
+                    { param = c; break; }
+            }
+        }
         if (param.isInterface() || param.isAssignableFrom(String.class))
             return "#"+nextArg();
         else
@@ -380,7 +386,7 @@
     }
     public static interface IntExample {
         public void            v0();
-        static class Impl implements IntExample {
+        public static class Impl implements IntExample {
             public void        v0()     { called("Int/v0", this); }
             final String name;
             public Impl() { name = "Impl#"+nextArg(); }
@@ -449,7 +455,7 @@
         countTest(positive);
         MethodType type = MethodType.methodType(ret, params);
         MethodHandle target = null;
-        RuntimeException noAccess = null;
+        Exception noAccess = null;
         try {
             if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
             target = lookup.findStatic(defc, name, type);
@@ -513,7 +519,7 @@
         String methodName = name.substring(1 + name.indexOf('/'));  // foo/bar => foo
         MethodType type = MethodType.methodType(ret, params);
         MethodHandle target = null;
-        RuntimeException noAccess = null;
+        Exception noAccess = null;
         try {
             if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
             target = lookup.findVirtual(defc, methodName, type);
@@ -567,7 +573,7 @@
         countTest(positive);
         MethodType type = MethodType.methodType(ret, params);
         MethodHandle target = null;
-        RuntimeException noAccess = null;
+        Exception noAccess = null;
         try {
             if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
             target = lookup.findSpecial(defc, name, type, specialCaller);
@@ -623,7 +629,7 @@
         MethodType type = MethodType.methodType(ret, params);
         Object receiver = randomArg(defc);
         MethodHandle target = null;
-        RuntimeException noAccess = null;
+        Exception noAccess = null;
         try {
             if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
             target = lookup.bind(receiver, methodName, type);
@@ -688,7 +694,7 @@
         MethodType type = MethodType.methodType(ret, params);
         Method rmethod = null;
         MethodHandle target = null;
-        RuntimeException noAccess = null;
+        Exception noAccess = null;
         try {
             rmethod = defc.getDeclaredMethod(name, params);
         } catch (NoSuchMethodException ex) {
@@ -1088,7 +1094,11 @@
             if (rtype != Object.class)
                 pfx = rtype.getSimpleName().substring(0, 1).toLowerCase();
             String name = pfx+"id";
-            return PRIVATE.findStatic(Callee.class, name, type);
+            try {
+                return PRIVATE.findStatic(Callee.class, name, type);
+            } catch (Exception ex) {
+                throw new RuntimeException(ex);
+            }
         }
     }
 
@@ -1327,7 +1337,8 @@
         MethodHandle result = MethodHandles.spreadArguments(target2, newType);
         Object[] returnValue;
         if (pos == 0) {
-            returnValue = (Object[]) result.invokeExact(args);
+            Object rawRetVal = result.invokeExact(args);
+            returnValue = (Object[]) rawRetVal;
         } else {
             Object[] args1 = Arrays.copyOfRange(args, 0, pos+1);
             args1[pos] = Arrays.copyOfRange(args, pos, args.length);
@@ -1817,8 +1828,13 @@
         testCastFailure("unbox/return", 11000);
     }
 
-    static class Surprise extends JavaMethodHandle {
-        Surprise() { super("value"); }
+    static class Surprise implements MethodHandleProvider {
+        public MethodHandle asMethodHandle() {
+            return VALUE.bindTo(this);
+        }
+        public MethodHandle asMethodHandle(MethodType type) {
+            return asMethodHandle().asType(type);
+        }
         Object value(Object x) {
             trace("value", x);
             if (boo != null)  return boo;
@@ -1833,22 +1849,32 @@
         static Object  refIdentity(Object x)  { trace("ref.x", x); return x; }
         static Integer boxIdentity(Integer x) { trace("box.x", x); return x; }
         static int     intIdentity(int x)     { trace("int.x", x); return x; }
-        static MethodHandle REF_IDENTITY = PRIVATE.findStatic(
-                Surprise.class, "refIdentity",
-                    MethodType.methodType(Object.class, Object.class));
-        static MethodHandle BOX_IDENTITY = PRIVATE.findStatic(
-                Surprise.class, "boxIdentity",
-                    MethodType.methodType(Integer.class, Integer.class));
-        static MethodHandle INT_IDENTITY = PRIVATE.findStatic(
-                Surprise.class, "intIdentity",
-                    MethodType.methodType(int.class, int.class));
+        static MethodHandle VALUE, REF_IDENTITY, BOX_IDENTITY, INT_IDENTITY;
+        static {
+            try {
+                VALUE = PRIVATE.findVirtual(
+                    Surprise.class, "value",
+                        MethodType.methodType(Object.class, Object.class));
+                REF_IDENTITY = PRIVATE.findStatic(
+                    Surprise.class, "refIdentity",
+                        MethodType.methodType(Object.class, Object.class));
+                BOX_IDENTITY = PRIVATE.findStatic(
+                    Surprise.class, "boxIdentity",
+                        MethodType.methodType(Integer.class, Integer.class));
+                INT_IDENTITY = PRIVATE.findStatic(
+                    Surprise.class, "intIdentity",
+                        MethodType.methodType(int.class, int.class));
+            } catch (Exception ex) {
+                throw new RuntimeException(ex);
+            }
+        }
     }
 
     void testCastFailure(String mode, int okCount) throws Throwable {
         countTest(false);
         if (verbosity > 2)  System.out.println("mode="+mode);
         Surprise boo = new Surprise();
-        MethodHandle identity = Surprise.REF_IDENTITY, surprise = boo;
+        MethodHandle identity = Surprise.REF_IDENTITY, surprise0 = boo.asMethodHandle(), surprise = surprise0;
         if (mode.endsWith("/return")) {
             if (mode.equals("unbox/return")) {
                 // fail on return to ((Integer)surprise).intValue
@@ -1874,7 +1900,7 @@
                 identity = MethodHandles.filterArguments(callee, identity);
             }
         }
-        assertNotSame(mode, surprise, boo);
+        assertNotSame(mode, surprise, surprise0);
         identity = MethodHandles.convertArguments(identity, MethodType.genericMethodType(1));
         surprise = MethodHandles.convertArguments(surprise, MethodType.genericMethodType(1));
         Object x = 42;
@@ -1936,6 +1962,107 @@
         mh.invokeVarargs(args);
         assertCalled(name, args);
     }
+
+    static void runForRunnable() {
+        called("runForRunnable");
+    }
+    private interface Fooable {
+        Object foo(Fooable x, Object y);
+        // this is for randomArg:
+        public class Impl implements Fooable {
+            public Object foo(Fooable x, Object y) {
+                throw new RuntimeException("do not call");
+            }
+            final String name;
+            public Impl() { name = "Fooable#"+nextArg(); }
+            @Override public String toString() { return name; }
+        }
+    }
+    static Object fooForFooable(Fooable x, Object y) {
+        return called("fooForFooable", x, y);
+    }
+    private static class MyCheckedException extends Exception {
+    }
+    private interface WillThrow {
+        void willThrow() throws MyCheckedException;
+    }
+
+    @Test
+    public void testAsInstance() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        Lookup lookup = MethodHandles.lookup();
+        {
+            MethodType mt = MethodType.methodType(void.class);
+            MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "runForRunnable", mt);
+            Runnable proxy = MethodHandles.asInstance(mh, Runnable.class);
+            proxy.run();
+            assertCalled("runForRunnable");
+        }
+        {
+            MethodType mt = MethodType.methodType(Object.class, Fooable.class, Object.class);
+            MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "fooForFooable", mt);
+            Fooable proxy = MethodHandles.asInstance(mh, Fooable.class);
+            Object[] args = randomArgs(mt.parameterArray());
+            Object result = proxy.foo((Fooable) args[0], args[1]);
+            assertCalled("fooForFooable", args);
+            assertEquals(result, logEntry("fooForFooable", args));
+        }
+        for (Throwable ex : new Throwable[] { new NullPointerException("ok"),
+                                              new InternalError("ok"),
+                                              new Throwable("fail"),
+                                              new Exception("fail"),
+                                              new MyCheckedException()
+                                            }) {
+            MethodHandle mh = MethodHandles.throwException(void.class, Throwable.class);
+            mh = MethodHandles.insertArguments(mh, 0, ex);
+            WillThrow proxy = MethodHandles.asInstance(mh, WillThrow.class);
+            try {
+                proxy.willThrow();
+                System.out.println("Failed to throw: "+ex);
+                assertTrue(false);
+            } catch (Throwable ex1) {
+                if (verbosity > 2) {
+                    System.out.println("throw "+ex);
+                    System.out.println("catch "+(ex == ex1 ? "UNWRAPPED" : ex1));
+                }
+                if (ex instanceof RuntimeException ||
+                    ex instanceof Error) {
+                    assertSame("must pass unchecked exception out without wrapping", ex, ex1);
+                } else if (ex instanceof MyCheckedException) {
+                    assertSame("must pass declared exception out without wrapping", ex, ex1);
+                } else {
+                    assertNotSame("must pass undeclared checked exception with wrapping", ex, ex1);
+                    UndeclaredThrowableException utex = (UndeclaredThrowableException) ex1;
+                    assertSame(ex, utex.getCause());
+                }
+            }
+        }
+        // Test error checking:
+        MethodHandle genericMH = ValueConversions.varargsArray(0);
+        genericMH = MethodHandles.convertArguments(genericMH, genericMH.type().generic());
+        for (Class<?> sam : new Class[] { Runnable.class,
+                                          Fooable.class,
+                                          Iterable.class }) {
+            try {
+                // Must throw, because none of these guys has generic type.
+                MethodHandles.asInstance(genericMH, sam);
+                System.out.println("Failed to throw");
+                assertTrue(false);
+            } catch (IllegalArgumentException ex) {
+            }
+        }
+        for (Class<?> nonSAM : new Class[] { Object.class,
+                                             String.class,
+                                             CharSequence.class,
+                                             Example.class }) {
+            try {
+                MethodHandles.asInstance(ValueConversions.varargsArray(0), nonSAM);
+                System.out.println("Failed to throw");
+                assertTrue(false);
+            } catch (IllegalArgumentException ex) {
+            }
+        }
+    }
 }
 // Local abbreviated copy of sun.dyn.util.ValueConversions
 class ValueConversions {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/StringBuilder/EnsureCapacity.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010, 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 6955504 6992121
+ * @summary Test the StringBuilder.ensureCapacity() with negative minimumCapacity
+ *    and append() method with negative length input argument.
+ *    Also, test the StringBuffer class.
+ */
+
+import java.util.ArrayList;
+import java.util.Vector;
+
+public class EnsureCapacity {
+    public static void main(String[] args) {
+        testStringBuilder();
+        testStringBuffer();
+    }
+
+    private static void checkCapacity(int before, int after) {
+        if (before != after) {
+            throw new RuntimeException("capacity is expected to be unchanged: " +
+                "before=" + before + " after=" + after);
+        }
+    }
+
+    private static void testStringBuilder() {
+        StringBuilder sb = new StringBuilder("abc");
+        int cap = sb.capacity();
+
+        // test if negative minimumCapacity
+        sb.ensureCapacity(Integer.MIN_VALUE);
+        checkCapacity(cap, sb.capacity());
+
+        try {
+            char[] str = {'a', 'b', 'c', 'd'};
+            // test if negative length
+            sb.append(str, 0, Integer.MIN_VALUE + 10);
+            throw new RuntimeException("IndexOutOfBoundsException not thrown");
+        } catch (IndexOutOfBoundsException ex) {
+        }
+    }
+
+    private static void testStringBuffer() {
+        StringBuffer sb = new StringBuffer("abc");
+        int cap = sb.capacity();
+
+        // test if negative minimumCapacity
+        sb.ensureCapacity(Integer.MIN_VALUE);
+        checkCapacity(cap, sb.capacity());
+
+        try {
+            char[] str = {'a', 'b', 'c', 'd'};
+            // test if negative length
+            sb.append(str, 0, Integer.MIN_VALUE + 10);
+            throw new RuntimeException("IndexOutOfBoundsException not thrown");
+        } catch (IndexOutOfBoundsException ex) {
+        }
+    }
+}
--- a/jdk/test/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java	Wed Jul 05 17:26:57 2017 +0200
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug     4959889
+ * @bug     4959889 6992968
  * @summary Basic unit test of memory management testing:
  *          1) setCollectionUsageThreshold() and getCollectionUsageThreshold()
  *          2) test notification emitted for two different memory pools.
@@ -34,8 +34,10 @@
  * @run main/timeout=300 CollectionUsageThreshold
  */
 
+import java.lang.Thread.*;
 import java.lang.management.*;
 import java.util.*;
+import java.util.concurrent.*;
 import javax.management.*;
 import javax.management.openmbean.CompositeData;
 
@@ -52,6 +54,12 @@
     private static Checker checker;
     private static int numGCs = 0;
 
+    // semaphore to signal the arrival of a low memory notification
+    private static Semaphore signals = new Semaphore(0);
+    // barrier for the main thread to wait until the checker thread
+    // finishes checking the low memory notification result
+    private static CyclicBarrier barrier = new CyclicBarrier(2);
+
     static class PoolRecord {
         private MemoryPoolMXBean pool;
         private int listenerInvoked = 0;
@@ -98,10 +106,9 @@
                 }
                 pr.addNotification(minfo);
                 synchronized (this) {
+                    System.out.println("notifying the checker thread to check result");
                     numNotifs++;
-                    if (numNotifs > 0 && (numNotifs % EXPECTED_NUM_POOLS) == 0) {
-                        checker.goCheckResult();
-                    }
+                    signals.release();
                 }
             }
         }
@@ -134,6 +141,9 @@
         }
 
         try {
+            // This test creates a checker thread responsible for checking
+            // the low memory notifications.  It blocks until a permit
+            // from the signals semaphore is available.
             checker = new Checker("Checker thread");
             checker.setDaemon(true);
             checker.start();
@@ -148,9 +158,18 @@
             NotificationEmitter emitter = (NotificationEmitter) mm;
             emitter.addNotificationListener(listener, null, null);
 
+            // The main thread invokes GC to trigger the VM to perform
+            // low memory detection and then waits until the checker thread
+            // finishes its work to check for a low-memory notification.
+            //
+            // At GC time, VM will issue low-memory notification and invoke
+            // the listener which will release a permit to the signals semaphore.
+            // When the checker thread acquires the permit and finishes
+            // checking the low-memory notification, it will also call
+            // barrier.await() to signal the main thread to resume its work.
             for (int i = 0; i < NUM_GCS; i++) {
                 invokeGC();
-                checker.waitForCheckResult();
+                barrier.await();
             }
         } finally {
             // restore the default
@@ -166,6 +185,7 @@
 
     }
 
+
     private static void invokeGC() {
         System.out.println("Calling System.gc()");
         numGCs++;
@@ -180,8 +200,6 @@
     }
 
     static class Checker extends Thread {
-        private Object lock = new Object();
-        private Object go = new Object();
         private boolean checkerReady = false;
         private int waiters = 0;
         private boolean readyToCheck = false;
@@ -190,83 +208,48 @@
         };
         public void run() {
             while (true) {
-                synchronized (lock) {
-                    checkerReady = true;
-                    try {
-                        lock.wait();
-                    } catch (InterruptedException e) {
-                        // ignore
-                    }
+                try {
+                    signals.acquire(EXPECTED_NUM_POOLS);
                     checkResult();
-                    checkerReady = false;
+                } catch (InterruptedException e) {
+                    throw new RuntimeException(e);
+                } catch (BrokenBarrierException e) {
+                    throw new RuntimeException(e);
                 }
             }
         }
-        private void checkResult() {
+        private void checkResult() throws InterruptedException, BrokenBarrierException {
             for (PoolRecord pr : result.values()) {
                 if (pr.getListenerInvokedCount() != numGCs) {
-                    throw new RuntimeException("Listeners invoked count = " +
+                    fail("Listeners invoked count = " +
                          pr.getListenerInvokedCount() + " expected to be " +
                          numGCs);
                 }
                 if (pr.getNotifCount() != numGCs) {
-                    throw new RuntimeException("Notif Count = " +
+                    fail("Notif Count = " +
                          pr.getNotifCount() + " expected to be " +
                          numGCs);
                 }
 
                 long count = pr.getPool().getCollectionUsageThresholdCount();
                 if (count != numGCs) {
-                    throw new RuntimeException("CollectionUsageThresholdCount = " +
+                    fail("CollectionUsageThresholdCount = " +
                          count + " expected to be " + numGCs);
                 }
                 if (!pr.getPool().isCollectionUsageThresholdExceeded()) {
-                    throw new RuntimeException("isCollectionUsageThresholdExceeded" +
+                    fail("isCollectionUsageThresholdExceeded" +
                          " expected to be true");
                 }
             }
-            synchronized (go) {
-                // wait until the main thread is waiting for notification
-                while (waiters == 0) {
-                    try {
-                        go.wait(50);
-                    } catch (InterruptedException e) {
-                        // ignore
-                    }
-                }
-
-                System.out.println(Thread.currentThread().getName() +
-                    " notifying main thread to continue - result checking finished");
-                go.notify();
-            }
-        }
-        public void goCheckResult() {
-            System.out.println(Thread.currentThread().getName() +
-                " notifying to check result");
-            synchronized (lock) {
-                while (!checkerReady) {
-                    try {
-                        lock.wait(50);
-                    } catch (InterruptedException e) {
-                        // ignore
-                    }
-                }
-                lock.notify();
-            }
+            // wait until the main thread is waiting for notification
+            barrier.await();
+            System.out.println("notifying main thread to continue - result checking finished");
         }
 
-        public void waitForCheckResult() {
-            System.out.println(Thread.currentThread().getName() +
-                " waiting for result checking finishes");
-            synchronized (go) {
-                waiters++;
-                try {
-                    go.wait();
-                } catch (InterruptedException e) {
-                    // ignore
-                }
-                waiters--;
-            }
+        private void fail(String msg) {
+            // reset the barrier to cause BrokenBarrierException to avoid hanging
+            barrier.reset();
+            throw new RuntimeException(msg);
         }
     }
 }
--- a/jdk/test/java/lang/management/MemoryMXBean/CollectionUsageThresholdConcMarkSweepGC.sh	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/java/lang/management/MemoryMXBean/CollectionUsageThresholdConcMarkSweepGC.sh	Wed Jul 05 17:26:57 2017 +0200
@@ -27,6 +27,7 @@
 # @summary Test CollectionUsageThreshold with concurrent marksweep collector
 # @author  Mandy Chung
 #
+# @ignore  6982965
 # @run build CollectionUsageThreshold
 # @run shell/timeout=300 CollectionUsageThresholdConcMarkSweepGC.sh
 #
--- a/jdk/test/java/nio/MappedByteBuffer/Basic.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/java/nio/MappedByteBuffer/Basic.java	Wed Jul 05 17:26:57 2017 +0200
@@ -24,7 +24,6 @@
 /* @test
  * @bug 4462336 6799037
  * @summary Simple MappedByteBuffer tests
- * @run main/othervm Basic
  */
 
 import java.io.*;
@@ -76,5 +75,10 @@
             throw new RuntimeException("Incorrect isReadOnly");
         fc.close();
         raf.close();
+
+        // clean-up
+        mbb = null;
+        System.gc();
+        Thread.sleep(500);
     }
 }
--- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Basic.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Basic.java	Wed Jul 05 17:26:57 2017 +0200
@@ -89,10 +89,9 @@
             }
             // create channel that is bound to group
             AsynchronousChannel ch;
-            switch (rand.nextInt(3)) {
+            switch (rand.nextInt(2)) {
                 case 0 : ch = AsynchronousSocketChannel.open(group); break;
                 case 1 : ch = AsynchronousServerSocketChannel.open(group); break;
-                case 2 : ch = AsynchronousDatagramChannel.open(null, group); break;
                 default : throw new AssertionError();
             }
             group.shutdown();
@@ -128,18 +127,9 @@
             }
 
             // I/O in progress
-            AsynchronousChannel ch;
-            if (rand.nextBoolean()) {
-                AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel
-                    .open(group).bind(new InetSocketAddress(0));
-                listener.accept();
-                ch = listener;
-            } else {
-                AsynchronousDatagramChannel adc =
-                    AsynchronousDatagramChannel.open(null, group);
-                adc.receive(ByteBuffer.allocate(100));
-                ch = adc;
-            }
+            AsynchronousServerSocketChannel ch = AsynchronousServerSocketChannel
+                .open(group).bind(new InetSocketAddress(0));
+            ch.accept();
 
             // forceful shutdown
             group.shutdownNow();
--- a/jdk/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,410 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 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 4527345 6842687
- * @summary Unit test for AsynchronousDatagramChannel
- */
-
-import java.nio.ByteBuffer;
-import java.nio.channels.*;
-import java.net.*;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.*;
-
-public class Basic {
-
-    public static void main(String[] args) throws Exception {
-        doReceiveTests();
-        doReadTests();
-        doSendTests();
-        doWriteTests();
-        doCancelTests();
-        doMulticastTests();
-    }
-
-    // basic receive tests
-    static void doReceiveTests() throws Exception {
-        final byte[] msg = "hello".getBytes();
-
-        AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open()
-            .bind(new InetSocketAddress(0));
-        int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort();
-        InetAddress rh = InetAddress.getLocalHost();
-        final SocketAddress sa = new InetSocketAddress(rh, port);
-
-        DatagramChannel sender = DatagramChannel.open();
-        ByteBuffer dst = ByteBuffer.allocateDirect(100);
-
-        // Test: datagram packet received immediately
-        sender.send(ByteBuffer.wrap(msg), sa);
-        dst.clear();
-        ch.receive(dst).get(1, TimeUnit.SECONDS);
-        if (dst.flip().remaining() != msg.length)
-            throw new RuntimeException("Unexpected number of bytes read");
-
-        // Test: datagram packet not received immediately
-        dst.clear();
-        final CountDownLatch latch = new CountDownLatch(1);
-        ch.receive(dst, (Void)null, new CompletionHandler<SocketAddress,Void>() {
-            public void completed(SocketAddress source, Void att) {
-                latch.countDown();
-            }
-            public void failed (Throwable exc, Void att) {
-            }
-        });
-        Thread.sleep(2000);
-        sender.send(ByteBuffer.wrap(msg), sa);
-        latch.await(2, TimeUnit.SECONDS);  // wait for completion handler
-
-        // Test: timeout
-        dst.clear();
-        final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();
-        ch.receive(dst, 2, TimeUnit.SECONDS, (Void)null, new CompletionHandler<SocketAddress,Void>() {
-            public void completed(SocketAddress source, Void att) {
-            }
-            public void failed (Throwable exc, Void att) {
-                exception.set(exc);
-            }
-        });
-        Throwable result;
-        while ((result = exception.get()) == null) {
-            Thread.sleep(100);
-        }
-        if (!(result instanceof InterruptedByTimeoutException))
-            throw new RuntimeException("InterruptedByTimeoutException expected");
-
-        // AsynchronousCloseException
-        dst = ByteBuffer.allocateDirect(100);
-        exception.set(null);
-        ch.receive(dst, (Void)null, new CompletionHandler<SocketAddress,Void>() {
-            public void completed(SocketAddress source, Void att) {
-            }
-            public void failed (Throwable exc, Void att) {
-                exception.set(exc);
-            }
-        });
-        ch.close();
-        while ((result = exception.get()) == null) {
-            Thread.sleep(100);
-        }
-        if (!(result instanceof AsynchronousCloseException))
-            throw new RuntimeException("AsynchronousCloseException expected");
-
-        // done
-        sender.close();
-    }
-
-    // basic read tests
-    static void doReadTests() throws Exception {
-        final byte[] msg = "hello".getBytes();
-
-        AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open()
-            .bind(new InetSocketAddress(0));
-        int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort();
-        InetAddress lh = InetAddress.getLocalHost();
-        final SocketAddress sa = new InetSocketAddress(lh, port);
-
-        DatagramChannel sender = DatagramChannel.open();
-        ByteBuffer dst = ByteBuffer.allocateDirect(100);
-
-        // Test: not connected
-        try {
-            ch.read(dst);
-            throw new RuntimeException("NotYetConnectedException expected");
-        } catch (NotYetConnectedException e) {
-        }
-
-        // connect the channel
-        sender.bind(new InetSocketAddress(0));
-        ch.connect(new InetSocketAddress(lh,
-                ((InetSocketAddress)(sender.getLocalAddress())).getPort()));
-
-        // Test: datagram packet received immediately
-        sender.send(ByteBuffer.wrap(msg), sa);
-        dst.clear();
-        ch.read(dst).get(1, TimeUnit.SECONDS);
-        if (dst.flip().remaining() != msg.length)
-            throw new RuntimeException("Unexpected number of bytes read");
-
-        // Test: datagram packet not received immediately
-        dst.clear();
-        final CountDownLatch l1 = new CountDownLatch(1);
-        ch.read(dst, (Void)null, new CompletionHandler<Integer,Void>() {
-            public void completed(Integer bytesRead, Void att) {
-                l1.countDown();
-            }
-            public void failed (Throwable exc, Void att) {
-            }
-        });
-        Thread.sleep(2000);
-        sender.send(ByteBuffer.wrap(msg), sa);
-        l1.await(2, TimeUnit.SECONDS);
-
-        // Test: timeout
-        dst.clear();
-        final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();
-        ch.read(dst, 2, TimeUnit.SECONDS, (Void)null, new CompletionHandler<Integer,Void>() {
-            public void completed(Integer bytesRead, Void att) {
-            }
-            public void failed (Throwable exc, Void att) {
-                exception.set(exc);
-            }
-        });
-        Throwable result;
-        while ((result = exception.get()) == null) {
-            Thread.sleep(100);
-        }
-        if (!(result instanceof InterruptedByTimeoutException))
-            throw new RuntimeException("InterruptedByTimeoutException expected");
-
-        // AsynchronousCloseException
-        dst.clear();
-        exception.set(null);
-        ch.read(dst, (Void)null, new CompletionHandler<Integer,Void>() {
-            public void completed(Integer bytesRead, Void att) {
-            }
-            public void failed (Throwable exc, Void att) {
-                exception.set(exc);
-            }
-        });
-        ch.close();
-        while ((result = exception.get()) == null) {
-            Thread.sleep(100);
-        }
-        if (!(result instanceof AsynchronousCloseException))
-            throw new RuntimeException("AsynchronousCloseException expected");
-
-        // done
-        sender.close();
-    }
-
-    // basic send tests
-    static void doSendTests() throws Exception {
-        final byte[] msg = "hello".getBytes();
-
-        DatagramChannel reader = DatagramChannel.open()
-            .bind(new InetSocketAddress(0));
-        int port = ((InetSocketAddress)(reader.getLocalAddress())).getPort();
-        InetAddress rh = InetAddress.getLocalHost();
-        SocketAddress sa = new InetSocketAddress(rh, port);
-
-        AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open();
-
-        // Test: send datagram packet to reader
-        int bytesSent = ch.send(ByteBuffer.wrap(msg), sa).get();
-        if (bytesSent != msg.length)
-            throw new RuntimeException("Unexpected number of bytes sent");
-
-        // check received
-        ByteBuffer dst = ByteBuffer.allocateDirect(100);
-        reader.receive(dst);
-        dst.flip();
-        if (dst.remaining() != msg.length)
-            throw new RuntimeException("Unexpected number of bytes received");
-
-        // Test: send datagram packet to reader and check completion handler
-        // is invoked
-        final CountDownLatch l2 = new CountDownLatch(1);
-        ch.send(ByteBuffer.wrap(msg), sa, (Void)null, new CompletionHandler<Integer,Void>() {
-            public void completed(Integer bytesSent, Void att) {
-                if (bytesSent != msg.length)
-                    throw new RuntimeException("Unexpected number of bytes received");
-                l2.countDown();
-            }
-            public void failed (Throwable exc, Void att) {
-            }
-        });
-        l2.await(5, TimeUnit.SECONDS);
-
-        // check received
-        dst.clear();
-        reader.receive(dst);
-        dst.flip();
-        if (dst.remaining() != msg.length)
-            throw new RuntimeException("Unexpected number of bytes received");
-
-        // Test: check that failed method is invoked
-        ch.close();
-        final CountDownLatch l3 = new CountDownLatch(1);
-        ch.send(ByteBuffer.wrap(msg), sa, (Void)null, new CompletionHandler<Integer,Void>() {
-            public void completed(Integer bytesSent, Void att) {
-                throw new RuntimeException("completed method invoked");
-            }
-            public void failed (Throwable exc, Void att) {
-                if (exc instanceof ClosedChannelException) {
-                    l3.countDown();
-                } else {
-                    throw new RuntimeException(exc);
-                }
-            }
-        });
-        l3.await(5, TimeUnit.SECONDS);
-
-        // done
-        reader.close();
-    }
-
-    // basic write tests
-    static void doWriteTests() throws Exception {
-        final byte[] msg = "hello".getBytes();
-
-        DatagramChannel reader = DatagramChannel.open()
-            .bind(new InetSocketAddress(0));
-        int port = ((InetSocketAddress)(reader.getLocalAddress())).getPort();
-        InetAddress rh = InetAddress.getLocalHost();
-        SocketAddress sa = new InetSocketAddress(rh, port);
-
-        AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open();
-
-        // Test: unconnected
-        try {
-            ch.write(ByteBuffer.wrap(msg)).get();
-            throw new RuntimeException("NotYetConnectedException expected");
-        } catch (NotYetConnectedException e) {
-        }
-
-        // Test: connect, and write datagram
-        ch.connect(sa);
-        int bytesSent = ch.write(ByteBuffer.wrap(msg)).get();
-        if (bytesSent != msg.length)
-            throw new RuntimeException("Unexpected number of bytes sent");
-
-        // check received
-        ByteBuffer dst = ByteBuffer.allocateDirect(100);
-        reader.receive(dst);
-        dst.flip();
-        if (dst.remaining() != msg.length)
-            throw new RuntimeException("Unexpected number of bytes received");
-
-        // Test: write datagram and check completion handler is invoked
-        final CountDownLatch l2 = new CountDownLatch(1);
-        ch.write(ByteBuffer.wrap(msg), (Void)null, new CompletionHandler<Integer,Void>() {
-            public void completed(Integer bytesSent, Void att) {
-                if (bytesSent != msg.length)
-                    throw new RuntimeException("Unexpected number of bytes received");
-                l2.countDown();
-            }
-            public void failed (Throwable exc, Void att) {
-            }
-        });
-        l2.await(5, TimeUnit.SECONDS);
-
-        // check received
-        dst.clear();
-        reader.receive(dst);
-        dst.flip();
-        if (dst.remaining() != msg.length)
-            throw new RuntimeException("Unexpected number of bytes received");
-
-        // done
-        ch.close();
-        reader.close();
-    }
-
-    static void cancelAndCheck(Future<?> result)
-        throws InterruptedException
-    {
-        boolean cancelled = result.cancel(false);
-        if (!cancelled)
-            throw new RuntimeException("Not cancelled");
-        if (!result.isDone())
-            throw new RuntimeException("Should be done");
-        try {
-            result.get();
-            throw new RuntimeException("Result not expected");
-        } catch (CancellationException e) {
-            // expected
-        } catch (ExecutionException e) {
-            throw new RuntimeException("Should not fail");
-        }
-    }
-
-    // basic cancel tests
-    static void doCancelTests() throws Exception {
-        InetAddress lh = InetAddress.getLocalHost();
-
-        // receive
-        for (int i=0; i<2; i++) {
-            AsynchronousDatagramChannel ch =
-                AsynchronousDatagramChannel.open().bind(new InetSocketAddress(0));
-            Future<SocketAddress> remote = ch.receive(ByteBuffer.allocate(100));
-            cancelAndCheck(remote);
-            ch.close();
-        }
-
-        // read
-        for (int i=0; i<2; i++) {
-            AsynchronousDatagramChannel ch =
-                AsynchronousDatagramChannel.open().bind(new InetSocketAddress(0));
-             ch.connect(new InetSocketAddress(lh,
-                ((InetSocketAddress)(ch.getLocalAddress())).getPort()));
-            final CountDownLatch latch = new CountDownLatch(1);
-            long timeout = (i == 0) ? 0L : 60L;
-            Future<Integer> result = ch.read(ByteBuffer.allocate(100));
-            cancelAndCheck(result);
-            ch.close();
-        }
-    }
-
-    // basic multicast test
-    static void doMulticastTests() throws Exception {
-        final byte[] msg = "hello".getBytes();
-
-        InetAddress lh = InetAddress.getLocalHost();
-        NetworkInterface interf = NetworkInterface.getByInetAddress(lh);
-        if (interf.isLoopback() || !interf.supportsMulticast()) {
-            System.out.println("Multicasting not tested");
-            return;
-        }
-
-        AsynchronousDatagramChannel ch = AsynchronousDatagramChannel
-            .open(StandardProtocolFamily.INET, null)
-            .setOption(StandardSocketOption.SO_REUSEADDR, true)
-            .bind(new InetSocketAddress(0));
-
-        int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort();
-
-        // join group
-        InetAddress group = InetAddress.getByName("225.4.5.6");
-        MembershipKey key = ch.join(group, interf);
-
-        // check key
-        if (key.channel() != ch)
-            throw new RuntimeException("Not the expected channel");
-
-        // send message to group
-        DatagramChannel sender = DatagramChannel.open();
-        sender.send(ByteBuffer.wrap(msg), new InetSocketAddress(group, port));
-        sender.close();
-
-        // check message received
-        ByteBuffer dst = ByteBuffer.allocate(200);
-        SocketAddress source = ch.receive(dst).get(2, TimeUnit.SECONDS);
-        if (!((InetSocketAddress)source).getAddress().equals(lh))
-            throw new RuntimeException("Unexpected source");
-
-        // done
-        ch.close();
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/channels/DatagramChannel/ChangingAddress.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010, 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 6431343
+ * @summary Test that DatagramChannel.getLocalAddress returns the right local
+ *    address after connect/disconnect.
+ */
+import java.net.*;
+import java.nio.channels.DatagramChannel;
+
+public class ChangingAddress {
+
+    // Checks that the given DatagramSocket and DatagramChannel are bound to the
+    // same local address.
+    static void check(DatagramSocket ds, DatagramChannel dc) {
+        InetAddress expected = ds.getLocalAddress();
+        InetAddress actual = dc.socket().getLocalAddress();
+        // okay if one bound to 0.0.0.0 and the other to ::0
+        if ((expected.isAnyLocalAddress() != actual.isAnyLocalAddress()) &&
+            !expected.equals(actual))
+        {
+            throw new RuntimeException("Expected: " + expected + ", actual: " + actual);
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        InetAddress lh = InetAddress.getLocalHost();
+        SocketAddress remote = new InetSocketAddress(lh, 1234);
+
+        DatagramSocket ds = null;
+        DatagramChannel dc = null;
+        try {
+
+            ds = new DatagramSocket();
+            dc = DatagramChannel.open().bind(new InetSocketAddress(0));
+            check(ds, dc);
+
+            ds.connect(remote);
+            dc.connect(remote);
+            check(ds, dc);
+
+            ds.disconnect();
+            dc.disconnect();
+            check(ds, dc);
+
+            // repeat tests using socket adapter
+            ds.connect(remote);
+            dc.socket().connect(remote);
+            check(ds, dc);
+
+            ds.disconnect();
+            dc.socket().disconnect();
+            check(ds, dc);
+
+       } finally {
+            if (ds != null) ds.close();
+            if (dc != null) dc.close();
+       }
+    }
+}
--- a/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/Provider1.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/Provider1.java	Wed Jul 05 17:26:57 2017 +0200
@@ -23,7 +23,6 @@
 
 import java.nio.channels.spi.AsynchronousChannelProvider;
 import java.nio.channels.*;
-import java.net.ProtocolFamily;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ThreadFactory;
 import java.io.IOException;
@@ -59,11 +58,4 @@
     {
         throw new RuntimeException();
     }
-
-    @Override
-    public AsynchronousDatagramChannel openAsynchronousDatagramChannel
-        (ProtocolFamily family, AsynchronousChannelGroup group) throws IOException
-    {
-        throw new RuntimeException();
-    }
 }
--- a/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/Provider2.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/Provider2.java	Wed Jul 05 17:26:57 2017 +0200
@@ -23,7 +23,6 @@
 
 import java.nio.channels.spi.AsynchronousChannelProvider;
 import java.nio.channels.*;
-import java.net.ProtocolFamily;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ThreadFactory;
 import java.io.IOException;
@@ -59,11 +58,4 @@
     {
         throw new RuntimeException();
     }
-
-    @Override
-    public AsynchronousDatagramChannel openAsynchronousDatagramChannel
-        (ProtocolFamily family, AsynchronousChannelGroup group) throws IOException
-    {
-        throw new RuntimeException();
-    }
 }
--- a/jdk/test/java/nio/file/Path/InterruptCopy.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/java/nio/file/Path/InterruptCopy.java	Wed Jul 05 17:26:57 2017 +0200
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4313887
+ * @bug 4313887 6993267
  * @summary Unit test for Sun-specific ExtendedCopyOption.INTERRUPTIBLE option
  * @library ..
  * @run main/othervm -XX:-UseVMInterruptibleIO InterruptCopy
@@ -36,8 +36,9 @@
 
 public class InterruptCopy {
 
-    private static final long FILE_SIZE_TO_COPY = 512 * 1024 * 1024;
+    private static final long FILE_SIZE_TO_COPY = 512L * 1024L * 1024L;
     private static final int DELAY_IN_MS = 500;
+    private static final int DURATION_MAX_IN_MS = 5000;
 
     public static void main(String[] args) throws Exception {
         Path dir = TestUtil.createTemporaryDirectory();
@@ -81,20 +82,27 @@
         try {
             // copy source to target in main thread, interrupting it after a delay
             final Thread me = Thread.currentThread();
-            pool.schedule(new Runnable() {
+            Future<?> wakeup = pool.schedule(new Runnable() {
                 public void run() {
                     me.interrupt();
                 }}, DELAY_IN_MS, TimeUnit.MILLISECONDS);
             System.out.println("Copying file...");
             try {
+                long start = System.currentTimeMillis();
                 source.copyTo(target, ExtendedCopyOption.INTERRUPTIBLE);
-                throw new RuntimeException("Copy completed (this is not expected)");
+                long duration = System.currentTimeMillis() - start;
+                if (duration > DURATION_MAX_IN_MS)
+                    throw new RuntimeException("Copy was not interrupted");
             } catch (IOException e) {
                 boolean interrupted = Thread.interrupted();
                 if (!interrupted)
                     throw new RuntimeException("Interrupt status was not set");
                 System.out.println("Copy failed (this is expected)");
             }
+            try {
+                wakeup.get();
+            } catch (InterruptedException ignore) { }
+            Thread.interrupted();
 
             // copy source to target via task in thread pool, interrupting it after
             // a delay using cancel(true)
@@ -113,7 +121,6 @@
             System.out.println("Copy cancelled.");
         } finally {
             pool.shutdown();
-            pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/ArrayList/EnsureCapacity.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2010, 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 6992121
+ * @summary Test the ArrayList.ensureCapacity() and Vector.ensureCapacity
+ *    method with negative minimumCapacity input argument.
+ */
+
+import java.util.ArrayList;
+import java.util.Vector;
+
+public class EnsureCapacity {
+    public static void main(String[] args) {
+        testArrayList();
+        testVector();
+    }
+
+    private static void checkCapacity(int before, int after) {
+        if (before != after) {
+            throw new RuntimeException("capacity is expected to be unchanged: " +
+                "before=" + before + " after=" + after);
+        }
+    }
+
+    private static void testArrayList() {
+        ArrayList<String> al = new ArrayList<String>();
+        al.add("abc");
+        al.ensureCapacity(Integer.MIN_VALUE);
+
+        // there is no method to query the capacity of ArrayList
+        // so before and after capacity are not checked
+    }
+
+    private static void testVector() {
+        Vector<String> vector = new Vector<String>();
+        vector.add("abc");
+
+        int cap = vector.capacity();
+        vector.ensureCapacity(Integer.MIN_VALUE);
+        checkCapacity(cap, vector.capacity());
+    }
+}
--- a/jdk/test/java/util/Locale/LocaleCategory.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/java/util/Locale/LocaleCategory.java	Wed Jul 05 17:26:57 2017 +0200
@@ -29,15 +29,28 @@
     private static String enc = null;
 
     public static void main(String[] args) {
-        base = new Locale(System.getProperty("user.language", ""),
-                          System.getProperty("user.country", ""),
-                          System.getProperty("user.variant", ""));
-        disp = new Locale(System.getProperty("user.language.display", ""),
-                          System.getProperty("user.country.display", ""),
-                          System.getProperty("user.variant.display", ""));
-        fmt  = new Locale(System.getProperty("user.language.format", ""),
-                          System.getProperty("user.country.format", ""),
-                          System.getProperty("user.variant.format", ""));
+        Locale.Builder builder = new Locale.Builder();
+
+        base = builder.setLanguage(System.getProperty("user.language", ""))
+                      .setScript(System.getProperty("user.script", ""))
+                      .setRegion(System.getProperty("user.country", ""))
+                      .setVariant(System.getProperty("user.variant", "")).build();
+        disp = builder.setLanguage(System.getProperty("user.language.display",
+                                                      Locale.getDefault().getLanguage()))
+                      .setScript(System.getProperty("user.script.display",
+                                                    Locale.getDefault().getScript()))
+                      .setRegion(System.getProperty("user.country.display",
+                                                    Locale.getDefault().getCountry()))
+                      .setVariant(System.getProperty("user.variant.display",
+                                                     Locale.getDefault().getVariant())).build();
+        fmt = builder.setLanguage(System.getProperty("user.language.format",
+                                                     Locale.getDefault().getLanguage()))
+                     .setScript(System.getProperty("user.script.format",
+                                                   Locale.getDefault().getScript()))
+                     .setRegion(System.getProperty("user.country.format",
+                                                   Locale.getDefault().getCountry()))
+                     .setVariant(System.getProperty("user.variant.format",
+                                                     Locale.getDefault().getVariant())).build();
         checkDefault();
         testGetSetDefault();
     }
--- a/jdk/test/java/util/Locale/LocaleCategory.sh	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/java/util/Locale/LocaleCategory.sh	Wed Jul 05 17:26:57 2017 +0200
@@ -1,7 +1,7 @@
 #!/bin/sh
 #
 # @test
-# @bug 4700857
+# @bug 4700857 6997928
 # @summary tests for Locale.getDefault(Locale.Category) and 
 #    Locale.setDefault(Locale.Category, Locale)
 # @build LocaleCategory
--- a/jdk/test/java/util/Locale/data/deflocale.rhel5	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/java/util/Locale/data/deflocale.rhel5	Wed Jul 05 17:26:57 2017 +0200
@@ -465,15 +465,15 @@
 default charset: UTF-8
 
 OS Locale:  be_BY.utf8@latin
-default locale: ID: be_BY, Name: Belarusian (Belarus)
-display locale: ID: be_BY, Name: Belarusian (Belarus)
-format locale: ID: be_BY, Name: Belarusian (Belarus)
+default locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
+display locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
+format locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
 default charset: UTF-8
 
 OS Locale:  be_BY@latin
-default locale: ID: be_BY, Name: Belarusian (Belarus)
-display locale: ID: be_BY, Name: Belarusian (Belarus)
-format locale: ID: be_BY, Name: Belarusian (Belarus)
+default locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
+display locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
+format locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
 default charset: UTF-8
 
 OS Locale:  bg_BG
@@ -518,18 +518,18 @@
 format locale: ID: bn_IN, Name: Bengali (India)
 default charset: UTF-8
 
+OS Locale:  bokmal
+default locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
+display locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
+format locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
+default charset: ISO-8859-1
+
 OS Locale:  bokmål
 default locale: ID: en, Name: English
 display locale: ID: en, Name: English
 format locale: ID: en, Name: English
 default charset: ISO-8859-1
 
-OS Locale:  bokmal
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
-default charset: ISO-8859-1
-
 OS Locale:  br_FR
 default locale: ID: br_FR, Name: Breton (France)
 display locale: ID: br_FR, Name: Breton (France)
@@ -579,15 +579,15 @@
 default charset: UTF-8
 
 OS Locale:  byn_ER
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: byn_ER, Name: Blin (Eritrea)
+display locale: ID: byn_ER, Name: Blin (Eritrea)
+format locale: ID: byn_ER, Name: Blin (Eritrea)
 default charset: UTF-8
 
 OS Locale:  byn_ER.utf8
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: byn_ER, Name: Blin (Eritrea)
+display locale: ID: byn_ER, Name: Blin (Eritrea)
+format locale: ID: byn_ER, Name: Blin (Eritrea)
 default charset: UTF-8
 
 OS Locale:  ca_AD
@@ -705,15 +705,15 @@
 default charset: UTF-8
 
 OS Locale:  csb_PL
-default locale: ID: en_PL, Name: English (Poland)
-display locale: ID: en_PL, Name: English (Poland)
-format locale: ID: en_PL, Name: English (Poland)
+default locale: ID: csb_PL, Name: Kashubian (Poland)
+display locale: ID: csb_PL, Name: Kashubian (Poland)
+format locale: ID: csb_PL, Name: Kashubian (Poland)
 default charset: UTF-8
 
 OS Locale:  csb_PL.utf8
-default locale: ID: en_PL, Name: English (Poland)
-display locale: ID: en_PL, Name: English (Poland)
-format locale: ID: en_PL, Name: English (Poland)
+default locale: ID: csb_PL, Name: Kashubian (Poland)
+display locale: ID: csb_PL, Name: Kashubian (Poland)
+format locale: ID: csb_PL, Name: Kashubian (Poland)
 default charset: UTF-8
 
 OS Locale:  cy_GB
@@ -939,9 +939,9 @@
 default charset: UTF-8
 
 OS Locale:  eesti
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: et_EE, Name: Estonian (Estonia)
+display locale: ID: et_EE, Name: Estonian (Estonia)
+format locale: ID: et_EE, Name: Estonian (Estonia)
 default charset: ISO-8859-1
 
 OS Locale:  el_CY
@@ -1623,9 +1623,9 @@
 default charset: UTF-8
 
 OS Locale:  estonian
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: et_EE, Name: Estonian (Estonia)
+display locale: ID: et_EE, Name: Estonian (Estonia)
+format locale: ID: et_EE, Name: Estonian (Estonia)
 default charset: ISO-8859-1
 
 OS Locale:  et_EE
@@ -1929,15 +1929,15 @@
 default charset: ISO-8859-15
 
 OS Locale:  galego
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: gl_ES, Name: Gallegan (Spain)
+display locale: ID: gl_ES, Name: Gallegan (Spain)
+format locale: ID: gl_ES, Name: Gallegan (Spain)
 default charset: ISO-8859-1
 
 OS Locale:  galician
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: gl_ES, Name: Gallegan (Spain)
+display locale: ID: gl_ES, Name: Gallegan (Spain)
+format locale: ID: gl_ES, Name: Gallegan (Spain)
 default charset: ISO-8859-1
 
 OS Locale:  gd_GB
@@ -1965,51 +1965,51 @@
 default charset: ISO-8859-1
 
 OS Locale:  gez_ER
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: gez_ER, Name: Geez (Eritrea)
+display locale: ID: gez_ER, Name: Geez (Eritrea)
+format locale: ID: gez_ER, Name: Geez (Eritrea)
 default charset: UTF-8
 
 OS Locale:  gez_ER.utf8
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: gez_ER, Name: Geez (Eritrea)
+display locale: ID: gez_ER, Name: Geez (Eritrea)
+format locale: ID: gez_ER, Name: Geez (Eritrea)
 default charset: UTF-8
 
 OS Locale:  gez_ER.utf8@abegede
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: gez_ER, Name: Geez (Eritrea)
+display locale: ID: gez_ER, Name: Geez (Eritrea)
+format locale: ID: gez_ER, Name: Geez (Eritrea)
 default charset: UTF-8
 
 OS Locale:  gez_ER@abegede
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: gez_ER, Name: Geez (Eritrea)
+display locale: ID: gez_ER, Name: Geez (Eritrea)
+format locale: ID: gez_ER, Name: Geez (Eritrea)
 default charset: UTF-8
 
 OS Locale:  gez_ET
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: gez_ET, Name: Geez (Ethiopia)
+display locale: ID: gez_ET, Name: Geez (Ethiopia)
+format locale: ID: gez_ET, Name: Geez (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  gez_ET.utf8
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: gez_ET, Name: Geez (Ethiopia)
+display locale: ID: gez_ET, Name: Geez (Ethiopia)
+format locale: ID: gez_ET, Name: Geez (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  gez_ET.utf8@abegede
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: gez_ET, Name: Geez (Ethiopia)
+display locale: ID: gez_ET, Name: Geez (Ethiopia)
+format locale: ID: gez_ET, Name: Geez (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  gez_ET@abegede
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: gez_ET, Name: Geez (Ethiopia)
+display locale: ID: gez_ET, Name: Geez (Ethiopia)
+format locale: ID: gez_ET, Name: Geez (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  gl_ES
@@ -2139,21 +2139,21 @@
 default charset: ISO-8859-2
 
 OS Locale:  hsb_DE
-default locale: ID: en_DE, Name: English (Germany)
-display locale: ID: en_DE, Name: English (Germany)
-format locale: ID: en_DE, Name: English (Germany)
+default locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+display locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
 default charset: ISO-8859-2
 
 OS Locale:  hsb_DE.iso88592
-default locale: ID: en_DE, Name: English (Germany)
-display locale: ID: en_DE, Name: English (Germany)
-format locale: ID: en_DE, Name: English (Germany)
+default locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+display locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
 default charset: ISO-8859-2
 
 OS Locale:  hsb_DE.utf8
-default locale: ID: en_DE, Name: English (Germany)
-display locale: ID: en_DE, Name: English (Germany)
-format locale: ID: en_DE, Name: English (Germany)
+default locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+display locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
 default charset: UTF-8
 
 OS Locale:  hu_HU
@@ -2445,15 +2445,15 @@
 default charset: UTF-8
 
 OS Locale:  korean
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: ko_KR, Name: Korean (South Korea)
+display locale: ID: ko_KR, Name: Korean (South Korea)
+format locale: ID: ko_KR, Name: Korean (South Korea)
 default charset: EUC-KR
 
 OS Locale:  korean.euc
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: ko_KR, Name: Korean (South Korea)
+display locale: ID: ko_KR, Name: Korean (South Korea)
+format locale: ID: ko_KR, Name: Korean (South Korea)
 default charset: EUC-KR
 
 OS Locale:  ku_TR
@@ -2523,9 +2523,9 @@
 default charset: UTF-8
 
 OS Locale:  lithuanian
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
+display locale: ID: lt_LT, Name: Lithuanian (Lithuania)
+format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
 default charset: ISO-8859-13
 
 OS Locale:  lo_LA
@@ -2577,15 +2577,15 @@
 default charset: UTF-8
 
 OS Locale:  mai_IN
-default locale: ID: en_IN, Name: English (India)
-display locale: ID: en_IN, Name: English (India)
-format locale: ID: en_IN, Name: English (India)
+default locale: ID: mai_IN, Name: Maithili (India)
+display locale: ID: mai_IN, Name: Maithili (India)
+format locale: ID: mai_IN, Name: Maithili (India)
 default charset: UTF-8
 
 OS Locale:  mai_IN.utf8
-default locale: ID: en_IN, Name: English (India)
-display locale: ID: en_IN, Name: English (India)
-format locale: ID: en_IN, Name: English (India)
+default locale: ID: mai_IN, Name: Maithili (India)
+display locale: ID: mai_IN, Name: Maithili (India)
+format locale: ID: mai_IN, Name: Maithili (India)
 default charset: UTF-8
 
 OS Locale:  mg_MG
@@ -2859,21 +2859,21 @@
 default charset: UTF-8
 
 OS Locale:  nso_ZA
-default locale: ID: en_ZA, Name: English (South Africa)
-display locale: ID: en_ZA, Name: English (South Africa)
-format locale: ID: en_ZA, Name: English (South Africa)
+default locale: ID: nso_ZA, Name: Pedi (South Africa)
+display locale: ID: nso_ZA, Name: Pedi (South Africa)
+format locale: ID: nso_ZA, Name: Pedi (South Africa)
 default charset: UTF-8
 
 OS Locale:  nso_ZA.utf8
-default locale: ID: en_ZA, Name: English (South Africa)
-display locale: ID: en_ZA, Name: English (South Africa)
-format locale: ID: en_ZA, Name: English (South Africa)
+default locale: ID: nso_ZA, Name: Pedi (South Africa)
+display locale: ID: nso_ZA, Name: Pedi (South Africa)
+format locale: ID: nso_ZA, Name: Pedi (South Africa)
 default charset: UTF-8
 
 OS Locale:  nynorsk
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
+display locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
+format locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
 default charset: ISO-8859-1
 
 OS Locale:  oc_FR
@@ -3147,15 +3147,15 @@
 default charset: UTF-8
 
 OS Locale:  sid_ET
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: sid_ET, Name: Sidamo (Ethiopia)
+display locale: ID: sid_ET, Name: Sidamo (Ethiopia)
+format locale: ID: sid_ET, Name: Sidamo (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  sid_ET.utf8
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: sid_ET, Name: Sidamo (Ethiopia)
+display locale: ID: sid_ET, Name: Sidamo (Ethiopia)
+format locale: ID: sid_ET, Name: Sidamo (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  sk_SK
@@ -3321,39 +3321,39 @@
 default charset: UTF-8
 
 OS Locale:  sr_ME
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_ME, Name: Serbian (Montenegro)
+display locale: ID: sr_ME, Name: Serbian (Montenegro)
+format locale: ID: sr_ME, Name: Serbian (Montenegro)
 default charset: UTF-8
 
 OS Locale:  sr_ME.utf8
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_ME, Name: Serbian (Montenegro)
+display locale: ID: sr_ME, Name: Serbian (Montenegro)
+format locale: ID: sr_ME, Name: Serbian (Montenegro)
 default charset: UTF-8
 
 OS Locale:  sr_RS
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_RS, Name: Serbian (Serbia)
+display locale: ID: sr_RS, Name: Serbian (Serbia)
+format locale: ID: sr_RS, Name: Serbian (Serbia)
 default charset: UTF-8
 
 OS Locale:  sr_RS.utf8
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_RS, Name: Serbian (Serbia)
+display locale: ID: sr_RS, Name: Serbian (Serbia)
+format locale: ID: sr_RS, Name: Serbian (Serbia)
 default charset: UTF-8
 
 OS Locale:  sr_RS.utf8@latin
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+display locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+format locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
 default charset: UTF-8
 
 OS Locale:  sr_RS@latin
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+display locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+format locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
 default charset: UTF-8
 
 OS Locale:  ss_ZA
@@ -3507,9 +3507,9 @@
 default charset: UTF-8
 
 OS Locale:  thai
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: th_TH, Name: Thai (Thailand)
+display locale: ID: th_TH, Name: Thai (Thailand)
+format locale: ID: th_TH, Name: Thai (Thailand)
 default charset: TIS-620
 
 OS Locale:  ti_ER
@@ -3537,15 +3537,15 @@
 default charset: UTF-8
 
 OS Locale:  tig_ER
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: tig_ER, Name: Tigre (Eritrea)
+display locale: ID: tig_ER, Name: Tigre (Eritrea)
+format locale: ID: tig_ER, Name: Tigre (Eritrea)
 default charset: UTF-8
 
 OS Locale:  tig_ER.utf8
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: tig_ER, Name: Tigre (Eritrea)
+display locale: ID: tig_ER, Name: Tigre (Eritrea)
+format locale: ID: tig_ER, Name: Tigre (Eritrea)
 default charset: UTF-8
 
 OS Locale:  tl_PH
@@ -3681,15 +3681,15 @@
 default charset: ISO-8859-1
 
 OS Locale:  uz_UZ.utf8@cyrillic
-default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-display locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+default locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
+display locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
+format locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 default charset: UTF-8
 
 OS Locale:  uz_UZ@cyrillic
-default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-display locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+default locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
+display locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
+format locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 default charset: UTF-8
 
 OS Locale:  ve_ZA
--- a/jdk/test/java/util/Locale/data/deflocale.rhel5.fmtasdefault	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/java/util/Locale/data/deflocale.rhel5.fmtasdefault	Wed Jul 05 17:26:57 2017 +0200
@@ -465,15 +465,15 @@
 default charset: UTF-8
 
 OS Locale:  be_BY.utf8@latin
-default locale: ID: be_BY, Name: Belarusian (Belarus)
-display locale: ID: be_BY, Name: Belarusian (Belarus)
-format locale: ID: be_BY, Name: Belarusian (Belarus)
+default locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
+display locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
+format locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
 default charset: UTF-8
 
 OS Locale:  be_BY@latin
-default locale: ID: be_BY, Name: Belarusian (Belarus)
-display locale: ID: be_BY, Name: Belarusian (Belarus)
-format locale: ID: be_BY, Name: Belarusian (Belarus)
+default locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
+display locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
+format locale: ID: be_BY_#Latn, Name: Belarusian (Latin,Belarus)
 default charset: UTF-8
 
 OS Locale:  bg_BG
@@ -518,18 +518,18 @@
 format locale: ID: bn_IN, Name: Bengali (India)
 default charset: UTF-8
 
+OS Locale:  bokmal
+default locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
+display locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
+format locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
+default charset: ISO-8859-1
+
 OS Locale:  bokmål
 default locale: ID: en, Name: English
 display locale: ID: en, Name: English
 format locale: ID: en, Name: English
 default charset: ISO-8859-1
 
-OS Locale:  bokmal
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
-default charset: ISO-8859-1
-
 OS Locale:  br_FR
 default locale: ID: br_FR, Name: Breton (France)
 display locale: ID: br_FR, Name: Breton (France)
@@ -579,15 +579,15 @@
 default charset: UTF-8
 
 OS Locale:  byn_ER
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: byn_ER, Name: Blin (Eritrea)
+display locale: ID: byn_ER, Name: Blin (Eritrea)
+format locale: ID: byn_ER, Name: Blin (Eritrea)
 default charset: UTF-8
 
 OS Locale:  byn_ER.utf8
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: byn_ER, Name: Blin (Eritrea)
+display locale: ID: byn_ER, Name: Blin (Eritrea)
+format locale: ID: byn_ER, Name: Blin (Eritrea)
 default charset: UTF-8
 
 OS Locale:  ca_AD
@@ -705,15 +705,15 @@
 default charset: UTF-8
 
 OS Locale:  csb_PL
-default locale: ID: en_PL, Name: English (Poland)
-display locale: ID: en_PL, Name: English (Poland)
-format locale: ID: en_PL, Name: English (Poland)
+default locale: ID: csb_PL, Name: Kashubian (Poland)
+display locale: ID: csb_PL, Name: Kashubian (Poland)
+format locale: ID: csb_PL, Name: Kashubian (Poland)
 default charset: UTF-8
 
 OS Locale:  csb_PL.utf8
-default locale: ID: en_PL, Name: English (Poland)
-display locale: ID: en_PL, Name: English (Poland)
-format locale: ID: en_PL, Name: English (Poland)
+default locale: ID: csb_PL, Name: Kashubian (Poland)
+display locale: ID: csb_PL, Name: Kashubian (Poland)
+format locale: ID: csb_PL, Name: Kashubian (Poland)
 default charset: UTF-8
 
 OS Locale:  cy_GB
@@ -939,9 +939,9 @@
 default charset: UTF-8
 
 OS Locale:  eesti
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: et_EE, Name: Estonian (Estonia)
+display locale: ID: et_EE, Name: Estonian (Estonia)
+format locale: ID: et_EE, Name: Estonian (Estonia)
 default charset: ISO-8859-1
 
 OS Locale:  el_CY
@@ -1623,9 +1623,9 @@
 default charset: UTF-8
 
 OS Locale:  estonian
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: et_EE, Name: Estonian (Estonia)
+display locale: ID: et_EE, Name: Estonian (Estonia)
+format locale: ID: et_EE, Name: Estonian (Estonia)
 default charset: ISO-8859-1
 
 OS Locale:  et_EE
@@ -1929,15 +1929,15 @@
 default charset: ISO-8859-15
 
 OS Locale:  galego
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: gl_ES, Name: Gallegan (Spain)
+display locale: ID: gl_ES, Name: Gallegan (Spain)
+format locale: ID: gl_ES, Name: Gallegan (Spain)
 default charset: ISO-8859-1
 
 OS Locale:  galician
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: gl_ES, Name: Gallegan (Spain)
+display locale: ID: gl_ES, Name: Gallegan (Spain)
+format locale: ID: gl_ES, Name: Gallegan (Spain)
 default charset: ISO-8859-1
 
 OS Locale:  gd_GB
@@ -1965,51 +1965,51 @@
 default charset: ISO-8859-1
 
 OS Locale:  gez_ER
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: gez_ER, Name: Geez (Eritrea)
+display locale: ID: gez_ER, Name: Geez (Eritrea)
+format locale: ID: gez_ER, Name: Geez (Eritrea)
 default charset: UTF-8
 
 OS Locale:  gez_ER.utf8
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: gez_ER, Name: Geez (Eritrea)
+display locale: ID: gez_ER, Name: Geez (Eritrea)
+format locale: ID: gez_ER, Name: Geez (Eritrea)
 default charset: UTF-8
 
 OS Locale:  gez_ER.utf8@abegede
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: gez_ER, Name: Geez (Eritrea)
+display locale: ID: gez_ER, Name: Geez (Eritrea)
+format locale: ID: gez_ER, Name: Geez (Eritrea)
 default charset: UTF-8
 
 OS Locale:  gez_ER@abegede
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: gez_ER, Name: Geez (Eritrea)
+display locale: ID: gez_ER, Name: Geez (Eritrea)
+format locale: ID: gez_ER, Name: Geez (Eritrea)
 default charset: UTF-8
 
 OS Locale:  gez_ET
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: gez_ET, Name: Geez (Ethiopia)
+display locale: ID: gez_ET, Name: Geez (Ethiopia)
+format locale: ID: gez_ET, Name: Geez (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  gez_ET.utf8
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: gez_ET, Name: Geez (Ethiopia)
+display locale: ID: gez_ET, Name: Geez (Ethiopia)
+format locale: ID: gez_ET, Name: Geez (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  gez_ET.utf8@abegede
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: gez_ET, Name: Geez (Ethiopia)
+display locale: ID: gez_ET, Name: Geez (Ethiopia)
+format locale: ID: gez_ET, Name: Geez (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  gez_ET@abegede
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: gez_ET, Name: Geez (Ethiopia)
+display locale: ID: gez_ET, Name: Geez (Ethiopia)
+format locale: ID: gez_ET, Name: Geez (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  gl_ES
@@ -2139,21 +2139,21 @@
 default charset: ISO-8859-2
 
 OS Locale:  hsb_DE
-default locale: ID: en_DE, Name: English (Germany)
-display locale: ID: en_DE, Name: English (Germany)
-format locale: ID: en_DE, Name: English (Germany)
+default locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+display locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
 default charset: ISO-8859-2
 
 OS Locale:  hsb_DE.iso88592
-default locale: ID: en_DE, Name: English (Germany)
-display locale: ID: en_DE, Name: English (Germany)
-format locale: ID: en_DE, Name: English (Germany)
+default locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+display locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
 default charset: ISO-8859-2
 
 OS Locale:  hsb_DE.utf8
-default locale: ID: en_DE, Name: English (Germany)
-display locale: ID: en_DE, Name: English (Germany)
-format locale: ID: en_DE, Name: English (Germany)
+default locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+display locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
 default charset: UTF-8
 
 OS Locale:  hu_HU
@@ -2445,15 +2445,15 @@
 default charset: UTF-8
 
 OS Locale:  korean
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: ko_KR, Name: Korean (South Korea)
+display locale: ID: ko_KR, Name: Korean (South Korea)
+format locale: ID: ko_KR, Name: Korean (South Korea)
 default charset: EUC-KR
 
 OS Locale:  korean.euc
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: ko_KR, Name: Korean (South Korea)
+display locale: ID: ko_KR, Name: Korean (South Korea)
+format locale: ID: ko_KR, Name: Korean (South Korea)
 default charset: EUC-KR
 
 OS Locale:  ku_TR
@@ -2523,9 +2523,9 @@
 default charset: UTF-8
 
 OS Locale:  lithuanian
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
+display locale: ID: lt_LT, Name: Lithuanian (Lithuania)
+format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
 default charset: ISO-8859-13
 
 OS Locale:  lo_LA
@@ -2577,15 +2577,15 @@
 default charset: UTF-8
 
 OS Locale:  mai_IN
-default locale: ID: en_IN, Name: English (India)
-display locale: ID: en_IN, Name: English (India)
-format locale: ID: en_IN, Name: English (India)
+default locale: ID: mai_IN, Name: Maithili (India)
+display locale: ID: mai_IN, Name: Maithili (India)
+format locale: ID: mai_IN, Name: Maithili (India)
 default charset: UTF-8
 
 OS Locale:  mai_IN.utf8
-default locale: ID: en_IN, Name: English (India)
-display locale: ID: en_IN, Name: English (India)
-format locale: ID: en_IN, Name: English (India)
+default locale: ID: mai_IN, Name: Maithili (India)
+display locale: ID: mai_IN, Name: Maithili (India)
+format locale: ID: mai_IN, Name: Maithili (India)
 default charset: UTF-8
 
 OS Locale:  mg_MG
@@ -2859,21 +2859,21 @@
 default charset: UTF-8
 
 OS Locale:  nso_ZA
-default locale: ID: en_ZA, Name: English (South Africa)
-display locale: ID: en_ZA, Name: English (South Africa)
-format locale: ID: en_ZA, Name: English (South Africa)
+default locale: ID: nso_ZA, Name: Pedi (South Africa)
+display locale: ID: nso_ZA, Name: Pedi (South Africa)
+format locale: ID: nso_ZA, Name: Pedi (South Africa)
 default charset: UTF-8
 
 OS Locale:  nso_ZA.utf8
-default locale: ID: en_ZA, Name: English (South Africa)
-display locale: ID: en_ZA, Name: English (South Africa)
-format locale: ID: en_ZA, Name: English (South Africa)
+default locale: ID: nso_ZA, Name: Pedi (South Africa)
+display locale: ID: nso_ZA, Name: Pedi (South Africa)
+format locale: ID: nso_ZA, Name: Pedi (South Africa)
 default charset: UTF-8
 
 OS Locale:  nynorsk
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
+display locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
+format locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
 default charset: ISO-8859-1
 
 OS Locale:  oc_FR
@@ -3147,15 +3147,15 @@
 default charset: UTF-8
 
 OS Locale:  sid_ET
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: sid_ET, Name: Sidamo (Ethiopia)
+display locale: ID: sid_ET, Name: Sidamo (Ethiopia)
+format locale: ID: sid_ET, Name: Sidamo (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  sid_ET.utf8
-default locale: ID: en_ET, Name: English (Ethiopia)
-display locale: ID: en_ET, Name: English (Ethiopia)
-format locale: ID: en_ET, Name: English (Ethiopia)
+default locale: ID: sid_ET, Name: Sidamo (Ethiopia)
+display locale: ID: sid_ET, Name: Sidamo (Ethiopia)
+format locale: ID: sid_ET, Name: Sidamo (Ethiopia)
 default charset: UTF-8
 
 OS Locale:  sk_SK
@@ -3321,39 +3321,39 @@
 default charset: UTF-8
 
 OS Locale:  sr_ME
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_ME, Name: Serbian (Montenegro)
+display locale: ID: sr_ME, Name: Serbian (Montenegro)
+format locale: ID: sr_ME, Name: Serbian (Montenegro)
 default charset: UTF-8
 
 OS Locale:  sr_ME.utf8
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_ME, Name: Serbian (Montenegro)
+display locale: ID: sr_ME, Name: Serbian (Montenegro)
+format locale: ID: sr_ME, Name: Serbian (Montenegro)
 default charset: UTF-8
 
 OS Locale:  sr_RS
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_RS, Name: Serbian (Serbia)
+display locale: ID: sr_RS, Name: Serbian (Serbia)
+format locale: ID: sr_RS, Name: Serbian (Serbia)
 default charset: UTF-8
 
 OS Locale:  sr_RS.utf8
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_RS, Name: Serbian (Serbia)
+display locale: ID: sr_RS, Name: Serbian (Serbia)
+format locale: ID: sr_RS, Name: Serbian (Serbia)
 default charset: UTF-8
 
 OS Locale:  sr_RS.utf8@latin
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+display locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+format locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
 default charset: UTF-8
 
 OS Locale:  sr_RS@latin
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+display locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+format locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
 default charset: UTF-8
 
 OS Locale:  ss_ZA
@@ -3507,9 +3507,9 @@
 default charset: UTF-8
 
 OS Locale:  thai
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+default locale: ID: th_TH, Name: Thai (Thailand)
+display locale: ID: th_TH, Name: Thai (Thailand)
+format locale: ID: th_TH, Name: Thai (Thailand)
 default charset: TIS-620
 
 OS Locale:  ti_ER
@@ -3537,15 +3537,15 @@
 default charset: UTF-8
 
 OS Locale:  tig_ER
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: tig_ER, Name: Tigre (Eritrea)
+display locale: ID: tig_ER, Name: Tigre (Eritrea)
+format locale: ID: tig_ER, Name: Tigre (Eritrea)
 default charset: UTF-8
 
 OS Locale:  tig_ER.utf8
-default locale: ID: en_ER, Name: English (Eritrea)
-display locale: ID: en_ER, Name: English (Eritrea)
-format locale: ID: en_ER, Name: English (Eritrea)
+default locale: ID: tig_ER, Name: Tigre (Eritrea)
+display locale: ID: tig_ER, Name: Tigre (Eritrea)
+format locale: ID: tig_ER, Name: Tigre (Eritrea)
 default charset: UTF-8
 
 OS Locale:  tl_PH
@@ -3681,15 +3681,15 @@
 default charset: ISO-8859-1
 
 OS Locale:  uz_UZ.utf8@cyrillic
-default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-display locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+default locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
+display locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
+format locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 default charset: UTF-8
 
 OS Locale:  uz_UZ@cyrillic
-default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-display locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+default locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
+display locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
+format locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 default charset: UTF-8
 
 OS Locale:  ve_ZA
--- a/jdk/test/java/util/Locale/data/deflocale.sol10	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/java/util/Locale/data/deflocale.sol10	Wed Jul 05 17:26:57 2017 +0200
@@ -1128,9 +1128,9 @@
 default charset: ISO-8859-1
 
 OS Locale:  no_NY
-default locale: ID: no_, Name: Norwegian ()
-display locale: ID: no_, Name: Norwegian ()
-format locale: ID: no_, Name: Norwegian ()
+default locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
+display locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
+format locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
 default charset: ISO-8859-1
 
 OS Locale:  nr
@@ -1332,9 +1332,9 @@
 default charset: ISO-8859-2
 
 OS Locale:  sr_SP
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+display locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
 default charset: ISO-8859-5
 
 OS Locale:  sr_YU
@@ -1721,5 +1721,5 @@
 OS Locale (LC_CTYPE: C, LC_MESSAGES: zh_CN.UTF-8)
 default locale: ID: zh_CN, Name: Chinese (China)
 display locale: ID: zh_CN, Name: Chinese (China)
-format locale: ID: en, Name: English
+format locale: ID: en_CN, Name: English (China)
 default charset: US-ASCII
--- a/jdk/test/java/util/Locale/data/deflocale.sol10.fmtasdefault	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/java/util/Locale/data/deflocale.sol10.fmtasdefault	Wed Jul 05 17:26:57 2017 +0200
@@ -1128,9 +1128,9 @@
 default charset: ISO-8859-1
 
 OS Locale:  no_NY
-default locale: ID: no_, Name: Norwegian ()
-display locale: ID: no_, Name: Norwegian ()
-format locale: ID: no_, Name: Norwegian ()
+default locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
+display locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
+format locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
 default charset: ISO-8859-1
 
 OS Locale:  nr
@@ -1332,9 +1332,9 @@
 default charset: ISO-8859-2
 
 OS Locale:  sr_SP
-default locale: ID: sr, Name: Serbian
-display locale: ID: sr, Name: Serbian
-format locale: ID: sr, Name: Serbian
+default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+display locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
 default charset: ISO-8859-5
 
 OS Locale:  sr_YU
--- a/jdk/test/java/util/Locale/data/deflocale.win7	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/java/util/Locale/data/deflocale.win7	Wed Jul 05 17:26:57 2017 +0200
@@ -1,1493 +1,1493 @@
-# OSVersionInfo
-# MajorVersion: 6
-# MinorVersion: 1
-# BuildNumber: 7600
-# CSDVersion: 
-
-
-OS Locale (lcid: 7f, name: ): Invariant Language (Invariant Country) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 401, name: ar-SA): Arabic (Saudi Arabia) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
-default charset: windows-1252
-
-OS Locale (lcid: 402, name: bg-BG): Bulgarian (Bulgaria) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
-default charset: windows-1252
-
-OS Locale (lcid: 403, name: ca-ES): Catalan (Spain) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ca_ES, Name: Catalan (Spain)
-default charset: windows-1252
-
-OS Locale (lcid: 404, name: zh-TW): Chinese (Traditional) (Taiwan) - 950
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: zh_TW, Name: Chinese (Taiwan)
-default charset: windows-1252
-
-OS Locale (lcid: 405, name: cs-CZ): Czech (Czech Republic) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: cs_CZ, Name: Czech (Czech Republic)
-default charset: windows-1252
-
-OS Locale (lcid: 406, name: da-DK): Danish (Denmark) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: da_DK, Name: Danish (Denmark)
-default charset: windows-1252
-
-OS Locale (lcid: 407, name: de-DE): German (Germany) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: de_DE, Name: German (Germany)
-default charset: windows-1252
-
-OS Locale (lcid: 408, name: el-GR): Greek (Greece) - 1253
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: el_GR, Name: Greek (Greece)
-default charset: windows-1252
-
-OS Locale (lcid: 409, name: en-US): English (United States) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 40b, name: fi-FI): Finnish (Finland) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fi_FI, Name: Finnish (Finland)
-default charset: windows-1252
-
-OS Locale (lcid: 40c, name: fr-FR): French (France) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fr_FR, Name: French (France)
-default charset: windows-1252
-
-OS Locale (lcid: 40d, name: he-IL): Hebrew (Israel) - 1255
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: iw_IL, Name: Hebrew (Israel)
-default charset: windows-1252
-
-OS Locale (lcid: 40e, name: hu-HU): Hungarian (Hungary) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: hu_HU, Name: Hungarian (Hungary)
-default charset: windows-1252
-
-OS Locale (lcid: 40f, name: is-IS): Icelandic (Iceland) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: is_IS, Name: Icelandic (Iceland)
-default charset: windows-1252
-
-OS Locale (lcid: 410, name: it-IT): Italian (Italy) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: it_IT, Name: Italian (Italy)
-default charset: windows-1252
-
-OS Locale (lcid: 411, name: ja-JP): Japanese (Japan) - 932
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ja_JP, Name: Japanese (Japan)
-default charset: windows-1252
-
-OS Locale (lcid: 412, name: ko-KR): Korean (Korea) - 949
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ko_KR, Name: Korean (South Korea)
-default charset: windows-1252
-
-OS Locale (lcid: 413, name: nl-NL): Dutch (Netherlands) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: nl_NL, Name: Dutch (Netherlands)
-default charset: windows-1252
-
-OS Locale (lcid: 414, name: nb-NO): Norwegian (Bokmål) (Norway) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: no_NO, Name: Norwegian (Norway)
-default charset: windows-1252
-
-OS Locale (lcid: 415, name: pl-PL): Polish (Poland) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: pl_PL, Name: Polish (Poland)
-default charset: windows-1252
-
-OS Locale (lcid: 416, name: pt-BR): Portuguese (Brazil) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: pt_BR, Name: Portuguese (Brazil)
-default charset: windows-1252
-
-OS Locale (lcid: 417, name: rm-CH): Romansh (Switzerland) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: rm_CH, Name: Raeto-Romance (Switzerland)
-default charset: windows-1252
-
-OS Locale (lcid: 418, name: ro-RO): Romanian (Romania) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ro_RO, Name: Romanian (Romania)
-default charset: windows-1252
-
-OS Locale (lcid: 419, name: ru-RU): Russian (Russia) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ru_RU, Name: Russian (Russia)
-default charset: windows-1252
-
-OS Locale (lcid: 41a, name: hr-HR): Croatian (Croatia) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: hr_HR, Name: Croatian (Croatia)
-default charset: windows-1252
-
-OS Locale (lcid: 41b, name: sk-SK): Slovak (Slovakia) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sk_SK, Name: Slovak (Slovakia)
-default charset: windows-1252
-
-OS Locale (lcid: 41c, name: sq-AL): Albanian (Albania) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sq_AL, Name: Albanian (Albania)
-default charset: windows-1252
-
-OS Locale (lcid: 41d, name: sv-SE): Swedish (Sweden) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sv_SE, Name: Swedish (Sweden)
-default charset: windows-1252
-
-OS Locale (lcid: 41e, name: th-TH): Thai (Thailand) - 874
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: th_TH, Name: Thai (Thailand)
-default charset: windows-1252
-
-OS Locale (lcid: 41f, name: tr-TR): Turkish (Turkey) - 1254
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tr_TR, Name: Turkish (Turkey)
-default charset: windows-1252
-
-OS Locale (lcid: 420, name: ur-PK): Urdu (Islamic Republic of Pakistan) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ur_PK, Name: Urdu (Pakistan)
-default charset: windows-1252
-
-OS Locale (lcid: 421, name: id-ID): Indonesian (Indonesia) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: in_ID, Name: Indonesian (Indonesia)
-default charset: windows-1252
-
-OS Locale (lcid: 422, name: uk-UA): Ukrainian (Ukraine) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: uk_UA, Name: Ukrainian (Ukraine)
-default charset: windows-1252
-
-OS Locale (lcid: 423, name: be-BY): Belarusian (Belarus) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: be_BY, Name: Belarusian (Belarus)
-default charset: windows-1252
-
-OS Locale (lcid: 424, name: sl-SI): Slovenian (Slovenia) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sl_SI, Name: Slovenian (Slovenia)
-default charset: windows-1252
-
-OS Locale (lcid: 425, name: et-EE): Estonian (Estonia) - 1257
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: et_EE, Name: Estonian (Estonia)
-default charset: windows-1252
-
-OS Locale (lcid: 426, name: lv-LV): Latvian (Latvia) - 1257
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: lv_LV, Name: Latvian (Latvia)
-default charset: windows-1252
-
-OS Locale (lcid: 427, name: lt-LT): Lithuanian (Lithuania) - 1257
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
-default charset: windows-1252
-
-OS Locale (lcid: 428, name: tg-Cyrl-TJ): Tajik (Cyrillic) (Tajikistan) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tg_TJ, Name: Tajik (Tajikistan)
-default charset: windows-1252
-
-OS Locale (lcid: 428, name: tg-Cyrl): Tajik (Cyrillic) (Tajikistan) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tg_TJ, Name: Tajik (Tajikistan)
-default charset: windows-1252
-
-OS Locale (lcid: 429, name: fa-IR): Persian (Iran) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fa_IR, Name: Persian (Iran)
-default charset: windows-1252
-
-OS Locale (lcid: 42a, name: vi-VN): Vietnamese (Vietnam) - 1258
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: vi_VN, Name: Vietnamese (Vietnam)
-default charset: windows-1252
-
-OS Locale (lcid: 42b, name: hy-AM): Armenian (Armenia) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: hy_AM, Name: Armenian (Armenia)
-default charset: windows-1252
-
-OS Locale (lcid: 42c, name: az-Latn-AZ): Azeri (Latin) (Azerbaijan) - 1254
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
-default charset: windows-1252
-
-OS Locale (lcid: 42c, name: az-Latn): Azeri (Latin) (Azerbaijan) - 1254
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
-default charset: windows-1252
-
-OS Locale (lcid: 42d, name: eu-ES): Basque (Spain) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: eu_ES, Name: Basque (Spain)
-default charset: windows-1252
-
-OS Locale (lcid: 42e, name: hsb-DE): Upper Sorbian (Germany) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 42e, name: hsb): Upper Sorbian (Germany) - 1252
+# OSVersionInfo
+# MajorVersion: 6
+# MinorVersion: 1
+# BuildNumber: 7600
+# CSDVersion: 
+
+
+OS Locale (lcid: 7f, name: ): Invariant Language (Invariant Country) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_US, Name: English (United States)
 default charset: windows-1252
-
-OS Locale (lcid: 42f, name: mk-MK): Macedonian (FYROM) (Macedonia (FYROM)) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mk_MK, Name: Macedonian (Macedonia)
-default charset: windows-1252
-
-OS Locale (lcid: 432, name: tn-ZA): Setswana (South Africa) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tn_ZA, Name: Tswana (South Africa)
-default charset: windows-1252
-
-OS Locale (lcid: 434, name: xh-ZA): isiXhosa (South Africa) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: xh_ZA, Name: Xhosa (South Africa)
-default charset: windows-1252
-
-OS Locale (lcid: 435, name: zu-ZA): isiZulu (South Africa) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: zu_ZA, Name: Zulu (South Africa)
-default charset: windows-1252
-
-OS Locale (lcid: 436, name: af-ZA): Afrikaans (South Africa) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: af_ZA, Name: Afrikaans (South Africa)
-default charset: windows-1252
-
-OS Locale (lcid: 437, name: ka-GE): Georgian (Georgia) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ka_GE, Name: Georgian (Georgia)
-default charset: windows-1252
-
-OS Locale (lcid: 438, name: fo-FO): Faroese (Faroe Islands) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fo_FO, Name: Faroese (Faroe Islands)
-default charset: windows-1252
-
-OS Locale (lcid: 439, name: hi-IN): Hindi (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: hi_IN, Name: Hindi (India)
-default charset: windows-1252
-
-OS Locale (lcid: 43a, name: mt-MT): Maltese (Malta) - 0
+
+OS Locale (lcid: 401, name: ar-SA): Arabic (Saudi Arabia) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: mt_MT, Name: Maltese (Malta)
-default charset: windows-1252
-
-OS Locale (lcid: 43b, name: se-NO): Sami (Northern) (Norway) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: se_NO, Name: Northern Sami (Norway)
-default charset: windows-1252
-
-OS Locale (lcid: 43e, name: ms-MY): Malay (Malaysia) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ms_MY, Name: Malay (Malaysia)
-default charset: windows-1252
-
-OS Locale (lcid: 43f, name: kk-KZ): Kazakh (Kazakhstan) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
-default charset: windows-1252
-
-OS Locale (lcid: 440, name: ky-KG): Kyrgyz (Kyrgyzstan) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
+format locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 default charset: windows-1252
-
-OS Locale (lcid: 441, name: sw-KE): Kiswahili (Kenya) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sw_KE, Name: Swahili (Kenya)
-default charset: windows-1252
-
-OS Locale (lcid: 442, name: tk-TM): Turkmen (Turkmenistan) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tk_TM, Name: Turkmen (Turkmenistan)
-default charset: windows-1252
-
-OS Locale (lcid: 443, name: uz-Latn): Uzbek (Latin) (Uzbekistan) - 1254
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-default charset: windows-1252
-
-OS Locale (lcid: 443, name: uz-Latn-UZ): Uzbek (Latin) (Uzbekistan) - 1254
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-default charset: windows-1252
-
-OS Locale (lcid: 444, name: tt-RU): Tatar (Russia) - 1251
+
+OS Locale (lcid: 402, name: bg-BG): Bulgarian (Bulgaria) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: tt_RU, Name: Tatar (Russia)
-default charset: windows-1252
-
-OS Locale (lcid: 445, name: bn-IN): Bengali (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: bn_IN, Name: Bengali (India)
-default charset: windows-1252
-
-OS Locale (lcid: 446, name: pa-IN): Punjabi (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: pa_IN, Name: Panjabi (India)
-default charset: windows-1252
-
-OS Locale (lcid: 447, name: gu-IN): Gujarati (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: gu_IN, Name: Gujarati (India)
-default charset: windows-1252
-
-OS Locale (lcid: 448, name: or-IN): Oriya (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: or_IN, Name: Oriya (India)
+format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 default charset: windows-1252
-
-OS Locale (lcid: 449, name: ta-IN): Tamil (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ta_IN, Name: Tamil (India)
-default charset: windows-1252
-
-OS Locale (lcid: 44a, name: te-IN): Telugu (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: te_IN, Name: Telugu (India)
-default charset: windows-1252
-
-OS Locale (lcid: 44b, name: kn-IN): Kannada (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: kn_IN, Name: Kannada (India)
-default charset: windows-1252
-
-OS Locale (lcid: 44c, name: ml-IN): Malayalam (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ml_IN, Name: Malayalam (India)
-default charset: windows-1252
-
-OS Locale (lcid: 44d, name: as-IN): Assamese (India) - 0
+
+OS Locale (lcid: 403, name: ca-ES): Catalan (Spain) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: as_IN, Name: Assamese (India)
-default charset: windows-1252
-
-OS Locale (lcid: 44e, name: mr-IN): Marathi (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mr_IN, Name: Marathi (India)
-default charset: windows-1252
-
-OS Locale (lcid: 44f, name: sa-IN): Sanskrit (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sa_IN, Name: Sanskrit (India)
-default charset: windows-1252
-
-OS Locale (lcid: 450, name: mn-MN): Mongolian (Cyrillic) (Mongolia) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mn_MN, Name: Mongolian (Mongolia)
-default charset: windows-1252
-
-OS Locale (lcid: 450, name: mn-Cyrl): Mongolian (Cyrillic) (Mongolia) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mn_MN, Name: Mongolian (Mongolia)
+format locale: ID: ca_ES, Name: Catalan (Spain)
 default charset: windows-1252
-
-OS Locale (lcid: 451, name: bo-CN): Tibetan (People's Republic of China) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: bo_CN, Name: Tibetan (China)
-default charset: windows-1252
-
-OS Locale (lcid: 452, name: cy-GB): Welsh (United Kingdom) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: cy_GB, Name: Welsh (United Kingdom)
-default charset: windows-1252
-
-OS Locale (lcid: 453, name: km-KH): Khmer (Cambodia) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: km_KH, Name: Khmer (Cambodia)
-default charset: windows-1252
-
-OS Locale (lcid: 454, name: lo-LA): Lao (Lao P.D.R.) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: lo_LA, Name: Lao (Laos)
-default charset: windows-1252
-
-OS Locale (lcid: 456, name: gl-ES): Galician (Spain) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: gl_ES, Name: Gallegan (Spain)
-default charset: windows-1252
-
-OS Locale (lcid: 457, name: kok-IN): Konkani (India) - 0
+
+OS Locale (lcid: 404, name: zh-TW): Chinese (Traditional) (Taiwan) - 950
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 457, name: kok): Konkani (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 45a, name: syr): Syriac (Syria) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 45a, name: syr-SY): Syriac (Syria) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: zh_TW, Name: Chinese (Taiwan)
 default charset: windows-1252
-
-OS Locale (lcid: 45b, name: si-LK): Sinhala (Sri Lanka) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
-default charset: windows-1252
-
-OS Locale (lcid: 45d, name: iu-Cans-CA): Inuktitut (Syllabics) (Canada) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: iu_CA, Name: Inuktitut (Canada)
-default charset: windows-1252
-
-OS Locale (lcid: 45d, name: iu-Cans): Inuktitut (Syllabics) (Canada) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: iu_CA, Name: Inuktitut (Canada)
-default charset: windows-1252
-
-OS Locale (lcid: 45e, name: am-ET): Amharic (Ethiopia) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: am_ET, Name: Amharic (Ethiopia)
-default charset: windows-1252
-
-OS Locale (lcid: 461, name: ne-NP): Nepali (Nepal) - 0
+
+OS Locale (lcid: 405, name: cs-CZ): Czech (Czech Republic) - 1250
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: ne_NP, Name: Nepali (Nepal)
-default charset: windows-1252
-
-OS Locale (lcid: 462, name: fy-NL): Frisian (Netherlands) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fy_NL, Name: Frisian (Netherlands)
-default charset: windows-1252
-
-OS Locale (lcid: 463, name: ps-AF): Pashto (Afghanistan) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ps_AF, Name: Pushto (Afghanistan)
-default charset: windows-1252
-
-OS Locale (lcid: 464, name: fil-PH): Filipino (Philippines) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 464, name: fil): Filipino (Philippines) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: cs_CZ, Name: Czech (Czech Republic)
 default charset: windows-1252
-
-OS Locale (lcid: 465, name: dv-MV): Divehi (Maldives) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: dv_MV, Name: Divehi (Maldives)
-default charset: windows-1252
-
-OS Locale (lcid: 468, name: ha-Latn-NG): Hausa (Latin) (Nigeria) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ha_NG, Name: Hausa (Nigeria)
-default charset: windows-1252
-
-OS Locale (lcid: 468, name: ha-Latn): Hausa (Latin) (Nigeria) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ha_NG, Name: Hausa (Nigeria)
-default charset: windows-1252
-
-OS Locale (lcid: 46a, name: yo-NG): Yoruba (Nigeria) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: yo_NG, Name: Yoruba (Nigeria)
-default charset: windows-1252
-
-OS Locale (lcid: 46b, name: quz): Quechua (Bolivia) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 46b, name: quz-BO): Quechua (Bolivia) - 1252
+
+OS Locale (lcid: 406, name: da-DK): Danish (Denmark) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 46c, name: nso): Sesotho sa Leboa (South Africa) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 46c, name: nso-ZA): Sesotho sa Leboa (South Africa) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 46d, name: ba-RU): Bashkir (Russia) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ba_RU, Name: Bashkir (Russia)
-default charset: windows-1252
-
-OS Locale (lcid: 46e, name: lb-LU): Luxembourgish (Luxembourg) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: lb_LU, Name: Luxembourgish (Luxembourg)
+format locale: ID: da_DK, Name: Danish (Denmark)
 default charset: windows-1252
-
-OS Locale (lcid: 46f, name: kl-GL): Greenlandic (Greenland) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: kl_GL, Name: Greenlandic (Greenland)
-default charset: windows-1252
-
-OS Locale (lcid: 470, name: ig-NG): Igbo (Nigeria) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ig_NG, Name: Igbo (Nigeria)
-default charset: windows-1252
-
-OS Locale (lcid: 478, name: ii-CN): Yi (People's Republic of China) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ii_CN, Name: Sichuan Yi (China)
-default charset: windows-1252
-
-OS Locale (lcid: 47a, name: arn): Mapudungun (Chile) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 47a, name: arn-CL): Mapudungun (Chile) - 1252
+
+OS Locale (lcid: 407, name: de-DE): German (Germany) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 47c, name: moh): Mohawk (Canada) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: de_DE, Name: German (Germany)
 default charset: windows-1252
-
-OS Locale (lcid: 47c, name: moh-CA): Mohawk (Canada) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 47e, name: br-FR): Breton (France) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: br_FR, Name: Breton (France)
-default charset: windows-1252
-
-OS Locale (lcid: 480, name: ug-CN): Uyghur (People's Republic of China) - 1256
+
+OS Locale (lcid: 408, name: el-GR): Greek (Greece) - 1253
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: ug_CN, Name: Uighur (China)
-default charset: windows-1252
-
-OS Locale (lcid: 481, name: mi-NZ): Maori (New Zealand) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mi_NZ, Name: Maori (New Zealand)
-default charset: windows-1252
-
-OS Locale (lcid: 482, name: oc-FR): Occitan (France) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: oc_FR, Name: Occitan (France)
+format locale: ID: el_GR, Name: Greek (Greece)
 default charset: windows-1252
-
-OS Locale (lcid: 483, name: co-FR): Corsican (France) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: co_FR, Name: Corsican (France)
-default charset: windows-1252
-
-OS Locale (lcid: 484, name: gsw): Alsatian (France) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 484, name: gsw-FR): Alsatian (France) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 485, name: sah): Yakut (Russia) - 1251
+
+OS Locale (lcid: 409, name: en-US): English (United States) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_US, Name: English (United States)
 default charset: windows-1252
-
-OS Locale (lcid: 485, name: sah-RU): Yakut (Russia) - 1251
+
+OS Locale (lcid: 40b, name: fi-FI): Finnish (Finland) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fi_FI, Name: Finnish (Finland)
+default charset: windows-1252
+
+OS Locale (lcid: 40c, name: fr-FR): French (France) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fr_FR, Name: French (France)
+default charset: windows-1252
+
+OS Locale (lcid: 40d, name: he-IL): Hebrew (Israel) - 1255
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: iw_IL, Name: Hebrew (Israel)
+default charset: windows-1252
+
+OS Locale (lcid: 40e, name: hu-HU): Hungarian (Hungary) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hu_HU, Name: Hungarian (Hungary)
+default charset: windows-1252
+
+OS Locale (lcid: 40f, name: is-IS): Icelandic (Iceland) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: is_IS, Name: Icelandic (Iceland)
+default charset: windows-1252
+
+OS Locale (lcid: 410, name: it-IT): Italian (Italy) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: it_IT, Name: Italian (Italy)
+default charset: windows-1252
+
+OS Locale (lcid: 411, name: ja-JP): Japanese (Japan) - 932
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ja_JP, Name: Japanese (Japan)
+default charset: windows-1252
+
+OS Locale (lcid: 412, name: ko-KR): Korean (Korea) - 949
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ko_KR, Name: Korean (South Korea)
+default charset: windows-1252
+
+OS Locale (lcid: 413, name: nl-NL): Dutch (Netherlands) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: nl_NL, Name: Dutch (Netherlands)
+default charset: windows-1252
+
+OS Locale (lcid: 414, name: nb-NO): Norwegian (Bokm…l) (Norway) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: no_NO, Name: Norwegian (Norway)
+default charset: windows-1252
+
+OS Locale (lcid: 415, name: pl-PL): Polish (Poland) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: pl_PL, Name: Polish (Poland)
+default charset: windows-1252
+
+OS Locale (lcid: 416, name: pt-BR): Portuguese (Brazil) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: pt_BR, Name: Portuguese (Brazil)
+default charset: windows-1252
+
+OS Locale (lcid: 417, name: rm-CH): Romansh (Switzerland) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: rm_CH, Name: Raeto-Romance (Switzerland)
+default charset: windows-1252
+
+OS Locale (lcid: 418, name: ro-RO): Romanian (Romania) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ro_RO, Name: Romanian (Romania)
+default charset: windows-1252
+
+OS Locale (lcid: 419, name: ru-RU): Russian (Russia) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ru_RU, Name: Russian (Russia)
+default charset: windows-1252
+
+OS Locale (lcid: 41a, name: hr-HR): Croatian (Croatia) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hr_HR, Name: Croatian (Croatia)
+default charset: windows-1252
+
+OS Locale (lcid: 41b, name: sk-SK): Slovak (Slovakia) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sk_SK, Name: Slovak (Slovakia)
+default charset: windows-1252
+
+OS Locale (lcid: 41c, name: sq-AL): Albanian (Albania) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sq_AL, Name: Albanian (Albania)
+default charset: windows-1252
+
+OS Locale (lcid: 41d, name: sv-SE): Swedish (Sweden) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sv_SE, Name: Swedish (Sweden)
+default charset: windows-1252
+
+OS Locale (lcid: 41e, name: th-TH): Thai (Thailand) - 874
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: th_TH, Name: Thai (Thailand)
+default charset: windows-1252
+
+OS Locale (lcid: 41f, name: tr-TR): Turkish (Turkey) - 1254
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tr_TR, Name: Turkish (Turkey)
+default charset: windows-1252
+
+OS Locale (lcid: 420, name: ur-PK): Urdu (Islamic Republic of Pakistan) - 1256
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ur_PK, Name: Urdu (Pakistan)
+default charset: windows-1252
+
+OS Locale (lcid: 421, name: id-ID): Indonesian (Indonesia) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: in_ID, Name: Indonesian (Indonesia)
+default charset: windows-1252
+
+OS Locale (lcid: 422, name: uk-UA): Ukrainian (Ukraine) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: uk_UA, Name: Ukrainian (Ukraine)
+default charset: windows-1252
+
+OS Locale (lcid: 423, name: be-BY): Belarusian (Belarus) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: be_BY, Name: Belarusian (Belarus)
+default charset: windows-1252
+
+OS Locale (lcid: 424, name: sl-SI): Slovenian (Slovenia) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sl_SI, Name: Slovenian (Slovenia)
+default charset: windows-1252
+
+OS Locale (lcid: 425, name: et-EE): Estonian (Estonia) - 1257
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: et_EE, Name: Estonian (Estonia)
+default charset: windows-1252
+
+OS Locale (lcid: 426, name: lv-LV): Latvian (Latvia) - 1257
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: lv_LV, Name: Latvian (Latvia)
+default charset: windows-1252
+
+OS Locale (lcid: 427, name: lt-LT): Lithuanian (Lithuania) - 1257
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
+default charset: windows-1252
+
+OS Locale (lcid: 428, name: tg-Cyrl-TJ): Tajik (Cyrillic) (Tajikistan) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tg_TJ_#Cyrl, Name: Tajik (Cyrillic,Tajikistan)
+default charset: windows-1252
+
+OS Locale (lcid: 428, name: tg-Cyrl): Tajik (Cyrillic) (Tajikistan) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tg_TJ_#Cyrl, Name: Tajik (Cyrillic,Tajikistan)
+default charset: windows-1252
+
+OS Locale (lcid: 429, name: fa-IR): Persian (Iran) - 1256
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fa_IR, Name: Persian (Iran)
+default charset: windows-1252
+
+OS Locale (lcid: 42a, name: vi-VN): Vietnamese (Vietnam) - 1258
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: vi_VN, Name: Vietnamese (Vietnam)
+default charset: windows-1252
+
+OS Locale (lcid: 42b, name: hy-AM): Armenian (Armenia) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hy_AM, Name: Armenian (Armenia)
+default charset: windows-1252
+
+OS Locale (lcid: 42c, name: az-Latn-AZ): Azeri (Latin) (Azerbaijan) - 1254
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: az_AZ_#Latn, Name: Azerbaijani (Latin,Azerbaijan)
+default charset: windows-1252
+
+OS Locale (lcid: 42c, name: az-Latn): Azeri (Latin) (Azerbaijan) - 1254
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: az_AZ_#Latn, Name: Azerbaijani (Latin,Azerbaijan)
+default charset: windows-1252
+
+OS Locale (lcid: 42d, name: eu-ES): Basque (Spain) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: eu_ES, Name: Basque (Spain)
+default charset: windows-1252
+
+OS Locale (lcid: 42e, name: hsb-DE): Upper Sorbian (Germany) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+default charset: windows-1252
+
+OS Locale (lcid: 42e, name: hsb): Upper Sorbian (Germany) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+default charset: windows-1252
+
+OS Locale (lcid: 42f, name: mk-MK): Macedonian (FYROM) (Macedonia (FYROM)) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mk_MK, Name: Macedonian (Macedonia)
+default charset: windows-1252
+
+OS Locale (lcid: 432, name: tn-ZA): Setswana (South Africa) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tn_ZA, Name: Tswana (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 434, name: xh-ZA): isiXhosa (South Africa) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: xh_ZA, Name: Xhosa (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 435, name: zu-ZA): isiZulu (South Africa) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: zu_ZA, Name: Zulu (South Africa)
 default charset: windows-1252
-
-OS Locale (lcid: 486, name: qut): K'iche (Guatemala) - 1252
+
+OS Locale (lcid: 436, name: af-ZA): Afrikaans (South Africa) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: af_ZA, Name: Afrikaans (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 437, name: ka-GE): Georgian (Georgia) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ka_GE, Name: Georgian (Georgia)
+default charset: windows-1252
+
+OS Locale (lcid: 438, name: fo-FO): Faroese (Faroe Islands) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fo_FO, Name: Faroese (Faroe Islands)
+default charset: windows-1252
+
+OS Locale (lcid: 439, name: hi-IN): Hindi (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hi_IN, Name: Hindi (India)
+default charset: windows-1252
+
+OS Locale (lcid: 43a, name: mt-MT): Maltese (Malta) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mt_MT, Name: Maltese (Malta)
+default charset: windows-1252
+
+OS Locale (lcid: 43b, name: se-NO): Sami (Northern) (Norway) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: se_NO, Name: Northern Sami (Norway)
+default charset: windows-1252
+
+OS Locale (lcid: 43e, name: ms-MY): Malay (Malaysia) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ms_MY, Name: Malay (Malaysia)
+default charset: windows-1252
+
+OS Locale (lcid: 43f, name: kk-KZ): Kazakh (Kazakhstan) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
+default charset: windows-1252
+
+OS Locale (lcid: 440, name: ky-KG): Kyrgyz (Kyrgyzstan) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
+default charset: windows-1252
+
+OS Locale (lcid: 441, name: sw-KE): Kiswahili (Kenya) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sw_KE, Name: Swahili (Kenya)
+default charset: windows-1252
+
+OS Locale (lcid: 442, name: tk-TM): Turkmen (Turkmenistan) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tk_TM, Name: Turkmen (Turkmenistan)
+default charset: windows-1252
+
+OS Locale (lcid: 443, name: uz-Latn): Uzbek (Latin) (Uzbekistan) - 1254
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: uz_UZ_#Latn, Name: Uzbek (Latin,Uzbekistan)
+default charset: windows-1252
+
+OS Locale (lcid: 443, name: uz-Latn-UZ): Uzbek (Latin) (Uzbekistan) - 1254
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: uz_UZ_#Latn, Name: Uzbek (Latin,Uzbekistan)
+default charset: windows-1252
+
+OS Locale (lcid: 444, name: tt-RU): Tatar (Russia) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tt_RU, Name: Tatar (Russia)
+default charset: windows-1252
+
+OS Locale (lcid: 445, name: bn-IN): Bengali (India) - 0
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: bn_IN, Name: Bengali (India)
+default charset: windows-1252
+
+OS Locale (lcid: 446, name: pa-IN): Punjabi (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: pa_IN, Name: Panjabi (India)
+default charset: windows-1252
+
+OS Locale (lcid: 447, name: gu-IN): Gujarati (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: gu_IN, Name: Gujarati (India)
+default charset: windows-1252
+
+OS Locale (lcid: 448, name: or-IN): Oriya (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: or_IN, Name: Oriya (India)
+default charset: windows-1252
+
+OS Locale (lcid: 449, name: ta-IN): Tamil (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ta_IN, Name: Tamil (India)
+default charset: windows-1252
+
+OS Locale (lcid: 44a, name: te-IN): Telugu (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: te_IN, Name: Telugu (India)
+default charset: windows-1252
+
+OS Locale (lcid: 44b, name: kn-IN): Kannada (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kn_IN, Name: Kannada (India)
+default charset: windows-1252
+
+OS Locale (lcid: 44c, name: ml-IN): Malayalam (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ml_IN, Name: Malayalam (India)
+default charset: windows-1252
+
+OS Locale (lcid: 44d, name: as-IN): Assamese (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: as_IN, Name: Assamese (India)
+default charset: windows-1252
+
+OS Locale (lcid: 44e, name: mr-IN): Marathi (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mr_IN, Name: Marathi (India)
+default charset: windows-1252
+
+OS Locale (lcid: 44f, name: sa-IN): Sanskrit (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sa_IN, Name: Sanskrit (India)
+default charset: windows-1252
+
+OS Locale (lcid: 450, name: mn-MN): Mongolian (Cyrillic) (Mongolia) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mn_MN, Name: Mongolian (Mongolia)
+default charset: windows-1252
+
+OS Locale (lcid: 450, name: mn-Cyrl): Mongolian (Cyrillic) (Mongolia) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mn_MN, Name: Mongolian (Mongolia)
+default charset: windows-1252
+
+OS Locale (lcid: 451, name: bo-CN): Tibetan (People's Republic of China) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: bo_CN, Name: Tibetan (China)
+default charset: windows-1252
+
+OS Locale (lcid: 452, name: cy-GB): Welsh (United Kingdom) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: cy_GB, Name: Welsh (United Kingdom)
 default charset: windows-1252
-
-OS Locale (lcid: 486, name: qut-GT): K'iche (Guatemala) - 1252
+
+OS Locale (lcid: 453, name: km-KH): Khmer (Cambodia) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: km_KH, Name: Khmer (Cambodia)
+default charset: windows-1252
+
+OS Locale (lcid: 454, name: lo-LA): Lao (Lao P.D.R.) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: lo_LA, Name: Lao (Laos)
+default charset: windows-1252
+
+OS Locale (lcid: 456, name: gl-ES): Galician (Spain) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: gl_ES, Name: Gallegan (Spain)
+default charset: windows-1252
+
+OS Locale (lcid: 457, name: kok-IN): Konkani (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kok_IN, Name: Konkani (India)
+default charset: windows-1252
+
+OS Locale (lcid: 457, name: kok): Konkani (India) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kok_IN, Name: Konkani (India)
+default charset: windows-1252
+
+OS Locale (lcid: 45a, name: syr): Syriac (Syria) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: syr_SY, Name: Syriac (Syria)
+default charset: windows-1252
+
+OS Locale (lcid: 45a, name: syr-SY): Syriac (Syria) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: syr_SY, Name: Syriac (Syria)
+default charset: windows-1252
+
+OS Locale (lcid: 45b, name: si-LK): Sinhala (Sri Lanka) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
+default charset: windows-1252
+
+OS Locale (lcid: 45d, name: iu-Cans-CA): Inuktitut (Syllabics) (Canada) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: iu_CA_#Cans, Name: Inuktitut (Unified Canadian Aboriginal Syllabics,Canada)
+default charset: windows-1252
+
+OS Locale (lcid: 45d, name: iu-Cans): Inuktitut (Syllabics) (Canada) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: iu_CA_#Cans, Name: Inuktitut (Unified Canadian Aboriginal Syllabics,Canada)
+default charset: windows-1252
+
+OS Locale (lcid: 45e, name: am-ET): Amharic (Ethiopia) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: am_ET, Name: Amharic (Ethiopia)
+default charset: windows-1252
+
+OS Locale (lcid: 461, name: ne-NP): Nepali (Nepal) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ne_NP, Name: Nepali (Nepal)
+default charset: windows-1252
+
+OS Locale (lcid: 462, name: fy-NL): Frisian (Netherlands) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fy_NL, Name: Frisian (Netherlands)
+default charset: windows-1252
+
+OS Locale (lcid: 463, name: ps-AF): Pashto (Afghanistan) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ps_AF, Name: Pushto (Afghanistan)
+default charset: windows-1252
+
+OS Locale (lcid: 464, name: fil-PH): Filipino (Philippines) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: fil_PH, Name: Filipino (Philippines)
+default charset: windows-1252
+
+OS Locale (lcid: 464, name: fil): Filipino (Philippines) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fil_PH, Name: Filipino (Philippines)
+default charset: windows-1252
+
+OS Locale (lcid: 465, name: dv-MV): Divehi (Maldives) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: dv_MV, Name: Divehi (Maldives)
+default charset: windows-1252
+
+OS Locale (lcid: 468, name: ha-Latn-NG): Hausa (Latin) (Nigeria) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ha_NG_#Latn, Name: Hausa (Latin,Nigeria)
+default charset: windows-1252
+
+OS Locale (lcid: 468, name: ha-Latn): Hausa (Latin) (Nigeria) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ha_NG_#Latn, Name: Hausa (Latin,Nigeria)
+default charset: windows-1252
+
+OS Locale (lcid: 46a, name: yo-NG): Yoruba (Nigeria) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: yo_NG, Name: Yoruba (Nigeria)
+default charset: windows-1252
+
+OS Locale (lcid: 46b, name: quz): Quechua (Bolivia) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: quz_BO, Name: quz (Bolivia)
+default charset: windows-1252
+
+OS Locale (lcid: 46b, name: quz-BO): Quechua (Bolivia) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: quz_BO, Name: quz (Bolivia)
+default charset: windows-1252
+
+OS Locale (lcid: 46c, name: nso): Sesotho sa Leboa (South Africa) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: nso_ZA, Name: Pedi (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 46c, name: nso-ZA): Sesotho sa Leboa (South Africa) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: nso_ZA, Name: Pedi (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 46d, name: ba-RU): Bashkir (Russia) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ba_RU, Name: Bashkir (Russia)
+default charset: windows-1252
+
+OS Locale (lcid: 46e, name: lb-LU): Luxembourgish (Luxembourg) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: lb_LU, Name: Luxembourgish (Luxembourg)
+default charset: windows-1252
+
+OS Locale (lcid: 46f, name: kl-GL): Greenlandic (Greenland) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kl_GL, Name: Greenlandic (Greenland)
+default charset: windows-1252
+
+OS Locale (lcid: 470, name: ig-NG): Igbo (Nigeria) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ig_NG, Name: Igbo (Nigeria)
+default charset: windows-1252
+
+OS Locale (lcid: 478, name: ii-CN): Yi (People's Republic of China) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ii_CN, Name: Sichuan Yi (China)
 default charset: windows-1252
-
-OS Locale (lcid: 487, name: rw-RW): Kinyarwanda (Rwanda) - 1252
+
+OS Locale (lcid: 47a, name: arn): Mapudungun (Chile) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: arn_CL, Name: Mapudungun (Chile)
+default charset: windows-1252
+
+OS Locale (lcid: 47a, name: arn-CL): Mapudungun (Chile) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: arn_CL, Name: Mapudungun (Chile)
+default charset: windows-1252
+
+OS Locale (lcid: 47c, name: moh): Mohawk (Canada) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: moh_CA, Name: Mohawk (Canada)
+default charset: windows-1252
+
+OS Locale (lcid: 47c, name: moh-CA): Mohawk (Canada) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: moh_CA, Name: Mohawk (Canada)
+default charset: windows-1252
+
+OS Locale (lcid: 47e, name: br-FR): Breton (France) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: br_FR, Name: Breton (France)
+default charset: windows-1252
+
+OS Locale (lcid: 480, name: ug-CN): Uyghur (People's Republic of China) - 1256
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ug_CN, Name: Uighur (China)
+default charset: windows-1252
+
+OS Locale (lcid: 481, name: mi-NZ): Maori (New Zealand) - 0
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mi_NZ, Name: Maori (New Zealand)
+default charset: windows-1252
+
+OS Locale (lcid: 482, name: oc-FR): Occitan (France) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: oc_FR, Name: Occitan (France)
+default charset: windows-1252
+
+OS Locale (lcid: 483, name: co-FR): Corsican (France) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: co_FR, Name: Corsican (France)
+default charset: windows-1252
+
+OS Locale (lcid: 484, name: gsw): Alsatian (France) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: gsw_FR, Name: Swiss German (France)
+default charset: windows-1252
+
+OS Locale (lcid: 484, name: gsw-FR): Alsatian (France) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: gsw_FR, Name: Swiss German (France)
+default charset: windows-1252
+
+OS Locale (lcid: 485, name: sah): Yakut (Russia) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sah_RU, Name: Yakut (Russia)
+default charset: windows-1252
+
+OS Locale (lcid: 485, name: sah-RU): Yakut (Russia) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sah_RU, Name: Yakut (Russia)
+default charset: windows-1252
+
+OS Locale (lcid: 486, name: qut): K'iche (Guatemala) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: qut_GT, Name: qut (Guatemala)
+default charset: windows-1252
+
+OS Locale (lcid: 486, name: qut-GT): K'iche (Guatemala) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: qut_GT, Name: qut (Guatemala)
+default charset: windows-1252
+
+OS Locale (lcid: 487, name: rw-RW): Kinyarwanda (Rwanda) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
 default charset: windows-1252
-
-OS Locale (lcid: 488, name: wo-SN): Wolof (Senegal) - 1252
+
+OS Locale (lcid: 488, name: wo-SN): Wolof (Senegal) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: wo_SN, Name: Wolof (Senegal)
 default charset: windows-1252
-
-OS Locale (lcid: 48c, name: prs): Dari (Afghanistan) - 1256
+
+OS Locale (lcid: 48c, name: prs): Dari (Afghanistan) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: prs_AF, Name: prs (Afghanistan)
 default charset: windows-1252
-
-OS Locale (lcid: 48c, name: prs-AF): Dari (Afghanistan) - 1256
+
+OS Locale (lcid: 48c, name: prs-AF): Dari (Afghanistan) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: prs_AF, Name: prs (Afghanistan)
 default charset: windows-1252
-
-OS Locale (lcid: 491, name: gd-GB): Scottish Gaelic (United Kingdom) - 1252
+
+OS Locale (lcid: 491, name: gd-GB): Scottish Gaelic (United Kingdom) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
 default charset: windows-1252
-
-OS Locale (lcid: 801, name: ar-IQ): Arabic (Iraq) - 1256
+
+OS Locale (lcid: 801, name: ar-IQ): Arabic (Iraq) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_IQ, Name: Arabic (Iraq)
 default charset: windows-1252
-
-OS Locale (lcid: 804, name: zh-Hans): Chinese (Simplified) (People's Republic of China) - 936
+
+OS Locale (lcid: 804, name: zh-Hans): Chinese (Simplified) (People's Republic of China) - 936
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_CN, Name: Chinese (China)
 default charset: windows-1252
-
-OS Locale (lcid: 804, name: zh-CN): Chinese (Simplified) (People's Republic of China) - 936
+
+OS Locale (lcid: 804, name: zh-CN): Chinese (Simplified) (People's Republic of China) - 936
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_CN, Name: Chinese (China)
 default charset: windows-1252
-
-OS Locale (lcid: 807, name: de-CH): German (Switzerland) - 1252
+
+OS Locale (lcid: 807, name: de-CH): German (Switzerland) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: de_CH, Name: German (Switzerland)
 default charset: windows-1252
-
-OS Locale (lcid: 809, name: en-GB): English (United Kingdom) - 1252
+
+OS Locale (lcid: 809, name: en-GB): English (United Kingdom) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: en_GB, Name: English (United Kingdom)
 default charset: windows-1252
-
-OS Locale (lcid: 80a, name: es-MX): Spanish (Mexico) - 1252
+
+OS Locale (lcid: 80a, name: es-MX): Spanish (Mexico) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_MX, Name: Spanish (Mexico)
 default charset: windows-1252
-
-OS Locale (lcid: 80c, name: fr-BE): French (Belgium) - 1252
+
+OS Locale (lcid: 80c, name: fr-BE): French (Belgium) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_BE, Name: French (Belgium)
 default charset: windows-1252
-
-OS Locale (lcid: 810, name: it-CH): Italian (Switzerland) - 1252
+
+OS Locale (lcid: 810, name: it-CH): Italian (Switzerland) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: it_CH, Name: Italian (Switzerland)
 default charset: windows-1252
-
-OS Locale (lcid: 813, name: nl-BE): Dutch (Belgium) - 1252
+
+OS Locale (lcid: 813, name: nl-BE): Dutch (Belgium) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: nl_BE, Name: Dutch (Belgium)
 default charset: windows-1252
-
-OS Locale (lcid: 814, name: nn-NO): Norwegian (Nynorsk) (Norway) - 1252
+
+OS Locale (lcid: 814, name: nn-NO): Norwegian (Nynorsk) (Norway) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
 default charset: windows-1252
-
-OS Locale (lcid: 816, name: pt-PT): Portuguese (Portugal) - 1252
+
+OS Locale (lcid: 816, name: pt-PT): Portuguese (Portugal) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: pt_PT, Name: Portuguese (Portugal)
 default charset: windows-1252
-
-OS Locale (lcid: 81a, name: sr-Latn-CS): Serbian (Latin) (Serbia and Montenegro (Former)) - 1250
+
+OS Locale (lcid: 81a, name: sr-Latn-CS): Serbian (Latin) (Serbia and Montenegro (Former)) - 1250
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+format locale: ID: sr_CS_#Latn, Name: Serbian (Latin,Serbia and Montenegro)
 default charset: windows-1252
-
-OS Locale (lcid: 81d, name: sv-FI): Swedish (Finland) - 1252
+
+OS Locale (lcid: 81d, name: sv-FI): Swedish (Finland) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: sv_FI, Name: Swedish (Finland)
 default charset: windows-1252
-
-OS Locale (lcid: 82c, name: az-Cyrl-AZ): Azeri (Cyrillic) (Azerbaijan) - 1251
+
+OS Locale (lcid: 82c, name: az-Cyrl-AZ): Azeri (Cyrillic) (Azerbaijan) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
+format locale: ID: az_AZ_#Cyrl, Name: Azerbaijani (Cyrillic,Azerbaijan)
 default charset: windows-1252
-
-OS Locale (lcid: 82c, name: az-Cyrl): Azeri (Cyrillic) (Azerbaijan) - 1251
+
+OS Locale (lcid: 82c, name: az-Cyrl): Azeri (Cyrillic) (Azerbaijan) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
+format locale: ID: az_AZ_#Cyrl, Name: Azerbaijani (Cyrillic,Azerbaijan)
 default charset: windows-1252
-
-OS Locale (lcid: 82e, name: dsb): Lower Sorbian (Germany) - 1252
+
+OS Locale (lcid: 82e, name: dsb): Lower Sorbian (Germany) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: dsb_DE, Name: Lower Sorbian (Germany)
 default charset: windows-1252
-
-OS Locale (lcid: 82e, name: dsb-DE): Lower Sorbian (Germany) - 1252
+
+OS Locale (lcid: 82e, name: dsb-DE): Lower Sorbian (Germany) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: dsb_DE, Name: Lower Sorbian (Germany)
 default charset: windows-1252
-
-OS Locale (lcid: 83b, name: se-SE): Sami (Northern) (Sweden) - 1252
+
+OS Locale (lcid: 83b, name: se-SE): Sami (Northern) (Sweden) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: se_SE, Name: Northern Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 83c, name: ga-IE): Irish (Ireland) - 1252
+
+OS Locale (lcid: 83c, name: ga-IE): Irish (Ireland) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ga_IE, Name: Irish (Ireland)
 default charset: windows-1252
-
-OS Locale (lcid: 83e, name: ms-BN): Malay (Brunei Darussalam) - 1252
+
+OS Locale (lcid: 83e, name: ms-BN): Malay (Brunei Darussalam) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ms_BN, Name: Malay (Brunei)
 default charset: windows-1252
-
-OS Locale (lcid: 843, name: uz-Cyrl-UZ): Uzbek (Cyrillic) (Uzbekistan) - 1251
+
+OS Locale (lcid: 843, name: uz-Cyrl-UZ): Uzbek (Cyrillic) (Uzbekistan) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+format locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 default charset: windows-1252
-
-OS Locale (lcid: 843, name: uz-Cyrl): Uzbek (Cyrillic) (Uzbekistan) - 1251
+
+OS Locale (lcid: 843, name: uz-Cyrl): Uzbek (Cyrillic) (Uzbekistan) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+format locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 default charset: windows-1252
-
-OS Locale (lcid: 845, name: bn-BD): Bengali (Bangladesh) - 0
+
+OS Locale (lcid: 845, name: bn-BD): Bengali (Bangladesh) - 0
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: bn_BD, Name: Bengali (Bangladesh)
 default charset: windows-1252
-
-OS Locale (lcid: 850, name: mn-Mong-CN): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
+
+OS Locale (lcid: 850, name: mn-Mong-CN): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: mn_CN, Name: Mongolian (China)
+format locale: ID: mn_CN_#Mong, Name: Mongolian (Mongolian,China)
 default charset: windows-1252
-
-OS Locale (lcid: 850, name: mn-Mong): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
+
+OS Locale (lcid: 850, name: mn-Mong): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: mn_CN, Name: Mongolian (China)
+format locale: ID: mn_CN_#Mong, Name: Mongolian (Mongolian,China)
 default charset: windows-1252
-
-OS Locale (lcid: 85d, name: iu-Latn): Inuktitut (Latin) (Canada) - 1252
+
+OS Locale (lcid: 85d, name: iu-Latn): Inuktitut (Latin) (Canada) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: iu_CA, Name: Inuktitut (Canada)
+format locale: ID: iu_CA_#Latn, Name: Inuktitut (Latin,Canada)
 default charset: windows-1252
-
-OS Locale (lcid: 85d, name: iu-Latn-CA): Inuktitut (Latin) (Canada) - 1252
+
+OS Locale (lcid: 85d, name: iu-Latn-CA): Inuktitut (Latin) (Canada) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: iu_CA, Name: Inuktitut (Canada)
+format locale: ID: iu_CA_#Latn, Name: Inuktitut (Latin,Canada)
 default charset: windows-1252
-
-OS Locale (lcid: 85f, name: tzm): Tamazight (Latin) (Algeria) - 1252
+
+OS Locale (lcid: 85f, name: tzm): Tamazight (Latin) (Algeria) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: tzm_DZ_#Latn, Name: tzm (Latin,Algeria)
 default charset: windows-1252
-
-OS Locale (lcid: 85f, name: tzm-Latn-DZ): Tamazight (Latin) (Algeria) - 1252
+
+OS Locale (lcid: 85f, name: tzm-Latn-DZ): Tamazight (Latin) (Algeria) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: tzm_DZ_#Latn, Name: tzm (Latin,Algeria)
 default charset: windows-1252
-
-OS Locale (lcid: 85f, name: tzm-Latn): Tamazight (Latin) (Algeria) - 1252
+
+OS Locale (lcid: 85f, name: tzm-Latn): Tamazight (Latin) (Algeria) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: tzm_DZ_#Latn, Name: tzm (Latin,Algeria)
 default charset: windows-1252
-
-OS Locale (lcid: 86b, name: quz-EC): Quechua (Ecuador) - 1252
+
+OS Locale (lcid: 86b, name: quz-EC): Quechua (Ecuador) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: quz_EC, Name: quz (Ecuador)
 default charset: windows-1252
-
-OS Locale (lcid: c01, name: ar-EG): Arabic (Egypt) - 1256
+
+OS Locale (lcid: c01, name: ar-EG): Arabic (Egypt) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_EG, Name: Arabic (Egypt)
 default charset: windows-1252
-
-OS Locale (lcid: c04, name: zh-HK): Chinese (Traditional) (Hong Kong S.A.R.) - 950
+
+OS Locale (lcid: c04, name: zh-HK): Chinese (Traditional) (Hong Kong S.A.R.) - 950
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_HK, Name: Chinese (Hong Kong)
 default charset: x-MS950-HKSCS
-
-OS Locale (lcid: c04, name: zh-Hant): Chinese (Traditional) (Hong Kong S.A.R.) - 950
+
+OS Locale (lcid: c04, name: zh-Hant): Chinese (Traditional) (Hong Kong S.A.R.) - 950
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_HK, Name: Chinese (Hong Kong)
 default charset: windows-1252
-
-OS Locale (lcid: c07, name: de-AT): German (Austria) - 1252
+
+OS Locale (lcid: c07, name: de-AT): German (Austria) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: de_AT, Name: German (Austria)
 default charset: windows-1252
-
-OS Locale (lcid: c09, name: en-AU): English (Australia) - 1252
+
+OS Locale (lcid: c09, name: en-AU): English (Australia) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: en_AU, Name: English (Australia)
 default charset: windows-1252
-
-OS Locale (lcid: c0a, name: es-ES): Spanish (Spain) - 1252
+
+OS Locale (lcid: c0a, name: es-ES): Spanish (Spain) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_ES, Name: Spanish (Spain)
 default charset: windows-1252
-
-OS Locale (lcid: c0c, name: fr-CA): French (Canada) - 1252
+
+OS Locale (lcid: c0c, name: fr-CA): French (Canada) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_CA, Name: French (Canada)
 default charset: windows-1252
-
-OS Locale (lcid: c1a, name: sr-Cyrl-CS): Serbian (Cyrillic) (Serbia and Montenegro (Former)) - 1251
+
+OS Locale (lcid: c1a, name: sr-Cyrl-CS): Serbian (Cyrillic) (Serbia and Montenegro (Former)) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+format locale: ID: sr_CS_#Cyrl, Name: Serbian (Cyrillic,Serbia and Montenegro)
 default charset: windows-1252
-
-OS Locale (lcid: c3b, name: se-FI): Sami (Northern) (Finland) - 1252
+
+OS Locale (lcid: c3b, name: se-FI): Sami (Northern) (Finland) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: se_FI, Name: Northern Sami (Finland)
 default charset: windows-1252
-
-OS Locale (lcid: c6b, name: quz-PE): Quechua (Peru) - 1252
+
+OS Locale (lcid: c6b, name: quz-PE): Quechua (Peru) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: quz_PE, Name: quz (Peru)
 default charset: windows-1252
-
-OS Locale (lcid: 1001, name: ar-LY): Arabic (Libya) - 1256
+
+OS Locale (lcid: 1001, name: ar-LY): Arabic (Libya) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_LY, Name: Arabic (Libya)
 default charset: windows-1252
-
-OS Locale (lcid: 1004, name: zh-SG): Chinese (Simplified) (Singapore) - 936
+
+OS Locale (lcid: 1004, name: zh-SG): Chinese (Simplified) (Singapore) - 936
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_SG, Name: Chinese (Singapore)
 default charset: windows-1252
-
-OS Locale (lcid: 1007, name: de-LU): German (Luxembourg) - 1252
+
+OS Locale (lcid: 1007, name: de-LU): German (Luxembourg) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: de_LU, Name: German (Luxembourg)
 default charset: windows-1252
-
-OS Locale (lcid: 1009, name: en-CA): English (Canada) - 1252
+
+OS Locale (lcid: 1009, name: en-CA): English (Canada) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: en_CA, Name: English (Canada)
 default charset: windows-1252
-
-OS Locale (lcid: 100a, name: es-GT): Spanish (Guatemala) - 1252
+
+OS Locale (lcid: 100a, name: es-GT): Spanish (Guatemala) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_GT, Name: Spanish (Guatemala)
 default charset: windows-1252
-
-OS Locale (lcid: 100c, name: fr-CH): French (Switzerland) - 1252
+
+OS Locale (lcid: 100c, name: fr-CH): French (Switzerland) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_CH, Name: French (Switzerland)
 default charset: windows-1252
-
-OS Locale (lcid: 101a, name: hr-BA): Croatian (Latin) (Bosnia and Herzegovina) - 1250
+
+OS Locale (lcid: 101a, name: hr-BA): Croatian (Latin) (Bosnia and Herzegovina) - 1250
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: hr_BA, Name: Croatian (Bosnia and Herzegovina)
 default charset: windows-1252
-
-OS Locale (lcid: 103b, name: smj-NO): Sami (Lule) (Norway) - 1252
+
+OS Locale (lcid: 103b, name: smj-NO): Sami (Lule) (Norway) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: smj_NO, Name: Lule Sami (Norway)
 default charset: windows-1252
-
-OS Locale (lcid: 1401, name: ar-DZ): Arabic (Algeria) - 1256
+
+OS Locale (lcid: 1401, name: ar-DZ): Arabic (Algeria) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_DZ, Name: Arabic (Algeria)
 default charset: windows-1252
-
-OS Locale (lcid: 1404, name: zh-MO): Chinese (Traditional) (Macao S.A.R.) - 950
+
+OS Locale (lcid: 1404, name: zh-MO): Chinese (Traditional) (Macao S.A.R.) - 950
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_MO, Name: Chinese (Macao)
 default charset: windows-1252
-
-OS Locale (lcid: 1407, name: de-LI): German (Liechtenstein) - 1252
+
+OS Locale (lcid: 1407, name: de-LI): German (Liechtenstein) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: de_LI, Name: German (Liechtenstein)
 default charset: windows-1252
-
-OS Locale (lcid: 1409, name: en-NZ): English (New Zealand) - 1252
+
+OS Locale (lcid: 1409, name: en-NZ): English (New Zealand) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: en_NZ, Name: English (New Zealand)
 default charset: windows-1252
-
-OS Locale (lcid: 140a, name: es-CR): Spanish (Costa Rica) - 1252
+
+OS Locale (lcid: 140a, name: es-CR): Spanish (Costa Rica) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_CR, Name: Spanish (Costa Rica)
 default charset: windows-1252
-
-OS Locale (lcid: 140c, name: fr-LU): French (Luxembourg) - 1252
+
+OS Locale (lcid: 140c, name: fr-LU): French (Luxembourg) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_LU, Name: French (Luxembourg)
 default charset: windows-1252
-
-OS Locale (lcid: 141a, name: bs-Latn): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
+
+OS Locale (lcid: 141a, name: bs-Latn): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+format locale: ID: bs_BA_#Latn, Name: Bosnian (Latin,Bosnia and Herzegovina)
 default charset: windows-1252
-
-OS Locale (lcid: 141a, name: bs-Latn-BA): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
+
+OS Locale (lcid: 141a, name: bs-Latn-BA): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+format locale: ID: bs_BA_#Latn, Name: Bosnian (Latin,Bosnia and Herzegovina)
 default charset: windows-1252
-
-OS Locale (lcid: 143b, name: smj-SE): Sami (Lule) (Sweden) - 1252
+
+OS Locale (lcid: 143b, name: smj-SE): Sami (Lule) (Sweden) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: smj_SE, Name: Lule Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 143b, name: smj): Sami (Lule) (Sweden) - 1252
+
+OS Locale (lcid: 143b, name: smj): Sami (Lule) (Sweden) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: smj_SE, Name: Lule Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 1801, name: ar-MA): Arabic (Morocco) - 1256
+
+OS Locale (lcid: 1801, name: ar-MA): Arabic (Morocco) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_MA, Name: Arabic (Morocco)
 default charset: windows-1252
-
-OS Locale (lcid: 1809, name: en-IE): English (Ireland) - 1252
+
+OS Locale (lcid: 1809, name: en-IE): English (Ireland) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: en_IE, Name: English (Ireland)
 default charset: windows-1252
-
-OS Locale (lcid: 180a, name: es-PA): Spanish (Panama) - 1252
+
+OS Locale (lcid: 180a, name: es-PA): Spanish (Panama) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_PA, Name: Spanish (Panama)
 default charset: windows-1252
-
-OS Locale (lcid: 180c, name: fr-MC): French (Principality of Monaco) - 1252
+
+OS Locale (lcid: 180c, name: fr-MC): French (Principality of Monaco) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_MC, Name: French (Monaco)
 default charset: windows-1252
-
-OS Locale (lcid: 181a, name: sr-Latn-BA): Serbian (Latin) (Bosnia and Herzegovina) - 1250
+
+OS Locale (lcid: 181a, name: sr-Latn-BA): Serbian (Latin) (Bosnia and Herzegovina) - 1250
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
+format locale: ID: sr_BA_#Latn, Name: Serbian (Latin,Bosnia and Herzegovina)
 default charset: windows-1252
-
-OS Locale (lcid: 183b, name: sma-NO): Sami (Southern) (Norway) - 1252
+
+OS Locale (lcid: 183b, name: sma-NO): Sami (Southern) (Norway) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sma_NO, Name: Southern Sami (Norway)
 default charset: windows-1252
-
-OS Locale (lcid: 1c01, name: ar-TN): Arabic (Tunisia) - 1256
+
+OS Locale (lcid: 1c01, name: ar-TN): Arabic (Tunisia) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_TN, Name: Arabic (Tunisia)
 default charset: windows-1252
-
-OS Locale (lcid: 1c09, name: en-ZA): English (South Africa) - 1252
+
+OS Locale (lcid: 1c09, name: en-ZA): English (South Africa) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: en_ZA, Name: English (South Africa)
 default charset: windows-1252
-
-OS Locale (lcid: 1c0a, name: es-DO): Spanish (Dominican Republic) - 1252
+
+OS Locale (lcid: 1c0a, name: es-DO): Spanish (Dominican Republic) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_DO, Name: Spanish (Dominican Republic)
 default charset: windows-1252
-
-OS Locale (lcid: 1c1a, name: sr-Cyrl-BA): Serbian (Cyrillic) (Bosnia and Herzegovina) - 1251
+
+OS Locale (lcid: 1c1a, name: sr-Cyrl-BA): Serbian (Cyrillic) (Bosnia and Herzegovina) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
+format locale: ID: sr_BA_#Cyrl, Name: Serbian (Cyrillic,Bosnia and Herzegovina)
 default charset: windows-1252
-
-OS Locale (lcid: 1c3b, name: sma): Sami (Southern) (Sweden) - 1252
+
+OS Locale (lcid: 1c3b, name: sma): Sami (Southern) (Sweden) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sma_SE, Name: Southern Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 1c3b, name: sma-SE): Sami (Southern) (Sweden) - 1252
+
+OS Locale (lcid: 1c3b, name: sma-SE): Sami (Southern) (Sweden) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sma_SE, Name: Southern Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 2001, name: ar-OM): Arabic (Oman) - 1256
+
+OS Locale (lcid: 2001, name: ar-OM): Arabic (Oman) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_OM, Name: Arabic (Oman)
 default charset: windows-1252
-
-OS Locale (lcid: 2009, name: en-JM): English (Jamaica) - 1252
+
+OS Locale (lcid: 2009, name: en-JM): English (Jamaica) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: en_JM, Name: English (Jamaica)
 default charset: windows-1252
-
-OS Locale (lcid: 200a, name: es-VE): Spanish (Bolivarian Republic of Venezuela) - 1252
+
+OS Locale (lcid: 200a, name: es-VE): Spanish (Bolivarian Republic of Venezuela) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_VE, Name: Spanish (Venezuela)
 default charset: windows-1252
-
-OS Locale (lcid: 201a, name: bs-Cyrl-BA): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
+
+OS Locale (lcid: 201a, name: bs-Cyrl-BA): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+format locale: ID: bs_BA_#Cyrl, Name: Bosnian (Cyrillic,Bosnia and Herzegovina)
 default charset: windows-1252
-
-OS Locale (lcid: 201a, name: bs-Cyrl): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
+
+OS Locale (lcid: 201a, name: bs-Cyrl): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+format locale: ID: bs_BA_#Cyrl, Name: Bosnian (Cyrillic,Bosnia and Herzegovina)
 default charset: windows-1252
-
-OS Locale (lcid: 203b, name: sms-FI): Sami (Skolt) (Finland) - 1252
+
+OS Locale (lcid: 203b, name: sms-FI): Sami (Skolt) (Finland) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sms_FI, Name: Skolt Sami (Finland)
 default charset: windows-1252
-
-OS Locale (lcid: 203b, name: sms): Sami (Skolt) (Finland) - 1252
+
+OS Locale (lcid: 203b, name: sms): Sami (Skolt) (Finland) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sms_FI, Name: Skolt Sami (Finland)
 default charset: windows-1252
-
-OS Locale (lcid: 2401, name: ar-YE): Arabic (Yemen) - 1256
+
+OS Locale (lcid: 2401, name: ar-YE): Arabic (Yemen) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_YE, Name: Arabic (Yemen)
 default charset: windows-1252
-
-OS Locale (lcid: 2409, name: en-029): English (Caribbean) - 1252
+
+OS Locale (lcid: 2409, name: en-029): English (Caribbean) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: en_029, Name: English (Caribbean)
 default charset: windows-1252
-
-OS Locale (lcid: 240a, name: es-CO): Spanish (Colombia) - 1252
+
+OS Locale (lcid: 240a, name: es-CO): Spanish (Colombia) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_CO, Name: Spanish (Colombia)
 default charset: windows-1252
-
-OS Locale (lcid: 241a, name: sr-Latn-RS): Serbian (Latin) (Serbia) - 1250
+
+OS Locale (lcid: 241a, name: sr-Latn-RS): Serbian (Latin) (Serbia) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+default charset: windows-1252
+
+OS Locale (lcid: 241a, name: sr-Latn): Serbian (Latin) (Serbia) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+default charset: windows-1252
+
+OS Locale (lcid: 243b, name: smn): Sami (Inari) (Finland) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: smn_FI, Name: Inari Sami (Finland)
+default charset: windows-1252
+
+OS Locale (lcid: 243b, name: smn-FI): Sami (Inari) (Finland) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: smn_FI, Name: Inari Sami (Finland)
+default charset: windows-1252
+
+OS Locale (lcid: 2801, name: ar-SY): Arabic (Syria) - 1256
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_SY, Name: Arabic (Syria)
+default charset: windows-1252
+
+OS Locale (lcid: 2809, name: en-BZ): English (Belize) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_BZ, Name: English (Belize)
+default charset: windows-1252
+
+OS Locale (lcid: 280a, name: es-PE): Spanish (Peru) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_PE, Name: Spanish (Peru)
+default charset: windows-1252
+
+OS Locale (lcid: 281a, name: sr-Cyrl-RS): Serbian (Cyrillic) (Serbia) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_RS, Name: Serbian (Serbia)
+format locale: ID: sr_RS_#Cyrl, Name: Serbian (Cyrillic,Serbia)
+default charset: windows-1252
+
+OS Locale (lcid: 281a, name: sr-Cyrl): Serbian (Cyrillic) (Serbia) - 1251
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sr_RS_#Cyrl, Name: Serbian (Cyrillic,Serbia)
+default charset: windows-1252
+
+OS Locale (lcid: 2c01, name: ar-JO): Arabic (Jordan) - 1256
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_JO, Name: Arabic (Jordan)
+default charset: windows-1252
+
+OS Locale (lcid: 2c09, name: en-TT): English (Trinidad and Tobago) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_TT, Name: English (Trinidad and Tobago)
+default charset: windows-1252
+
+OS Locale (lcid: 2c0a, name: es-AR): Spanish (Argentina) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_AR, Name: Spanish (Argentina)
 default charset: windows-1252
-
-OS Locale (lcid: 241a, name: sr-Latn): Serbian (Latin) (Serbia) - 1250
+
+OS Locale (lcid: 2c1a, name: sr-Latn-ME): Serbian (Latin) (Montenegro) - 1250
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sr_ME_#Latn, Name: Serbian (Latin,Montenegro)
+default charset: windows-1252
+
+OS Locale (lcid: 3001, name: ar-LB): Arabic (Lebanon) - 1256
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_LB, Name: Arabic (Lebanon)
+default charset: windows-1252
+
+OS Locale (lcid: 3009, name: en-ZW): English (Zimbabwe) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_ZW, Name: English (Zimbabwe)
+default charset: windows-1252
+
+OS Locale (lcid: 300a, name: es-EC): Spanish (Ecuador) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_EC, Name: Spanish (Ecuador)
+default charset: windows-1252
+
+OS Locale (lcid: 301a, name: sr-Cyrl-ME): Serbian (Cyrillic) (Montenegro) - 1251
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_RS, Name: Serbian (Serbia)
+format locale: ID: sr_ME_#Cyrl, Name: Serbian (Cyrillic,Montenegro)
+default charset: windows-1252
+
+OS Locale (lcid: 3401, name: ar-KW): Arabic (Kuwait) - 1256
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_KW, Name: Arabic (Kuwait)
+default charset: windows-1252
+
+OS Locale (lcid: 3409, name: en-PH): English (Republic of the Philippines) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_PH, Name: English (Philippines)
+default charset: windows-1252
+
+OS Locale (lcid: 340a, name: es-CL): Spanish (Chile) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_CL, Name: Spanish (Chile)
 default charset: windows-1252
-
-OS Locale (lcid: 243b, name: smn): Sami (Inari) (Finland) - 1252
+
+OS Locale (lcid: 3801, name: ar-AE): Arabic (U.A.E.) - 1256
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
+default charset: windows-1252
+
+OS Locale (lcid: 380a, name: es-UY): Spanish (Uruguay) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_UY, Name: Spanish (Uruguay)
+default charset: windows-1252
+
+OS Locale (lcid: 3c01, name: ar-BH): Arabic (Bahrain) - 1256
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_BH, Name: Arabic (Bahrain)
+default charset: windows-1252
+
+OS Locale (lcid: 3c0a, name: es-PY): Spanish (Paraguay) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_PY, Name: Spanish (Paraguay)
+default charset: windows-1252
+
+OS Locale (lcid: 4001, name: ar-QA): Arabic (Qatar) - 1256
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_QA, Name: Arabic (Qatar)
+default charset: windows-1252
+
+OS Locale (lcid: 4009, name: en-IN): English (India) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_IN, Name: English (India)
+default charset: windows-1252
+
+OS Locale (lcid: 400a, name: es-BO): Spanish (Bolivia) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_BO, Name: Spanish (Bolivia)
+default charset: windows-1252
+
+OS Locale (lcid: 4409, name: en-MY): English (Malaysia) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_MY, Name: English (Malaysia)
+default charset: windows-1252
+
+OS Locale (lcid: 440a, name: es-SV): Spanish (El Salvador) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_SV, Name: Spanish (El Salvador)
 default charset: windows-1252
-
-OS Locale (lcid: 243b, name: smn-FI): Sami (Inari) (Finland) - 1252
+
+OS Locale (lcid: 4809, name: en-SG): English (Singapore) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_SG, Name: English (Singapore)
+default charset: windows-1252
+
+OS Locale (lcid: 480a, name: es-HN): Spanish (Honduras) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_HN, Name: Spanish (Honduras)
+default charset: windows-1252
+
+OS Locale (lcid: 4c0a, name: es-NI): Spanish (Nicaragua) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_NI, Name: Spanish (Nicaragua)
+default charset: windows-1252
+
+OS Locale (lcid: 500a, name: es-PR): Spanish (Puerto Rico) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_PR, Name: Spanish (Puerto Rico)
+default charset: windows-1252
+
+OS Locale (lcid: 540a, name: es-US): Spanish (United States) - 1252
+default locale: ID: en_US, Name: English (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_US, Name: Spanish (United States)
+default charset: windows-1252
+
+OS UI Language (name: en-US)
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_US, Name: English (United States)
 default charset: windows-1252
-
-OS Locale (lcid: 2801, name: ar-SY): Arabic (Syria) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_SY, Name: Arabic (Syria)
-default charset: windows-1252
-
-OS Locale (lcid: 2809, name: en-BZ): English (Belize) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 280a, name: es-PE): Spanish (Peru) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_PE, Name: Spanish (Peru)
-default charset: windows-1252
-
-OS Locale (lcid: 281a, name: sr-Cyrl-RS): Serbian (Cyrillic) (Serbia) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_RS, Name: Serbian (Serbia)
-default charset: windows-1252
-
-OS Locale (lcid: 281a, name: sr-Cyrl): Serbian (Cyrillic) (Serbia) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_RS, Name: Serbian (Serbia)
-default charset: windows-1252
-
-OS Locale (lcid: 2c01, name: ar-JO): Arabic (Jordan) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_JO, Name: Arabic (Jordan)
-default charset: windows-1252
-
-OS Locale (lcid: 2c09, name: en-TT): English (Trinidad and Tobago) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 2c0a, name: es-AR): Spanish (Argentina) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_AR, Name: Spanish (Argentina)
-default charset: windows-1252
-
-OS Locale (lcid: 2c1a, name: sr-Latn-ME): Serbian (Latin) (Montenegro) - 1250
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_ME, Name: Serbian (Montenegro)
-default charset: windows-1252
-
-OS Locale (lcid: 3001, name: ar-LB): Arabic (Lebanon) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_LB, Name: Arabic (Lebanon)
-default charset: windows-1252
-
-OS Locale (lcid: 3009, name: en-ZW): English (Zimbabwe) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 300a, name: es-EC): Spanish (Ecuador) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_EC, Name: Spanish (Ecuador)
-default charset: windows-1252
-
-OS Locale (lcid: 301a, name: sr-Cyrl-ME): Serbian (Cyrillic) (Montenegro) - 1251
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_ME, Name: Serbian (Montenegro)
-default charset: windows-1252
-
-OS Locale (lcid: 3401, name: ar-KW): Arabic (Kuwait) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_KW, Name: Arabic (Kuwait)
-default charset: windows-1252
-
-OS Locale (lcid: 3409, name: en-PH): English (Republic of the Philippines) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 340a, name: es-CL): Spanish (Chile) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_CL, Name: Spanish (Chile)
-default charset: windows-1252
-
-OS Locale (lcid: 3801, name: ar-AE): Arabic (U.A.E.) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
-default charset: windows-1252
-
-OS Locale (lcid: 380a, name: es-UY): Spanish (Uruguay) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_UY, Name: Spanish (Uruguay)
-default charset: windows-1252
-
-OS Locale (lcid: 3c01, name: ar-BH): Arabic (Bahrain) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_BH, Name: Arabic (Bahrain)
-default charset: windows-1252
-
-OS Locale (lcid: 3c0a, name: es-PY): Spanish (Paraguay) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_PY, Name: Spanish (Paraguay)
-default charset: windows-1252
-
-OS Locale (lcid: 4001, name: ar-QA): Arabic (Qatar) - 1256
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_QA, Name: Arabic (Qatar)
-default charset: windows-1252
-
-OS Locale (lcid: 4009, name: en-IN): English (India) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 400a, name: es-BO): Spanish (Bolivia) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_BO, Name: Spanish (Bolivia)
-default charset: windows-1252
-
-OS Locale (lcid: 4409, name: en-MY): English (Malaysia) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 440a, name: es-SV): Spanish (El Salvador) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_SV, Name: Spanish (El Salvador)
-default charset: windows-1252
-
-OS Locale (lcid: 4809, name: en-SG): English (Singapore) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 480a, name: es-HN): Spanish (Honduras) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_HN, Name: Spanish (Honduras)
-default charset: windows-1252
-
-OS Locale (lcid: 4c0a, name: es-NI): Spanish (Nicaragua) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_NI, Name: Spanish (Nicaragua)
-default charset: windows-1252
-
-OS Locale (lcid: 500a, name: es-PR): Spanish (Puerto Rico) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_PR, Name: Spanish (Puerto Rico)
-default charset: windows-1252
-
-OS Locale (lcid: 540a, name: es-US): Spanish (United States) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es, Name: Spanish
-default charset: windows-1252
-
-OS UI Language (name: en-US)
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS UI Language (name: ja-JP)
+
+OS UI Language (name: ja-JP)
 default locale: ID: ja_JP, Name: Japanese (Japan)
 display locale: ID: ja_JP, Name: Japanese (Japan)
 format locale: ID: en_US, Name: English (United States)
--- a/jdk/test/java/util/Locale/data/deflocale.win7.fmtasdefault	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/java/util/Locale/data/deflocale.win7.fmtasdefault	Wed Jul 05 17:26:57 2017 +0200
@@ -1,1493 +1,1493 @@
-# OSVersionInfo
-# MajorVersion: 6
-# MinorVersion: 1
-# BuildNumber: 7600
-# CSDVersion: 
-
-
-OS Locale (lcid: 7f, name: ): Invariant Language (Invariant Country) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 401, name: ar-SA): Arabic (Saudi Arabia) - 1256
-default locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
-default charset: windows-1256
-
-OS Locale (lcid: 402, name: bg-BG): Bulgarian (Bulgaria) - 1251
-default locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
-default charset: windows-1251
-
-OS Locale (lcid: 403, name: ca-ES): Catalan (Spain) - 1252
-default locale: ID: ca_ES, Name: Catalan (Spain)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ca_ES, Name: Catalan (Spain)
-default charset: windows-1252
-
-OS Locale (lcid: 404, name: zh-TW): Chinese (Traditional) (Taiwan) - 950
-default locale: ID: zh_TW, Name: Chinese (Taiwan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: zh_TW, Name: Chinese (Taiwan)
-default charset: x-windows-950
-
-OS Locale (lcid: 405, name: cs-CZ): Czech (Czech Republic) - 1250
-default locale: ID: cs_CZ, Name: Czech (Czech Republic)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: cs_CZ, Name: Czech (Czech Republic)
-default charset: windows-1250
-
-OS Locale (lcid: 406, name: da-DK): Danish (Denmark) - 1252
-default locale: ID: da_DK, Name: Danish (Denmark)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: da_DK, Name: Danish (Denmark)
-default charset: windows-1252
-
-OS Locale (lcid: 407, name: de-DE): German (Germany) - 1252
-default locale: ID: de_DE, Name: German (Germany)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: de_DE, Name: German (Germany)
-default charset: windows-1252
-
-OS Locale (lcid: 408, name: el-GR): Greek (Greece) - 1253
-default locale: ID: el_GR, Name: Greek (Greece)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: el_GR, Name: Greek (Greece)
-default charset: windows-1253
-
-OS Locale (lcid: 409, name: en-US): English (United States) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 40b, name: fi-FI): Finnish (Finland) - 1252
-default locale: ID: fi_FI, Name: Finnish (Finland)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fi_FI, Name: Finnish (Finland)
-default charset: windows-1252
-
-OS Locale (lcid: 40c, name: fr-FR): French (France) - 1252
-default locale: ID: fr_FR, Name: French (France)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fr_FR, Name: French (France)
-default charset: windows-1252
-
-OS Locale (lcid: 40d, name: he-IL): Hebrew (Israel) - 1255
-default locale: ID: iw_IL, Name: Hebrew (Israel)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: iw_IL, Name: Hebrew (Israel)
-default charset: windows-1255
-
-OS Locale (lcid: 40e, name: hu-HU): Hungarian (Hungary) - 1250
-default locale: ID: hu_HU, Name: Hungarian (Hungary)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: hu_HU, Name: Hungarian (Hungary)
-default charset: windows-1250
-
-OS Locale (lcid: 40f, name: is-IS): Icelandic (Iceland) - 1252
-default locale: ID: is_IS, Name: Icelandic (Iceland)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: is_IS, Name: Icelandic (Iceland)
-default charset: windows-1252
-
-OS Locale (lcid: 410, name: it-IT): Italian (Italy) - 1252
-default locale: ID: it_IT, Name: Italian (Italy)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: it_IT, Name: Italian (Italy)
-default charset: windows-1252
-
-OS Locale (lcid: 411, name: ja-JP): Japanese (Japan) - 932
-default locale: ID: ja_JP, Name: Japanese (Japan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ja_JP, Name: Japanese (Japan)
-default charset: windows-31j
-
-OS Locale (lcid: 412, name: ko-KR): Korean (Korea) - 949
-default locale: ID: ko_KR, Name: Korean (South Korea)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ko_KR, Name: Korean (South Korea)
-default charset: x-windows-949
-
-OS Locale (lcid: 413, name: nl-NL): Dutch (Netherlands) - 1252
-default locale: ID: nl_NL, Name: Dutch (Netherlands)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: nl_NL, Name: Dutch (Netherlands)
-default charset: windows-1252
-
-OS Locale (lcid: 414, name: nb-NO): Norwegian (Bokmål) (Norway) - 1252
-default locale: ID: no_NO, Name: Norwegian (Norway)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: no_NO, Name: Norwegian (Norway)
-default charset: windows-1252
-
-OS Locale (lcid: 415, name: pl-PL): Polish (Poland) - 1250
-default locale: ID: pl_PL, Name: Polish (Poland)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: pl_PL, Name: Polish (Poland)
-default charset: windows-1250
-
-OS Locale (lcid: 416, name: pt-BR): Portuguese (Brazil) - 1252
-default locale: ID: pt_BR, Name: Portuguese (Brazil)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: pt_BR, Name: Portuguese (Brazil)
-default charset: windows-1252
-
-OS Locale (lcid: 417, name: rm-CH): Romansh (Switzerland) - 1252
-default locale: ID: rm_CH, Name: Raeto-Romance (Switzerland)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: rm_CH, Name: Raeto-Romance (Switzerland)
-default charset: windows-1252
-
-OS Locale (lcid: 418, name: ro-RO): Romanian (Romania) - 1250
-default locale: ID: ro_RO, Name: Romanian (Romania)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ro_RO, Name: Romanian (Romania)
-default charset: windows-1250
-
-OS Locale (lcid: 419, name: ru-RU): Russian (Russia) - 1251
-default locale: ID: ru_RU, Name: Russian (Russia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ru_RU, Name: Russian (Russia)
-default charset: windows-1251
-
-OS Locale (lcid: 41a, name: hr-HR): Croatian (Croatia) - 1250
-default locale: ID: hr_HR, Name: Croatian (Croatia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: hr_HR, Name: Croatian (Croatia)
-default charset: windows-1250
-
-OS Locale (lcid: 41b, name: sk-SK): Slovak (Slovakia) - 1250
-default locale: ID: sk_SK, Name: Slovak (Slovakia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sk_SK, Name: Slovak (Slovakia)
-default charset: windows-1250
-
-OS Locale (lcid: 41c, name: sq-AL): Albanian (Albania) - 1250
-default locale: ID: sq_AL, Name: Albanian (Albania)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sq_AL, Name: Albanian (Albania)
-default charset: windows-1250
-
-OS Locale (lcid: 41d, name: sv-SE): Swedish (Sweden) - 1252
-default locale: ID: sv_SE, Name: Swedish (Sweden)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sv_SE, Name: Swedish (Sweden)
-default charset: windows-1252
-
-OS Locale (lcid: 41e, name: th-TH): Thai (Thailand) - 874
-default locale: ID: th_TH, Name: Thai (Thailand)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: th_TH, Name: Thai (Thailand)
-default charset: x-windows-874
-
-OS Locale (lcid: 41f, name: tr-TR): Turkish (Turkey) - 1254
-default locale: ID: tr_TR, Name: Turkish (Turkey)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tr_TR, Name: Turkish (Turkey)
-default charset: windows-1254
-
-OS Locale (lcid: 420, name: ur-PK): Urdu (Islamic Republic of Pakistan) - 1256
-default locale: ID: ur_PK, Name: Urdu (Pakistan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ur_PK, Name: Urdu (Pakistan)
-default charset: windows-1256
-
-OS Locale (lcid: 421, name: id-ID): Indonesian (Indonesia) - 1252
-default locale: ID: in_ID, Name: Indonesian (Indonesia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: in_ID, Name: Indonesian (Indonesia)
-default charset: windows-1252
-
-OS Locale (lcid: 422, name: uk-UA): Ukrainian (Ukraine) - 1251
-default locale: ID: uk_UA, Name: Ukrainian (Ukraine)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: uk_UA, Name: Ukrainian (Ukraine)
-default charset: windows-1251
-
-OS Locale (lcid: 423, name: be-BY): Belarusian (Belarus) - 1251
-default locale: ID: be_BY, Name: Belarusian (Belarus)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: be_BY, Name: Belarusian (Belarus)
-default charset: windows-1251
-
-OS Locale (lcid: 424, name: sl-SI): Slovenian (Slovenia) - 1250
-default locale: ID: sl_SI, Name: Slovenian (Slovenia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sl_SI, Name: Slovenian (Slovenia)
-default charset: windows-1250
-
-OS Locale (lcid: 425, name: et-EE): Estonian (Estonia) - 1257
-default locale: ID: et_EE, Name: Estonian (Estonia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: et_EE, Name: Estonian (Estonia)
-default charset: windows-1257
-
-OS Locale (lcid: 426, name: lv-LV): Latvian (Latvia) - 1257
-default locale: ID: lv_LV, Name: Latvian (Latvia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: lv_LV, Name: Latvian (Latvia)
-default charset: windows-1257
-
-OS Locale (lcid: 427, name: lt-LT): Lithuanian (Lithuania) - 1257
-default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
-default charset: windows-1257
-
-OS Locale (lcid: 428, name: tg-Cyrl-TJ): Tajik (Cyrillic) (Tajikistan) - 1251
-default locale: ID: tg_TJ, Name: Tajik (Tajikistan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tg_TJ, Name: Tajik (Tajikistan)
-default charset: windows-1251
-
-OS Locale (lcid: 428, name: tg-Cyrl): Tajik (Cyrillic) (Tajikistan) - 1251
-default locale: ID: tg_TJ, Name: Tajik (Tajikistan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tg_TJ, Name: Tajik (Tajikistan)
-default charset: windows-1251
-
-OS Locale (lcid: 429, name: fa-IR): Persian (Iran) - 1256
-default locale: ID: fa_IR, Name: Persian (Iran)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fa_IR, Name: Persian (Iran)
-default charset: windows-1256
-
-OS Locale (lcid: 42a, name: vi-VN): Vietnamese (Vietnam) - 1258
-default locale: ID: vi_VN, Name: Vietnamese (Vietnam)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: vi_VN, Name: Vietnamese (Vietnam)
-default charset: windows-1258
-
-OS Locale (lcid: 42b, name: hy-AM): Armenian (Armenia) - 0
-default locale: ID: hy_AM, Name: Armenian (Armenia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: hy_AM, Name: Armenian (Armenia)
-default charset: UTF-8
-
-OS Locale (lcid: 42c, name: az-Latn-AZ): Azeri (Latin) (Azerbaijan) - 1254
-default locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
-default charset: windows-1254
-
-OS Locale (lcid: 42c, name: az-Latn): Azeri (Latin) (Azerbaijan) - 1254
-default locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
-default charset: windows-1254
-
-OS Locale (lcid: 42d, name: eu-ES): Basque (Spain) - 1252
-default locale: ID: eu_ES, Name: Basque (Spain)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: eu_ES, Name: Basque (Spain)
-default charset: windows-1252
-
-OS Locale (lcid: 42e, name: hsb-DE): Upper Sorbian (Germany) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 42e, name: hsb): Upper Sorbian (Germany) - 1252
+# OSVersionInfo
+# MajorVersion: 6
+# MinorVersion: 1
+# BuildNumber: 7600
+# CSDVersion: 
+
+
+OS Locale (lcid: 7f, name: ): Invariant Language (Invariant Country) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_US, Name: English (United States)
 default charset: windows-1252
-
-OS Locale (lcid: 42f, name: mk-MK): Macedonian (FYROM) (Macedonia (FYROM)) - 1251
-default locale: ID: mk_MK, Name: Macedonian (Macedonia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mk_MK, Name: Macedonian (Macedonia)
-default charset: windows-1251
-
-OS Locale (lcid: 432, name: tn-ZA): Setswana (South Africa) - 1252
-default locale: ID: tn_ZA, Name: Tswana (South Africa)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tn_ZA, Name: Tswana (South Africa)
-default charset: windows-1252
-
-OS Locale (lcid: 434, name: xh-ZA): isiXhosa (South Africa) - 1252
-default locale: ID: xh_ZA, Name: Xhosa (South Africa)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: xh_ZA, Name: Xhosa (South Africa)
-default charset: windows-1252
-
-OS Locale (lcid: 435, name: zu-ZA): isiZulu (South Africa) - 1252
-default locale: ID: zu_ZA, Name: Zulu (South Africa)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: zu_ZA, Name: Zulu (South Africa)
-default charset: windows-1252
-
-OS Locale (lcid: 436, name: af-ZA): Afrikaans (South Africa) - 1252
-default locale: ID: af_ZA, Name: Afrikaans (South Africa)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: af_ZA, Name: Afrikaans (South Africa)
-default charset: windows-1252
-
-OS Locale (lcid: 437, name: ka-GE): Georgian (Georgia) - 0
-default locale: ID: ka_GE, Name: Georgian (Georgia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ka_GE, Name: Georgian (Georgia)
-default charset: UTF-8
-
-OS Locale (lcid: 438, name: fo-FO): Faroese (Faroe Islands) - 1252
-default locale: ID: fo_FO, Name: Faroese (Faroe Islands)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fo_FO, Name: Faroese (Faroe Islands)
-default charset: windows-1252
-
-OS Locale (lcid: 439, name: hi-IN): Hindi (India) - 0
-default locale: ID: hi_IN, Name: Hindi (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: hi_IN, Name: Hindi (India)
-default charset: UTF-8
-
-OS Locale (lcid: 43a, name: mt-MT): Maltese (Malta) - 0
-default locale: ID: mt_MT, Name: Maltese (Malta)
+
+OS Locale (lcid: 401, name: ar-SA): Arabic (Saudi Arabia) - 1256
+default locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: mt_MT, Name: Maltese (Malta)
-default charset: UTF-8
-
-OS Locale (lcid: 43b, name: se-NO): Sami (Northern) (Norway) - 1252
-default locale: ID: se_NO, Name: Northern Sami (Norway)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: se_NO, Name: Northern Sami (Norway)
-default charset: windows-1252
-
-OS Locale (lcid: 43e, name: ms-MY): Malay (Malaysia) - 1252
-default locale: ID: ms_MY, Name: Malay (Malaysia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ms_MY, Name: Malay (Malaysia)
-default charset: windows-1252
-
-OS Locale (lcid: 43f, name: kk-KZ): Kazakh (Kazakhstan) - 0
-default locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
-default charset: UTF-8
-
-OS Locale (lcid: 440, name: ky-KG): Kyrgyz (Kyrgyzstan) - 1251
-default locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
+format locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
+default charset: windows-1256
+
+OS Locale (lcid: 402, name: bg-BG): Bulgarian (Bulgaria) - 1251
+default locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
-default charset: windows-1251
-
-OS Locale (lcid: 441, name: sw-KE): Kiswahili (Kenya) - 1252
-default locale: ID: sw_KE, Name: Swahili (Kenya)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sw_KE, Name: Swahili (Kenya)
-default charset: windows-1252
-
-OS Locale (lcid: 442, name: tk-TM): Turkmen (Turkmenistan) - 1250
-default locale: ID: tk_TM, Name: Turkmen (Turkmenistan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tk_TM, Name: Turkmen (Turkmenistan)
-default charset: windows-1250
-
-OS Locale (lcid: 443, name: uz-Latn): Uzbek (Latin) (Uzbekistan) - 1254
-default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-default charset: windows-1254
-
-OS Locale (lcid: 443, name: uz-Latn-UZ): Uzbek (Latin) (Uzbekistan) - 1254
-default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
-default charset: windows-1254
-
-OS Locale (lcid: 444, name: tt-RU): Tatar (Russia) - 1251
-default locale: ID: tt_RU, Name: Tatar (Russia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: tt_RU, Name: Tatar (Russia)
+format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 default charset: windows-1251
-
-OS Locale (lcid: 445, name: bn-IN): Bengali (India) - 0
-default locale: ID: bn_IN, Name: Bengali (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: bn_IN, Name: Bengali (India)
-default charset: UTF-8
-
-OS Locale (lcid: 446, name: pa-IN): Punjabi (India) - 0
-default locale: ID: pa_IN, Name: Panjabi (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: pa_IN, Name: Panjabi (India)
-default charset: UTF-8
-
-OS Locale (lcid: 447, name: gu-IN): Gujarati (India) - 0
-default locale: ID: gu_IN, Name: Gujarati (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: gu_IN, Name: Gujarati (India)
-default charset: UTF-8
-
-OS Locale (lcid: 448, name: or-IN): Oriya (India) - 0
-default locale: ID: or_IN, Name: Oriya (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: or_IN, Name: Oriya (India)
-default charset: UTF-8
-
-OS Locale (lcid: 449, name: ta-IN): Tamil (India) - 0
-default locale: ID: ta_IN, Name: Tamil (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ta_IN, Name: Tamil (India)
-default charset: UTF-8
-
-OS Locale (lcid: 44a, name: te-IN): Telugu (India) - 0
-default locale: ID: te_IN, Name: Telugu (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: te_IN, Name: Telugu (India)
-default charset: UTF-8
-
-OS Locale (lcid: 44b, name: kn-IN): Kannada (India) - 0
-default locale: ID: kn_IN, Name: Kannada (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: kn_IN, Name: Kannada (India)
-default charset: UTF-8
-
-OS Locale (lcid: 44c, name: ml-IN): Malayalam (India) - 0
-default locale: ID: ml_IN, Name: Malayalam (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ml_IN, Name: Malayalam (India)
-default charset: UTF-8
-
-OS Locale (lcid: 44d, name: as-IN): Assamese (India) - 0
-default locale: ID: as_IN, Name: Assamese (India)
+
+OS Locale (lcid: 403, name: ca-ES): Catalan (Spain) - 1252
+default locale: ID: ca_ES, Name: Catalan (Spain)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: as_IN, Name: Assamese (India)
-default charset: UTF-8
-
-OS Locale (lcid: 44e, name: mr-IN): Marathi (India) - 0
-default locale: ID: mr_IN, Name: Marathi (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mr_IN, Name: Marathi (India)
-default charset: UTF-8
-
-OS Locale (lcid: 44f, name: sa-IN): Sanskrit (India) - 0
-default locale: ID: sa_IN, Name: Sanskrit (India)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sa_IN, Name: Sanskrit (India)
-default charset: UTF-8
-
-OS Locale (lcid: 450, name: mn-MN): Mongolian (Cyrillic) (Mongolia) - 1251
-default locale: ID: mn_MN, Name: Mongolian (Mongolia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mn_MN, Name: Mongolian (Mongolia)
-default charset: windows-1251
-
-OS Locale (lcid: 450, name: mn-Cyrl): Mongolian (Cyrillic) (Mongolia) - 1251
-default locale: ID: mn_MN, Name: Mongolian (Mongolia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mn_MN, Name: Mongolian (Mongolia)
-default charset: windows-1251
-
-OS Locale (lcid: 451, name: bo-CN): Tibetan (People's Republic of China) - 0
-default locale: ID: bo_CN, Name: Tibetan (China)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: bo_CN, Name: Tibetan (China)
-default charset: UTF-8
-
-OS Locale (lcid: 452, name: cy-GB): Welsh (United Kingdom) - 1252
-default locale: ID: cy_GB, Name: Welsh (United Kingdom)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: cy_GB, Name: Welsh (United Kingdom)
-default charset: windows-1252
-
-OS Locale (lcid: 453, name: km-KH): Khmer (Cambodia) - 0
-default locale: ID: km_KH, Name: Khmer (Cambodia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: km_KH, Name: Khmer (Cambodia)
-default charset: UTF-8
-
-OS Locale (lcid: 454, name: lo-LA): Lao (Lao P.D.R.) - 0
-default locale: ID: lo_LA, Name: Lao (Laos)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: lo_LA, Name: Lao (Laos)
-default charset: UTF-8
-
-OS Locale (lcid: 456, name: gl-ES): Galician (Spain) - 1252
-default locale: ID: gl_ES, Name: Gallegan (Spain)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: gl_ES, Name: Gallegan (Spain)
+format locale: ID: ca_ES, Name: Catalan (Spain)
 default charset: windows-1252
-
-OS Locale (lcid: 457, name: kok-IN): Konkani (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: UTF-8
-
-OS Locale (lcid: 457, name: kok): Konkani (India) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: UTF-8
-
-OS Locale (lcid: 45a, name: syr): Syriac (Syria) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: UTF-8
-
-OS Locale (lcid: 45a, name: syr-SY): Syriac (Syria) - 0
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: UTF-8
-
-OS Locale (lcid: 45b, name: si-LK): Sinhala (Sri Lanka) - 0
-default locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
-default charset: UTF-8
-
-OS Locale (lcid: 45d, name: iu-Cans-CA): Inuktitut (Syllabics) (Canada) - 0
-default locale: ID: iu_CA, Name: Inuktitut (Canada)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: iu_CA, Name: Inuktitut (Canada)
-default charset: UTF-8
-
-OS Locale (lcid: 45d, name: iu-Cans): Inuktitut (Syllabics) (Canada) - 0
-default locale: ID: iu_CA, Name: Inuktitut (Canada)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: iu_CA, Name: Inuktitut (Canada)
-default charset: UTF-8
-
-OS Locale (lcid: 45e, name: am-ET): Amharic (Ethiopia) - 0
-default locale: ID: am_ET, Name: Amharic (Ethiopia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: am_ET, Name: Amharic (Ethiopia)
-default charset: UTF-8
-
-OS Locale (lcid: 461, name: ne-NP): Nepali (Nepal) - 0
-default locale: ID: ne_NP, Name: Nepali (Nepal)
+
+OS Locale (lcid: 404, name: zh-TW): Chinese (Traditional) (Taiwan) - 950
+default locale: ID: zh_TW, Name: Chinese (Taiwan)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: ne_NP, Name: Nepali (Nepal)
-default charset: UTF-8
-
-OS Locale (lcid: 462, name: fy-NL): Frisian (Netherlands) - 1252
-default locale: ID: fy_NL, Name: Frisian (Netherlands)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: fy_NL, Name: Frisian (Netherlands)
-default charset: windows-1252
-
-OS Locale (lcid: 463, name: ps-AF): Pashto (Afghanistan) - 0
-default locale: ID: ps_AF, Name: Pushto (Afghanistan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ps_AF, Name: Pushto (Afghanistan)
-default charset: UTF-8
-
-OS Locale (lcid: 464, name: fil-PH): Filipino (Philippines) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 464, name: fil): Filipino (Philippines) - 1252
-default locale: ID: en_US, Name: English (United States)
+format locale: ID: zh_TW, Name: Chinese (Taiwan)
+default charset: x-windows-950
+
+OS Locale (lcid: 405, name: cs-CZ): Czech (Czech Republic) - 1250
+default locale: ID: cs_CZ, Name: Czech (Czech Republic)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 465, name: dv-MV): Divehi (Maldives) - 0
-default locale: ID: dv_MV, Name: Divehi (Maldives)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: dv_MV, Name: Divehi (Maldives)
-default charset: UTF-8
-
-OS Locale (lcid: 468, name: ha-Latn-NG): Hausa (Latin) (Nigeria) - 1252
-default locale: ID: ha_NG, Name: Hausa (Nigeria)
+format locale: ID: cs_CZ, Name: Czech (Czech Republic)
+default charset: windows-1250
+
+OS Locale (lcid: 406, name: da-DK): Danish (Denmark) - 1252
+default locale: ID: da_DK, Name: Danish (Denmark)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: ha_NG, Name: Hausa (Nigeria)
-default charset: windows-1252
-
-OS Locale (lcid: 468, name: ha-Latn): Hausa (Latin) (Nigeria) - 1252
-default locale: ID: ha_NG, Name: Hausa (Nigeria)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ha_NG, Name: Hausa (Nigeria)
-default charset: windows-1252
-
-OS Locale (lcid: 46a, name: yo-NG): Yoruba (Nigeria) - 1252
-default locale: ID: yo_NG, Name: Yoruba (Nigeria)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: yo_NG, Name: Yoruba (Nigeria)
-default charset: windows-1252
-
-OS Locale (lcid: 46b, name: quz): Quechua (Bolivia) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: da_DK, Name: Danish (Denmark)
 default charset: windows-1252
-
-OS Locale (lcid: 46b, name: quz-BO): Quechua (Bolivia) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 46c, name: nso): Sesotho sa Leboa (South Africa) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 46c, name: nso-ZA): Sesotho sa Leboa (South Africa) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 46d, name: ba-RU): Bashkir (Russia) - 1251
-default locale: ID: ba_RU, Name: Bashkir (Russia)
+
+OS Locale (lcid: 407, name: de-DE): German (Germany) - 1252
+default locale: ID: de_DE, Name: German (Germany)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: ba_RU, Name: Bashkir (Russia)
-default charset: windows-1251
-
-OS Locale (lcid: 46e, name: lb-LU): Luxembourgish (Luxembourg) - 1252
-default locale: ID: lb_LU, Name: Luxembourgish (Luxembourg)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: lb_LU, Name: Luxembourgish (Luxembourg)
-default charset: windows-1252
-
-OS Locale (lcid: 46f, name: kl-GL): Greenlandic (Greenland) - 1252
-default locale: ID: kl_GL, Name: Greenlandic (Greenland)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: kl_GL, Name: Greenlandic (Greenland)
-default charset: windows-1252
-
-OS Locale (lcid: 470, name: ig-NG): Igbo (Nigeria) - 1252
-default locale: ID: ig_NG, Name: Igbo (Nigeria)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ig_NG, Name: Igbo (Nigeria)
-default charset: windows-1252
-
-OS Locale (lcid: 478, name: ii-CN): Yi (People's Republic of China) - 0
-default locale: ID: ii_CN, Name: Sichuan Yi (China)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ii_CN, Name: Sichuan Yi (China)
-default charset: UTF-8
-
-OS Locale (lcid: 47a, name: arn): Mapudungun (Chile) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: de_DE, Name: German (Germany)
 default charset: windows-1252
-
-OS Locale (lcid: 47a, name: arn-CL): Mapudungun (Chile) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 47c, name: moh): Mohawk (Canada) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 47c, name: moh-CA): Mohawk (Canada) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 47e, name: br-FR): Breton (France) - 1252
-default locale: ID: br_FR, Name: Breton (France)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: br_FR, Name: Breton (France)
-default charset: windows-1252
-
-OS Locale (lcid: 480, name: ug-CN): Uyghur (People's Republic of China) - 1256
-default locale: ID: ug_CN, Name: Uighur (China)
+
+OS Locale (lcid: 408, name: el-GR): Greek (Greece) - 1253
+default locale: ID: el_GR, Name: Greek (Greece)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: ug_CN, Name: Uighur (China)
-default charset: windows-1256
-
-OS Locale (lcid: 481, name: mi-NZ): Maori (New Zealand) - 0
-default locale: ID: mi_NZ, Name: Maori (New Zealand)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: mi_NZ, Name: Maori (New Zealand)
-default charset: UTF-8
-
-OS Locale (lcid: 482, name: oc-FR): Occitan (France) - 1252
-default locale: ID: oc_FR, Name: Occitan (France)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: oc_FR, Name: Occitan (France)
-default charset: windows-1252
-
-OS Locale (lcid: 483, name: co-FR): Corsican (France) - 1252
-default locale: ID: co_FR, Name: Corsican (France)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: co_FR, Name: Corsican (France)
-default charset: windows-1252
-
-OS Locale (lcid: 484, name: gsw): Alsatian (France) - 1252
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS Locale (lcid: 484, name: gsw-FR): Alsatian (France) - 1252
+format locale: ID: el_GR, Name: Greek (Greece)
+default charset: windows-1253
+
+OS Locale (lcid: 409, name: en-US): English (United States) - 1252
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_US, Name: English (United States)
 default charset: windows-1252
-
-OS Locale (lcid: 485, name: sah): Yakut (Russia) - 1251
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 40b, name: fi-FI): Finnish (Finland) - 1252
+default locale: ID: fi_FI, Name: Finnish (Finland)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fi_FI, Name: Finnish (Finland)
+default charset: windows-1252
+
+OS Locale (lcid: 40c, name: fr-FR): French (France) - 1252
+default locale: ID: fr_FR, Name: French (France)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fr_FR, Name: French (France)
+default charset: windows-1252
+
+OS Locale (lcid: 40d, name: he-IL): Hebrew (Israel) - 1255
+default locale: ID: iw_IL, Name: Hebrew (Israel)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: iw_IL, Name: Hebrew (Israel)
+default charset: windows-1255
+
+OS Locale (lcid: 40e, name: hu-HU): Hungarian (Hungary) - 1250
+default locale: ID: hu_HU, Name: Hungarian (Hungary)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hu_HU, Name: Hungarian (Hungary)
+default charset: windows-1250
+
+OS Locale (lcid: 40f, name: is-IS): Icelandic (Iceland) - 1252
+default locale: ID: is_IS, Name: Icelandic (Iceland)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: is_IS, Name: Icelandic (Iceland)
+default charset: windows-1252
+
+OS Locale (lcid: 410, name: it-IT): Italian (Italy) - 1252
+default locale: ID: it_IT, Name: Italian (Italy)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: it_IT, Name: Italian (Italy)
+default charset: windows-1252
+
+OS Locale (lcid: 411, name: ja-JP): Japanese (Japan) - 932
+default locale: ID: ja_JP, Name: Japanese (Japan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ja_JP, Name: Japanese (Japan)
+default charset: windows-31j
+
+OS Locale (lcid: 412, name: ko-KR): Korean (Korea) - 949
+default locale: ID: ko_KR, Name: Korean (South Korea)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ko_KR, Name: Korean (South Korea)
+default charset: x-windows-949
+
+OS Locale (lcid: 413, name: nl-NL): Dutch (Netherlands) - 1252
+default locale: ID: nl_NL, Name: Dutch (Netherlands)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: nl_NL, Name: Dutch (Netherlands)
+default charset: windows-1252
+
+OS Locale (lcid: 414, name: nb-NO): Norwegian (Bokm…l) (Norway) - 1252
+default locale: ID: no_NO, Name: Norwegian (Norway)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: no_NO, Name: Norwegian (Norway)
+default charset: windows-1252
+
+OS Locale (lcid: 415, name: pl-PL): Polish (Poland) - 1250
+default locale: ID: pl_PL, Name: Polish (Poland)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: pl_PL, Name: Polish (Poland)
+default charset: windows-1250
+
+OS Locale (lcid: 416, name: pt-BR): Portuguese (Brazil) - 1252
+default locale: ID: pt_BR, Name: Portuguese (Brazil)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: pt_BR, Name: Portuguese (Brazil)
+default charset: windows-1252
+
+OS Locale (lcid: 417, name: rm-CH): Romansh (Switzerland) - 1252
+default locale: ID: rm_CH, Name: Raeto-Romance (Switzerland)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: rm_CH, Name: Raeto-Romance (Switzerland)
+default charset: windows-1252
+
+OS Locale (lcid: 418, name: ro-RO): Romanian (Romania) - 1250
+default locale: ID: ro_RO, Name: Romanian (Romania)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ro_RO, Name: Romanian (Romania)
+default charset: windows-1250
+
+OS Locale (lcid: 419, name: ru-RU): Russian (Russia) - 1251
+default locale: ID: ru_RU, Name: Russian (Russia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ru_RU, Name: Russian (Russia)
+default charset: windows-1251
+
+OS Locale (lcid: 41a, name: hr-HR): Croatian (Croatia) - 1250
+default locale: ID: hr_HR, Name: Croatian (Croatia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hr_HR, Name: Croatian (Croatia)
+default charset: windows-1250
+
+OS Locale (lcid: 41b, name: sk-SK): Slovak (Slovakia) - 1250
+default locale: ID: sk_SK, Name: Slovak (Slovakia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sk_SK, Name: Slovak (Slovakia)
+default charset: windows-1250
+
+OS Locale (lcid: 41c, name: sq-AL): Albanian (Albania) - 1250
+default locale: ID: sq_AL, Name: Albanian (Albania)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sq_AL, Name: Albanian (Albania)
+default charset: windows-1250
+
+OS Locale (lcid: 41d, name: sv-SE): Swedish (Sweden) - 1252
+default locale: ID: sv_SE, Name: Swedish (Sweden)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sv_SE, Name: Swedish (Sweden)
+default charset: windows-1252
+
+OS Locale (lcid: 41e, name: th-TH): Thai (Thailand) - 874
+default locale: ID: th_TH, Name: Thai (Thailand)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: th_TH, Name: Thai (Thailand)
+default charset: x-windows-874
+
+OS Locale (lcid: 41f, name: tr-TR): Turkish (Turkey) - 1254
+default locale: ID: tr_TR, Name: Turkish (Turkey)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tr_TR, Name: Turkish (Turkey)
+default charset: windows-1254
+
+OS Locale (lcid: 420, name: ur-PK): Urdu (Islamic Republic of Pakistan) - 1256
+default locale: ID: ur_PK, Name: Urdu (Pakistan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ur_PK, Name: Urdu (Pakistan)
+default charset: windows-1256
+
+OS Locale (lcid: 421, name: id-ID): Indonesian (Indonesia) - 1252
+default locale: ID: in_ID, Name: Indonesian (Indonesia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: in_ID, Name: Indonesian (Indonesia)
+default charset: windows-1252
+
+OS Locale (lcid: 422, name: uk-UA): Ukrainian (Ukraine) - 1251
+default locale: ID: uk_UA, Name: Ukrainian (Ukraine)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: uk_UA, Name: Ukrainian (Ukraine)
+default charset: windows-1251
+
+OS Locale (lcid: 423, name: be-BY): Belarusian (Belarus) - 1251
+default locale: ID: be_BY, Name: Belarusian (Belarus)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: be_BY, Name: Belarusian (Belarus)
 default charset: windows-1251
-
-OS Locale (lcid: 485, name: sah-RU): Yakut (Russia) - 1251
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 424, name: sl-SI): Slovenian (Slovenia) - 1250
+default locale: ID: sl_SI, Name: Slovenian (Slovenia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sl_SI, Name: Slovenian (Slovenia)
+default charset: windows-1250
+
+OS Locale (lcid: 425, name: et-EE): Estonian (Estonia) - 1257
+default locale: ID: et_EE, Name: Estonian (Estonia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: et_EE, Name: Estonian (Estonia)
+default charset: windows-1257
+
+OS Locale (lcid: 426, name: lv-LV): Latvian (Latvia) - 1257
+default locale: ID: lv_LV, Name: Latvian (Latvia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: lv_LV, Name: Latvian (Latvia)
+default charset: windows-1257
+
+OS Locale (lcid: 427, name: lt-LT): Lithuanian (Lithuania) - 1257
+default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
+default charset: windows-1257
+
+OS Locale (lcid: 428, name: tg-Cyrl-TJ): Tajik (Cyrillic) (Tajikistan) - 1251
+default locale: ID: tg_TJ_#Cyrl, Name: Tajik (Cyrillic,Tajikistan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tg_TJ_#Cyrl, Name: Tajik (Cyrillic,Tajikistan)
+default charset: windows-1251
+
+OS Locale (lcid: 428, name: tg-Cyrl): Tajik (Cyrillic) (Tajikistan) - 1251
+default locale: ID: tg_TJ_#Cyrl, Name: Tajik (Cyrillic,Tajikistan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tg_TJ_#Cyrl, Name: Tajik (Cyrillic,Tajikistan)
+default charset: windows-1251
+
+OS Locale (lcid: 429, name: fa-IR): Persian (Iran) - 1256
+default locale: ID: fa_IR, Name: Persian (Iran)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fa_IR, Name: Persian (Iran)
+default charset: windows-1256
+
+OS Locale (lcid: 42a, name: vi-VN): Vietnamese (Vietnam) - 1258
+default locale: ID: vi_VN, Name: Vietnamese (Vietnam)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: vi_VN, Name: Vietnamese (Vietnam)
+default charset: windows-1258
+
+OS Locale (lcid: 42b, name: hy-AM): Armenian (Armenia) - 0
+default locale: ID: hy_AM, Name: Armenian (Armenia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hy_AM, Name: Armenian (Armenia)
+default charset: UTF-8
+
+OS Locale (lcid: 42c, name: az-Latn-AZ): Azeri (Latin) (Azerbaijan) - 1254
+default locale: ID: az_AZ_#Latn, Name: Azerbaijani (Latin,Azerbaijan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: az_AZ_#Latn, Name: Azerbaijani (Latin,Azerbaijan)
+default charset: windows-1254
+
+OS Locale (lcid: 42c, name: az-Latn): Azeri (Latin) (Azerbaijan) - 1254
+default locale: ID: az_AZ_#Latn, Name: Azerbaijani (Latin,Azerbaijan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: az_AZ_#Latn, Name: Azerbaijani (Latin,Azerbaijan)
+default charset: windows-1254
+
+OS Locale (lcid: 42d, name: eu-ES): Basque (Spain) - 1252
+default locale: ID: eu_ES, Name: Basque (Spain)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: eu_ES, Name: Basque (Spain)
+default charset: windows-1252
+
+OS Locale (lcid: 42e, name: hsb-DE): Upper Sorbian (Germany) - 1252
+default locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+default charset: windows-1252
+
+OS Locale (lcid: 42e, name: hsb): Upper Sorbian (Germany) - 1252
+default locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hsb_DE, Name: Upper Sorbian (Germany)
+default charset: windows-1252
+
+OS Locale (lcid: 42f, name: mk-MK): Macedonian (FYROM) (Macedonia (FYROM)) - 1251
+default locale: ID: mk_MK, Name: Macedonian (Macedonia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mk_MK, Name: Macedonian (Macedonia)
+default charset: windows-1251
+
+OS Locale (lcid: 432, name: tn-ZA): Setswana (South Africa) - 1252
+default locale: ID: tn_ZA, Name: Tswana (South Africa)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: tn_ZA, Name: Tswana (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 434, name: xh-ZA): isiXhosa (South Africa) - 1252
+default locale: ID: xh_ZA, Name: Xhosa (South Africa)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: xh_ZA, Name: Xhosa (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 435, name: zu-ZA): isiZulu (South Africa) - 1252
+default locale: ID: zu_ZA, Name: Zulu (South Africa)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: zu_ZA, Name: Zulu (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 436, name: af-ZA): Afrikaans (South Africa) - 1252
+default locale: ID: af_ZA, Name: Afrikaans (South Africa)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: af_ZA, Name: Afrikaans (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 437, name: ka-GE): Georgian (Georgia) - 0
+default locale: ID: ka_GE, Name: Georgian (Georgia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ka_GE, Name: Georgian (Georgia)
+default charset: UTF-8
+
+OS Locale (lcid: 438, name: fo-FO): Faroese (Faroe Islands) - 1252
+default locale: ID: fo_FO, Name: Faroese (Faroe Islands)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fo_FO, Name: Faroese (Faroe Islands)
+default charset: windows-1252
+
+OS Locale (lcid: 439, name: hi-IN): Hindi (India) - 0
+default locale: ID: hi_IN, Name: Hindi (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: hi_IN, Name: Hindi (India)
+default charset: UTF-8
+
+OS Locale (lcid: 43a, name: mt-MT): Maltese (Malta) - 0
+default locale: ID: mt_MT, Name: Maltese (Malta)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mt_MT, Name: Maltese (Malta)
+default charset: UTF-8
+
+OS Locale (lcid: 43b, name: se-NO): Sami (Northern) (Norway) - 1252
+default locale: ID: se_NO, Name: Northern Sami (Norway)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: se_NO, Name: Northern Sami (Norway)
+default charset: windows-1252
+
+OS Locale (lcid: 43e, name: ms-MY): Malay (Malaysia) - 1252
+default locale: ID: ms_MY, Name: Malay (Malaysia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ms_MY, Name: Malay (Malaysia)
+default charset: windows-1252
+
+OS Locale (lcid: 43f, name: kk-KZ): Kazakh (Kazakhstan) - 0
+default locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
+default charset: UTF-8
+
+OS Locale (lcid: 440, name: ky-KG): Kyrgyz (Kyrgyzstan) - 1251
+default locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
+default charset: windows-1251
+
+OS Locale (lcid: 441, name: sw-KE): Kiswahili (Kenya) - 1252
+default locale: ID: sw_KE, Name: Swahili (Kenya)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sw_KE, Name: Swahili (Kenya)
+default charset: windows-1252
+
+OS Locale (lcid: 442, name: tk-TM): Turkmen (Turkmenistan) - 1250
+default locale: ID: tk_TM, Name: Turkmen (Turkmenistan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tk_TM, Name: Turkmen (Turkmenistan)
+default charset: windows-1250
+
+OS Locale (lcid: 443, name: uz-Latn): Uzbek (Latin) (Uzbekistan) - 1254
+default locale: ID: uz_UZ_#Latn, Name: Uzbek (Latin,Uzbekistan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: uz_UZ_#Latn, Name: Uzbek (Latin,Uzbekistan)
+default charset: windows-1254
+
+OS Locale (lcid: 443, name: uz-Latn-UZ): Uzbek (Latin) (Uzbekistan) - 1254
+default locale: ID: uz_UZ_#Latn, Name: Uzbek (Latin,Uzbekistan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: uz_UZ_#Latn, Name: Uzbek (Latin,Uzbekistan)
+default charset: windows-1254
+
+OS Locale (lcid: 444, name: tt-RU): Tatar (Russia) - 1251
+default locale: ID: tt_RU, Name: Tatar (Russia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: tt_RU, Name: Tatar (Russia)
 default charset: windows-1251
-
-OS Locale (lcid: 486, name: qut): K'iche (Guatemala) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 445, name: bn-IN): Bengali (India) - 0
+default locale: ID: bn_IN, Name: Bengali (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: bn_IN, Name: Bengali (India)
+default charset: UTF-8
+
+OS Locale (lcid: 446, name: pa-IN): Punjabi (India) - 0
+default locale: ID: pa_IN, Name: Panjabi (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: pa_IN, Name: Panjabi (India)
+default charset: UTF-8
+
+OS Locale (lcid: 447, name: gu-IN): Gujarati (India) - 0
+default locale: ID: gu_IN, Name: Gujarati (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: gu_IN, Name: Gujarati (India)
+default charset: UTF-8
+
+OS Locale (lcid: 448, name: or-IN): Oriya (India) - 0
+default locale: ID: or_IN, Name: Oriya (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: or_IN, Name: Oriya (India)
+default charset: UTF-8
+
+OS Locale (lcid: 449, name: ta-IN): Tamil (India) - 0
+default locale: ID: ta_IN, Name: Tamil (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ta_IN, Name: Tamil (India)
+default charset: UTF-8
+
+OS Locale (lcid: 44a, name: te-IN): Telugu (India) - 0
+default locale: ID: te_IN, Name: Telugu (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: te_IN, Name: Telugu (India)
+default charset: UTF-8
+
+OS Locale (lcid: 44b, name: kn-IN): Kannada (India) - 0
+default locale: ID: kn_IN, Name: Kannada (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kn_IN, Name: Kannada (India)
+default charset: UTF-8
+
+OS Locale (lcid: 44c, name: ml-IN): Malayalam (India) - 0
+default locale: ID: ml_IN, Name: Malayalam (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ml_IN, Name: Malayalam (India)
+default charset: UTF-8
+
+OS Locale (lcid: 44d, name: as-IN): Assamese (India) - 0
+default locale: ID: as_IN, Name: Assamese (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: as_IN, Name: Assamese (India)
+default charset: UTF-8
+
+OS Locale (lcid: 44e, name: mr-IN): Marathi (India) - 0
+default locale: ID: mr_IN, Name: Marathi (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mr_IN, Name: Marathi (India)
+default charset: UTF-8
+
+OS Locale (lcid: 44f, name: sa-IN): Sanskrit (India) - 0
+default locale: ID: sa_IN, Name: Sanskrit (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sa_IN, Name: Sanskrit (India)
+default charset: UTF-8
+
+OS Locale (lcid: 450, name: mn-MN): Mongolian (Cyrillic) (Mongolia) - 1251
+default locale: ID: mn_MN, Name: Mongolian (Mongolia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mn_MN, Name: Mongolian (Mongolia)
+default charset: windows-1251
+
+OS Locale (lcid: 450, name: mn-Cyrl): Mongolian (Cyrillic) (Mongolia) - 1251
+default locale: ID: mn_MN, Name: Mongolian (Mongolia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mn_MN, Name: Mongolian (Mongolia)
+default charset: windows-1251
+
+OS Locale (lcid: 451, name: bo-CN): Tibetan (People's Republic of China) - 0
+default locale: ID: bo_CN, Name: Tibetan (China)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: bo_CN, Name: Tibetan (China)
+default charset: UTF-8
+
+OS Locale (lcid: 452, name: cy-GB): Welsh (United Kingdom) - 1252
+default locale: ID: cy_GB, Name: Welsh (United Kingdom)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: cy_GB, Name: Welsh (United Kingdom)
+default charset: windows-1252
+
+OS Locale (lcid: 453, name: km-KH): Khmer (Cambodia) - 0
+default locale: ID: km_KH, Name: Khmer (Cambodia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: km_KH, Name: Khmer (Cambodia)
+default charset: UTF-8
+
+OS Locale (lcid: 454, name: lo-LA): Lao (Lao P.D.R.) - 0
+default locale: ID: lo_LA, Name: Lao (Laos)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: lo_LA, Name: Lao (Laos)
+default charset: UTF-8
+
+OS Locale (lcid: 456, name: gl-ES): Galician (Spain) - 1252
+default locale: ID: gl_ES, Name: Gallegan (Spain)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: gl_ES, Name: Gallegan (Spain)
+default charset: windows-1252
+
+OS Locale (lcid: 457, name: kok-IN): Konkani (India) - 0
+default locale: ID: kok_IN, Name: Konkani (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kok_IN, Name: Konkani (India)
+default charset: UTF-8
+
+OS Locale (lcid: 457, name: kok): Konkani (India) - 0
+default locale: ID: kok_IN, Name: Konkani (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kok_IN, Name: Konkani (India)
+default charset: UTF-8
+
+OS Locale (lcid: 45a, name: syr): Syriac (Syria) - 0
+default locale: ID: syr_SY, Name: Syriac (Syria)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: syr_SY, Name: Syriac (Syria)
+default charset: UTF-8
+
+OS Locale (lcid: 45a, name: syr-SY): Syriac (Syria) - 0
+default locale: ID: syr_SY, Name: Syriac (Syria)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: syr_SY, Name: Syriac (Syria)
+default charset: UTF-8
+
+OS Locale (lcid: 45b, name: si-LK): Sinhala (Sri Lanka) - 0
+default locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
+default charset: UTF-8
+
+OS Locale (lcid: 45d, name: iu-Cans-CA): Inuktitut (Syllabics) (Canada) - 0
+default locale: ID: iu_CA_#Cans, Name: Inuktitut (Unified Canadian Aboriginal Syllabics,Canada)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: iu_CA_#Cans, Name: Inuktitut (Unified Canadian Aboriginal Syllabics,Canada)
+default charset: UTF-8
+
+OS Locale (lcid: 45d, name: iu-Cans): Inuktitut (Syllabics) (Canada) - 0
+default locale: ID: iu_CA_#Cans, Name: Inuktitut (Unified Canadian Aboriginal Syllabics,Canada)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: iu_CA_#Cans, Name: Inuktitut (Unified Canadian Aboriginal Syllabics,Canada)
+default charset: UTF-8
+
+OS Locale (lcid: 45e, name: am-ET): Amharic (Ethiopia) - 0
+default locale: ID: am_ET, Name: Amharic (Ethiopia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: am_ET, Name: Amharic (Ethiopia)
+default charset: UTF-8
+
+OS Locale (lcid: 461, name: ne-NP): Nepali (Nepal) - 0
+default locale: ID: ne_NP, Name: Nepali (Nepal)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ne_NP, Name: Nepali (Nepal)
+default charset: UTF-8
+
+OS Locale (lcid: 462, name: fy-NL): Frisian (Netherlands) - 1252
+default locale: ID: fy_NL, Name: Frisian (Netherlands)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fy_NL, Name: Frisian (Netherlands)
 default charset: windows-1252
-
-OS Locale (lcid: 486, name: qut-GT): K'iche (Guatemala) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 463, name: ps-AF): Pashto (Afghanistan) - 0
+default locale: ID: ps_AF, Name: Pushto (Afghanistan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ps_AF, Name: Pushto (Afghanistan)
+default charset: UTF-8
+
+OS Locale (lcid: 464, name: fil-PH): Filipino (Philippines) - 1252
+default locale: ID: fil_PH, Name: Filipino (Philippines)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fil_PH, Name: Filipino (Philippines)
+default charset: windows-1252
+
+OS Locale (lcid: 464, name: fil): Filipino (Philippines) - 1252
+default locale: ID: fil_PH, Name: Filipino (Philippines)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: fil_PH, Name: Filipino (Philippines)
+default charset: windows-1252
+
+OS Locale (lcid: 465, name: dv-MV): Divehi (Maldives) - 0
+default locale: ID: dv_MV, Name: Divehi (Maldives)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: dv_MV, Name: Divehi (Maldives)
+default charset: UTF-8
+
+OS Locale (lcid: 468, name: ha-Latn-NG): Hausa (Latin) (Nigeria) - 1252
+default locale: ID: ha_NG_#Latn, Name: Hausa (Latin,Nigeria)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ha_NG_#Latn, Name: Hausa (Latin,Nigeria)
+default charset: windows-1252
+
+OS Locale (lcid: 468, name: ha-Latn): Hausa (Latin) (Nigeria) - 1252
+default locale: ID: ha_NG_#Latn, Name: Hausa (Latin,Nigeria)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ha_NG_#Latn, Name: Hausa (Latin,Nigeria)
+default charset: windows-1252
+
+OS Locale (lcid: 46a, name: yo-NG): Yoruba (Nigeria) - 1252
+default locale: ID: yo_NG, Name: Yoruba (Nigeria)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: yo_NG, Name: Yoruba (Nigeria)
+default charset: windows-1252
+
+OS Locale (lcid: 46b, name: quz): Quechua (Bolivia) - 1252
+default locale: ID: quz_BO, Name: quz (Bolivia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: quz_BO, Name: quz (Bolivia)
+default charset: windows-1252
+
+OS Locale (lcid: 46b, name: quz-BO): Quechua (Bolivia) - 1252
+default locale: ID: quz_BO, Name: quz (Bolivia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: quz_BO, Name: quz (Bolivia)
+default charset: windows-1252
+
+OS Locale (lcid: 46c, name: nso): Sesotho sa Leboa (South Africa) - 1252
+default locale: ID: nso_ZA, Name: Pedi (South Africa)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: nso_ZA, Name: Pedi (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 46c, name: nso-ZA): Sesotho sa Leboa (South Africa) - 1252
+default locale: ID: nso_ZA, Name: Pedi (South Africa)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: nso_ZA, Name: Pedi (South Africa)
+default charset: windows-1252
+
+OS Locale (lcid: 46d, name: ba-RU): Bashkir (Russia) - 1251
+default locale: ID: ba_RU, Name: Bashkir (Russia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ba_RU, Name: Bashkir (Russia)
+default charset: windows-1251
+
+OS Locale (lcid: 46e, name: lb-LU): Luxembourgish (Luxembourg) - 1252
+default locale: ID: lb_LU, Name: Luxembourgish (Luxembourg)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: lb_LU, Name: Luxembourgish (Luxembourg)
+default charset: windows-1252
+
+OS Locale (lcid: 46f, name: kl-GL): Greenlandic (Greenland) - 1252
+default locale: ID: kl_GL, Name: Greenlandic (Greenland)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: kl_GL, Name: Greenlandic (Greenland)
+default charset: windows-1252
+
+OS Locale (lcid: 470, name: ig-NG): Igbo (Nigeria) - 1252
+default locale: ID: ig_NG, Name: Igbo (Nigeria)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ig_NG, Name: Igbo (Nigeria)
+default charset: windows-1252
+
+OS Locale (lcid: 478, name: ii-CN): Yi (People's Republic of China) - 0
+default locale: ID: ii_CN, Name: Sichuan Yi (China)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: ii_CN, Name: Sichuan Yi (China)
+default charset: UTF-8
+
+OS Locale (lcid: 47a, name: arn): Mapudungun (Chile) - 1252
+default locale: ID: arn_CL, Name: Mapudungun (Chile)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: arn_CL, Name: Mapudungun (Chile)
+default charset: windows-1252
+
+OS Locale (lcid: 47a, name: arn-CL): Mapudungun (Chile) - 1252
+default locale: ID: arn_CL, Name: Mapudungun (Chile)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: arn_CL, Name: Mapudungun (Chile)
+default charset: windows-1252
+
+OS Locale (lcid: 47c, name: moh): Mohawk (Canada) - 1252
+default locale: ID: moh_CA, Name: Mohawk (Canada)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: moh_CA, Name: Mohawk (Canada)
+default charset: windows-1252
+
+OS Locale (lcid: 47c, name: moh-CA): Mohawk (Canada) - 1252
+default locale: ID: moh_CA, Name: Mohawk (Canada)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: moh_CA, Name: Mohawk (Canada)
+default charset: windows-1252
+
+OS Locale (lcid: 47e, name: br-FR): Breton (France) - 1252
+default locale: ID: br_FR, Name: Breton (France)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: br_FR, Name: Breton (France)
 default charset: windows-1252
-
-OS Locale (lcid: 487, name: rw-RW): Kinyarwanda (Rwanda) - 1252
+
+OS Locale (lcid: 480, name: ug-CN): Uyghur (People's Republic of China) - 1256
+default locale: ID: ug_CN, Name: Uighur (China)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ug_CN, Name: Uighur (China)
+default charset: windows-1256
+
+OS Locale (lcid: 481, name: mi-NZ): Maori (New Zealand) - 0
+default locale: ID: mi_NZ, Name: Maori (New Zealand)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: mi_NZ, Name: Maori (New Zealand)
+default charset: UTF-8
+
+OS Locale (lcid: 482, name: oc-FR): Occitan (France) - 1252
+default locale: ID: oc_FR, Name: Occitan (France)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: oc_FR, Name: Occitan (France)
+default charset: windows-1252
+
+OS Locale (lcid: 483, name: co-FR): Corsican (France) - 1252
+default locale: ID: co_FR, Name: Corsican (France)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: co_FR, Name: Corsican (France)
+default charset: windows-1252
+
+OS Locale (lcid: 484, name: gsw): Alsatian (France) - 1252
+default locale: ID: gsw_FR, Name: Swiss German (France)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: gsw_FR, Name: Swiss German (France)
+default charset: windows-1252
+
+OS Locale (lcid: 484, name: gsw-FR): Alsatian (France) - 1252
+default locale: ID: gsw_FR, Name: Swiss German (France)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: gsw_FR, Name: Swiss German (France)
+default charset: windows-1252
+
+OS Locale (lcid: 485, name: sah): Yakut (Russia) - 1251
+default locale: ID: sah_RU, Name: Yakut (Russia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sah_RU, Name: Yakut (Russia)
+default charset: windows-1251
+
+OS Locale (lcid: 485, name: sah-RU): Yakut (Russia) - 1251
+default locale: ID: sah_RU, Name: Yakut (Russia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sah_RU, Name: Yakut (Russia)
+default charset: windows-1251
+
+OS Locale (lcid: 486, name: qut): K'iche (Guatemala) - 1252
+default locale: ID: qut_GT, Name: qut (Guatemala)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: qut_GT, Name: qut (Guatemala)
+default charset: windows-1252
+
+OS Locale (lcid: 486, name: qut-GT): K'iche (Guatemala) - 1252
+default locale: ID: qut_GT, Name: qut (Guatemala)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: qut_GT, Name: qut (Guatemala)
+default charset: windows-1252
+
+OS Locale (lcid: 487, name: rw-RW): Kinyarwanda (Rwanda) - 1252
 default locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
 default charset: windows-1252
-
-OS Locale (lcid: 488, name: wo-SN): Wolof (Senegal) - 1252
+
+OS Locale (lcid: 488, name: wo-SN): Wolof (Senegal) - 1252
 default locale: ID: wo_SN, Name: Wolof (Senegal)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: wo_SN, Name: Wolof (Senegal)
 default charset: windows-1252
-
-OS Locale (lcid: 48c, name: prs): Dari (Afghanistan) - 1256
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 48c, name: prs): Dari (Afghanistan) - 1256
+default locale: ID: prs_AF, Name: prs (Afghanistan)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: prs_AF, Name: prs (Afghanistan)
 default charset: windows-1256
-
-OS Locale (lcid: 48c, name: prs-AF): Dari (Afghanistan) - 1256
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 48c, name: prs-AF): Dari (Afghanistan) - 1256
+default locale: ID: prs_AF, Name: prs (Afghanistan)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: prs_AF, Name: prs (Afghanistan)
 default charset: windows-1256
-
-OS Locale (lcid: 491, name: gd-GB): Scottish Gaelic (United Kingdom) - 1252
+
+OS Locale (lcid: 491, name: gd-GB): Scottish Gaelic (United Kingdom) - 1252
 default locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
 default charset: windows-1252
-
-OS Locale (lcid: 801, name: ar-IQ): Arabic (Iraq) - 1256
+
+OS Locale (lcid: 801, name: ar-IQ): Arabic (Iraq) - 1256
 default locale: ID: ar_IQ, Name: Arabic (Iraq)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_IQ, Name: Arabic (Iraq)
 default charset: windows-1256
-
-OS Locale (lcid: 804, name: zh-Hans): Chinese (Simplified) (People's Republic of China) - 936
+
+OS Locale (lcid: 804, name: zh-Hans): Chinese (Simplified) (People's Republic of China) - 936
 default locale: ID: zh_CN, Name: Chinese (China)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_CN, Name: Chinese (China)
 default charset: GBK
-
-OS Locale (lcid: 804, name: zh-CN): Chinese (Simplified) (People's Republic of China) - 936
+
+OS Locale (lcid: 804, name: zh-CN): Chinese (Simplified) (People's Republic of China) - 936
 default locale: ID: zh_CN, Name: Chinese (China)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_CN, Name: Chinese (China)
 default charset: GBK
-
-OS Locale (lcid: 807, name: de-CH): German (Switzerland) - 1252
+
+OS Locale (lcid: 807, name: de-CH): German (Switzerland) - 1252
 default locale: ID: de_CH, Name: German (Switzerland)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: de_CH, Name: German (Switzerland)
 default charset: windows-1252
-
-OS Locale (lcid: 809, name: en-GB): English (United Kingdom) - 1252
+
+OS Locale (lcid: 809, name: en-GB): English (United Kingdom) - 1252
 default locale: ID: en_GB, Name: English (United Kingdom)
-display locale: ID: en_GB, Name: English (United Kingdom)
+display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_GB, Name: English (United Kingdom)
 default charset: windows-1252
-
-OS Locale (lcid: 80a, name: es-MX): Spanish (Mexico) - 1252
+
+OS Locale (lcid: 80a, name: es-MX): Spanish (Mexico) - 1252
 default locale: ID: es_MX, Name: Spanish (Mexico)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_MX, Name: Spanish (Mexico)
 default charset: windows-1252
-
-OS Locale (lcid: 80c, name: fr-BE): French (Belgium) - 1252
+
+OS Locale (lcid: 80c, name: fr-BE): French (Belgium) - 1252
 default locale: ID: fr_BE, Name: French (Belgium)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_BE, Name: French (Belgium)
 default charset: windows-1252
-
-OS Locale (lcid: 810, name: it-CH): Italian (Switzerland) - 1252
+
+OS Locale (lcid: 810, name: it-CH): Italian (Switzerland) - 1252
 default locale: ID: it_CH, Name: Italian (Switzerland)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: it_CH, Name: Italian (Switzerland)
 default charset: windows-1252
-
-OS Locale (lcid: 813, name: nl-BE): Dutch (Belgium) - 1252
+
+OS Locale (lcid: 813, name: nl-BE): Dutch (Belgium) - 1252
 default locale: ID: nl_BE, Name: Dutch (Belgium)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: nl_BE, Name: Dutch (Belgium)
 default charset: windows-1252
-
-OS Locale (lcid: 814, name: nn-NO): Norwegian (Nynorsk) (Norway) - 1252
+
+OS Locale (lcid: 814, name: nn-NO): Norwegian (Nynorsk) (Norway) - 1252
 default locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
 default charset: windows-1252
-
-OS Locale (lcid: 816, name: pt-PT): Portuguese (Portugal) - 1252
+
+OS Locale (lcid: 816, name: pt-PT): Portuguese (Portugal) - 1252
 default locale: ID: pt_PT, Name: Portuguese (Portugal)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: pt_PT, Name: Portuguese (Portugal)
 default charset: windows-1252
-
-OS Locale (lcid: 81a, name: sr-Latn-CS): Serbian (Latin) (Serbia and Montenegro (Former)) - 1250
-default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+
+OS Locale (lcid: 81a, name: sr-Latn-CS): Serbian (Latin) (Serbia and Montenegro (Former)) - 1250
+default locale: ID: sr_CS_#Latn, Name: Serbian (Latin,Serbia and Montenegro)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+format locale: ID: sr_CS_#Latn, Name: Serbian (Latin,Serbia and Montenegro)
 default charset: windows-1250
-
-OS Locale (lcid: 81d, name: sv-FI): Swedish (Finland) - 1252
+
+OS Locale (lcid: 81d, name: sv-FI): Swedish (Finland) - 1252
 default locale: ID: sv_FI, Name: Swedish (Finland)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: sv_FI, Name: Swedish (Finland)
 default charset: windows-1252
-
-OS Locale (lcid: 82c, name: az-Cyrl-AZ): Azeri (Cyrillic) (Azerbaijan) - 1251
-default locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
+
+OS Locale (lcid: 82c, name: az-Cyrl-AZ): Azeri (Cyrillic) (Azerbaijan) - 1251
+default locale: ID: az_AZ_#Cyrl, Name: Azerbaijani (Cyrillic,Azerbaijan)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
+format locale: ID: az_AZ_#Cyrl, Name: Azerbaijani (Cyrillic,Azerbaijan)
 default charset: windows-1251
-
-OS Locale (lcid: 82c, name: az-Cyrl): Azeri (Cyrillic) (Azerbaijan) - 1251
-default locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
+
+OS Locale (lcid: 82c, name: az-Cyrl): Azeri (Cyrillic) (Azerbaijan) - 1251
+default locale: ID: az_AZ_#Cyrl, Name: Azerbaijani (Cyrillic,Azerbaijan)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
+format locale: ID: az_AZ_#Cyrl, Name: Azerbaijani (Cyrillic,Azerbaijan)
 default charset: windows-1251
-
-OS Locale (lcid: 82e, name: dsb): Lower Sorbian (Germany) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 82e, name: dsb): Lower Sorbian (Germany) - 1252
+default locale: ID: dsb_DE, Name: Lower Sorbian (Germany)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: dsb_DE, Name: Lower Sorbian (Germany)
 default charset: windows-1252
-
-OS Locale (lcid: 82e, name: dsb-DE): Lower Sorbian (Germany) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 82e, name: dsb-DE): Lower Sorbian (Germany) - 1252
+default locale: ID: dsb_DE, Name: Lower Sorbian (Germany)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: dsb_DE, Name: Lower Sorbian (Germany)
 default charset: windows-1252
-
-OS Locale (lcid: 83b, name: se-SE): Sami (Northern) (Sweden) - 1252
+
+OS Locale (lcid: 83b, name: se-SE): Sami (Northern) (Sweden) - 1252
 default locale: ID: se_SE, Name: Northern Sami (Sweden)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: se_SE, Name: Northern Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 83c, name: ga-IE): Irish (Ireland) - 1252
+
+OS Locale (lcid: 83c, name: ga-IE): Irish (Ireland) - 1252
 default locale: ID: ga_IE, Name: Irish (Ireland)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ga_IE, Name: Irish (Ireland)
 default charset: windows-1252
-
-OS Locale (lcid: 83e, name: ms-BN): Malay (Brunei Darussalam) - 1252
+
+OS Locale (lcid: 83e, name: ms-BN): Malay (Brunei Darussalam) - 1252
 default locale: ID: ms_BN, Name: Malay (Brunei)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ms_BN, Name: Malay (Brunei)
 default charset: windows-1252
-
-OS Locale (lcid: 843, name: uz-Cyrl-UZ): Uzbek (Cyrillic) (Uzbekistan) - 1251
-default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+
+OS Locale (lcid: 843, name: uz-Cyrl-UZ): Uzbek (Cyrillic) (Uzbekistan) - 1251
+default locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+format locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 default charset: windows-1251
-
-OS Locale (lcid: 843, name: uz-Cyrl): Uzbek (Cyrillic) (Uzbekistan) - 1251
-default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+
+OS Locale (lcid: 843, name: uz-Cyrl): Uzbek (Cyrillic) (Uzbekistan) - 1251
+default locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
+format locale: ID: uz_UZ_#Cyrl, Name: Uzbek (Cyrillic,Uzbekistan)
 default charset: windows-1251
-
-OS Locale (lcid: 845, name: bn-BD): Bengali (Bangladesh) - 0
+
+OS Locale (lcid: 845, name: bn-BD): Bengali (Bangladesh) - 0
 default locale: ID: bn_BD, Name: Bengali (Bangladesh)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: bn_BD, Name: Bengali (Bangladesh)
 default charset: UTF-8
-
-OS Locale (lcid: 850, name: mn-Mong-CN): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
-default locale: ID: mn_CN, Name: Mongolian (China)
+
+OS Locale (lcid: 850, name: mn-Mong-CN): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
+default locale: ID: mn_CN_#Mong, Name: Mongolian (Mongolian,China)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: mn_CN, Name: Mongolian (China)
+format locale: ID: mn_CN_#Mong, Name: Mongolian (Mongolian,China)
 default charset: UTF-8
-
-OS Locale (lcid: 850, name: mn-Mong): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
-default locale: ID: mn_CN, Name: Mongolian (China)
+
+OS Locale (lcid: 850, name: mn-Mong): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
+default locale: ID: mn_CN_#Mong, Name: Mongolian (Mongolian,China)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: mn_CN, Name: Mongolian (China)
+format locale: ID: mn_CN_#Mong, Name: Mongolian (Mongolian,China)
 default charset: UTF-8
-
-OS Locale (lcid: 85d, name: iu-Latn): Inuktitut (Latin) (Canada) - 1252
-default locale: ID: iu_CA, Name: Inuktitut (Canada)
+
+OS Locale (lcid: 85d, name: iu-Latn): Inuktitut (Latin) (Canada) - 1252
+default locale: ID: iu_CA_#Latn, Name: Inuktitut (Latin,Canada)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: iu_CA, Name: Inuktitut (Canada)
+format locale: ID: iu_CA_#Latn, Name: Inuktitut (Latin,Canada)
 default charset: windows-1252
-
-OS Locale (lcid: 85d, name: iu-Latn-CA): Inuktitut (Latin) (Canada) - 1252
-default locale: ID: iu_CA, Name: Inuktitut (Canada)
+
+OS Locale (lcid: 85d, name: iu-Latn-CA): Inuktitut (Latin) (Canada) - 1252
+default locale: ID: iu_CA_#Latn, Name: Inuktitut (Latin,Canada)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: iu_CA, Name: Inuktitut (Canada)
+format locale: ID: iu_CA_#Latn, Name: Inuktitut (Latin,Canada)
 default charset: windows-1252
-
-OS Locale (lcid: 85f, name: tzm): Tamazight (Latin) (Algeria) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 85f, name: tzm): Tamazight (Latin) (Algeria) - 1252
+default locale: ID: tzm_DZ_#Latn, Name: tzm (Latin,Algeria)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: tzm_DZ_#Latn, Name: tzm (Latin,Algeria)
 default charset: windows-1252
-
-OS Locale (lcid: 85f, name: tzm-Latn-DZ): Tamazight (Latin) (Algeria) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 85f, name: tzm-Latn-DZ): Tamazight (Latin) (Algeria) - 1252
+default locale: ID: tzm_DZ_#Latn, Name: tzm (Latin,Algeria)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: tzm_DZ_#Latn, Name: tzm (Latin,Algeria)
 default charset: windows-1252
-
-OS Locale (lcid: 85f, name: tzm-Latn): Tamazight (Latin) (Algeria) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 85f, name: tzm-Latn): Tamazight (Latin) (Algeria) - 1252
+default locale: ID: tzm_DZ_#Latn, Name: tzm (Latin,Algeria)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: tzm_DZ_#Latn, Name: tzm (Latin,Algeria)
 default charset: windows-1252
-
-OS Locale (lcid: 86b, name: quz-EC): Quechua (Ecuador) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 86b, name: quz-EC): Quechua (Ecuador) - 1252
+default locale: ID: quz_EC, Name: quz (Ecuador)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: quz_EC, Name: quz (Ecuador)
 default charset: windows-1252
-
-OS Locale (lcid: c01, name: ar-EG): Arabic (Egypt) - 1256
+
+OS Locale (lcid: c01, name: ar-EG): Arabic (Egypt) - 1256
 default locale: ID: ar_EG, Name: Arabic (Egypt)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_EG, Name: Arabic (Egypt)
 default charset: windows-1256
-
-OS Locale (lcid: c04, name: zh-HK): Chinese (Traditional) (Hong Kong S.A.R.) - 950
+
+OS Locale (lcid: c04, name: zh-HK): Chinese (Traditional) (Hong Kong S.A.R.) - 950
 default locale: ID: zh_HK, Name: Chinese (Hong Kong)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_HK, Name: Chinese (Hong Kong)
 default charset: x-MS950-HKSCS
-
-OS Locale (lcid: c04, name: zh-Hant): Chinese (Traditional) (Hong Kong S.A.R.) - 950
+
+OS Locale (lcid: c04, name: zh-Hant): Chinese (Traditional) (Hong Kong S.A.R.) - 950
 default locale: ID: zh_HK, Name: Chinese (Hong Kong)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_HK, Name: Chinese (Hong Kong)
 default charset: x-windows-950
-
-OS Locale (lcid: c07, name: de-AT): German (Austria) - 1252
+
+OS Locale (lcid: c07, name: de-AT): German (Austria) - 1252
 default locale: ID: de_AT, Name: German (Austria)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: de_AT, Name: German (Austria)
 default charset: windows-1252
-
-OS Locale (lcid: c09, name: en-AU): English (Australia) - 1252
+
+OS Locale (lcid: c09, name: en-AU): English (Australia) - 1252
 default locale: ID: en_AU, Name: English (Australia)
-display locale: ID: en_AU, Name: English (Australia)
+display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_AU, Name: English (Australia)
 default charset: windows-1252
-
-OS Locale (lcid: c0a, name: es-ES): Spanish (Spain) - 1252
+
+OS Locale (lcid: c0a, name: es-ES): Spanish (Spain) - 1252
 default locale: ID: es_ES, Name: Spanish (Spain)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_ES, Name: Spanish (Spain)
 default charset: windows-1252
-
-OS Locale (lcid: c0c, name: fr-CA): French (Canada) - 1252
+
+OS Locale (lcid: c0c, name: fr-CA): French (Canada) - 1252
 default locale: ID: fr_CA, Name: French (Canada)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_CA, Name: French (Canada)
 default charset: windows-1252
-
-OS Locale (lcid: c1a, name: sr-Cyrl-CS): Serbian (Cyrillic) (Serbia and Montenegro (Former)) - 1251
-default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+
+OS Locale (lcid: c1a, name: sr-Cyrl-CS): Serbian (Cyrillic) (Serbia and Montenegro (Former)) - 1251
+default locale: ID: sr_CS_#Cyrl, Name: Serbian (Cyrillic,Serbia and Montenegro)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
+format locale: ID: sr_CS_#Cyrl, Name: Serbian (Cyrillic,Serbia and Montenegro)
 default charset: windows-1251
-
-OS Locale (lcid: c3b, name: se-FI): Sami (Northern) (Finland) - 1252
+
+OS Locale (lcid: c3b, name: se-FI): Sami (Northern) (Finland) - 1252
 default locale: ID: se_FI, Name: Northern Sami (Finland)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: se_FI, Name: Northern Sami (Finland)
 default charset: windows-1252
-
-OS Locale (lcid: c6b, name: quz-PE): Quechua (Peru) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: c6b, name: quz-PE): Quechua (Peru) - 1252
+default locale: ID: quz_PE, Name: quz (Peru)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: quz_PE, Name: quz (Peru)
 default charset: windows-1252
-
-OS Locale (lcid: 1001, name: ar-LY): Arabic (Libya) - 1256
+
+OS Locale (lcid: 1001, name: ar-LY): Arabic (Libya) - 1256
 default locale: ID: ar_LY, Name: Arabic (Libya)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_LY, Name: Arabic (Libya)
 default charset: windows-1256
-
-OS Locale (lcid: 1004, name: zh-SG): Chinese (Simplified) (Singapore) - 936
+
+OS Locale (lcid: 1004, name: zh-SG): Chinese (Simplified) (Singapore) - 936
 default locale: ID: zh_SG, Name: Chinese (Singapore)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_SG, Name: Chinese (Singapore)
 default charset: GBK
-
-OS Locale (lcid: 1007, name: de-LU): German (Luxembourg) - 1252
+
+OS Locale (lcid: 1007, name: de-LU): German (Luxembourg) - 1252
 default locale: ID: de_LU, Name: German (Luxembourg)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: de_LU, Name: German (Luxembourg)
 default charset: windows-1252
-
-OS Locale (lcid: 1009, name: en-CA): English (Canada) - 1252
+
+OS Locale (lcid: 1009, name: en-CA): English (Canada) - 1252
 default locale: ID: en_CA, Name: English (Canada)
-display locale: ID: en_CA, Name: English (Canada)
+display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_CA, Name: English (Canada)
 default charset: windows-1252
-
-OS Locale (lcid: 100a, name: es-GT): Spanish (Guatemala) - 1252
+
+OS Locale (lcid: 100a, name: es-GT): Spanish (Guatemala) - 1252
 default locale: ID: es_GT, Name: Spanish (Guatemala)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_GT, Name: Spanish (Guatemala)
 default charset: windows-1252
-
-OS Locale (lcid: 100c, name: fr-CH): French (Switzerland) - 1252
+
+OS Locale (lcid: 100c, name: fr-CH): French (Switzerland) - 1252
 default locale: ID: fr_CH, Name: French (Switzerland)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_CH, Name: French (Switzerland)
 default charset: windows-1252
-
-OS Locale (lcid: 101a, name: hr-BA): Croatian (Latin) (Bosnia and Herzegovina) - 1250
+
+OS Locale (lcid: 101a, name: hr-BA): Croatian (Latin) (Bosnia and Herzegovina) - 1250
 default locale: ID: hr_BA, Name: Croatian (Bosnia and Herzegovina)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: hr_BA, Name: Croatian (Bosnia and Herzegovina)
 default charset: windows-1250
-
-OS Locale (lcid: 103b, name: smj-NO): Sami (Lule) (Norway) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 103b, name: smj-NO): Sami (Lule) (Norway) - 1252
+default locale: ID: smj_NO, Name: Lule Sami (Norway)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: smj_NO, Name: Lule Sami (Norway)
 default charset: windows-1252
-
-OS Locale (lcid: 1401, name: ar-DZ): Arabic (Algeria) - 1256
+
+OS Locale (lcid: 1401, name: ar-DZ): Arabic (Algeria) - 1256
 default locale: ID: ar_DZ, Name: Arabic (Algeria)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_DZ, Name: Arabic (Algeria)
 default charset: windows-1256
-
-OS Locale (lcid: 1404, name: zh-MO): Chinese (Traditional) (Macao S.A.R.) - 950
+
+OS Locale (lcid: 1404, name: zh-MO): Chinese (Traditional) (Macao S.A.R.) - 950
 default locale: ID: zh_MO, Name: Chinese (Macao)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: zh_MO, Name: Chinese (Macao)
 default charset: x-windows-950
-
-OS Locale (lcid: 1407, name: de-LI): German (Liechtenstein) - 1252
+
+OS Locale (lcid: 1407, name: de-LI): German (Liechtenstein) - 1252
 default locale: ID: de_LI, Name: German (Liechtenstein)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: de_LI, Name: German (Liechtenstein)
 default charset: windows-1252
-
-OS Locale (lcid: 1409, name: en-NZ): English (New Zealand) - 1252
+
+OS Locale (lcid: 1409, name: en-NZ): English (New Zealand) - 1252
 default locale: ID: en_NZ, Name: English (New Zealand)
-display locale: ID: en_NZ, Name: English (New Zealand)
+display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_NZ, Name: English (New Zealand)
 default charset: windows-1252
-
-OS Locale (lcid: 140a, name: es-CR): Spanish (Costa Rica) - 1252
+
+OS Locale (lcid: 140a, name: es-CR): Spanish (Costa Rica) - 1252
 default locale: ID: es_CR, Name: Spanish (Costa Rica)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_CR, Name: Spanish (Costa Rica)
 default charset: windows-1252
-
-OS Locale (lcid: 140c, name: fr-LU): French (Luxembourg) - 1252
+
+OS Locale (lcid: 140c, name: fr-LU): French (Luxembourg) - 1252
 default locale: ID: fr_LU, Name: French (Luxembourg)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_LU, Name: French (Luxembourg)
 default charset: windows-1252
-
-OS Locale (lcid: 141a, name: bs-Latn): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
-default locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+
+OS Locale (lcid: 141a, name: bs-Latn): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
+default locale: ID: bs_BA_#Latn, Name: Bosnian (Latin,Bosnia and Herzegovina)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+format locale: ID: bs_BA_#Latn, Name: Bosnian (Latin,Bosnia and Herzegovina)
 default charset: windows-1250
-
-OS Locale (lcid: 141a, name: bs-Latn-BA): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
-default locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+
+OS Locale (lcid: 141a, name: bs-Latn-BA): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
+default locale: ID: bs_BA_#Latn, Name: Bosnian (Latin,Bosnia and Herzegovina)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+format locale: ID: bs_BA_#Latn, Name: Bosnian (Latin,Bosnia and Herzegovina)
 default charset: windows-1250
-
-OS Locale (lcid: 143b, name: smj-SE): Sami (Lule) (Sweden) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 143b, name: smj-SE): Sami (Lule) (Sweden) - 1252
+default locale: ID: smj_SE, Name: Lule Sami (Sweden)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: smj_SE, Name: Lule Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 143b, name: smj): Sami (Lule) (Sweden) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 143b, name: smj): Sami (Lule) (Sweden) - 1252
+default locale: ID: smj_SE, Name: Lule Sami (Sweden)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: smj_SE, Name: Lule Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 1801, name: ar-MA): Arabic (Morocco) - 1256
+
+OS Locale (lcid: 1801, name: ar-MA): Arabic (Morocco) - 1256
 default locale: ID: ar_MA, Name: Arabic (Morocco)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_MA, Name: Arabic (Morocco)
 default charset: windows-1256
-
-OS Locale (lcid: 1809, name: en-IE): English (Ireland) - 1252
+
+OS Locale (lcid: 1809, name: en-IE): English (Ireland) - 1252
 default locale: ID: en_IE, Name: English (Ireland)
-display locale: ID: en_IE, Name: English (Ireland)
+display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_IE, Name: English (Ireland)
 default charset: windows-1252
-
-OS Locale (lcid: 180a, name: es-PA): Spanish (Panama) - 1252
+
+OS Locale (lcid: 180a, name: es-PA): Spanish (Panama) - 1252
 default locale: ID: es_PA, Name: Spanish (Panama)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_PA, Name: Spanish (Panama)
 default charset: windows-1252
-
-OS Locale (lcid: 180c, name: fr-MC): French (Principality of Monaco) - 1252
+
+OS Locale (lcid: 180c, name: fr-MC): French (Principality of Monaco) - 1252
 default locale: ID: fr_MC, Name: French (Monaco)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: fr_MC, Name: French (Monaco)
 default charset: windows-1252
-
-OS Locale (lcid: 181a, name: sr-Latn-BA): Serbian (Latin) (Bosnia and Herzegovina) - 1250
-default locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
+
+OS Locale (lcid: 181a, name: sr-Latn-BA): Serbian (Latin) (Bosnia and Herzegovina) - 1250
+default locale: ID: sr_BA_#Latn, Name: Serbian (Latin,Bosnia and Herzegovina)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
+format locale: ID: sr_BA_#Latn, Name: Serbian (Latin,Bosnia and Herzegovina)
 default charset: windows-1250
-
-OS Locale (lcid: 183b, name: sma-NO): Sami (Southern) (Norway) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 183b, name: sma-NO): Sami (Southern) (Norway) - 1252
+default locale: ID: sma_NO, Name: Southern Sami (Norway)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sma_NO, Name: Southern Sami (Norway)
 default charset: windows-1252
-
-OS Locale (lcid: 1c01, name: ar-TN): Arabic (Tunisia) - 1256
+
+OS Locale (lcid: 1c01, name: ar-TN): Arabic (Tunisia) - 1256
 default locale: ID: ar_TN, Name: Arabic (Tunisia)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_TN, Name: Arabic (Tunisia)
 default charset: windows-1256
-
-OS Locale (lcid: 1c09, name: en-ZA): English (South Africa) - 1252
+
+OS Locale (lcid: 1c09, name: en-ZA): English (South Africa) - 1252
 default locale: ID: en_ZA, Name: English (South Africa)
-display locale: ID: en_ZA, Name: English (South Africa)
+display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_ZA, Name: English (South Africa)
 default charset: windows-1252
-
-OS Locale (lcid: 1c0a, name: es-DO): Spanish (Dominican Republic) - 1252
+
+OS Locale (lcid: 1c0a, name: es-DO): Spanish (Dominican Republic) - 1252
 default locale: ID: es_DO, Name: Spanish (Dominican Republic)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_DO, Name: Spanish (Dominican Republic)
 default charset: windows-1252
-
-OS Locale (lcid: 1c1a, name: sr-Cyrl-BA): Serbian (Cyrillic) (Bosnia and Herzegovina) - 1251
-default locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
+
+OS Locale (lcid: 1c1a, name: sr-Cyrl-BA): Serbian (Cyrillic) (Bosnia and Herzegovina) - 1251
+default locale: ID: sr_BA_#Cyrl, Name: Serbian (Cyrillic,Bosnia and Herzegovina)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
+format locale: ID: sr_BA_#Cyrl, Name: Serbian (Cyrillic,Bosnia and Herzegovina)
 default charset: windows-1251
-
-OS Locale (lcid: 1c3b, name: sma): Sami (Southern) (Sweden) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 1c3b, name: sma): Sami (Southern) (Sweden) - 1252
+default locale: ID: sma_SE, Name: Southern Sami (Sweden)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sma_SE, Name: Southern Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 1c3b, name: sma-SE): Sami (Southern) (Sweden) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 1c3b, name: sma-SE): Sami (Southern) (Sweden) - 1252
+default locale: ID: sma_SE, Name: Southern Sami (Sweden)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sma_SE, Name: Southern Sami (Sweden)
 default charset: windows-1252
-
-OS Locale (lcid: 2001, name: ar-OM): Arabic (Oman) - 1256
+
+OS Locale (lcid: 2001, name: ar-OM): Arabic (Oman) - 1256
 default locale: ID: ar_OM, Name: Arabic (Oman)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_OM, Name: Arabic (Oman)
 default charset: windows-1256
-
-OS Locale (lcid: 2009, name: en-JM): English (Jamaica) - 1252
+
+OS Locale (lcid: 2009, name: en-JM): English (Jamaica) - 1252
 default locale: ID: en_JM, Name: English (Jamaica)
-display locale: ID: en_JM, Name: English (Jamaica)
+display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_JM, Name: English (Jamaica)
 default charset: windows-1252
-
-OS Locale (lcid: 200a, name: es-VE): Spanish (Bolivarian Republic of Venezuela) - 1252
+
+OS Locale (lcid: 200a, name: es-VE): Spanish (Bolivarian Republic of Venezuela) - 1252
 default locale: ID: es_VE, Name: Spanish (Venezuela)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_VE, Name: Spanish (Venezuela)
 default charset: windows-1252
-
-OS Locale (lcid: 201a, name: bs-Cyrl-BA): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
-default locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+
+OS Locale (lcid: 201a, name: bs-Cyrl-BA): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
+default locale: ID: bs_BA_#Cyrl, Name: Bosnian (Cyrillic,Bosnia and Herzegovina)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+format locale: ID: bs_BA_#Cyrl, Name: Bosnian (Cyrillic,Bosnia and Herzegovina)
 default charset: windows-1251
-
-OS Locale (lcid: 201a, name: bs-Cyrl): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
-default locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+
+OS Locale (lcid: 201a, name: bs-Cyrl): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
+default locale: ID: bs_BA_#Cyrl, Name: Bosnian (Cyrillic,Bosnia and Herzegovina)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
+format locale: ID: bs_BA_#Cyrl, Name: Bosnian (Cyrillic,Bosnia and Herzegovina)
 default charset: windows-1251
-
-OS Locale (lcid: 203b, name: sms-FI): Sami (Skolt) (Finland) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 203b, name: sms-FI): Sami (Skolt) (Finland) - 1252
+default locale: ID: sms_FI, Name: Skolt Sami (Finland)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sms_FI, Name: Skolt Sami (Finland)
 default charset: windows-1252
-
-OS Locale (lcid: 203b, name: sms): Sami (Skolt) (Finland) - 1252
-default locale: ID: en_US, Name: English (United States)
+
+OS Locale (lcid: 203b, name: sms): Sami (Skolt) (Finland) - 1252
+default locale: ID: sms_FI, Name: Skolt Sami (Finland)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: sms_FI, Name: Skolt Sami (Finland)
 default charset: windows-1252
-
-OS Locale (lcid: 2401, name: ar-YE): Arabic (Yemen) - 1256
+
+OS Locale (lcid: 2401, name: ar-YE): Arabic (Yemen) - 1256
 default locale: ID: ar_YE, Name: Arabic (Yemen)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: ar_YE, Name: Arabic (Yemen)
 default charset: windows-1256
-
-OS Locale (lcid: 2409, name: en-029): English (Caribbean) - 1252
-default locale: ID: en, Name: English
-display locale: ID: en, Name: English
-format locale: ID: en, Name: English
+
+OS Locale (lcid: 2409, name: en-029): English (Caribbean) - 1252
+default locale: ID: en_029, Name: English (Caribbean)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_029, Name: English (Caribbean)
 default charset: windows-1252
-
-OS Locale (lcid: 240a, name: es-CO): Spanish (Colombia) - 1252
+
+OS Locale (lcid: 240a, name: es-CO): Spanish (Colombia) - 1252
 default locale: ID: es_CO, Name: Spanish (Colombia)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: es_CO, Name: Spanish (Colombia)
 default charset: windows-1252
-
-OS Locale (lcid: 241a, name: sr-Latn-RS): Serbian (Latin) (Serbia) - 1250
-default locale: ID: sr_RS, Name: Serbian (Serbia)
+
+OS Locale (lcid: 241a, name: sr-Latn-RS): Serbian (Latin) (Serbia) - 1250
+default locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+default charset: windows-1250
+
+OS Locale (lcid: 241a, name: sr-Latn): Serbian (Latin) (Serbia) - 1250
+default locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sr_RS_#Latn, Name: Serbian (Latin,Serbia)
+default charset: windows-1250
+
+OS Locale (lcid: 243b, name: smn): Sami (Inari) (Finland) - 1252
+default locale: ID: smn_FI, Name: Inari Sami (Finland)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: smn_FI, Name: Inari Sami (Finland)
+default charset: windows-1252
+
+OS Locale (lcid: 243b, name: smn-FI): Sami (Inari) (Finland) - 1252
+default locale: ID: smn_FI, Name: Inari Sami (Finland)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: smn_FI, Name: Inari Sami (Finland)
+default charset: windows-1252
+
+OS Locale (lcid: 2801, name: ar-SY): Arabic (Syria) - 1256
+default locale: ID: ar_SY, Name: Arabic (Syria)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_SY, Name: Arabic (Syria)
+default charset: windows-1256
+
+OS Locale (lcid: 2809, name: en-BZ): English (Belize) - 1252
+default locale: ID: en_BZ, Name: English (Belize)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_BZ, Name: English (Belize)
+default charset: windows-1252
+
+OS Locale (lcid: 280a, name: es-PE): Spanish (Peru) - 1252
+default locale: ID: es_PE, Name: Spanish (Peru)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_PE, Name: Spanish (Peru)
+default charset: windows-1252
+
+OS Locale (lcid: 281a, name: sr-Cyrl-RS): Serbian (Cyrillic) (Serbia) - 1251
+default locale: ID: sr_RS_#Cyrl, Name: Serbian (Cyrillic,Serbia)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_RS, Name: Serbian (Serbia)
+format locale: ID: sr_RS_#Cyrl, Name: Serbian (Cyrillic,Serbia)
+default charset: windows-1251
+
+OS Locale (lcid: 281a, name: sr-Cyrl): Serbian (Cyrillic) (Serbia) - 1251
+default locale: ID: sr_RS_#Cyrl, Name: Serbian (Cyrillic,Serbia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sr_RS_#Cyrl, Name: Serbian (Cyrillic,Serbia)
+default charset: windows-1251
+
+OS Locale (lcid: 2c01, name: ar-JO): Arabic (Jordan) - 1256
+default locale: ID: ar_JO, Name: Arabic (Jordan)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_JO, Name: Arabic (Jordan)
+default charset: windows-1256
+
+OS Locale (lcid: 2c09, name: en-TT): English (Trinidad and Tobago) - 1252
+default locale: ID: en_TT, Name: English (Trinidad and Tobago)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_TT, Name: English (Trinidad and Tobago)
+default charset: windows-1252
+
+OS Locale (lcid: 2c0a, name: es-AR): Spanish (Argentina) - 1252
+default locale: ID: es_AR, Name: Spanish (Argentina)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_AR, Name: Spanish (Argentina)
+default charset: windows-1252
+
+OS Locale (lcid: 2c1a, name: sr-Latn-ME): Serbian (Latin) (Montenegro) - 1250
+default locale: ID: sr_ME_#Latn, Name: Serbian (Latin,Montenegro)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: sr_ME_#Latn, Name: Serbian (Latin,Montenegro)
 default charset: windows-1250
-
-OS Locale (lcid: 241a, name: sr-Latn): Serbian (Latin) (Serbia) - 1250
-default locale: ID: sr_RS, Name: Serbian (Serbia)
+
+OS Locale (lcid: 3001, name: ar-LB): Arabic (Lebanon) - 1256
+default locale: ID: ar_LB, Name: Arabic (Lebanon)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_LB, Name: Arabic (Lebanon)
+default charset: windows-1256
+
+OS Locale (lcid: 3009, name: en-ZW): English (Zimbabwe) - 1252
+default locale: ID: en_ZW, Name: English (Zimbabwe)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_ZW, Name: English (Zimbabwe)
+default charset: windows-1252
+
+OS Locale (lcid: 300a, name: es-EC): Spanish (Ecuador) - 1252
+default locale: ID: es_EC, Name: Spanish (Ecuador)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_EC, Name: Spanish (Ecuador)
+default charset: windows-1252
+
+OS Locale (lcid: 301a, name: sr-Cyrl-ME): Serbian (Cyrillic) (Montenegro) - 1251
+default locale: ID: sr_ME_#Cyrl, Name: Serbian (Cyrillic,Montenegro)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_RS, Name: Serbian (Serbia)
-default charset: windows-1250
-
-OS Locale (lcid: 243b, name: smn): Sami (Inari) (Finland) - 1252
-default locale: ID: en_US, Name: English (United States)
+format locale: ID: sr_ME_#Cyrl, Name: Serbian (Cyrillic,Montenegro)
+default charset: windows-1251
+
+OS Locale (lcid: 3401, name: ar-KW): Arabic (Kuwait) - 1256
+default locale: ID: ar_KW, Name: Arabic (Kuwait)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_KW, Name: Arabic (Kuwait)
+default charset: windows-1256
+
+OS Locale (lcid: 3409, name: en-PH): English (Republic of the Philippines) - 1252
+default locale: ID: en_PH, Name: English (Philippines)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_PH, Name: English (Philippines)
+default charset: windows-1252
+
+OS Locale (lcid: 340a, name: es-CL): Spanish (Chile) - 1252
+default locale: ID: es_CL, Name: Spanish (Chile)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_CL, Name: Spanish (Chile)
+default charset: windows-1252
+
+OS Locale (lcid: 3801, name: ar-AE): Arabic (U.A.E.) - 1256
+default locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
+default charset: windows-1256
+
+OS Locale (lcid: 380a, name: es-UY): Spanish (Uruguay) - 1252
+default locale: ID: es_UY, Name: Spanish (Uruguay)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_UY, Name: Spanish (Uruguay)
+default charset: windows-1252
+
+OS Locale (lcid: 3c01, name: ar-BH): Arabic (Bahrain) - 1256
+default locale: ID: ar_BH, Name: Arabic (Bahrain)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_BH, Name: Arabic (Bahrain)
+default charset: windows-1256
+
+OS Locale (lcid: 3c0a, name: es-PY): Spanish (Paraguay) - 1252
+default locale: ID: es_PY, Name: Spanish (Paraguay)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_PY, Name: Spanish (Paraguay)
+default charset: windows-1252
+
+OS Locale (lcid: 4001, name: ar-QA): Arabic (Qatar) - 1256
+default locale: ID: ar_QA, Name: Arabic (Qatar)
 display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
+format locale: ID: ar_QA, Name: Arabic (Qatar)
+default charset: windows-1256
+
+OS Locale (lcid: 4009, name: en-IN): English (India) - 1252
+default locale: ID: en_IN, Name: English (India)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_IN, Name: English (India)
+default charset: windows-1252
+
+OS Locale (lcid: 400a, name: es-BO): Spanish (Bolivia) - 1252
+default locale: ID: es_BO, Name: Spanish (Bolivia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_BO, Name: Spanish (Bolivia)
+default charset: windows-1252
+
+OS Locale (lcid: 4409, name: en-MY): English (Malaysia) - 1252
+default locale: ID: en_MY, Name: English (Malaysia)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_MY, Name: English (Malaysia)
+default charset: windows-1252
+
+OS Locale (lcid: 440a, name: es-SV): Spanish (El Salvador) - 1252
+default locale: ID: es_SV, Name: Spanish (El Salvador)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_SV, Name: Spanish (El Salvador)
 default charset: windows-1252
-
-OS Locale (lcid: 243b, name: smn-FI): Sami (Inari) (Finland) - 1252
+
+OS Locale (lcid: 4809, name: en-SG): English (Singapore) - 1252
+default locale: ID: en_SG, Name: English (Singapore)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: en_SG, Name: English (Singapore)
+default charset: windows-1252
+
+OS Locale (lcid: 480a, name: es-HN): Spanish (Honduras) - 1252
+default locale: ID: es_HN, Name: Spanish (Honduras)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_HN, Name: Spanish (Honduras)
+default charset: windows-1252
+
+OS Locale (lcid: 4c0a, name: es-NI): Spanish (Nicaragua) - 1252
+default locale: ID: es_NI, Name: Spanish (Nicaragua)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_NI, Name: Spanish (Nicaragua)
+default charset: windows-1252
+
+OS Locale (lcid: 500a, name: es-PR): Spanish (Puerto Rico) - 1252
+default locale: ID: es_PR, Name: Spanish (Puerto Rico)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_PR, Name: Spanish (Puerto Rico)
+default charset: windows-1252
+
+OS Locale (lcid: 540a, name: es-US): Spanish (United States) - 1252
+default locale: ID: es_US, Name: Spanish (United States)
+display locale: ID: en_US, Name: English (United States)
+format locale: ID: es_US, Name: Spanish (United States)
+default charset: windows-1252
+
+OS UI Language (name: en-US)
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: en_US, Name: English (United States)
 format locale: ID: en_US, Name: English (United States)
 default charset: windows-1252
-
-OS Locale (lcid: 2801, name: ar-SY): Arabic (Syria) - 1256
-default locale: ID: ar_SY, Name: Arabic (Syria)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_SY, Name: Arabic (Syria)
-default charset: windows-1256
-
-OS Locale (lcid: 2809, name: en-BZ): English (Belize) - 1252
-default locale: ID: en_BZ, Name: English (Belize)
-display locale: ID: en_BZ, Name: English (Belize)
-format locale: ID: en_BZ, Name: English (Belize)
-default charset: windows-1252
-
-OS Locale (lcid: 280a, name: es-PE): Spanish (Peru) - 1252
-default locale: ID: es_PE, Name: Spanish (Peru)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_PE, Name: Spanish (Peru)
-default charset: windows-1252
-
-OS Locale (lcid: 281a, name: sr-Cyrl-RS): Serbian (Cyrillic) (Serbia) - 1251
-default locale: ID: sr_RS, Name: Serbian (Serbia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_RS, Name: Serbian (Serbia)
-default charset: windows-1251
-
-OS Locale (lcid: 281a, name: sr-Cyrl): Serbian (Cyrillic) (Serbia) - 1251
-default locale: ID: sr_RS, Name: Serbian (Serbia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_RS, Name: Serbian (Serbia)
-default charset: windows-1251
-
-OS Locale (lcid: 2c01, name: ar-JO): Arabic (Jordan) - 1256
-default locale: ID: ar_JO, Name: Arabic (Jordan)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_JO, Name: Arabic (Jordan)
-default charset: windows-1256
-
-OS Locale (lcid: 2c09, name: en-TT): English (Trinidad and Tobago) - 1252
-default locale: ID: en_TT, Name: English (Trinidad and Tobago)
-display locale: ID: en_TT, Name: English (Trinidad and Tobago)
-format locale: ID: en_TT, Name: English (Trinidad and Tobago)
-default charset: windows-1252
-
-OS Locale (lcid: 2c0a, name: es-AR): Spanish (Argentina) - 1252
-default locale: ID: es_AR, Name: Spanish (Argentina)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_AR, Name: Spanish (Argentina)
-default charset: windows-1252
-
-OS Locale (lcid: 2c1a, name: sr-Latn-ME): Serbian (Latin) (Montenegro) - 1250
-default locale: ID: sr_ME, Name: Serbian (Montenegro)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_ME, Name: Serbian (Montenegro)
-default charset: windows-1250
-
-OS Locale (lcid: 3001, name: ar-LB): Arabic (Lebanon) - 1256
-default locale: ID: ar_LB, Name: Arabic (Lebanon)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_LB, Name: Arabic (Lebanon)
-default charset: windows-1256
-
-OS Locale (lcid: 3009, name: en-ZW): English (Zimbabwe) - 1252
-default locale: ID: en_ZW, Name: English (Zimbabwe)
-display locale: ID: en_ZW, Name: English (Zimbabwe)
-format locale: ID: en_ZW, Name: English (Zimbabwe)
-default charset: windows-1252
-
-OS Locale (lcid: 300a, name: es-EC): Spanish (Ecuador) - 1252
-default locale: ID: es_EC, Name: Spanish (Ecuador)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_EC, Name: Spanish (Ecuador)
-default charset: windows-1252
-
-OS Locale (lcid: 301a, name: sr-Cyrl-ME): Serbian (Cyrillic) (Montenegro) - 1251
-default locale: ID: sr_ME, Name: Serbian (Montenegro)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: sr_ME, Name: Serbian (Montenegro)
-default charset: windows-1251
-
-OS Locale (lcid: 3401, name: ar-KW): Arabic (Kuwait) - 1256
-default locale: ID: ar_KW, Name: Arabic (Kuwait)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_KW, Name: Arabic (Kuwait)
-default charset: windows-1256
-
-OS Locale (lcid: 3409, name: en-PH): English (Republic of the Philippines) - 1252
-default locale: ID: en_PH, Name: English (Philippines)
-display locale: ID: en_PH, Name: English (Philippines)
-format locale: ID: en_PH, Name: English (Philippines)
-default charset: windows-1252
-
-OS Locale (lcid: 340a, name: es-CL): Spanish (Chile) - 1252
-default locale: ID: es_CL, Name: Spanish (Chile)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_CL, Name: Spanish (Chile)
-default charset: windows-1252
-
-OS Locale (lcid: 3801, name: ar-AE): Arabic (U.A.E.) - 1256
-default locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
-default charset: windows-1256
-
-OS Locale (lcid: 380a, name: es-UY): Spanish (Uruguay) - 1252
-default locale: ID: es_UY, Name: Spanish (Uruguay)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_UY, Name: Spanish (Uruguay)
-default charset: windows-1252
-
-OS Locale (lcid: 3c01, name: ar-BH): Arabic (Bahrain) - 1256
-default locale: ID: ar_BH, Name: Arabic (Bahrain)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_BH, Name: Arabic (Bahrain)
-default charset: windows-1256
-
-OS Locale (lcid: 3c0a, name: es-PY): Spanish (Paraguay) - 1252
-default locale: ID: es_PY, Name: Spanish (Paraguay)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_PY, Name: Spanish (Paraguay)
-default charset: windows-1252
-
-OS Locale (lcid: 4001, name: ar-QA): Arabic (Qatar) - 1256
-default locale: ID: ar_QA, Name: Arabic (Qatar)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: ar_QA, Name: Arabic (Qatar)
-default charset: windows-1256
-
-OS Locale (lcid: 4009, name: en-IN): English (India) - 1252
-default locale: ID: en_IN, Name: English (India)
-display locale: ID: en_IN, Name: English (India)
-format locale: ID: en_IN, Name: English (India)
-default charset: windows-1252
-
-OS Locale (lcid: 400a, name: es-BO): Spanish (Bolivia) - 1252
-default locale: ID: es_BO, Name: Spanish (Bolivia)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_BO, Name: Spanish (Bolivia)
-default charset: windows-1252
-
-OS Locale (lcid: 4409, name: en-MY): English (Malaysia) - 1252
-default locale: ID: en_MY, Name: English (Malaysia)
-display locale: ID: en_MY, Name: English (Malaysia)
-format locale: ID: en_MY, Name: English (Malaysia)
-default charset: windows-1252
-
-OS Locale (lcid: 440a, name: es-SV): Spanish (El Salvador) - 1252
-default locale: ID: es_SV, Name: Spanish (El Salvador)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_SV, Name: Spanish (El Salvador)
-default charset: windows-1252
-
-OS Locale (lcid: 4809, name: en-SG): English (Singapore) - 1252
-default locale: ID: en_SG, Name: English (Singapore)
-display locale: ID: en_SG, Name: English (Singapore)
-format locale: ID: en_SG, Name: English (Singapore)
-default charset: windows-1252
-
-OS Locale (lcid: 480a, name: es-HN): Spanish (Honduras) - 1252
-default locale: ID: es_HN, Name: Spanish (Honduras)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_HN, Name: Spanish (Honduras)
-default charset: windows-1252
-
-OS Locale (lcid: 4c0a, name: es-NI): Spanish (Nicaragua) - 1252
-default locale: ID: es_NI, Name: Spanish (Nicaragua)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_NI, Name: Spanish (Nicaragua)
-default charset: windows-1252
-
-OS Locale (lcid: 500a, name: es-PR): Spanish (Puerto Rico) - 1252
-default locale: ID: es_PR, Name: Spanish (Puerto Rico)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: es_PR, Name: Spanish (Puerto Rico)
-default charset: windows-1252
-
-OS Locale (lcid: 540a, name: es-US): Spanish (United States) - 1252
-default locale: ID: es_US, Name: Spanish (United States)
-display locale: ID: en, Name: English
-format locale: ID: es_US, Name: Spanish (United States)
-default charset: windows-1252
-
-OS UI Language (name: en-US)
-default locale: ID: en_US, Name: English (United States)
-display locale: ID: en_US, Name: English (United States)
-format locale: ID: en_US, Name: English (United States)
-default charset: windows-1252
-
-OS UI Language (name: ja-JP)
+
+OS UI Language (name: ja-JP)
 default locale: ID: en_US, Name: English (United States)
 display locale: ID: ja_JP, Name: Japanese (Japan)
 format locale: ID: en_US, Name: English (United States)
--- a/jdk/test/java/util/ResourceBundle/Bug4168625Test.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/java/util/ResourceBundle/Bug4168625Test.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,7 +25,7 @@
     @summary test Resource Bundle for bug 4168625
     @build Bug4168625Class Bug4168625Getter Bug4168625Resource Bug4168625Resource3 Bug4168625Resource3_en Bug4168625Resource3_en_CA Bug4168625Resource3_en_IE Bug4168625Resource3_en_US Bug4168625Resource2_en_US Bug4168625Resource2
     @run main/timeout=600 Bug4168625Test
-    @bug 4168625
+    @bug 4168625 6993339
 */
 /*
  *
@@ -50,9 +50,8 @@
 import java.io.*;
 
 /**
- *  This test tries to correct three efficiency problems with the caching
- *  mechanism of ResourceBundle.  All tests assume that none of the bundles
- *  have been previously loaded and cached.  It also allows concurrent loads
+ *  This test tries to correct two efficiency problems with the caching
+ *  mechanism of ResourceBundle.  It also allows concurrent loads
  *  of resource bundles to be performed if the bundles are unrelated (ex. a
  *  load of a local system resource by one thread while another thread is
  *  doing a slow load over a network).
@@ -230,83 +229,6 @@
         }
     }
 
-    /**
-     *  Previous versions of ResourceBundle exhibited the following caching behavior.
-     *  Assume the class Bug4168625Resource_en exists. Bug4168625Resource_en_US does
-     *  not.  Two threads, ThreadA and ThreadB both try to get the same bundle.
-     *  <P>
-     *  <pre>
-     *  ThreadA.getBundle("Bug4168625Resource", new Locale("en", "US"));
-     *      A-->try to load Bug4168625Resource_en_US
-     *  ThreadB.getBundle("Bug4168625Resource", new Locale("en", "US"));
-     *      B-->try to load Bug4168625Resource_en_US
-     *      B-->load Bug4168625Resource_en (#1)
-     *      A-->load Bug4168625Resource_en (#2)
-     *      A-->cache Bug4168625Resource_en (#2) as Bug4168625Resource_en
-     *      A-->cache Bug4168625Resource_en (#2) as Bug4168625Resource_en_US
-     *      A-->return Bug4168625Resource_en (#2)
-     *      B-->cache Bug4168625Resource_en (#1) as Bug4168625Resource_en
-     *      B-->cache Bug4168625Resource_en (#1) as Bug4168625Resource_en_US
-     *      B-->return Bug4168625Resource_en (#1)
-     *  </pre>
-     *  <P>
-     *  Both threads try and fail to load Bug4168625Resource_en_US.  Both
-     *  threads load Bug4168625Resource_en.  Both threads get their own copy
-     *  of the Bug4168625Resource_en resource.
-     *
-     *  The desired behavior is as follows:
-     *  <P>
-     *  <pre>
-     *  ThreadA.getBundle("Bug4168625Resource", new Locale("en", "US"));
-     *      A-->try to load Bug4168625Resource_en_US
-     *  ThreadB.getBundle("Bug4168625Resource", new Locale("en", "US"));
-     *      B-->try to load Bug4168625Resource_en_US
-     *      B-->load Bug4168625Resource_en
-     *      A-->load Bug4168625Resource_en (block in ResourceBundle.getBundle)
-     *      B-->cache Bug4168625Resource_en as Bug4168625Resource_en
-     *      B-->cache Bug4168625Resource_en as Bug4168625Resource_en_US
-     *      A-->return Bug4168625Resource_en
-     *      B-->return Bug4168625Resource_en
-     *  </pre>
-     *  <P>
-     *  Note that both threads return the same bundle object.
-     */
-    public void testConcurrentLoading1() throws Exception {
-        final Loader loader = new Loader( new String[] { "Bug4168625Class" }, new String[] { "Bug4168625Resource3_en_US", "Bug4168625Resource3_en_CA" });
-        final Class c = loader.loadClass("Bug4168625Class");
-        final Bug4168625Getter test = (Bug4168625Getter)c.newInstance();
-
-            //both threads want the same resource
-        ConcurrentLoadingThread thread1 = new ConcurrentLoadingThread(loader, test, new Locale("en", "US"));
-        ConcurrentLoadingThread thread2 = new ConcurrentLoadingThread(loader, test, new Locale("en", "US"));
-
-        thread1.start();            //start thread 1
-        loader.waitForNotify(1);    //wait for thread1 to do getBundle & block in loader
-        thread2.start();            //start second thread
-        loader.waitForNotify(2, 1000);  //wait until thread2 blocks somewhere in getBundle
-        thread1.ping();             //continue both threads
-        thread2.ping();
-
-        thread1.join();             //wait unitl both threads complete
-        thread2.join();
-
-            //Now, examine the class loads that were done.
-        loader.logClasses("Classes loaded after completion of both threads:");
-
-        boolean dups = false;
-        for (int i = loader.loadedClasses.size() - 1; i >= 0 ; i--) {
-            final Object item = loader.loadedClasses.elementAt(i);
-            loader.loadedClasses.removeElementAt(i);
-            if (loader.loadedClasses.contains(item)) {
-                logln("Resource loaded more than once: "+item);
-                dups = true;
-            }
-        }
-        if (dups) {
-            errln("ResourceBundle loaded some classes multiple times");
-        }
-    }
-
     private class ConcurrentLoadingThread extends Thread {
         private Loader loader;
         public Object bundle;
@@ -355,7 +277,7 @@
      * This test ensures that multiple resources can be loading at the same
      * time as long as they don't depend on each other in some way.
      */
-    public void testConcurrentLoading2() throws Exception {
+    public void testConcurrentLoading() throws Exception {
         final Loader loader = new Loader( new String[] { "Bug4168625Class" }, new String[] { "Bug4168625Resource3_en_US", "Bug4168625Resource3_en_CA" });
         final Class c = loader.loadClass("Bug4168625Class");
         final Bug4168625Getter test = (Bug4168625Getter)c.newInstance();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JComponent/6989617/bug6989617.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2010, 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 6989617
+   @summary Enable JComponent to control repaintings of its children
+   @author Alexander Potochkin
+   @run main bug6989617
+*/
+
+import javax.swing.*;
+import java.awt.*;
+
+public class bug6989617 {
+
+    private boolean isPaintingOrigin;
+    private boolean innerPanelRepainted, outerPanelRepainted;
+
+    public bug6989617() {
+
+        final JButton button = new JButton("button");
+
+        JPanel innerPanel = new JPanel() {
+            protected boolean isPaintingOrigin() {
+                return isPaintingOrigin;
+            }
+
+            public void repaint(long tm, int x, int y, int width, int height) {
+                if (button.getParent() != null) {
+                    innerPanelRepainted = true;
+                    if (!button.getSize().equals(new Dimension(width, height))) {
+                        throw new RuntimeException("Wrong size of the dirty area");
+                    }
+                    if (!button.getLocation().equals(new Point(x, y))) {
+                        throw new RuntimeException("Wrong location of the dirty area");
+                    }
+                }
+                super.repaint(tm, x, y, width, height);
+            }
+        };
+
+        JPanel outerPanel = new JPanel() {
+            protected boolean isPaintingOrigin() {
+                return isPaintingOrigin;
+            }
+
+            public void repaint(long tm, int x, int y, int width, int height) {
+                if (button.getParent() != null) {
+                    outerPanelRepainted = true;
+                    if (!button.getSize().equals(new Dimension(width, height))) {
+                        throw new RuntimeException("Wrong size of the dirty area");
+                    }
+                }
+                super.repaint(tm, x, y, width, height);
+            }
+        };
+
+
+        outerPanel.add(innerPanel);
+        innerPanel.add(button);
+
+        outerPanel.setSize(100, 100);
+        innerPanel.setBounds(10, 10, 50, 50);
+        button.setBounds(10, 10, 20, 20);
+
+        if (innerPanelRepainted || outerPanelRepainted) {
+            throw new RuntimeException("Repainted flag is unexpectedly on");
+        }
+        button.repaint();
+        if (innerPanelRepainted || outerPanelRepainted) {
+            throw new RuntimeException("Repainted flag is unexpectedly on");
+        }
+        isPaintingOrigin = true;
+        button.repaint();
+        if (!innerPanelRepainted || !outerPanelRepainted) {
+            throw new RuntimeException("Repainted flag is unexpectedly off");
+        }
+    }
+
+    public static void main(String... args) throws Exception {
+        new bug6989617();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JTable/6735286/bug6735286.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010, 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 6735286
+   @summary javax.swing.DefaultTableCellRender.getTableCellRendererComponent() doesn't allow passing null Tables
+   @author Pavel Porvatov
+*/
+
+import javax.swing.*;
+
+public class bug6735286 {
+    public static void main(String[] args) {
+        SwingUtilities.invokeLater(new Runnable() {
+            public void run() {
+                new JTable().getDefaultRenderer(Object.class).getTableCellRendererComponent(null, "a value",
+                        true, true, 0, 0);
+
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/plaf/basic/BasicScrollPaneUI/Test6632810.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2010, 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 6632810
+ * @summary javax.swing.plaf.basic.BasicScrollPaneUI.getBaseline(JComponent, int, int) doesn't throw NPE and IAE
+ * @author Pavel Porvatov
+ */
+
+import javax.swing.*;
+import javax.swing.plaf.basic.BasicScrollPaneUI;
+
+public class Test6632810 {
+    public static void main(String[] args) {
+        SwingUtilities.invokeLater(new Runnable() {
+            public void run() {
+                BasicScrollPaneUI ui = new BasicScrollPaneUI();
+
+                ui.installUI(new JScrollPane());
+
+                try {
+                    ui.getBaseline(null, 1, 1);
+
+                    throw new RuntimeException("getBaseline(null, 1, 1) does not throw NPE");
+                } catch (NullPointerException e) {
+                    // Ok
+                }
+
+                int[][] illegelParams = new int[][]{
+                        {-1, 1,},
+                        {1, -1,},
+                        {-1, -1,},
+                };
+
+                for (int[] illegelParam : illegelParams) {
+                    try {
+                        int width = illegelParam[0];
+                        int height = illegelParam[1];
+
+                        ui.getBaseline(new JScrollPane(), width, height);
+
+                        throw new RuntimeException("getBaseline(new JScrollPane(), " + width + ", " + height +
+                                ") does not throw IAE");
+                    } catch (IllegalArgumentException e) {
+                        // Ok
+                    }
+                }
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/misc/Version/Version.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2010, 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 6994413
+ * @summary Check the JDK and JVM version returned by sun.misc.Version
+ *          matches the versions defined in the system properties
+ * @compile -XDignore.symbol.file Version.java
+ * @run main Version
+ */
+
+import static sun.misc.Version.*;
+public class Version {
+
+    public static void main(String[] args) throws Exception {
+        VersionInfo jdk = newVersionInfo(System.getProperty("java.runtime.version"));
+        VersionInfo v1 = new VersionInfo(jdkMajorVersion(),
+                                         jdkMinorVersion(),
+                                         jdkMicroVersion(),
+                                         jdkUpdateVersion(),
+                                         jdkSpecialVersion(),
+                                         jdkBuildNumber());
+        System.out.println("JDK version = " + jdk + "  " + v1);
+        if (!jdk.equals(v1)) {
+            throw new RuntimeException("Unmatched version: " + jdk + " vs " + v1);
+        }
+        VersionInfo jvm = newVersionInfo(System.getProperty("java.vm.version"));
+        VersionInfo v2 = new VersionInfo(jvmMajorVersion(),
+                                         jvmMinorVersion(),
+                                         jvmMicroVersion(),
+                                         jvmUpdateVersion(),
+                                         jvmSpecialVersion(),
+                                         jvmBuildNumber());
+        System.out.println("JVM version = " + jvm + " " + v2);
+        if (!jvm.equals(v2)) {
+            throw new RuntimeException("Unmatched version: " + jvm + " vs " + v2);
+        }
+    }
+
+    static class VersionInfo {
+        final int major;
+        final int minor;
+        final int micro;
+        final int update;
+        final String special;
+        final int build;
+        VersionInfo(int major, int minor, int micro,
+                    int update, String special, int build) {
+            this.major = major;
+            this.minor = minor;
+            this.micro = micro;
+            this.update = update;
+            this.special = special;
+            this.build = build;
+        }
+
+        public boolean equals(VersionInfo v) {
+            return (this.major == v.major && this.minor == v.minor &&
+                    this.micro == v.micro && this.update == v.update &&
+                    this.special.equals(v.special) && this.build == v.build);
+        }
+
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append(major + "." + minor + "." + micro);
+            if (update > 0) {
+                sb.append("_" + update);
+            }
+
+            if (!special.isEmpty()) {
+                sb.append(special);
+            }
+            sb.append("-b" + build);
+            return sb.toString();
+        }
+    }
+
+    private static VersionInfo newVersionInfo(String version) throws Exception {
+        // valid format of the version string is:
+        // n.n.n[_uu[c]][-<identifer>]-bxx
+        int major = 0;
+        int minor = 0;
+        int micro = 0;
+        int update = 0;
+        String special = "";
+        int build = 0;
+        CharSequence cs = version;
+        if (cs.length() >= 5) {
+            if (Character.isDigit(cs.charAt(0)) && cs.charAt(1) == '.' &&
+                Character.isDigit(cs.charAt(2)) && cs.charAt(3) == '.' &&
+                Character.isDigit(cs.charAt(4))) {
+                major = Character.digit(cs.charAt(0), 10);
+                minor = Character.digit(cs.charAt(2), 10);
+                micro = Character.digit(cs.charAt(4), 10);
+                cs = cs.subSequence(5, cs.length());
+            } else if (Character.isDigit(cs.charAt(0)) &&
+                       Character.isDigit(cs.charAt(1)) && cs.charAt(2) == '.' &&
+                       Character.isDigit(cs.charAt(3))) {
+                // HSX has nn.n (major.minor) version
+                major = Integer.valueOf(version.substring(0, 2)).intValue();
+                minor = Character.digit(cs.charAt(3), 10);
+                cs = cs.subSequence(4, cs.length());
+            }
+            if (cs.charAt(0) == '_' && cs.length() >= 3 &&
+                Character.isDigit(cs.charAt(1)) &&
+                Character.isDigit(cs.charAt(2))) {
+                int nextChar = 3;
+                String uu = cs.subSequence(1, 3).toString();
+                update = Integer.valueOf(uu).intValue();
+                if (cs.length() >= 4) {
+                    char c = cs.charAt(3);
+                    if (c >= 'a' && c <= 'z') {
+                        special = Character.toString(c);
+                        nextChar++;
+                    }
+                }
+                cs = cs.subSequence(nextChar, cs.length());
+            }
+            if (cs.charAt(0) == '-') {
+                // skip the first character
+                // valid format: <identifier>-bxx or bxx
+                // non-product VM will have -debug|-release appended
+                cs = cs.subSequence(1, cs.length());
+                String[] res = cs.toString().split("-");
+                for (String s : res) {
+                    if (s.charAt(0) == 'b') {
+                        build =
+                            Integer.valueOf(s.substring(1, s.length())).intValue();
+                        break;
+                    }
+                }
+            }
+        }
+        return new VersionInfo(major, minor, micro, update, special, build);
+    }
+}
--- a/jdk/test/sun/net/www/http/HttpClient/B6726695.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/net/www/http/HttpClient/B6726695.java	Wed Jul 05 17:26:57 2017 +0200
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 6726695
+ * @bug 6726695 6993490
  * @summary HttpURLConnection shoul support 'Expect: 100-contimue' headers for PUT
 */
 
@@ -184,7 +184,15 @@
         out.flush();
         // Then read the body
         char[] cbuf = new char[512];
-        int l = in.read(cbuf);
+        in.read(cbuf);
+
+        /* Force the server to not respond for more that the expect 100-Continue
+         * timeout set by the HTTP handler (5000 millis). This ensures the
+         * timeout is correctly resets the default read timeout, infinity.
+         * See 6993490. */
+        System.out.println("server sleeping...");
+        try {Thread.sleep(6000); } catch (InterruptedException e) {}
+
         // finally send the 200 OK
         out.print("HTTP/1.1 200 OK");
         out.print("Server: Sun-Java-System-Web-Server/7.0\r\n");
--- a/jdk/test/sun/net/www/http/KeepAliveCache/B5045306.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/net/www/http/KeepAliveCache/B5045306.java	Wed Jul 05 17:26:57 2017 +0200
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 5045306 6356004
+ * @bug 5045306 6356004 6993490
  * @library ../../httptest/
  * @build HttpCallback HttpServer HttpTransaction
  * @run main/othervm B5045306
@@ -32,7 +32,6 @@
 
 import java.net.*;
 import java.io.*;
-import java.nio.channels.*;
 import java.lang.management.*;
 
 /* Part 1:
@@ -164,6 +163,14 @@
                     failed = true;
 
                 trans.setResponseHeader ("Content-length", Integer.toString(0));
+
+                 /* Force the server to not respond for more that the timeout
+                  * set by the keepalive cleaner (5000 millis). This ensures the
+                  * timeout is correctly resets the default read timeout,
+                  * infinity. See 6993490. */
+                System.out.println("server sleeping...");
+                try {Thread.sleep(6000); } catch (InterruptedException e) {}
+
                 trans.sendResponse(200, "OK");
             } else if(path.equals("/part2")) {
                 System.out.println("Call to /part2");
--- a/jdk/test/sun/net/www/protocol/http/ChunkedErrorStream.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/net/www/protocol/http/ChunkedErrorStream.java	Wed Jul 05 17:26:57 2017 +0200
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 6488669 6595324
+ * @bug 6488669 6595324 6993490
  * @run main/othervm ChunkedErrorStream
  * @summary Chunked ErrorStream tests
  */
@@ -48,6 +48,18 @@
  * 2) Client sends request to server and tries to
  *    getErrorStream(). 4K + 10 bytes must be read from
  *    the errorStream.
+ *
+ * Part 3: 6993490
+ *    Reuse persistent connection from part 2, the error stream
+ *    buffering will have set a reduced timeout on the socket and
+ *    tried to reset it to the default, infinity. Client must not
+ *    throw a timeout exception. If it does, it indicates that the
+ *    default timeout was not reset correctly.
+ *    If no timeout exception is thrown, it does not guarantee that
+ *    the timeout was reset correctly, as there is a potential race
+ *    between the sleeping server and the client thread. Typically,
+ *    1000 millis has been enought to reliable reproduce this problem
+ *    since the error stream buffering sets the timeout to 60 millis.
  */
 
 public class ChunkedErrorStream
@@ -75,19 +87,18 @@
         }  finally {
             httpServer.stop(1);
         }
-
     }
 
     void doClient() {
-        for (int times=0; times<2; times++) {
+        for (int times=0; times<3; times++) {
             HttpURLConnection uc = null;
             try {
                 InetSocketAddress address = httpServer.getAddress();
                 String URLStr = "http://localhost:" + address.getPort() + "/test/";
                 if (times == 0) {
-                    URLStr += 6488669;
+                    URLStr += "first";
                 } else {
-                    URLStr += 6595324;
+                    URLStr += "second";
                 }
 
                 System.out.println("Trying " + URLStr);
@@ -97,6 +108,11 @@
 
                 throw new RuntimeException("Failed: getInputStream should throw and IOException");
             }  catch (IOException e) {
+                if (e instanceof SocketTimeoutException) {
+                    e.printStackTrace();
+                    throw new RuntimeException("Failed: SocketTimeoutException should not happen");
+                }
+
                 // This is what we expect to happen.
                 InputStream es = uc.getErrorStream();
                 byte[] ba = new byte[1024];
@@ -112,7 +128,7 @@
                 if (count == 0)
                     throw new RuntimeException("Failed: ErrorStream returning 0 bytes");
 
-                if (times == 1 && count != (4096+10))
+                if (times >= 1 && count != (4096+10))
                     throw new RuntimeException("Failed: ErrorStream returning " + count +
                                                  " bytes. Expecting " + (4096+10));
 
@@ -128,13 +144,13 @@
         httpServer = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(0), 0);
 
         // create HttpServer context
-        HttpContext ctx1 = httpServer.createContext("/test/6488669", new Handler6488669());
-        HttpContext ctx2 = httpServer.createContext("/test/6595324", new Handler6595324());
+        httpServer.createContext("/test/first", new FirstHandler());
+        httpServer.createContext("/test/second", new SecondHandler());
 
         httpServer.start();
     }
 
-    class Handler6488669 implements HttpHandler {
+    class FirstHandler implements HttpHandler {
         public void handle(HttpExchange t) throws IOException {
             InputStream is = t.getRequestBody();
             byte[] ba = new byte[1024];
@@ -156,13 +172,22 @@
         }
     }
 
-    class Handler6595324 implements HttpHandler {
+    static class SecondHandler implements HttpHandler {
+        /* count greater than 0, slow response */
+        static int count = 0;
+
         public void handle(HttpExchange t) throws IOException {
             InputStream is = t.getRequestBody();
             byte[] ba = new byte[1024];
             while (is.read(ba) != -1);
             is.close();
 
+            if (count > 0) {
+                System.out.println("server sleeping...");
+                try { Thread.sleep(1000); } catch(InterruptedException e) {}
+            }
+            count++;
+
             t.sendResponseHeaders(404, 0);
             OutputStream os = t.getResponseBody();
 
--- a/jdk/test/sun/security/ec/TestEC.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/security/ec/TestEC.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2010, 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,6 +25,8 @@
  * @test
  * @bug 6840752
  * @summary  Provide out-of-the-box support for ECC algorithms
+ * @ignore JSSE supported cipher suites are changed with CR 6916074,
+ *     need to update this test case in JDK 7 soon
  * @library ../pkcs11
  * @library ../pkcs11/ec
  * @library ../pkcs11/sslecc
--- a/jdk/test/sun/security/krb5/auto/KDC.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/security/krb5/auto/KDC.java	Wed Jul 05 17:26:57 2017 +0200
@@ -245,7 +245,7 @@
                         name.indexOf('/') < 0 ?
                             PrincipalName.KRB_NT_UNKNOWN :
                             PrincipalName.KRB_NT_SRV_HST),
-                            kdc.passwords.get(name));
+                            kdc.passwords.get(name), -1, true);
             }
         }
         ktab.save();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/tools/KtabCheck.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010, 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.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import sun.security.krb5.internal.ktab.KeyTab;
+import sun.security.krb5.internal.ktab.KeyTabEntry;
+
+/**
+ * This class is called by the test ktcheck.sh and is not meant to run
+ * by itself.
+ */
+public class KtabCheck {
+    /**
+     * Checks if a keytab contains exactly the keys (kvno and etype)
+     * @param args keytabname kvno etype...
+     */
+    public static void main(String[] args) throws Exception {
+        System.out.println("Checking " + Arrays.toString(args));
+        KeyTab ktab = KeyTab.getInstance(args[0]);
+        Set<String> expected = new HashSet<String>();
+        for (int i=1; i<args.length; i += 2) {
+            expected.add(args[i]+":"+args[i+1]);
+        }
+        for (KeyTabEntry e: ktab.getEntries()) {
+            // KVNO and etype
+            String vne = e.getKey().getKeyVersionNumber() + ":" +
+                    e.getKey().getEType();
+            if (!expected.contains(vne)) {
+                throw new Exception("No " + vne + " in expected");
+            }
+            expected.remove(vne);
+        }
+        if (!expected.isEmpty()) {
+            throw new Exception("Extra elements in expected");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/tools/ktcheck.sh	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,94 @@
+#
+# Copyright (c) 2010, 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 6950546
+# @summary "ktab -d name etype" to "ktab -d name [-e etype] [kvno | all | old]"
+# @run shell ktcheck.sh
+#
+
+if [ "${TESTJAVA}" = "" ] ; then
+  JAVAC_CMD=`which javac`
+  TESTJAVA=`dirname $JAVAC_CMD`/..
+fi
+
+if [ "${TESTSRC}" = "" ] ; then
+  TESTSRC="."
+fi
+
+OS=`uname -s`
+case "$OS" in
+  CYGWIN* )
+    FS="/"
+    ;;
+  Windows_* )
+    FS="\\"
+    ;;
+  * )
+    FS="/"
+    echo "Unsupported system!"
+    exit 0;
+    ;;
+esac
+
+KEYTAB=ktab.tmp
+
+rm $KEYTAB
+${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}KtabCheck.java
+
+EXTRA_OPTIONS="-Djava.security.krb5.conf=${TESTSRC}${FS}onlythree.conf"
+KTAB="${TESTJAVA}${FS}bin${FS}ktab -J${EXTRA_OPTIONS} -k $KEYTAB -f"
+CHECK="${TESTJAVA}${FS}bin${FS}java ${EXTRA_OPTIONS} KtabCheck $KEYTAB"
+
+echo ${EXTRA_OPTIONS}
+
+$KTAB -a me mine
+$CHECK 1 16 1 23 1 17 || exit 1
+$KTAB -a me mine -n 0
+$CHECK 0 16 0 23 0 17 || exit 1
+$KTAB -a me mine -n 1 -append
+$CHECK 0 16 0 23 0 17 1 16 1 23 1 17 || exit 1
+$KTAB -a me mine -append
+$CHECK 0 16 0 23 0 17 1 16 1 23 1 17 2 16 2 23 2 17 || exit 1
+$KTAB -a me mine
+$CHECK 3 16 3 23 3 17 || exit 1
+$KTAB -a me mine -n 4 -append
+$CHECK 3 16 3 23 3 17 4 16 4 23 4 17 || exit 1
+$KTAB -a me mine -n 5 -append
+$CHECK 3 16 3 23 3 17 4 16 4 23 4 17 5 16 5 23 5 17 || exit 1
+$KTAB -a me mine -n 6 -append
+$CHECK 3 16 3 23 3 17 4 16 4 23 4 17 5 16 5 23 5 17 6 16 6 23 6 17 || exit 1
+$KTAB -d me 3
+$CHECK 4 16 4 23 4 17 5 16 5 23 5 17 6 16 6 23 6 17 || exit 1
+$KTAB -d me -e 16 6
+$CHECK 4 16 4 23 4 17 5 16 5 23 5 17 6 23 6 17 || exit 1
+$KTAB -d me -e 17 6
+$CHECK 4 16 4 23 4 17 5 16 5 23 5 17 6 23 || exit 1
+$KTAB -d me -e 16 5
+$CHECK 4 16 4 23 4 17 5 23 5 17 6 23 || exit 1
+$KTAB -d me old
+$CHECK 4 16 5 17 6 23 || exit 1
+$KTAB -d me old
+$CHECK 4 16 5 17 6 23 || exit 1
+$KTAB -d me
+$CHECK || exit 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/tools/onlythree.conf	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,9 @@
+[libdefaults]
+default_realm = LOCAL.COM
+default_tkt_enctypes = des3-cbc-sha1 rc4-hmac aes128-cts
+
+[realms]
+LOCAL.COM = {
+    kdc = localhost
+}
+
--- a/jdk/test/sun/security/pkcs11/fips/CipherTest.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/security/pkcs11/fips/CipherTest.java	Wed Jul 05 17:26:57 2017 +0200
@@ -119,6 +119,13 @@
                 return false;
             }
 
+            // ignore exportable cipher suite for TLSv1.1
+            if (protocol.equals("TLSv1.1")) {
+                if(cipherSuite.indexOf("_EXPORT_") != -1) {
+                    return false;
+                }
+            }
+
             return true;
         }
 
@@ -149,18 +156,14 @@
             cipherSuites.length * protocols.length * clientAuths.length);
         for (int i = 0; i < cipherSuites.length; i++) {
             String cipherSuite = cipherSuites[i];
-            if (peerFactory.isSupported(cipherSuite) == false) {
-                continue;
-            }
-            // skip kerberos cipher suites
-            if (cipherSuite.startsWith("TLS_KRB5")) {
-                continue;
-            }
+
             for (int j = 0; j < protocols.length; j++) {
                 String protocol = protocols[j];
-                if (protocol.equals("SSLv2Hello")) {
+
+                if (!peerFactory.isSupported(cipherSuite, protocol)) {
                     continue;
                 }
+
                 for (int k = 0; k < clientAuths.length; k++) {
                     String clientAuth = clientAuths[k];
                     if ((clientAuth != null) &&
@@ -293,11 +296,12 @@
         return ks;
     }
 
-    public static void main(PeerFactory peerFactory, KeyStore keyStore, String[] args)
-            throws Exception {
+    public static void main(PeerFactory peerFactory, KeyStore keyStore,
+            String[] args) throws Exception {
+
         long time = System.currentTimeMillis();
         String relPath;
-        if ((args.length > 0) && args[0].equals("sh")) {
+        if ((args != null) && (args.length > 0) && args[0].equals("sh")) {
             relPath = pathToStoresSH;
         } else {
             relPath = pathToStores;
@@ -345,7 +349,30 @@
 
         abstract Server newServer(CipherTest cipherTest) throws Exception;
 
-        boolean isSupported(String cipherSuite) {
+        boolean isSupported(String cipherSuite, String protocol) {
+            // skip kerberos cipher suites
+            if (cipherSuite.startsWith("TLS_KRB5")) {
+                System.out.println("Skipping unsupported test for " +
+                                    cipherSuite + " of " + protocol);
+                return false;
+            }
+
+            // skip SSLv2Hello protocol
+            if (protocol.equals("SSLv2Hello")) {
+                System.out.println("Skipping unsupported test for " +
+                                    cipherSuite + " of " + protocol);
+                return false;
+            }
+
+            // ignore exportable cipher suite for TLSv1.1
+            if (protocol.equals("TLSv1.1")) {
+                if (cipherSuite.indexOf("_EXPORT_WITH") != -1) {
+                    System.out.println("Skipping obsoleted test for " +
+                                        cipherSuite + " of " + protocol);
+                    return false;
+                }
+            }
+
             return true;
         }
     }
--- a/jdk/test/sun/security/pkcs11/fips/ClientJSSEServerJSSE.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/security/pkcs11/fips/ClientJSSEServerJSSE.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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,6 +25,8 @@
  * @test
  * @bug 6313675 6323647
  * @summary Verify that all ciphersuites work in FIPS mode
+ * @ignore JSSE supported cipher suites are changed with CR 6916074,
+ *     need to update this test case in JDK 7 soon
  * @author Andreas Sterbenz
  * @library ..
  */
--- a/jdk/test/sun/security/pkcs11/sslecc/CipherTest.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/security/pkcs11/sslecc/CipherTest.java	Wed Jul 05 17:26:57 2017 +0200
@@ -119,6 +119,13 @@
                 return false;
             }
 
+            // ignore exportable cipher suite for TLSv1.1
+            if (protocol.equals("TLSv1.1")) {
+                if(cipherSuite.indexOf("_EXPORT_") != -1) {
+                    return false;
+                }
+            }
+
             return true;
         }
 
@@ -148,18 +155,14 @@
             cipherSuites.length * protocols.length * clientAuths.length);
         for (int i = 0; i < cipherSuites.length; i++) {
             String cipherSuite = cipherSuites[i];
-            if (peerFactory.isSupported(cipherSuite) == false) {
-                continue;
-            }
-            // skip kerberos cipher suites
-            if (cipherSuite.startsWith("TLS_KRB5")) {
-                continue;
-            }
+
             for (int j = 0; j < protocols.length; j++) {
                 String protocol = protocols[j];
-                if (protocol.equals("SSLv2Hello")) {
+
+                if (!peerFactory.isSupported(cipherSuite, protocol)) {
                     continue;
                 }
+
                 for (int k = 0; k < clientAuths.length; k++) {
                     String clientAuth = clientAuths[k];
                     if ((clientAuth != null) &&
@@ -275,7 +278,6 @@
 
     // for some reason, ${test.src} has a different value when the
     // test is called from the script and when it is called directly...
-//    static String pathToStores = "../../etc";
     static String pathToStores = ".";
     static String pathToStoresSH = ".";
     static String keyStoreFile = "keystore";
@@ -336,7 +338,30 @@
 
         abstract Server newServer(CipherTest cipherTest) throws Exception;
 
-        boolean isSupported(String cipherSuite) {
+        boolean isSupported(String cipherSuite, String protocol) {
+            // skip kerberos cipher suites
+            if (cipherSuite.startsWith("TLS_KRB5")) {
+                System.out.println("Skipping unsupported test for " +
+                                    cipherSuite + " of " + protocol);
+                return false;
+            }
+
+            // skip SSLv2Hello protocol
+            if (protocol.equals("SSLv2Hello")) {
+                System.out.println("Skipping unsupported test for " +
+                                    cipherSuite + " of " + protocol);
+                return false;
+            }
+
+            // ignore exportable cipher suite for TLSv1.1
+            if (protocol.equals("TLSv1.1")) {
+                if (cipherSuite.indexOf("_EXPORT_WITH") != -1) {
+                    System.out.println("Skipping obsoleted test for " +
+                                        cipherSuite + " of " + protocol);
+                    return false;
+                }
+            }
+
             return true;
         }
     }
--- a/jdk/test/sun/security/pkcs11/tls/TestKeyMaterial.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/security/pkcs11/tls/TestKeyMaterial.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -125,16 +125,23 @@
                 System.out.print(".");
                 n++;
 
-                KeyGenerator kg = KeyGenerator.getInstance("SunTlsKeyMaterial", provider);
-                SecretKey masterKey = new SecretKeySpec(master, "TlsMasterSecret");
-                TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec
-                (masterKey, major, minor, clientRandom, serverRandom, cipherAlgorithm,
-                keyLength, expandedKeyLength, ivLength, macLength);
+                KeyGenerator kg =
+                    KeyGenerator.getInstance("SunTlsKeyMaterial", provider);
+                SecretKey masterKey =
+                    new SecretKeySpec(master, "TlsMasterSecret");
+                TlsKeyMaterialParameterSpec spec =
+                    new TlsKeyMaterialParameterSpec(masterKey, major, minor,
+                    clientRandom, serverRandom, cipherAlgorithm,
+                    keyLength, expandedKeyLength, ivLength, macLength,
+                    null, -1, -1);
 
                 kg.init(spec);
-                TlsKeyMaterialSpec result = (TlsKeyMaterialSpec)kg.generateKey();
-                match(lineNumber, clientCipherBytes, result.getClientCipherKey(), cipherAlgorithm);
-                match(lineNumber, serverCipherBytes, result.getServerCipherKey(), cipherAlgorithm);
+                TlsKeyMaterialSpec result =
+                    (TlsKeyMaterialSpec)kg.generateKey();
+                match(lineNumber, clientCipherBytes,
+                    result.getClientCipherKey(), cipherAlgorithm);
+                match(lineNumber, serverCipherBytes,
+                    result.getServerCipherKey(), cipherAlgorithm);
                 match(lineNumber, clientIv, result.getClientIv(), "");
                 match(lineNumber, serverIv, result.getServerIv(), "");
                 match(lineNumber, clientMacBytes, result.getClientMacKey(), "");
@@ -158,7 +165,8 @@
         }
     }
 
-    private static void match(int lineNumber, byte[] out, Object res, String cipherAlgorithm) throws Exception {
+    private static void match(int lineNumber, byte[] out, Object res,
+            String cipherAlgorithm) throws Exception {
         if ((out == null) || (res == null)) {
             if (out != res) {
                 throw new Exception("null mismatch line " + lineNumber);
@@ -169,7 +177,8 @@
         byte[] b;
         if (res instanceof SecretKey) {
             b = ((SecretKey)res).getEncoded();
-            if (cipherAlgorithm.equalsIgnoreCase("DES") || cipherAlgorithm.equalsIgnoreCase("DESede")) {
+            if (cipherAlgorithm.equalsIgnoreCase("DES") ||
+                    cipherAlgorithm.equalsIgnoreCase("DESede")) {
                 // strip DES parity bits before comparision
                 stripParity(out);
                 stripParity(b);
--- a/jdk/test/sun/security/pkcs11/tls/TestMasterSecret.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/security/pkcs11/tls/TestMasterSecret.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -104,17 +104,22 @@
                 System.out.print(".");
                 n++;
 
-                KeyGenerator kg = KeyGenerator.getInstance("SunTlsMasterSecret", provider);
-                SecretKey premasterKey = new SecretKeySpec(premaster, algorithm);
-                TlsMasterSecretParameterSpec spec = new TlsMasterSecretParameterSpec
-                    (premasterKey, protoMajor, protoMinor, clientRandom, serverRandom);
+                KeyGenerator kg =
+                    KeyGenerator.getInstance("SunTlsMasterSecret", provider);
+                SecretKey premasterKey =
+                    new SecretKeySpec(premaster, algorithm);
+                TlsMasterSecretParameterSpec spec =
+                    new TlsMasterSecretParameterSpec(premasterKey,
+                        protoMajor, protoMinor, clientRandom, serverRandom,
+                        null, -1, -1);
                 kg.init(spec);
                 TlsMasterSecret key = (TlsMasterSecret)kg.generateKey();
                 byte[] enc = key.getEncoded();
                 if (Arrays.equals(master, enc) == false) {
                     throw new Exception("mismatch line: " + lineNumber);
                 }
-                if ((preMajor != key.getMajorVersion()) || (preMinor != key.getMinorVersion())) {
+                if ((preMajor != key.getMajorVersion()) ||
+                        (preMinor != key.getMinorVersion())) {
                     throw new Exception("version mismatch line: " + lineNumber);
                 }
             } else {
--- a/jdk/test/sun/security/pkcs11/tls/TestPRF.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/security/pkcs11/tls/TestPRF.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -93,14 +93,17 @@
                 System.out.print(".");
                 n++;
 
-                KeyGenerator kg = KeyGenerator.getInstance("SunTlsPrf", provider);
+                KeyGenerator kg =
+                    KeyGenerator.getInstance("SunTlsPrf", provider);
                 SecretKey inKey;
                 if (secret == null) {
                     inKey = null;
                 } else {
                     inKey = new SecretKeySpec(secret, "Generic");
                 }
-                TlsPrfParameterSpec spec = new TlsPrfParameterSpec(inKey, label, seed, length);
+                TlsPrfParameterSpec spec =
+                    new TlsPrfParameterSpec(inKey, label, seed, length,
+                        null, -1, -1);
                 SecretKey key;
                 try {
                     kg.init(spec);
@@ -109,7 +112,8 @@
                     if (secret == null) {
                         // This fails on Solaris, but since we never call this
                         // API for this case in JSSE, ignore the failure.
-                        // (SunJSSE uses the CKM_TLS_KEY_AND_MAC_DERIVE mechanism)
+                        // (SunJSSE uses the CKM_TLS_KEY_AND_MAC_DERIVE
+                        // mechanism)
                         System.out.print("X");
                         continue;
                     }
--- a/jdk/test/sun/security/pkcs11/tls/TestPremaster.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/security/pkcs11/tls/TestPremaster.java	Wed Jul 05 17:26:57 2017 +0200
@@ -44,7 +44,8 @@
     }
 
     public void main(Provider provider) throws Exception {
-        if (provider.getService("KeyGenerator", "SunTlsRsaPremasterSecret") == null) {
+        if (provider.getService(
+                "KeyGenerator", "SunTlsRsaPremasterSecret") == null) {
             System.out.println("Not supported by provider, skipping");
             return;
         }
@@ -66,7 +67,8 @@
         System.out.println("Done.");
     }
 
-    private static void test(KeyGenerator kg, int major, int minor) throws Exception {
+    private static void test(KeyGenerator kg, int major, int minor)
+            throws Exception {
 
         kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor));
         SecretKey key = kg.generateKey();
@@ -75,7 +77,8 @@
             throw new Exception("length: " + encoded.length);
         }
         if ((encoded[0] != major) || (encoded[1] != minor)) {
-            throw new Exception("version mismatch: "  + encoded[0] + "." + encoded[1]);
+            throw new Exception("version mismatch: "  + encoded[0] +
+                "." + encoded[1]);
         }
         System.out.println("OK: " + major + "." + minor);
     }
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ClientModeClientAuth.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ClientModeClientAuth.java	Wed Jul 05 17:26:57 2017 +0200
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 4390659
+ * @run main/othervm -Djavax.net.debug=all ClientModeClientAuth
  * @summary setNeedClientAuth() isn't working after a handshaker is established
  * @author Brad Wetmore
  */
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/ClientServer.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/ClientServer.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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,6 +25,8 @@
  * @test
  * @bug 4717766
  * @summary 1.0.3 JsseX509TrustManager erroneously calls isClientTrusted()
+ * @ignore JSSE supports algorithm constraints with CR 6916074,
+ *     need to update this test case in JDK 7 soon
  * @author Brad Wetmore
  *
  * This problem didn't exist in JSSE 1.4, only JSSE 1.0.3.  However,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/PKIXExtendedTM.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,882 @@
+/*
+ * Copyright (c) 2010, 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 6916074
+ * @summary Add support for TLS 1.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 java.math.BigInteger;
+
+
+/*
+ * Certificates and key used in the test.
+ *
+ * TLS server certificate:
+ * server private key:
+ * -----BEGIN RSA PRIVATE KEY-----
+ * Proc-Type: 4,ENCRYPTED
+ * DEK-Info: DES-EDE3-CBC,D9AE407F6D0E389A
+ *
+ * WPrA7TFol/cQCcp9oHnXWNpYlvRbbIcQj0m+RKT2Iuzfus+DHt3Zadf8nJpKfX2e
+ * h2rnhlzCN9M7djRDooZKDOPCsdBn51Au7HlZF3S3Opgo7D8XFM1a8t1Je4ke14oI
+ * nw6QKYsBblRziPnP2PZ0zvX24nOv7bbY8beynlJHGs00VWSFdoH2DS0aE1p6D+3n
+ * ptJuJ75dVfZFK4X7162APlNXevX8D6PEQpSiRw1rjjGGcnvQ4HdWk3BxDVDcCNJb
+ * Y1aGNRxsjTDvPi3R9Qx2M+W03QzEPx4SR3ZHVskeSJHaetM0TM/w/45Paq4GokXP
+ * ZeTnbEx1xmjkA7h+t4doLL4watx5F6yLsJzu8xB3lt/1EtmkYtLz1t7X4BetPAXz
+ * zS69X/VwhKfsOI3qXBWuL2oHPyhDmT1gcaUQwEPSV6ogHEEQEDXdiUS8heNK13KF
+ * TCQYFkETvV2BLxUhV1hypPzRQ6tUpJiAbD5KmoK2lD9slshG2QtvKQq0/bgkDY5J
+ * LhDHV2dtcZ3kDPkkZXpbcJQvoeH3d09C5sIsuTFo2zgNR6oETHUc5TzP6FY2YYRa
+ * QcK5HcmtsRRiXFm01ac+aMejJUIujjFt84SiKWT/73vC8AmY4tYcJBLjCg4XIxSH
+ * fdDFLL1YZENNO5ivlp8mdiHqcawx+36L7DrEZQ8RZt6cqST5t/+XTdM74s6k81GT
+ * pNsa82P2K2zmIUZ/DL2mKjW1vfRByw1NQFEBkN3vdyZxYfM/JyUzX4hbjXBEkh9Q
+ * QYrcwLKLjis2QzSvK04B3bvRzRb+4ocWiso8ZPAXAIxZFBWDpTMM2A==
+ * -----END RSA PRIVATE KEY-----
+ *
+ * -----BEGIN RSA PRIVATE KEY-----
+ * MIICXAIBAAKBgQClrFscN6LdmYktsnm4j9VIpecchBeNaZzGrG358h0fORna03Ie
+ * buxEzHCk3LoAMPagTz1UemFqzFfQCn+VKBg/mtmU8hvIJIh+/p0PPftXUwizIDPU
+ * PxdHFNHN6gjYDnVOr77M0uyvqXpJ38LZrLgkQJCmA1Yq0DAFQCxPq9l0iQIDAQAB
+ * AoGAbqcbg1E1mkR99uOJoNeQYKFOJyGiiXTMnXV1TseC4+PDfQBU7Dax35GcesBi
+ * CtapIpFKKS5D+ozY6b7ZT8ojxuQ/uHLPAvz0WDR3ds4iRF8tyu71Q1ZHcQsJa17y
+ * yO7UbkSSKn/Mp9Rb+/dKqftUGNXVFLqgHBOzN2s3We3bbbECQQDYBPKOg3hkaGHo
+ * OhpHKqtQ6EVkldihG/3i4WejRonelXN+HRh1KrB2HBx0M8D/qAzP1i3rNSlSHer4
+ * 59YRTJnHAkEAxFX/sVYSn07BHv9Zhn6XXct/Cj43z/tKNbzlNbcxqQwQerw3IH51
+ * 8UH2YOA+GD3lXbKp+MytoFLWv8zg4YT/LwJAfqan75Z1R6lLffRS49bIiq8jwE16
+ * rTrUJ+kv8jKxMqc9B3vXkxpsS1M/+4E8bqgAmvpgAb8xcsvHsBd9ErdukQJBAKs2
+ * j67W75BrPjBI34pQ1LEfp56IGWXOrq1kF8IbCjxv3+MYRT6Z6UJFkpRymNPNDjsC
+ * dgUYgITiGJHUGXuw3lMCQHEHqo9ZtXz92yFT+VhsNc29B8m/sqUJdtCcMd/jGpAF
+ * u6GHufjqIZBpQsk63wbwESAPZZ+kk1O1kS5GIRLX608=
+ * -----END RSA PRIVATE KEY-----
+ *
+ * Private-Key: (1024 bit)
+ * modulus:
+ *     00:a5:ac:5b:1c:37:a2:dd:99:89:2d:b2:79:b8:8f:
+ *     d5:48:a5:e7:1c:84:17:8d:69:9c:c6:ac:6d:f9:f2:
+ *     1d:1f:39:19:da:d3:72:1e:6e:ec:44:cc:70:a4:dc:
+ *     ba:00:30:f6:a0:4f:3d:54:7a:61:6a:cc:57:d0:0a:
+ *     7f:95:28:18:3f:9a:d9:94:f2:1b:c8:24:88:7e:fe:
+ *     9d:0f:3d:fb:57:53:08:b3:20:33:d4:3f:17:47:14:
+ *     d1:cd:ea:08:d8:0e:75:4e:af:be:cc:d2:ec:af:a9:
+ *     7a:49:df:c2:d9:ac:b8:24:40:90:a6:03:56:2a:d0:
+ *     30:05:40:2c:4f:ab:d9:74:89
+ * publicExponent: 65537 (0x10001)
+ * privateExponent:
+ *     6e:a7:1b:83:51:35:9a:44:7d:f6:e3:89:a0:d7:90:
+ *     60:a1:4e:27:21:a2:89:74:cc:9d:75:75:4e:c7:82:
+ *     e3:e3:c3:7d:00:54:ec:36:b1:df:91:9c:7a:c0:62:
+ *     0a:d6:a9:22:91:4a:29:2e:43:fa:8c:d8:e9:be:d9:
+ *     4f:ca:23:c6:e4:3f:b8:72:cf:02:fc:f4:58:34:77:
+ *     76:ce:22:44:5f:2d:ca:ee:f5:43:56:47:71:0b:09:
+ *     6b:5e:f2:c8:ee:d4:6e:44:92:2a:7f:cc:a7:d4:5b:
+ *     fb:f7:4a:a9:fb:54:18:d5:d5:14:ba:a0:1c:13:b3:
+ *     37:6b:37:59:ed:db:6d:b1
+ * prime1:
+ *     00:d8:04:f2:8e:83:78:64:68:61:e8:3a:1a:47:2a:
+ *     ab:50:e8:45:64:95:d8:a1:1b:fd:e2:e1:67:a3:46:
+ *     89:de:95:73:7e:1d:18:75:2a:b0:76:1c:1c:74:33:
+ *     c0:ff:a8:0c:cf:d6:2d:eb:35:29:52:1d:ea:f8:e7:
+ *     d6:11:4c:99:c7
+ * prime2:
+ *     00:c4:55:ff:b1:56:12:9f:4e:c1:1e:ff:59:86:7e:
+ *     97:5d:cb:7f:0a:3e:37:cf:fb:4a:35:bc:e5:35:b7:
+ *     31:a9:0c:10:7a:bc:37:20:7e:75:f1:41:f6:60:e0:
+ *     3e:18:3d:e5:5d:b2:a9:f8:cc:ad:a0:52:d6:bf:cc:
+ *     e0:e1:84:ff:2f
+ * exponent1:
+ *     7e:a6:a7:ef:96:75:47:a9:4b:7d:f4:52:e3:d6:c8:
+ *     8a:af:23:c0:4d:7a:ad:3a:d4:27:e9:2f:f2:32:b1:
+ *     32:a7:3d:07:7b:d7:93:1a:6c:4b:53:3f:fb:81:3c:
+ *     6e:a8:00:9a:fa:60:01:bf:31:72:cb:c7:b0:17:7d:
+ *     12:b7:6e:91
+ * exponent2:
+ *     00:ab:36:8f:ae:d6:ef:90:6b:3e:30:48:df:8a:50:
+ *     d4:b1:1f:a7:9e:88:19:65:ce:ae:ad:64:17:c2:1b:
+ *     0a:3c:6f:df:e3:18:45:3e:99:e9:42:45:92:94:72:
+ *     98:d3:cd:0e:3b:02:76:05:18:80:84:e2:18:91:d4:
+ *     19:7b:b0:de:53
+ * coefficient:
+ *     71:07:aa:8f:59:b5:7c:fd:db:21:53:f9:58:6c:35:
+ *     cd:bd:07:c9:bf:b2:a5:09:76:d0:9c:31:df:e3:1a:
+ *     90:05:bb:a1:87:b9:f8:ea:21:90:69:42:c9:3a:df:
+ *     06:f0:11:20:0f:65:9f:a4:93:53:b5:91:2e:46:21:
+ *     12:d7:eb:4f
+ *
+ *
+ * server certificate:
+ * Data:
+ *     Version: 3 (0x2)
+ *     Serial Number: 8 (0x8)
+ *     Signature Algorithm: md5WithRSAEncryption
+ *     Issuer: C=US, ST=Some-State, L=Some-City, O=Some-Org
+ *     Validity
+ *         Not Before: Dec  8 03:43:04 2008 GMT
+ *         Not After : Aug 25 03:43:04 2028 GMT
+ *     Subject: C=US, ST=Some-State, L=Some-City, O=Some-Org, OU=SSL-Server, CN=localhost
+ *     Subject Public Key Info:
+ *         Public Key Algorithm: rsaEncryption
+ *         RSA Public Key: (1024 bit)
+ *             Modulus (1024 bit):
+ *                 00:a5:ac:5b:1c:37:a2:dd:99:89:2d:b2:79:b8:8f:
+ *                 d5:48:a5:e7:1c:84:17:8d:69:9c:c6:ac:6d:f9:f2:
+ *                 1d:1f:39:19:da:d3:72:1e:6e:ec:44:cc:70:a4:dc:
+ *                 ba:00:30:f6:a0:4f:3d:54:7a:61:6a:cc:57:d0:0a:
+ *                 7f:95:28:18:3f:9a:d9:94:f2:1b:c8:24:88:7e:fe:
+ *                 9d:0f:3d:fb:57:53:08:b3:20:33:d4:3f:17:47:14:
+ *                 d1:cd:ea:08:d8:0e:75:4e:af:be:cc:d2:ec:af:a9:
+ *                 7a:49:df:c2:d9:ac:b8:24:40:90:a6:03:56:2a:d0:
+ *                 30:05:40:2c:4f:ab:d9:74:89
+ *             Exponent: 65537 (0x10001)
+ *     X509v3 extensions:
+ *         X509v3 Basic Constraints:
+ *             CA:FALSE
+ *         X509v3 Key Usage:
+ *             Digital Signature, Non Repudiation, Key Encipherment
+ *         X509v3 Subject Key Identifier:
+ *             ED:6E:DB:F4:B5:56:C8:FB:1A:06:61:3F:0F:08:BB:A6:04:D8:16:54
+ *         X509v3 Authority Key Identifier:
+ *             keyid:FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14
+ *
+ *         X509v3 Subject Alternative Name: critical
+ *             DNS:localhost
+ * Signature Algorithm: md5WithRSAEncryption0
+ *
+ * -----BEGIN CERTIFICATE-----
+ * MIICpDCCAg2gAwIBAgIBCDANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET
+ * MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK
+ * EwhTb21lLU9yZzAeFw0wODEyMDgwMzQzMDRaFw0yODA4MjUwMzQzMDRaMHIxCzAJ
+ * BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp
+ * dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtU2VydmVyMRIwEAYD
+ * VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKWsWxw3
+ * ot2ZiS2yebiP1Uil5xyEF41pnMasbfnyHR85GdrTch5u7ETMcKTcugAw9qBPPVR6
+ * YWrMV9AKf5UoGD+a2ZTyG8gkiH7+nQ89+1dTCLMgM9Q/F0cU0c3qCNgOdU6vvszS
+ * 7K+peknfwtmsuCRAkKYDVirQMAVALE+r2XSJAgMBAAGjczBxMAkGA1UdEwQCMAAw
+ * CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTtbtv0tVbI+xoGYT8PCLumBNgWVDAfBgNV
+ * HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDAXBgNVHREBAf8EDTALgglsb2Nh
+ * bGhvc3QwDQYJKoZIhvcNAQEEBQADgYEAoqVTciHtcvsUj+YaTct8tUh3aTCsKsac
+ * PHhfQ+ObjiXSgxsKYTX7ym/wk/wvlbUcbqLKxsu7qrcJitH+H9heV1hEHEu65Uoi
+ * nRugFruyOrwvAylV8Cm2af7ddilmYJ+sdJA6N2M3xJRxR0G2LFHEXDNEjYReyexn
+ * JqCpf5uZGOo=
+ * -----END CERTIFICATE-----
+ *
+ *
+ * TLS client certificate:
+ * client private key:
+ * ----BEGIN RSA PRIVATE KEY-----
+ * Proc-Type: 4,ENCRYPTED
+ * DEK-Info: DES-EDE3-CBC,FA2A435CD35A9390
+ *
+ * Z+Y2uaETbsUWIyJUyVu1UV2G4rgFYJyACZT6Tp1KjRtxflSh2kXkJ9MpuXMXA0V4
+ * Yy3fDzPqCL9NJmQAYRlAx/W/+j4F5EyMWDIx8fUxzONRZyoiwF7jLm+KscAfv6Pf
+ * q7ItWOdj3z7IYrwlB8YIGd3F2cDKT3S+lYRk7rKb/qT7itbuHnY4Ardh3yl+MZak
+ * jBp+ELUlRsUqSr1V0LoM+0rCCykarpyfhpxEcqsrl0v9Cyi5uhU50/oKv5zql3SH
+ * l2ImgDjp3batAs8+Bd4NF2aqi0a7Hy44JUHxRm4caZryU/i/D9N1MbuM6882HLat
+ * 5N0G+NaIUfywa8mjwq2D5aiit18HqKA6XeRRYeJ5Dvu9DCO4GeFSwcUFIBMI0L46
+ * 7s114+oDodg57pMgITi+04vmUxvqlN9aiyd7f5Fgd7PeHGeOdbMz1NaJLJaPI9++
+ * NakK8eK9iwT/Gdq0Uap5/CHW7vCT5PO+h3HY0STH0lWStXhdWnFO04zTdywsbSp+
+ * DLpHeFT66shfeUlxR0PsCbG9vPRt/QmGLeYQZITppWo/ylSq4j+pRIuXvuWHdBRN
+ * rTZ8QF4Y7AxQUXVz1j1++s6ZMHTzaK2i9HrhmDs1MbJl+QwWre3Xpv3LvTVz3k5U
+ * wX8kuY1m3STt71QCaRWENq5sRaMImLxZbxc/ivFl9RAzUqo4NCxLod/QgA4iLqtO
+ * ztnlpzwlC/F8HbQ1oqYWwnZAPhzU/cULtstl+Yrws2c2atO323LbPXZqbASySgig
+ * sNpFXQMObdfP6LN23bY+1SvtK7V4NUTNhpdIc6INQAQ=
+ * -----END RSA PRIVATE KEY-----
+ *
+ * -----BEGIN RSA PRIVATE KEY-----
+ * MIICWwIBAAKBgQC78EA2rCZUTvSjWgAvaSFvuXo6k+yi9uGOx2PYLxIwmS6w8o/4
+ * Jy0keCiE9wG/jUR53TvSVfPOPLJbIX3v/TNKsaP/xsibuQ98QTWX+ds6BWAFFa9Z
+ * F5KjEK0WHOQHU6+odqJWKpLT+SjgeM9eH0irXBnd4WdDunWN9YKsQ5JEGwIDAQAB
+ * AoGAEbdqNj0wN85hnWyEi/ObJU8UyKTdL9eaF72QGfcF/fLSxfd3vurihIeXOkGW
+ * tpn4lIxYcVGM9CognhqgJpl11jFTQzn1KqZ+NEJRKkCHA4hDabKJbSC9fXHvRwrf
+ * BsFpZqgiNxp3HseUTiwnaUVeyPgMt/jAj5nB5Sib+UyUxrECQQDnNQBiF2aifEg6
+ * zbJOOC7he5CHAdkFxSxWVFVHL6EfXfqdLVkUohMbgZv+XxyIeU2biOExSg49Kds3
+ * FOKgTau1AkEA0Bd1haj6QuCo8I0AXm2WO+MMTZMTvtHD/bGjKNM+fT4I8rKYnQRX
+ * 1acHdqS9Xx2rNJqZgkMmpESIdPR2fc4yjwJALFeM6EMmqvj8/VIf5UJ/Mz14fXwM
+ * PEARfckUxd9LnnFutCBTWlKvKXJVEZb6KO5ixPaegc57Jp3Vbh3yTN44lQJADD/1
+ * SSMDaIB1MYP7a5Oj7m6VQNPRq8AJe5vDcRnOae0G9dKRrVyeFxO4GsHj6/+BHp2j
+ * P8nYMn9eURQ7DXjf/QJAAQzMlWnKGSO8pyTDtnQx3hRMoUkOEhmNq4bQhLkYqtnY
+ * FcqpUQ2qMjW+NiNWk5HnTrMS3L9EdJobMUzaNZLy4w==
+ * -----END RSA PRIVATE KEY-----
+ *
+ * Private-Key: (1024 bit)
+ * modulus:
+ *     00:bb:f0:40:36:ac:26:54:4e:f4:a3:5a:00:2f:69:
+ *     21:6f:b9:7a:3a:93:ec:a2:f6:e1:8e:c7:63:d8:2f:
+ *     12:30:99:2e:b0:f2:8f:f8:27:2d:24:78:28:84:f7:
+ *     01:bf:8d:44:79:dd:3b:d2:55:f3:ce:3c:b2:5b:21:
+ *     7d:ef:fd:33:4a:b1:a3:ff:c6:c8:9b:b9:0f:7c:41:
+ *     35:97:f9:db:3a:05:60:05:15:af:59:17:92:a3:10:
+ *     ad:16:1c:e4:07:53:af:a8:76:a2:56:2a:92:d3:f9:
+ *     28:e0:78:cf:5e:1f:48:ab:5c:19:dd:e1:67:43:ba:
+ *     75:8d:f5:82:ac:43:92:44:1b
+ * publicExponent: 65537 (0x10001)
+ * privateExponent:
+ *     11:b7:6a:36:3d:30:37:ce:61:9d:6c:84:8b:f3:9b:
+ *     25:4f:14:c8:a4:dd:2f:d7:9a:17:bd:90:19:f7:05:
+ *     fd:f2:d2:c5:f7:77:be:ea:e2:84:87:97:3a:41:96:
+ *     b6:99:f8:94:8c:58:71:51:8c:f4:2a:20:9e:1a:a0:
+ *     26:99:75:d6:31:53:43:39:f5:2a:a6:7e:34:42:51:
+ *     2a:40:87:03:88:43:69:b2:89:6d:20:bd:7d:71:ef:
+ *     47:0a:df:06:c1:69:66:a8:22:37:1a:77:1e:c7:94:
+ *     4e:2c:27:69:45:5e:c8:f8:0c:b7:f8:c0:8f:99:c1:
+ *     e5:28:9b:f9:4c:94:c6:b1
+ * prime1:
+ *     00:e7:35:00:62:17:66:a2:7c:48:3a:cd:b2:4e:38:
+ *     2e:e1:7b:90:87:01:d9:05:c5:2c:56:54:55:47:2f:
+ *     a1:1f:5d:fa:9d:2d:59:14:a2:13:1b:81:9b:fe:5f:
+ *     1c:88:79:4d:9b:88:e1:31:4a:0e:3d:29:db:37:14:
+ *     e2:a0:4d:ab:b5
+ * prime2:
+ *     00:d0:17:75:85:a8:fa:42:e0:a8:f0:8d:00:5e:6d:
+ *     96:3b:e3:0c:4d:93:13:be:d1:c3:fd:b1:a3:28:d3:
+ *     3e:7d:3e:08:f2:b2:98:9d:04:57:d5:a7:07:76:a4:
+ *     bd:5f:1d:ab:34:9a:99:82:43:26:a4:44:88:74:f4:
+ *     76:7d:ce:32:8f
+ * exponent1:
+ *     2c:57:8c:e8:43:26:aa:f8:fc:fd:52:1f:e5:42:7f:
+ *     33:3d:78:7d:7c:0c:3c:40:11:7d:c9:14:c5:df:4b:
+ *     9e:71:6e:b4:20:53:5a:52:af:29:72:55:11:96:fa:
+ *     28:ee:62:c4:f6:9e:81:ce:7b:26:9d:d5:6e:1d:f2:
+ *     4c:de:38:95
+ * exponent2:
+ *     0c:3f:f5:49:23:03:68:80:75:31:83:fb:6b:93:a3:
+ *     ee:6e:95:40:d3:d1:ab:c0:09:7b:9b:c3:71:19:ce:
+ *     69:ed:06:f5:d2:91:ad:5c:9e:17:13:b8:1a:c1:e3:
+ *     eb:ff:81:1e:9d:a3:3f:c9:d8:32:7f:5e:51:14:3b:
+ *     0d:78:df:fd
+ * coefficient:
+ *     01:0c:cc:95:69:ca:19:23:bc:a7:24:c3:b6:74:31:
+ *     de:14:4c:a1:49:0e:12:19:8d:ab:86:d0:84:b9:18:
+ *     aa:d9:d8:15:ca:a9:51:0d:aa:32:35:be:36:23:56:
+ *     93:91:e7:4e:b3:12:dc:bf:44:74:9a:1b:31:4c:da:
+ *     35:92:f2:e3
+ *
+ * client certificate:
+ * Data:
+ *     Version: 3 (0x2)
+ *     Serial Number: 9 (0x9)
+ *     Signature Algorithm: md5WithRSAEncryption
+ *     Issuer: C=US, ST=Some-State, L=Some-City, O=Some-Org
+ *     Validity
+ *         Not Before: Dec  8 03:43:24 2008 GMT
+ *         Not After : Aug 25 03:43:24 2028 GMT
+ *     Subject: C=US, ST=Some-State, L=Some-City, O=Some-Org, OU=SSL-Client, CN=localhost
+ *     Subject Public Key Info:
+ *         Public Key Algorithm: rsaEncryption
+ *         RSA Public Key: (1024 bit)
+ *             Modulus (1024 bit):
+ *                 00:bb:f0:40:36:ac:26:54:4e:f4:a3:5a:00:2f:69:
+ *                 21:6f:b9:7a:3a:93:ec:a2:f6:e1:8e:c7:63:d8:2f:
+ *                 12:30:99:2e:b0:f2:8f:f8:27:2d:24:78:28:84:f7:
+ *                 01:bf:8d:44:79:dd:3b:d2:55:f3:ce:3c:b2:5b:21:
+ *                 7d:ef:fd:33:4a:b1:a3:ff:c6:c8:9b:b9:0f:7c:41:
+ *                 35:97:f9:db:3a:05:60:05:15:af:59:17:92:a3:10:
+ *                 ad:16:1c:e4:07:53:af:a8:76:a2:56:2a:92:d3:f9:
+ *                 28:e0:78:cf:5e:1f:48:ab:5c:19:dd:e1:67:43:ba:
+ *                 75:8d:f5:82:ac:43:92:44:1b
+ *             Exponent: 65537 (0x10001)
+ *     X509v3 extensions:
+ *         X509v3 Basic Constraints:
+ *             CA:FALSE
+ *         X509v3 Key Usage:
+ *             Digital Signature, Non Repudiation, Key Encipherment
+ *         X509v3 Subject Key Identifier:
+ *             CD:BB:C8:85:AA:91:BD:FD:1D:BE:CD:67:7C:FF:B3:E9:4C:A8:22:E6
+ *         X509v3 Authority Key Identifier:
+ *             keyid:FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14
+ *
+ *         X509v3 Subject Alternative Name: critical
+ *             DNS:localhost
+ * Signature Algorithm: md5WithRSAEncryption
+ *
+ * -----BEGIN CERTIFICATE-----
+ * MIICpDCCAg2gAwIBAgIBCTANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET
+ * MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK
+ * EwhTb21lLU9yZzAeFw0wODEyMDgwMzQzMjRaFw0yODA4MjUwMzQzMjRaMHIxCzAJ
+ * BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp
+ * dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtQ2xpZW50MRIwEAYD
+ * VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALvwQDas
+ * JlRO9KNaAC9pIW+5ejqT7KL24Y7HY9gvEjCZLrDyj/gnLSR4KIT3Ab+NRHndO9JV
+ * 8848slshfe/9M0qxo//GyJu5D3xBNZf52zoFYAUVr1kXkqMQrRYc5AdTr6h2olYq
+ * ktP5KOB4z14fSKtcGd3hZ0O6dY31gqxDkkQbAgMBAAGjczBxMAkGA1UdEwQCMAAw
+ * CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTNu8iFqpG9/R2+zWd8/7PpTKgi5jAfBgNV
+ * HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDAXBgNVHREBAf8EDTALgglsb2Nh
+ * bGhvc3QwDQYJKoZIhvcNAQEEBQADgYEAm25gJyqW1JznQ1EyOtTGswBVwfgBOf+F
+ * HJuBTcflYQLbTD/AETPQJGvZU9tdhuLtbG3OPhR7vSY8zeAbfM3dbH7QFr3r47Gj
+ * XEH7qM/MX+Z3ifVaC4MeJmrYQkYFSuKeyyKpdRVX4w4nnFHF6OsNASsYrMW6LpxN
+ * cl/epUcHL7E=
+ * -----END CERTIFICATE-----
+ *
+ *
+ *
+ * Trusted CA certificate:
+ * Certificate:
+ *   Data:
+ *     Version: 3 (0x2)
+ *     Serial Number: 0 (0x0)
+ *     Signature Algorithm: md5WithRSAEncryption
+ *     Issuer: C=US, ST=Some-State, L=Some-City, O=Some-Org
+ *     Validity
+ *         Not Before: Dec  8 02:43:36 2008 GMT
+ *         Not After : Aug 25 02:43:36 2028 GMT
+ *     Subject: C=US, ST=Some-State, L=Some-City, O=Some-Org
+ *     Subject Public Key Info:
+ *         Public Key Algorithm: rsaEncryption
+ *         RSA Public Key: (1024 bit)
+ *             Modulus (1024 bit):
+ *                 00:cb:c4:38:20:07:be:88:a7:93:b0:a1:43:51:2d:
+ *                 d7:8e:85:af:54:dd:ad:a2:7b:23:5b:cf:99:13:53:
+ *                 99:45:7d:ee:6d:ba:2d:bf:e3:ad:6e:3d:9f:1a:f9:
+ *                 03:97:e0:17:55:ae:11:26:57:de:01:29:8e:05:3f:
+ *                 21:f7:e7:36:e8:2e:37:d7:48:ac:53:d6:60:0e:c7:
+ *                 50:6d:f6:c5:85:f7:8b:a6:c5:91:35:72:3c:94:ee:
+ *                 f1:17:f0:71:e3:ec:1b:ce:ca:4e:40:42:b0:6d:ee:
+ *                 6a:0e:d6:e5:ad:3c:0f:c9:ba:82:4f:78:f8:89:97:
+ *                 89:2a:95:12:4c:d8:09:2a:e9
+ *             Exponent: 65537 (0x10001)
+ *     X509v3 extensions:
+ *         X509v3 Subject Key Identifier:
+ *             FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14
+ *         X509v3 Authority Key Identifier:
+ *             keyid:FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14
+ *             DirName:/C=US/ST=Some-State/L=Some-City/O=Some-Org
+ *             serial:00
+ *
+ *         X509v3 Basic Constraints:
+ *             CA:TRUE
+ *  Signature Algorithm: md5WithRSAEncryption
+ *
+ * -----BEGIN CERTIFICATE-----
+ * MIICrDCCAhWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET
+ * MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK
+ * EwhTb21lLU9yZzAeFw0wODEyMDgwMjQzMzZaFw0yODA4MjUwMjQzMzZaMEkxCzAJ
+ * BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp
+ * dHkxETAPBgNVBAoTCFNvbWUtT3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
+ * gQDLxDggB76Ip5OwoUNRLdeOha9U3a2ieyNbz5kTU5lFfe5tui2/461uPZ8a+QOX
+ * 4BdVrhEmV94BKY4FPyH35zboLjfXSKxT1mAOx1Bt9sWF94umxZE1cjyU7vEX8HHj
+ * 7BvOyk5AQrBt7moO1uWtPA/JuoJPePiJl4kqlRJM2Akq6QIDAQABo4GjMIGgMB0G
+ * A1UdDgQWBBT6uVG/TOfZhpgz+efLHvEzSfeoFDBxBgNVHSMEajBogBT6uVG/TOfZ
+ * hpgz+efLHvEzSfeoFKFNpEswSTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUt
+ * U3RhdGUxEjAQBgNVBAcTCVNvbWUtQ2l0eTERMA8GA1UEChMIU29tZS1PcmeCAQAw
+ * DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBcIm534U123Hz+rtyYO5uA
+ * ofd81G6FnTfEAV8Kw9fGyyEbQZclBv34A9JsFKeMvU4OFIaixD7nLZ/NZ+IWbhmZ
+ * LovmJXyCkOufea73pNiZ+f/4/ScZaIlM/PRycQSqbFNd4j9Wott+08qxHPLpsf3P
+ * 6Mvf0r1PNTY2hwTJLJmKtg==
+ * -----END CERTIFICATE---
+ */
+
+
+public class PKIXExtendedTM {
+
+    /*
+     * =============================================================
+     * 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 = true;
+
+    /*
+     * Where do we find the keystores?
+     */
+    static String trusedCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICrDCCAhWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET\n" +
+        "MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK\n" +
+        "EwhTb21lLU9yZzAeFw0wODEyMDgwMjQzMzZaFw0yODA4MjUwMjQzMzZaMEkxCzAJ\n" +
+        "BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp\n" +
+        "dHkxETAPBgNVBAoTCFNvbWUtT3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n" +
+        "gQDLxDggB76Ip5OwoUNRLdeOha9U3a2ieyNbz5kTU5lFfe5tui2/461uPZ8a+QOX\n" +
+        "4BdVrhEmV94BKY4FPyH35zboLjfXSKxT1mAOx1Bt9sWF94umxZE1cjyU7vEX8HHj\n" +
+        "7BvOyk5AQrBt7moO1uWtPA/JuoJPePiJl4kqlRJM2Akq6QIDAQABo4GjMIGgMB0G\n" +
+        "A1UdDgQWBBT6uVG/TOfZhpgz+efLHvEzSfeoFDBxBgNVHSMEajBogBT6uVG/TOfZ\n" +
+        "hpgz+efLHvEzSfeoFKFNpEswSTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUt\n" +
+        "U3RhdGUxEjAQBgNVBAcTCVNvbWUtQ2l0eTERMA8GA1UEChMIU29tZS1PcmeCAQAw\n" +
+        "DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBcIm534U123Hz+rtyYO5uA\n" +
+        "ofd81G6FnTfEAV8Kw9fGyyEbQZclBv34A9JsFKeMvU4OFIaixD7nLZ/NZ+IWbhmZ\n" +
+        "LovmJXyCkOufea73pNiZ+f/4/ScZaIlM/PRycQSqbFNd4j9Wott+08qxHPLpsf3P\n" +
+        "6Mvf0r1PNTY2hwTJLJmKtg==\n" +
+        "-----END CERTIFICATE-----";
+
+    static String serverCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICpDCCAg2gAwIBAgIBCDANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET\n" +
+        "MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK\n" +
+        "EwhTb21lLU9yZzAeFw0wODEyMDgwMzQzMDRaFw0yODA4MjUwMzQzMDRaMHIxCzAJ\n" +
+        "BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp\n" +
+        "dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtU2VydmVyMRIwEAYD\n" +
+        "VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKWsWxw3\n" +
+        "ot2ZiS2yebiP1Uil5xyEF41pnMasbfnyHR85GdrTch5u7ETMcKTcugAw9qBPPVR6\n" +
+        "YWrMV9AKf5UoGD+a2ZTyG8gkiH7+nQ89+1dTCLMgM9Q/F0cU0c3qCNgOdU6vvszS\n" +
+        "7K+peknfwtmsuCRAkKYDVirQMAVALE+r2XSJAgMBAAGjczBxMAkGA1UdEwQCMAAw\n" +
+        "CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTtbtv0tVbI+xoGYT8PCLumBNgWVDAfBgNV\n" +
+        "HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDAXBgNVHREBAf8EDTALgglsb2Nh\n" +
+        "bGhvc3QwDQYJKoZIhvcNAQEEBQADgYEAoqVTciHtcvsUj+YaTct8tUh3aTCsKsac\n" +
+        "PHhfQ+ObjiXSgxsKYTX7ym/wk/wvlbUcbqLKxsu7qrcJitH+H9heV1hEHEu65Uoi\n" +
+        "nRugFruyOrwvAylV8Cm2af7ddilmYJ+sdJA6N2M3xJRxR0G2LFHEXDNEjYReyexn\n" +
+        "JqCpf5uZGOo=\n" +
+        "-----END CERTIFICATE-----";
+
+    static String clientCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICpDCCAg2gAwIBAgIBCTANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET\n" +
+        "MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK\n" +
+        "EwhTb21lLU9yZzAeFw0wODEyMDgwMzQzMjRaFw0yODA4MjUwMzQzMjRaMHIxCzAJ\n" +
+        "BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp\n" +
+        "dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtQ2xpZW50MRIwEAYD\n" +
+        "VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALvwQDas\n" +
+        "JlRO9KNaAC9pIW+5ejqT7KL24Y7HY9gvEjCZLrDyj/gnLSR4KIT3Ab+NRHndO9JV\n" +
+        "8848slshfe/9M0qxo//GyJu5D3xBNZf52zoFYAUVr1kXkqMQrRYc5AdTr6h2olYq\n" +
+        "ktP5KOB4z14fSKtcGd3hZ0O6dY31gqxDkkQbAgMBAAGjczBxMAkGA1UdEwQCMAAw\n" +
+        "CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTNu8iFqpG9/R2+zWd8/7PpTKgi5jAfBgNV\n" +
+        "HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDAXBgNVHREBAf8EDTALgglsb2Nh\n" +
+        "bGhvc3QwDQYJKoZIhvcNAQEEBQADgYEAm25gJyqW1JznQ1EyOtTGswBVwfgBOf+F\n" +
+        "HJuBTcflYQLbTD/AETPQJGvZU9tdhuLtbG3OPhR7vSY8zeAbfM3dbH7QFr3r47Gj\n" +
+        "XEH7qM/MX+Z3ifVaC4MeJmrYQkYFSuKeyyKpdRVX4w4nnFHF6OsNASsYrMW6LpxN\n" +
+        "cl/epUcHL7E=\n" +
+        "-----END CERTIFICATE-----";
+
+    static byte serverPrivateExponent[] = {
+        (byte)0x6e, (byte)0xa7, (byte)0x1b, (byte)0x83,
+        (byte)0x51, (byte)0x35, (byte)0x9a, (byte)0x44,
+        (byte)0x7d, (byte)0xf6, (byte)0xe3, (byte)0x89,
+        (byte)0xa0, (byte)0xd7, (byte)0x90, (byte)0x60,
+        (byte)0xa1, (byte)0x4e, (byte)0x27, (byte)0x21,
+        (byte)0xa2, (byte)0x89, (byte)0x74, (byte)0xcc,
+        (byte)0x9d, (byte)0x75, (byte)0x75, (byte)0x4e,
+        (byte)0xc7, (byte)0x82, (byte)0xe3, (byte)0xe3,
+        (byte)0xc3, (byte)0x7d, (byte)0x00, (byte)0x54,
+        (byte)0xec, (byte)0x36, (byte)0xb1, (byte)0xdf,
+        (byte)0x91, (byte)0x9c, (byte)0x7a, (byte)0xc0,
+        (byte)0x62, (byte)0x0a, (byte)0xd6, (byte)0xa9,
+        (byte)0x22, (byte)0x91, (byte)0x4a, (byte)0x29,
+        (byte)0x2e, (byte)0x43, (byte)0xfa, (byte)0x8c,
+        (byte)0xd8, (byte)0xe9, (byte)0xbe, (byte)0xd9,
+        (byte)0x4f, (byte)0xca, (byte)0x23, (byte)0xc6,
+        (byte)0xe4, (byte)0x3f, (byte)0xb8, (byte)0x72,
+        (byte)0xcf, (byte)0x02, (byte)0xfc, (byte)0xf4,
+        (byte)0x58, (byte)0x34, (byte)0x77, (byte)0x76,
+        (byte)0xce, (byte)0x22, (byte)0x44, (byte)0x5f,
+        (byte)0x2d, (byte)0xca, (byte)0xee, (byte)0xf5,
+        (byte)0x43, (byte)0x56, (byte)0x47, (byte)0x71,
+        (byte)0x0b, (byte)0x09, (byte)0x6b, (byte)0x5e,
+        (byte)0xf2, (byte)0xc8, (byte)0xee, (byte)0xd4,
+        (byte)0x6e, (byte)0x44, (byte)0x92, (byte)0x2a,
+        (byte)0x7f, (byte)0xcc, (byte)0xa7, (byte)0xd4,
+        (byte)0x5b, (byte)0xfb, (byte)0xf7, (byte)0x4a,
+        (byte)0xa9, (byte)0xfb, (byte)0x54, (byte)0x18,
+        (byte)0xd5, (byte)0xd5, (byte)0x14, (byte)0xba,
+        (byte)0xa0, (byte)0x1c, (byte)0x13, (byte)0xb3,
+        (byte)0x37, (byte)0x6b, (byte)0x37, (byte)0x59,
+        (byte)0xed, (byte)0xdb, (byte)0x6d, (byte)0xb1
+    };
+
+    static byte serverModulus[] = {
+        (byte)0x00,
+        (byte)0xa5, (byte)0xac, (byte)0x5b, (byte)0x1c,
+        (byte)0x37, (byte)0xa2, (byte)0xdd, (byte)0x99,
+        (byte)0x89, (byte)0x2d, (byte)0xb2, (byte)0x79,
+        (byte)0xb8, (byte)0x8f, (byte)0xd5, (byte)0x48,
+        (byte)0xa5, (byte)0xe7, (byte)0x1c, (byte)0x84,
+        (byte)0x17, (byte)0x8d, (byte)0x69, (byte)0x9c,
+        (byte)0xc6, (byte)0xac, (byte)0x6d, (byte)0xf9,
+        (byte)0xf2, (byte)0x1d, (byte)0x1f, (byte)0x39,
+        (byte)0x19, (byte)0xda, (byte)0xd3, (byte)0x72,
+        (byte)0x1e, (byte)0x6e, (byte)0xec, (byte)0x44,
+        (byte)0xcc, (byte)0x70, (byte)0xa4, (byte)0xdc,
+        (byte)0xba, (byte)0x00, (byte)0x30, (byte)0xf6,
+        (byte)0xa0, (byte)0x4f, (byte)0x3d, (byte)0x54,
+        (byte)0x7a, (byte)0x61, (byte)0x6a, (byte)0xcc,
+        (byte)0x57, (byte)0xd0, (byte)0x0a, (byte)0x7f,
+        (byte)0x95, (byte)0x28, (byte)0x18, (byte)0x3f,
+        (byte)0x9a, (byte)0xd9, (byte)0x94, (byte)0xf2,
+        (byte)0x1b, (byte)0xc8, (byte)0x24, (byte)0x88,
+        (byte)0x7e, (byte)0xfe, (byte)0x9d, (byte)0x0f,
+        (byte)0x3d, (byte)0xfb, (byte)0x57, (byte)0x53,
+        (byte)0x08, (byte)0xb3, (byte)0x20, (byte)0x33,
+        (byte)0xd4, (byte)0x3f, (byte)0x17, (byte)0x47,
+        (byte)0x14, (byte)0xd1, (byte)0xcd, (byte)0xea,
+        (byte)0x08, (byte)0xd8, (byte)0x0e, (byte)0x75,
+        (byte)0x4e, (byte)0xaf, (byte)0xbe, (byte)0xcc,
+        (byte)0xd2, (byte)0xec, (byte)0xaf, (byte)0xa9,
+        (byte)0x7a, (byte)0x49, (byte)0xdf, (byte)0xc2,
+        (byte)0xd9, (byte)0xac, (byte)0xb8, (byte)0x24,
+        (byte)0x40, (byte)0x90, (byte)0xa6, (byte)0x03,
+        (byte)0x56, (byte)0x2a, (byte)0xd0, (byte)0x30,
+        (byte)0x05, (byte)0x40, (byte)0x2c, (byte)0x4f,
+        (byte)0xab, (byte)0xd9, (byte)0x74, (byte)0x89
+    };
+
+    static byte clientPrivateExponent[] = {
+        (byte)0x11, (byte)0xb7, (byte)0x6a, (byte)0x36,
+        (byte)0x3d, (byte)0x30, (byte)0x37, (byte)0xce,
+        (byte)0x61, (byte)0x9d, (byte)0x6c, (byte)0x84,
+        (byte)0x8b, (byte)0xf3, (byte)0x9b, (byte)0x25,
+        (byte)0x4f, (byte)0x14, (byte)0xc8, (byte)0xa4,
+        (byte)0xdd, (byte)0x2f, (byte)0xd7, (byte)0x9a,
+        (byte)0x17, (byte)0xbd, (byte)0x90, (byte)0x19,
+        (byte)0xf7, (byte)0x05, (byte)0xfd, (byte)0xf2,
+        (byte)0xd2, (byte)0xc5, (byte)0xf7, (byte)0x77,
+        (byte)0xbe, (byte)0xea, (byte)0xe2, (byte)0x84,
+        (byte)0x87, (byte)0x97, (byte)0x3a, (byte)0x41,
+        (byte)0x96, (byte)0xb6, (byte)0x99, (byte)0xf8,
+        (byte)0x94, (byte)0x8c, (byte)0x58, (byte)0x71,
+        (byte)0x51, (byte)0x8c, (byte)0xf4, (byte)0x2a,
+        (byte)0x20, (byte)0x9e, (byte)0x1a, (byte)0xa0,
+        (byte)0x26, (byte)0x99, (byte)0x75, (byte)0xd6,
+        (byte)0x31, (byte)0x53, (byte)0x43, (byte)0x39,
+        (byte)0xf5, (byte)0x2a, (byte)0xa6, (byte)0x7e,
+        (byte)0x34, (byte)0x42, (byte)0x51, (byte)0x2a,
+        (byte)0x40, (byte)0x87, (byte)0x03, (byte)0x88,
+        (byte)0x43, (byte)0x69, (byte)0xb2, (byte)0x89,
+        (byte)0x6d, (byte)0x20, (byte)0xbd, (byte)0x7d,
+        (byte)0x71, (byte)0xef, (byte)0x47, (byte)0x0a,
+        (byte)0xdf, (byte)0x06, (byte)0xc1, (byte)0x69,
+        (byte)0x66, (byte)0xa8, (byte)0x22, (byte)0x37,
+        (byte)0x1a, (byte)0x77, (byte)0x1e, (byte)0xc7,
+        (byte)0x94, (byte)0x4e, (byte)0x2c, (byte)0x27,
+        (byte)0x69, (byte)0x45, (byte)0x5e, (byte)0xc8,
+        (byte)0xf8, (byte)0x0c, (byte)0xb7, (byte)0xf8,
+        (byte)0xc0, (byte)0x8f, (byte)0x99, (byte)0xc1,
+        (byte)0xe5, (byte)0x28, (byte)0x9b, (byte)0xf9,
+        (byte)0x4c, (byte)0x94, (byte)0xc6, (byte)0xb1
+    };
+
+    static byte clientModulus[] = {
+        (byte)0x00,
+        (byte)0xbb, (byte)0xf0, (byte)0x40, (byte)0x36,
+        (byte)0xac, (byte)0x26, (byte)0x54, (byte)0x4e,
+        (byte)0xf4, (byte)0xa3, (byte)0x5a, (byte)0x00,
+        (byte)0x2f, (byte)0x69, (byte)0x21, (byte)0x6f,
+        (byte)0xb9, (byte)0x7a, (byte)0x3a, (byte)0x93,
+        (byte)0xec, (byte)0xa2, (byte)0xf6, (byte)0xe1,
+        (byte)0x8e, (byte)0xc7, (byte)0x63, (byte)0xd8,
+        (byte)0x2f, (byte)0x12, (byte)0x30, (byte)0x99,
+        (byte)0x2e, (byte)0xb0, (byte)0xf2, (byte)0x8f,
+        (byte)0xf8, (byte)0x27, (byte)0x2d, (byte)0x24,
+        (byte)0x78, (byte)0x28, (byte)0x84, (byte)0xf7,
+        (byte)0x01, (byte)0xbf, (byte)0x8d, (byte)0x44,
+        (byte)0x79, (byte)0xdd, (byte)0x3b, (byte)0xd2,
+        (byte)0x55, (byte)0xf3, (byte)0xce, (byte)0x3c,
+        (byte)0xb2, (byte)0x5b, (byte)0x21, (byte)0x7d,
+        (byte)0xef, (byte)0xfd, (byte)0x33, (byte)0x4a,
+        (byte)0xb1, (byte)0xa3, (byte)0xff, (byte)0xc6,
+        (byte)0xc8, (byte)0x9b, (byte)0xb9, (byte)0x0f,
+        (byte)0x7c, (byte)0x41, (byte)0x35, (byte)0x97,
+        (byte)0xf9, (byte)0xdb, (byte)0x3a, (byte)0x05,
+        (byte)0x60, (byte)0x05, (byte)0x15, (byte)0xaf,
+        (byte)0x59, (byte)0x17, (byte)0x92, (byte)0xa3,
+        (byte)0x10, (byte)0xad, (byte)0x16, (byte)0x1c,
+        (byte)0xe4, (byte)0x07, (byte)0x53, (byte)0xaf,
+        (byte)0xa8, (byte)0x76, (byte)0xa2, (byte)0x56,
+        (byte)0x2a, (byte)0x92, (byte)0xd3, (byte)0xf9,
+        (byte)0x28, (byte)0xe0, (byte)0x78, (byte)0xcf,
+        (byte)0x5e, (byte)0x1f, (byte)0x48, (byte)0xab,
+        (byte)0x5c, (byte)0x19, (byte)0xdd, (byte)0xe1,
+        (byte)0x67, (byte)0x43, (byte)0xba, (byte)0x75,
+        (byte)0x8d, (byte)0xf5, (byte)0x82, (byte)0xac,
+        (byte)0x43, (byte)0x92, (byte)0x44, (byte)0x1b
+    };
+
+    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 = getSSLContext(trusedCertStr, serverCertStr,
+            serverModulus, serverPrivateExponent, passphrase);
+        SSLServerSocketFactory sslssf = context.getServerSocketFactory();
+
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket) sslssf.createServerSocket(serverPort);
+        serverPort = sslServerSocket.getLocalPort();
+
+        // enable endpoint identification
+        // ignore, we may test the feature when known how to parse client
+        // hostname
+        //SSLParameters params = sslServerSocket.getSSLParameters();
+        //params.setEndpointIdentificationAlgorithm("HTTPS");
+        //sslServerSocket.setSSLParameters(params);
+
+        /*
+         * Signal Client, we're ready for his connect.
+         */
+        serverReady = true;
+
+        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+        sslSocket.setNeedClientAuth(true);
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslIS.read();
+        sslOS.write(85);
+        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 = getSSLContext(trusedCertStr, clientCertStr,
+            clientModulus, clientPrivateExponent, passphrase);
+
+        SSLSocketFactory sslsf = context.getSocketFactory();
+        SSLSocket sslSocket = (SSLSocket)
+            sslsf.createSocket("localhost", serverPort);
+
+        // enable endpoint identification
+        SSLParameters params = sslSocket.getSSLParameters();
+        params.setEndpointIdentificationAlgorithm("HTTPS");
+        sslSocket.setSSLParameters(params);
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslOS.write(280);
+        sslOS.flush();
+        sslIS.read();
+
+        sslSocket.close();
+
+    }
+
+    // get the ssl context
+    private static SSLContext getSSLContext(String trusedCertStr,
+            String keyCertStr, byte[] modulus,
+            byte[] privateExponent, char[] passphrase) throws Exception {
+
+        // generate certificate from cert string
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+        ByteArrayInputStream is =
+                    new ByteArrayInputStream(trusedCertStr.getBytes());
+        Certificate trusedCert = cf.generateCertificate(is);
+        is.close();
+
+        // create a key store
+        KeyStore ks = KeyStore.getInstance("JKS");
+        ks.load(null, null);
+
+        // import the trused cert
+        ks.setCertificateEntry("RSA Export Signer", trusedCert);
+
+        if (keyCertStr != null) {
+            // generate the private key.
+            RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(
+                                            new BigInteger(modulus),
+                                            new BigInteger(privateExponent));
+            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();
+
+            Certificate[] chain = new Certificate[2];
+            chain[0] = keyCert;
+            chain[1] = trusedCert;
+
+            // import the key entry.
+            ks.setKeyEntry("Whatever", priKey, passphrase, chain);
+        }
+
+        // create SSL context
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
+        tmf.init(ks);
+
+        TrustManager tms[] = tmf.getTrustManagers();
+        if (tms == null || tms.length == 0) {
+            throw new Exception("unexpected trust manager implementation");
+        } else {
+           if (!(tms[0] instanceof X509ExtendedTrustManager)) {
+               throw new Exception("unexpected trust manager implementation: "
+                                + tms[0].getClass().getCanonicalName());
+           }
+        }
+
+
+        SSLContext ctx = SSLContext.getInstance("TLS");
+
+        if (keyCertStr != null) {
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+            kmf.init(ks, passphrase);
+
+            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+        } else {
+            ctx.init(null, tmf.getTrustManagers(), null);
+        }
+
+        return ctx;
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+
+    // 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");
+
+        /*
+         * Start the tests.
+         */
+        new PKIXExtendedTM();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    PKIXExtendedTM() throws Exception {
+        if (separateServerThread) {
+            startServer(true);
+            startClient(false);
+        } else {
+            startClient(true);
+            startServer(false);
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            serverThread.join();
+        } else {
+            clientThread.join();
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         *
+         * If the main thread excepted, that propagates back
+         * immediately.  If the other thread threw an exception, we
+         * should report back.
+         */
+        if (serverException != null)
+            throw serverException;
+        if (clientException != null)
+            throw clientException;
+    }
+
+    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 {
+            doServerSide();
+        }
+    }
+
+    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 {
+            doClientSide();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/SunX509ExtendedTM.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,884 @@
+/*
+ * Copyright (c) 2010, 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 6916074
+ * @run main/othervm -Djavax.net.debug=all SunX509ExtendedTM
+ * @summary Add support for TLS 1.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 java.math.BigInteger;
+
+
+/*
+ * Certificates and key used in the test.
+ *
+ * TLS server certificate:
+ * server private key:
+ * -----BEGIN RSA PRIVATE KEY-----
+ * Proc-Type: 4,ENCRYPTED
+ * DEK-Info: DES-EDE3-CBC,D9AE407F6D0E389A
+ *
+ * WPrA7TFol/cQCcp9oHnXWNpYlvRbbIcQj0m+RKT2Iuzfus+DHt3Zadf8nJpKfX2e
+ * h2rnhlzCN9M7djRDooZKDOPCsdBn51Au7HlZF3S3Opgo7D8XFM1a8t1Je4ke14oI
+ * nw6QKYsBblRziPnP2PZ0zvX24nOv7bbY8beynlJHGs00VWSFdoH2DS0aE1p6D+3n
+ * ptJuJ75dVfZFK4X7162APlNXevX8D6PEQpSiRw1rjjGGcnvQ4HdWk3BxDVDcCNJb
+ * Y1aGNRxsjTDvPi3R9Qx2M+W03QzEPx4SR3ZHVskeSJHaetM0TM/w/45Paq4GokXP
+ * ZeTnbEx1xmjkA7h+t4doLL4watx5F6yLsJzu8xB3lt/1EtmkYtLz1t7X4BetPAXz
+ * zS69X/VwhKfsOI3qXBWuL2oHPyhDmT1gcaUQwEPSV6ogHEEQEDXdiUS8heNK13KF
+ * TCQYFkETvV2BLxUhV1hypPzRQ6tUpJiAbD5KmoK2lD9slshG2QtvKQq0/bgkDY5J
+ * LhDHV2dtcZ3kDPkkZXpbcJQvoeH3d09C5sIsuTFo2zgNR6oETHUc5TzP6FY2YYRa
+ * QcK5HcmtsRRiXFm01ac+aMejJUIujjFt84SiKWT/73vC8AmY4tYcJBLjCg4XIxSH
+ * fdDFLL1YZENNO5ivlp8mdiHqcawx+36L7DrEZQ8RZt6cqST5t/+XTdM74s6k81GT
+ * pNsa82P2K2zmIUZ/DL2mKjW1vfRByw1NQFEBkN3vdyZxYfM/JyUzX4hbjXBEkh9Q
+ * QYrcwLKLjis2QzSvK04B3bvRzRb+4ocWiso8ZPAXAIxZFBWDpTMM2A==
+ * -----END RSA PRIVATE KEY-----
+ *
+ * -----BEGIN RSA PRIVATE KEY-----
+ * MIICXAIBAAKBgQClrFscN6LdmYktsnm4j9VIpecchBeNaZzGrG358h0fORna03Ie
+ * buxEzHCk3LoAMPagTz1UemFqzFfQCn+VKBg/mtmU8hvIJIh+/p0PPftXUwizIDPU
+ * PxdHFNHN6gjYDnVOr77M0uyvqXpJ38LZrLgkQJCmA1Yq0DAFQCxPq9l0iQIDAQAB
+ * AoGAbqcbg1E1mkR99uOJoNeQYKFOJyGiiXTMnXV1TseC4+PDfQBU7Dax35GcesBi
+ * CtapIpFKKS5D+ozY6b7ZT8ojxuQ/uHLPAvz0WDR3ds4iRF8tyu71Q1ZHcQsJa17y
+ * yO7UbkSSKn/Mp9Rb+/dKqftUGNXVFLqgHBOzN2s3We3bbbECQQDYBPKOg3hkaGHo
+ * OhpHKqtQ6EVkldihG/3i4WejRonelXN+HRh1KrB2HBx0M8D/qAzP1i3rNSlSHer4
+ * 59YRTJnHAkEAxFX/sVYSn07BHv9Zhn6XXct/Cj43z/tKNbzlNbcxqQwQerw3IH51
+ * 8UH2YOA+GD3lXbKp+MytoFLWv8zg4YT/LwJAfqan75Z1R6lLffRS49bIiq8jwE16
+ * rTrUJ+kv8jKxMqc9B3vXkxpsS1M/+4E8bqgAmvpgAb8xcsvHsBd9ErdukQJBAKs2
+ * j67W75BrPjBI34pQ1LEfp56IGWXOrq1kF8IbCjxv3+MYRT6Z6UJFkpRymNPNDjsC
+ * dgUYgITiGJHUGXuw3lMCQHEHqo9ZtXz92yFT+VhsNc29B8m/sqUJdtCcMd/jGpAF
+ * u6GHufjqIZBpQsk63wbwESAPZZ+kk1O1kS5GIRLX608=
+ * -----END RSA PRIVATE KEY-----
+ *
+ * Private-Key: (1024 bit)
+ * modulus:
+ *     00:a5:ac:5b:1c:37:a2:dd:99:89:2d:b2:79:b8:8f:
+ *     d5:48:a5:e7:1c:84:17:8d:69:9c:c6:ac:6d:f9:f2:
+ *     1d:1f:39:19:da:d3:72:1e:6e:ec:44:cc:70:a4:dc:
+ *     ba:00:30:f6:a0:4f:3d:54:7a:61:6a:cc:57:d0:0a:
+ *     7f:95:28:18:3f:9a:d9:94:f2:1b:c8:24:88:7e:fe:
+ *     9d:0f:3d:fb:57:53:08:b3:20:33:d4:3f:17:47:14:
+ *     d1:cd:ea:08:d8:0e:75:4e:af:be:cc:d2:ec:af:a9:
+ *     7a:49:df:c2:d9:ac:b8:24:40:90:a6:03:56:2a:d0:
+ *     30:05:40:2c:4f:ab:d9:74:89
+ * publicExponent: 65537 (0x10001)
+ * privateExponent:
+ *     6e:a7:1b:83:51:35:9a:44:7d:f6:e3:89:a0:d7:90:
+ *     60:a1:4e:27:21:a2:89:74:cc:9d:75:75:4e:c7:82:
+ *     e3:e3:c3:7d:00:54:ec:36:b1:df:91:9c:7a:c0:62:
+ *     0a:d6:a9:22:91:4a:29:2e:43:fa:8c:d8:e9:be:d9:
+ *     4f:ca:23:c6:e4:3f:b8:72:cf:02:fc:f4:58:34:77:
+ *     76:ce:22:44:5f:2d:ca:ee:f5:43:56:47:71:0b:09:
+ *     6b:5e:f2:c8:ee:d4:6e:44:92:2a:7f:cc:a7:d4:5b:
+ *     fb:f7:4a:a9:fb:54:18:d5:d5:14:ba:a0:1c:13:b3:
+ *     37:6b:37:59:ed:db:6d:b1
+ * prime1:
+ *     00:d8:04:f2:8e:83:78:64:68:61:e8:3a:1a:47:2a:
+ *     ab:50:e8:45:64:95:d8:a1:1b:fd:e2:e1:67:a3:46:
+ *     89:de:95:73:7e:1d:18:75:2a:b0:76:1c:1c:74:33:
+ *     c0:ff:a8:0c:cf:d6:2d:eb:35:29:52:1d:ea:f8:e7:
+ *     d6:11:4c:99:c7
+ * prime2:
+ *     00:c4:55:ff:b1:56:12:9f:4e:c1:1e:ff:59:86:7e:
+ *     97:5d:cb:7f:0a:3e:37:cf:fb:4a:35:bc:e5:35:b7:
+ *     31:a9:0c:10:7a:bc:37:20:7e:75:f1:41:f6:60:e0:
+ *     3e:18:3d:e5:5d:b2:a9:f8:cc:ad:a0:52:d6:bf:cc:
+ *     e0:e1:84:ff:2f
+ * exponent1:
+ *     7e:a6:a7:ef:96:75:47:a9:4b:7d:f4:52:e3:d6:c8:
+ *     8a:af:23:c0:4d:7a:ad:3a:d4:27:e9:2f:f2:32:b1:
+ *     32:a7:3d:07:7b:d7:93:1a:6c:4b:53:3f:fb:81:3c:
+ *     6e:a8:00:9a:fa:60:01:bf:31:72:cb:c7:b0:17:7d:
+ *     12:b7:6e:91
+ * exponent2:
+ *     00:ab:36:8f:ae:d6:ef:90:6b:3e:30:48:df:8a:50:
+ *     d4:b1:1f:a7:9e:88:19:65:ce:ae:ad:64:17:c2:1b:
+ *     0a:3c:6f:df:e3:18:45:3e:99:e9:42:45:92:94:72:
+ *     98:d3:cd:0e:3b:02:76:05:18:80:84:e2:18:91:d4:
+ *     19:7b:b0:de:53
+ * coefficient:
+ *     71:07:aa:8f:59:b5:7c:fd:db:21:53:f9:58:6c:35:
+ *     cd:bd:07:c9:bf:b2:a5:09:76:d0:9c:31:df:e3:1a:
+ *     90:05:bb:a1:87:b9:f8:ea:21:90:69:42:c9:3a:df:
+ *     06:f0:11:20:0f:65:9f:a4:93:53:b5:91:2e:46:21:
+ *     12:d7:eb:4f
+ *
+ *
+ * server certificate:
+ * Data:
+ *     Version: 3 (0x2)
+ *     Serial Number: 8 (0x8)
+ *     Signature Algorithm: md5WithRSAEncryption
+ *     Issuer: C=US, ST=Some-State, L=Some-City, O=Some-Org
+ *     Validity
+ *         Not Before: Dec  8 03:43:04 2008 GMT
+ *         Not After : Aug 25 03:43:04 2028 GMT
+ *     Subject: C=US, ST=Some-State, L=Some-City, O=Some-Org, OU=SSL-Server, CN=localhost
+ *     Subject Public Key Info:
+ *         Public Key Algorithm: rsaEncryption
+ *         RSA Public Key: (1024 bit)
+ *             Modulus (1024 bit):
+ *                 00:a5:ac:5b:1c:37:a2:dd:99:89:2d:b2:79:b8:8f:
+ *                 d5:48:a5:e7:1c:84:17:8d:69:9c:c6:ac:6d:f9:f2:
+ *                 1d:1f:39:19:da:d3:72:1e:6e:ec:44:cc:70:a4:dc:
+ *                 ba:00:30:f6:a0:4f:3d:54:7a:61:6a:cc:57:d0:0a:
+ *                 7f:95:28:18:3f:9a:d9:94:f2:1b:c8:24:88:7e:fe:
+ *                 9d:0f:3d:fb:57:53:08:b3:20:33:d4:3f:17:47:14:
+ *                 d1:cd:ea:08:d8:0e:75:4e:af:be:cc:d2:ec:af:a9:
+ *                 7a:49:df:c2:d9:ac:b8:24:40:90:a6:03:56:2a:d0:
+ *                 30:05:40:2c:4f:ab:d9:74:89
+ *             Exponent: 65537 (0x10001)
+ *     X509v3 extensions:
+ *         X509v3 Basic Constraints:
+ *             CA:FALSE
+ *         X509v3 Key Usage:
+ *             Digital Signature, Non Repudiation, Key Encipherment
+ *         X509v3 Subject Key Identifier:
+ *             ED:6E:DB:F4:B5:56:C8:FB:1A:06:61:3F:0F:08:BB:A6:04:D8:16:54
+ *         X509v3 Authority Key Identifier:
+ *             keyid:FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14
+ *
+ *         X509v3 Subject Alternative Name: critical
+ *             DNS:localhost
+ * Signature Algorithm: md5WithRSAEncryption0
+ *
+ * -----BEGIN CERTIFICATE-----
+ * MIICpDCCAg2gAwIBAgIBCDANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET
+ * MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK
+ * EwhTb21lLU9yZzAeFw0wODEyMDgwMzQzMDRaFw0yODA4MjUwMzQzMDRaMHIxCzAJ
+ * BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp
+ * dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtU2VydmVyMRIwEAYD
+ * VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKWsWxw3
+ * ot2ZiS2yebiP1Uil5xyEF41pnMasbfnyHR85GdrTch5u7ETMcKTcugAw9qBPPVR6
+ * YWrMV9AKf5UoGD+a2ZTyG8gkiH7+nQ89+1dTCLMgM9Q/F0cU0c3qCNgOdU6vvszS
+ * 7K+peknfwtmsuCRAkKYDVirQMAVALE+r2XSJAgMBAAGjczBxMAkGA1UdEwQCMAAw
+ * CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTtbtv0tVbI+xoGYT8PCLumBNgWVDAfBgNV
+ * HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDAXBgNVHREBAf8EDTALgglsb2Nh
+ * bGhvc3QwDQYJKoZIhvcNAQEEBQADgYEAoqVTciHtcvsUj+YaTct8tUh3aTCsKsac
+ * PHhfQ+ObjiXSgxsKYTX7ym/wk/wvlbUcbqLKxsu7qrcJitH+H9heV1hEHEu65Uoi
+ * nRugFruyOrwvAylV8Cm2af7ddilmYJ+sdJA6N2M3xJRxR0G2LFHEXDNEjYReyexn
+ * JqCpf5uZGOo=
+ * -----END CERTIFICATE-----
+ *
+ *
+ * TLS client certificate:
+ * client private key:
+ * ----BEGIN RSA PRIVATE KEY-----
+ * Proc-Type: 4,ENCRYPTED
+ * DEK-Info: DES-EDE3-CBC,FA2A435CD35A9390
+ *
+ * Z+Y2uaETbsUWIyJUyVu1UV2G4rgFYJyACZT6Tp1KjRtxflSh2kXkJ9MpuXMXA0V4
+ * Yy3fDzPqCL9NJmQAYRlAx/W/+j4F5EyMWDIx8fUxzONRZyoiwF7jLm+KscAfv6Pf
+ * q7ItWOdj3z7IYrwlB8YIGd3F2cDKT3S+lYRk7rKb/qT7itbuHnY4Ardh3yl+MZak
+ * jBp+ELUlRsUqSr1V0LoM+0rCCykarpyfhpxEcqsrl0v9Cyi5uhU50/oKv5zql3SH
+ * l2ImgDjp3batAs8+Bd4NF2aqi0a7Hy44JUHxRm4caZryU/i/D9N1MbuM6882HLat
+ * 5N0G+NaIUfywa8mjwq2D5aiit18HqKA6XeRRYeJ5Dvu9DCO4GeFSwcUFIBMI0L46
+ * 7s114+oDodg57pMgITi+04vmUxvqlN9aiyd7f5Fgd7PeHGeOdbMz1NaJLJaPI9++
+ * NakK8eK9iwT/Gdq0Uap5/CHW7vCT5PO+h3HY0STH0lWStXhdWnFO04zTdywsbSp+
+ * DLpHeFT66shfeUlxR0PsCbG9vPRt/QmGLeYQZITppWo/ylSq4j+pRIuXvuWHdBRN
+ * rTZ8QF4Y7AxQUXVz1j1++s6ZMHTzaK2i9HrhmDs1MbJl+QwWre3Xpv3LvTVz3k5U
+ * wX8kuY1m3STt71QCaRWENq5sRaMImLxZbxc/ivFl9RAzUqo4NCxLod/QgA4iLqtO
+ * ztnlpzwlC/F8HbQ1oqYWwnZAPhzU/cULtstl+Yrws2c2atO323LbPXZqbASySgig
+ * sNpFXQMObdfP6LN23bY+1SvtK7V4NUTNhpdIc6INQAQ=
+ * -----END RSA PRIVATE KEY-----
+ *
+ * -----BEGIN RSA PRIVATE KEY-----
+ * MIICWwIBAAKBgQC78EA2rCZUTvSjWgAvaSFvuXo6k+yi9uGOx2PYLxIwmS6w8o/4
+ * Jy0keCiE9wG/jUR53TvSVfPOPLJbIX3v/TNKsaP/xsibuQ98QTWX+ds6BWAFFa9Z
+ * F5KjEK0WHOQHU6+odqJWKpLT+SjgeM9eH0irXBnd4WdDunWN9YKsQ5JEGwIDAQAB
+ * AoGAEbdqNj0wN85hnWyEi/ObJU8UyKTdL9eaF72QGfcF/fLSxfd3vurihIeXOkGW
+ * tpn4lIxYcVGM9CognhqgJpl11jFTQzn1KqZ+NEJRKkCHA4hDabKJbSC9fXHvRwrf
+ * BsFpZqgiNxp3HseUTiwnaUVeyPgMt/jAj5nB5Sib+UyUxrECQQDnNQBiF2aifEg6
+ * zbJOOC7he5CHAdkFxSxWVFVHL6EfXfqdLVkUohMbgZv+XxyIeU2biOExSg49Kds3
+ * FOKgTau1AkEA0Bd1haj6QuCo8I0AXm2WO+MMTZMTvtHD/bGjKNM+fT4I8rKYnQRX
+ * 1acHdqS9Xx2rNJqZgkMmpESIdPR2fc4yjwJALFeM6EMmqvj8/VIf5UJ/Mz14fXwM
+ * PEARfckUxd9LnnFutCBTWlKvKXJVEZb6KO5ixPaegc57Jp3Vbh3yTN44lQJADD/1
+ * SSMDaIB1MYP7a5Oj7m6VQNPRq8AJe5vDcRnOae0G9dKRrVyeFxO4GsHj6/+BHp2j
+ * P8nYMn9eURQ7DXjf/QJAAQzMlWnKGSO8pyTDtnQx3hRMoUkOEhmNq4bQhLkYqtnY
+ * FcqpUQ2qMjW+NiNWk5HnTrMS3L9EdJobMUzaNZLy4w==
+ * -----END RSA PRIVATE KEY-----
+ *
+ * Private-Key: (1024 bit)
+ * modulus:
+ *     00:bb:f0:40:36:ac:26:54:4e:f4:a3:5a:00:2f:69:
+ *     21:6f:b9:7a:3a:93:ec:a2:f6:e1:8e:c7:63:d8:2f:
+ *     12:30:99:2e:b0:f2:8f:f8:27:2d:24:78:28:84:f7:
+ *     01:bf:8d:44:79:dd:3b:d2:55:f3:ce:3c:b2:5b:21:
+ *     7d:ef:fd:33:4a:b1:a3:ff:c6:c8:9b:b9:0f:7c:41:
+ *     35:97:f9:db:3a:05:60:05:15:af:59:17:92:a3:10:
+ *     ad:16:1c:e4:07:53:af:a8:76:a2:56:2a:92:d3:f9:
+ *     28:e0:78:cf:5e:1f:48:ab:5c:19:dd:e1:67:43:ba:
+ *     75:8d:f5:82:ac:43:92:44:1b
+ * publicExponent: 65537 (0x10001)
+ * privateExponent:
+ *     11:b7:6a:36:3d:30:37:ce:61:9d:6c:84:8b:f3:9b:
+ *     25:4f:14:c8:a4:dd:2f:d7:9a:17:bd:90:19:f7:05:
+ *     fd:f2:d2:c5:f7:77:be:ea:e2:84:87:97:3a:41:96:
+ *     b6:99:f8:94:8c:58:71:51:8c:f4:2a:20:9e:1a:a0:
+ *     26:99:75:d6:31:53:43:39:f5:2a:a6:7e:34:42:51:
+ *     2a:40:87:03:88:43:69:b2:89:6d:20:bd:7d:71:ef:
+ *     47:0a:df:06:c1:69:66:a8:22:37:1a:77:1e:c7:94:
+ *     4e:2c:27:69:45:5e:c8:f8:0c:b7:f8:c0:8f:99:c1:
+ *     e5:28:9b:f9:4c:94:c6:b1
+ * prime1:
+ *     00:e7:35:00:62:17:66:a2:7c:48:3a:cd:b2:4e:38:
+ *     2e:e1:7b:90:87:01:d9:05:c5:2c:56:54:55:47:2f:
+ *     a1:1f:5d:fa:9d:2d:59:14:a2:13:1b:81:9b:fe:5f:
+ *     1c:88:79:4d:9b:88:e1:31:4a:0e:3d:29:db:37:14:
+ *     e2:a0:4d:ab:b5
+ * prime2:
+ *     00:d0:17:75:85:a8:fa:42:e0:a8:f0:8d:00:5e:6d:
+ *     96:3b:e3:0c:4d:93:13:be:d1:c3:fd:b1:a3:28:d3:
+ *     3e:7d:3e:08:f2:b2:98:9d:04:57:d5:a7:07:76:a4:
+ *     bd:5f:1d:ab:34:9a:99:82:43:26:a4:44:88:74:f4:
+ *     76:7d:ce:32:8f
+ * exponent1:
+ *     2c:57:8c:e8:43:26:aa:f8:fc:fd:52:1f:e5:42:7f:
+ *     33:3d:78:7d:7c:0c:3c:40:11:7d:c9:14:c5:df:4b:
+ *     9e:71:6e:b4:20:53:5a:52:af:29:72:55:11:96:fa:
+ *     28:ee:62:c4:f6:9e:81:ce:7b:26:9d:d5:6e:1d:f2:
+ *     4c:de:38:95
+ * exponent2:
+ *     0c:3f:f5:49:23:03:68:80:75:31:83:fb:6b:93:a3:
+ *     ee:6e:95:40:d3:d1:ab:c0:09:7b:9b:c3:71:19:ce:
+ *     69:ed:06:f5:d2:91:ad:5c:9e:17:13:b8:1a:c1:e3:
+ *     eb:ff:81:1e:9d:a3:3f:c9:d8:32:7f:5e:51:14:3b:
+ *     0d:78:df:fd
+ * coefficient:
+ *     01:0c:cc:95:69:ca:19:23:bc:a7:24:c3:b6:74:31:
+ *     de:14:4c:a1:49:0e:12:19:8d:ab:86:d0:84:b9:18:
+ *     aa:d9:d8:15:ca:a9:51:0d:aa:32:35:be:36:23:56:
+ *     93:91:e7:4e:b3:12:dc:bf:44:74:9a:1b:31:4c:da:
+ *     35:92:f2:e3
+ *
+ * client certificate:
+ * Data:
+ *     Version: 3 (0x2)
+ *     Serial Number: 9 (0x9)
+ *     Signature Algorithm: md5WithRSAEncryption
+ *     Issuer: C=US, ST=Some-State, L=Some-City, O=Some-Org
+ *     Validity
+ *         Not Before: Dec  8 03:43:24 2008 GMT
+ *         Not After : Aug 25 03:43:24 2028 GMT
+ *     Subject: C=US, ST=Some-State, L=Some-City, O=Some-Org, OU=SSL-Client, CN=localhost
+ *     Subject Public Key Info:
+ *         Public Key Algorithm: rsaEncryption
+ *         RSA Public Key: (1024 bit)
+ *             Modulus (1024 bit):
+ *                 00:bb:f0:40:36:ac:26:54:4e:f4:a3:5a:00:2f:69:
+ *                 21:6f:b9:7a:3a:93:ec:a2:f6:e1:8e:c7:63:d8:2f:
+ *                 12:30:99:2e:b0:f2:8f:f8:27:2d:24:78:28:84:f7:
+ *                 01:bf:8d:44:79:dd:3b:d2:55:f3:ce:3c:b2:5b:21:
+ *                 7d:ef:fd:33:4a:b1:a3:ff:c6:c8:9b:b9:0f:7c:41:
+ *                 35:97:f9:db:3a:05:60:05:15:af:59:17:92:a3:10:
+ *                 ad:16:1c:e4:07:53:af:a8:76:a2:56:2a:92:d3:f9:
+ *                 28:e0:78:cf:5e:1f:48:ab:5c:19:dd:e1:67:43:ba:
+ *                 75:8d:f5:82:ac:43:92:44:1b
+ *             Exponent: 65537 (0x10001)
+ *     X509v3 extensions:
+ *         X509v3 Basic Constraints:
+ *             CA:FALSE
+ *         X509v3 Key Usage:
+ *             Digital Signature, Non Repudiation, Key Encipherment
+ *         X509v3 Subject Key Identifier:
+ *             CD:BB:C8:85:AA:91:BD:FD:1D:BE:CD:67:7C:FF:B3:E9:4C:A8:22:E6
+ *         X509v3 Authority Key Identifier:
+ *             keyid:FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14
+ *
+ *         X509v3 Subject Alternative Name: critical
+ *             DNS:localhost
+ * Signature Algorithm: md5WithRSAEncryption
+ *
+ * -----BEGIN CERTIFICATE-----
+ * MIICpDCCAg2gAwIBAgIBCTANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET
+ * MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK
+ * EwhTb21lLU9yZzAeFw0wODEyMDgwMzQzMjRaFw0yODA4MjUwMzQzMjRaMHIxCzAJ
+ * BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp
+ * dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtQ2xpZW50MRIwEAYD
+ * VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALvwQDas
+ * JlRO9KNaAC9pIW+5ejqT7KL24Y7HY9gvEjCZLrDyj/gnLSR4KIT3Ab+NRHndO9JV
+ * 8848slshfe/9M0qxo//GyJu5D3xBNZf52zoFYAUVr1kXkqMQrRYc5AdTr6h2olYq
+ * ktP5KOB4z14fSKtcGd3hZ0O6dY31gqxDkkQbAgMBAAGjczBxMAkGA1UdEwQCMAAw
+ * CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTNu8iFqpG9/R2+zWd8/7PpTKgi5jAfBgNV
+ * HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDAXBgNVHREBAf8EDTALgglsb2Nh
+ * bGhvc3QwDQYJKoZIhvcNAQEEBQADgYEAm25gJyqW1JznQ1EyOtTGswBVwfgBOf+F
+ * HJuBTcflYQLbTD/AETPQJGvZU9tdhuLtbG3OPhR7vSY8zeAbfM3dbH7QFr3r47Gj
+ * XEH7qM/MX+Z3ifVaC4MeJmrYQkYFSuKeyyKpdRVX4w4nnFHF6OsNASsYrMW6LpxN
+ * cl/epUcHL7E=
+ * -----END CERTIFICATE-----
+ *
+ *
+ *
+ * Trusted CA certificate:
+ * Certificate:
+ *   Data:
+ *     Version: 3 (0x2)
+ *     Serial Number: 0 (0x0)
+ *     Signature Algorithm: md5WithRSAEncryption
+ *     Issuer: C=US, ST=Some-State, L=Some-City, O=Some-Org
+ *     Validity
+ *         Not Before: Dec  8 02:43:36 2008 GMT
+ *         Not After : Aug 25 02:43:36 2028 GMT
+ *     Subject: C=US, ST=Some-State, L=Some-City, O=Some-Org
+ *     Subject Public Key Info:
+ *         Public Key Algorithm: rsaEncryption
+ *         RSA Public Key: (1024 bit)
+ *             Modulus (1024 bit):
+ *                 00:cb:c4:38:20:07:be:88:a7:93:b0:a1:43:51:2d:
+ *                 d7:8e:85:af:54:dd:ad:a2:7b:23:5b:cf:99:13:53:
+ *                 99:45:7d:ee:6d:ba:2d:bf:e3:ad:6e:3d:9f:1a:f9:
+ *                 03:97:e0:17:55:ae:11:26:57:de:01:29:8e:05:3f:
+ *                 21:f7:e7:36:e8:2e:37:d7:48:ac:53:d6:60:0e:c7:
+ *                 50:6d:f6:c5:85:f7:8b:a6:c5:91:35:72:3c:94:ee:
+ *                 f1:17:f0:71:e3:ec:1b:ce:ca:4e:40:42:b0:6d:ee:
+ *                 6a:0e:d6:e5:ad:3c:0f:c9:ba:82:4f:78:f8:89:97:
+ *                 89:2a:95:12:4c:d8:09:2a:e9
+ *             Exponent: 65537 (0x10001)
+ *     X509v3 extensions:
+ *         X509v3 Subject Key Identifier:
+ *             FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14
+ *         X509v3 Authority Key Identifier:
+ *             keyid:FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14
+ *             DirName:/C=US/ST=Some-State/L=Some-City/O=Some-Org
+ *             serial:00
+ *
+ *         X509v3 Basic Constraints:
+ *             CA:TRUE
+ *  Signature Algorithm: md5WithRSAEncryption
+ *
+ * -----BEGIN CERTIFICATE-----
+ * MIICrDCCAhWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET
+ * MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK
+ * EwhTb21lLU9yZzAeFw0wODEyMDgwMjQzMzZaFw0yODA4MjUwMjQzMzZaMEkxCzAJ
+ * BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp
+ * dHkxETAPBgNVBAoTCFNvbWUtT3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
+ * gQDLxDggB76Ip5OwoUNRLdeOha9U3a2ieyNbz5kTU5lFfe5tui2/461uPZ8a+QOX
+ * 4BdVrhEmV94BKY4FPyH35zboLjfXSKxT1mAOx1Bt9sWF94umxZE1cjyU7vEX8HHj
+ * 7BvOyk5AQrBt7moO1uWtPA/JuoJPePiJl4kqlRJM2Akq6QIDAQABo4GjMIGgMB0G
+ * A1UdDgQWBBT6uVG/TOfZhpgz+efLHvEzSfeoFDBxBgNVHSMEajBogBT6uVG/TOfZ
+ * hpgz+efLHvEzSfeoFKFNpEswSTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUt
+ * U3RhdGUxEjAQBgNVBAcTCVNvbWUtQ2l0eTERMA8GA1UEChMIU29tZS1PcmeCAQAw
+ * DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBcIm534U123Hz+rtyYO5uA
+ * ofd81G6FnTfEAV8Kw9fGyyEbQZclBv34A9JsFKeMvU4OFIaixD7nLZ/NZ+IWbhmZ
+ * LovmJXyCkOufea73pNiZ+f/4/ScZaIlM/PRycQSqbFNd4j9Wott+08qxHPLpsf3P
+ * 6Mvf0r1PNTY2hwTJLJmKtg==
+ * -----END CERTIFICATE---
+ */
+
+
+public class SunX509ExtendedTM {
+
+    /*
+     * =============================================================
+     * 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;
+
+    /*
+     * Where do we find the keystores?
+     */
+    static String trusedCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICrDCCAhWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET\n" +
+        "MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK\n" +
+        "EwhTb21lLU9yZzAeFw0wODEyMDgwMjQzMzZaFw0yODA4MjUwMjQzMzZaMEkxCzAJ\n" +
+        "BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp\n" +
+        "dHkxETAPBgNVBAoTCFNvbWUtT3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n" +
+        "gQDLxDggB76Ip5OwoUNRLdeOha9U3a2ieyNbz5kTU5lFfe5tui2/461uPZ8a+QOX\n" +
+        "4BdVrhEmV94BKY4FPyH35zboLjfXSKxT1mAOx1Bt9sWF94umxZE1cjyU7vEX8HHj\n" +
+        "7BvOyk5AQrBt7moO1uWtPA/JuoJPePiJl4kqlRJM2Akq6QIDAQABo4GjMIGgMB0G\n" +
+        "A1UdDgQWBBT6uVG/TOfZhpgz+efLHvEzSfeoFDBxBgNVHSMEajBogBT6uVG/TOfZ\n" +
+        "hpgz+efLHvEzSfeoFKFNpEswSTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUt\n" +
+        "U3RhdGUxEjAQBgNVBAcTCVNvbWUtQ2l0eTERMA8GA1UEChMIU29tZS1PcmeCAQAw\n" +
+        "DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBcIm534U123Hz+rtyYO5uA\n" +
+        "ofd81G6FnTfEAV8Kw9fGyyEbQZclBv34A9JsFKeMvU4OFIaixD7nLZ/NZ+IWbhmZ\n" +
+        "LovmJXyCkOufea73pNiZ+f/4/ScZaIlM/PRycQSqbFNd4j9Wott+08qxHPLpsf3P\n" +
+        "6Mvf0r1PNTY2hwTJLJmKtg==\n" +
+        "-----END CERTIFICATE-----";
+
+    static String serverCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICpDCCAg2gAwIBAgIBCDANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET\n" +
+        "MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK\n" +
+        "EwhTb21lLU9yZzAeFw0wODEyMDgwMzQzMDRaFw0yODA4MjUwMzQzMDRaMHIxCzAJ\n" +
+        "BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp\n" +
+        "dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtU2VydmVyMRIwEAYD\n" +
+        "VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKWsWxw3\n" +
+        "ot2ZiS2yebiP1Uil5xyEF41pnMasbfnyHR85GdrTch5u7ETMcKTcugAw9qBPPVR6\n" +
+        "YWrMV9AKf5UoGD+a2ZTyG8gkiH7+nQ89+1dTCLMgM9Q/F0cU0c3qCNgOdU6vvszS\n" +
+        "7K+peknfwtmsuCRAkKYDVirQMAVALE+r2XSJAgMBAAGjczBxMAkGA1UdEwQCMAAw\n" +
+        "CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTtbtv0tVbI+xoGYT8PCLumBNgWVDAfBgNV\n" +
+        "HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDAXBgNVHREBAf8EDTALgglsb2Nh\n" +
+        "bGhvc3QwDQYJKoZIhvcNAQEEBQADgYEAoqVTciHtcvsUj+YaTct8tUh3aTCsKsac\n" +
+        "PHhfQ+ObjiXSgxsKYTX7ym/wk/wvlbUcbqLKxsu7qrcJitH+H9heV1hEHEu65Uoi\n" +
+        "nRugFruyOrwvAylV8Cm2af7ddilmYJ+sdJA6N2M3xJRxR0G2LFHEXDNEjYReyexn\n" +
+        "JqCpf5uZGOo=\n" +
+        "-----END CERTIFICATE-----";
+
+    static String clientCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICpDCCAg2gAwIBAgIBCTANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET\n" +
+        "MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK\n" +
+        "EwhTb21lLU9yZzAeFw0wODEyMDgwMzQzMjRaFw0yODA4MjUwMzQzMjRaMHIxCzAJ\n" +
+        "BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp\n" +
+        "dHkxETAPBgNVBAoTCFNvbWUtT3JnMRMwEQYDVQQLEwpTU0wtQ2xpZW50MRIwEAYD\n" +
+        "VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALvwQDas\n" +
+        "JlRO9KNaAC9pIW+5ejqT7KL24Y7HY9gvEjCZLrDyj/gnLSR4KIT3Ab+NRHndO9JV\n" +
+        "8848slshfe/9M0qxo//GyJu5D3xBNZf52zoFYAUVr1kXkqMQrRYc5AdTr6h2olYq\n" +
+        "ktP5KOB4z14fSKtcGd3hZ0O6dY31gqxDkkQbAgMBAAGjczBxMAkGA1UdEwQCMAAw\n" +
+        "CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTNu8iFqpG9/R2+zWd8/7PpTKgi5jAfBgNV\n" +
+        "HSMEGDAWgBT6uVG/TOfZhpgz+efLHvEzSfeoFDAXBgNVHREBAf8EDTALgglsb2Nh\n" +
+        "bGhvc3QwDQYJKoZIhvcNAQEEBQADgYEAm25gJyqW1JznQ1EyOtTGswBVwfgBOf+F\n" +
+        "HJuBTcflYQLbTD/AETPQJGvZU9tdhuLtbG3OPhR7vSY8zeAbfM3dbH7QFr3r47Gj\n" +
+        "XEH7qM/MX+Z3ifVaC4MeJmrYQkYFSuKeyyKpdRVX4w4nnFHF6OsNASsYrMW6LpxN\n" +
+        "cl/epUcHL7E=\n" +
+        "-----END CERTIFICATE-----";
+
+    static byte serverPrivateExponent[] = {
+        (byte)0x6e, (byte)0xa7, (byte)0x1b, (byte)0x83,
+        (byte)0x51, (byte)0x35, (byte)0x9a, (byte)0x44,
+        (byte)0x7d, (byte)0xf6, (byte)0xe3, (byte)0x89,
+        (byte)0xa0, (byte)0xd7, (byte)0x90, (byte)0x60,
+        (byte)0xa1, (byte)0x4e, (byte)0x27, (byte)0x21,
+        (byte)0xa2, (byte)0x89, (byte)0x74, (byte)0xcc,
+        (byte)0x9d, (byte)0x75, (byte)0x75, (byte)0x4e,
+        (byte)0xc7, (byte)0x82, (byte)0xe3, (byte)0xe3,
+        (byte)0xc3, (byte)0x7d, (byte)0x00, (byte)0x54,
+        (byte)0xec, (byte)0x36, (byte)0xb1, (byte)0xdf,
+        (byte)0x91, (byte)0x9c, (byte)0x7a, (byte)0xc0,
+        (byte)0x62, (byte)0x0a, (byte)0xd6, (byte)0xa9,
+        (byte)0x22, (byte)0x91, (byte)0x4a, (byte)0x29,
+        (byte)0x2e, (byte)0x43, (byte)0xfa, (byte)0x8c,
+        (byte)0xd8, (byte)0xe9, (byte)0xbe, (byte)0xd9,
+        (byte)0x4f, (byte)0xca, (byte)0x23, (byte)0xc6,
+        (byte)0xe4, (byte)0x3f, (byte)0xb8, (byte)0x72,
+        (byte)0xcf, (byte)0x02, (byte)0xfc, (byte)0xf4,
+        (byte)0x58, (byte)0x34, (byte)0x77, (byte)0x76,
+        (byte)0xce, (byte)0x22, (byte)0x44, (byte)0x5f,
+        (byte)0x2d, (byte)0xca, (byte)0xee, (byte)0xf5,
+        (byte)0x43, (byte)0x56, (byte)0x47, (byte)0x71,
+        (byte)0x0b, (byte)0x09, (byte)0x6b, (byte)0x5e,
+        (byte)0xf2, (byte)0xc8, (byte)0xee, (byte)0xd4,
+        (byte)0x6e, (byte)0x44, (byte)0x92, (byte)0x2a,
+        (byte)0x7f, (byte)0xcc, (byte)0xa7, (byte)0xd4,
+        (byte)0x5b, (byte)0xfb, (byte)0xf7, (byte)0x4a,
+        (byte)0xa9, (byte)0xfb, (byte)0x54, (byte)0x18,
+        (byte)0xd5, (byte)0xd5, (byte)0x14, (byte)0xba,
+        (byte)0xa0, (byte)0x1c, (byte)0x13, (byte)0xb3,
+        (byte)0x37, (byte)0x6b, (byte)0x37, (byte)0x59,
+        (byte)0xed, (byte)0xdb, (byte)0x6d, (byte)0xb1
+    };
+
+    static byte serverModulus[] = {
+        (byte)0x00,
+        (byte)0xa5, (byte)0xac, (byte)0x5b, (byte)0x1c,
+        (byte)0x37, (byte)0xa2, (byte)0xdd, (byte)0x99,
+        (byte)0x89, (byte)0x2d, (byte)0xb2, (byte)0x79,
+        (byte)0xb8, (byte)0x8f, (byte)0xd5, (byte)0x48,
+        (byte)0xa5, (byte)0xe7, (byte)0x1c, (byte)0x84,
+        (byte)0x17, (byte)0x8d, (byte)0x69, (byte)0x9c,
+        (byte)0xc6, (byte)0xac, (byte)0x6d, (byte)0xf9,
+        (byte)0xf2, (byte)0x1d, (byte)0x1f, (byte)0x39,
+        (byte)0x19, (byte)0xda, (byte)0xd3, (byte)0x72,
+        (byte)0x1e, (byte)0x6e, (byte)0xec, (byte)0x44,
+        (byte)0xcc, (byte)0x70, (byte)0xa4, (byte)0xdc,
+        (byte)0xba, (byte)0x00, (byte)0x30, (byte)0xf6,
+        (byte)0xa0, (byte)0x4f, (byte)0x3d, (byte)0x54,
+        (byte)0x7a, (byte)0x61, (byte)0x6a, (byte)0xcc,
+        (byte)0x57, (byte)0xd0, (byte)0x0a, (byte)0x7f,
+        (byte)0x95, (byte)0x28, (byte)0x18, (byte)0x3f,
+        (byte)0x9a, (byte)0xd9, (byte)0x94, (byte)0xf2,
+        (byte)0x1b, (byte)0xc8, (byte)0x24, (byte)0x88,
+        (byte)0x7e, (byte)0xfe, (byte)0x9d, (byte)0x0f,
+        (byte)0x3d, (byte)0xfb, (byte)0x57, (byte)0x53,
+        (byte)0x08, (byte)0xb3, (byte)0x20, (byte)0x33,
+        (byte)0xd4, (byte)0x3f, (byte)0x17, (byte)0x47,
+        (byte)0x14, (byte)0xd1, (byte)0xcd, (byte)0xea,
+        (byte)0x08, (byte)0xd8, (byte)0x0e, (byte)0x75,
+        (byte)0x4e, (byte)0xaf, (byte)0xbe, (byte)0xcc,
+        (byte)0xd2, (byte)0xec, (byte)0xaf, (byte)0xa9,
+        (byte)0x7a, (byte)0x49, (byte)0xdf, (byte)0xc2,
+        (byte)0xd9, (byte)0xac, (byte)0xb8, (byte)0x24,
+        (byte)0x40, (byte)0x90, (byte)0xa6, (byte)0x03,
+        (byte)0x56, (byte)0x2a, (byte)0xd0, (byte)0x30,
+        (byte)0x05, (byte)0x40, (byte)0x2c, (byte)0x4f,
+        (byte)0xab, (byte)0xd9, (byte)0x74, (byte)0x89
+    };
+
+    static byte clientPrivateExponent[] = {
+        (byte)0x11, (byte)0xb7, (byte)0x6a, (byte)0x36,
+        (byte)0x3d, (byte)0x30, (byte)0x37, (byte)0xce,
+        (byte)0x61, (byte)0x9d, (byte)0x6c, (byte)0x84,
+        (byte)0x8b, (byte)0xf3, (byte)0x9b, (byte)0x25,
+        (byte)0x4f, (byte)0x14, (byte)0xc8, (byte)0xa4,
+        (byte)0xdd, (byte)0x2f, (byte)0xd7, (byte)0x9a,
+        (byte)0x17, (byte)0xbd, (byte)0x90, (byte)0x19,
+        (byte)0xf7, (byte)0x05, (byte)0xfd, (byte)0xf2,
+        (byte)0xd2, (byte)0xc5, (byte)0xf7, (byte)0x77,
+        (byte)0xbe, (byte)0xea, (byte)0xe2, (byte)0x84,
+        (byte)0x87, (byte)0x97, (byte)0x3a, (byte)0x41,
+        (byte)0x96, (byte)0xb6, (byte)0x99, (byte)0xf8,
+        (byte)0x94, (byte)0x8c, (byte)0x58, (byte)0x71,
+        (byte)0x51, (byte)0x8c, (byte)0xf4, (byte)0x2a,
+        (byte)0x20, (byte)0x9e, (byte)0x1a, (byte)0xa0,
+        (byte)0x26, (byte)0x99, (byte)0x75, (byte)0xd6,
+        (byte)0x31, (byte)0x53, (byte)0x43, (byte)0x39,
+        (byte)0xf5, (byte)0x2a, (byte)0xa6, (byte)0x7e,
+        (byte)0x34, (byte)0x42, (byte)0x51, (byte)0x2a,
+        (byte)0x40, (byte)0x87, (byte)0x03, (byte)0x88,
+        (byte)0x43, (byte)0x69, (byte)0xb2, (byte)0x89,
+        (byte)0x6d, (byte)0x20, (byte)0xbd, (byte)0x7d,
+        (byte)0x71, (byte)0xef, (byte)0x47, (byte)0x0a,
+        (byte)0xdf, (byte)0x06, (byte)0xc1, (byte)0x69,
+        (byte)0x66, (byte)0xa8, (byte)0x22, (byte)0x37,
+        (byte)0x1a, (byte)0x77, (byte)0x1e, (byte)0xc7,
+        (byte)0x94, (byte)0x4e, (byte)0x2c, (byte)0x27,
+        (byte)0x69, (byte)0x45, (byte)0x5e, (byte)0xc8,
+        (byte)0xf8, (byte)0x0c, (byte)0xb7, (byte)0xf8,
+        (byte)0xc0, (byte)0x8f, (byte)0x99, (byte)0xc1,
+        (byte)0xe5, (byte)0x28, (byte)0x9b, (byte)0xf9,
+        (byte)0x4c, (byte)0x94, (byte)0xc6, (byte)0xb1
+    };
+
+    static byte clientModulus[] = {
+        (byte)0x00,
+        (byte)0xbb, (byte)0xf0, (byte)0x40, (byte)0x36,
+        (byte)0xac, (byte)0x26, (byte)0x54, (byte)0x4e,
+        (byte)0xf4, (byte)0xa3, (byte)0x5a, (byte)0x00,
+        (byte)0x2f, (byte)0x69, (byte)0x21, (byte)0x6f,
+        (byte)0xb9, (byte)0x7a, (byte)0x3a, (byte)0x93,
+        (byte)0xec, (byte)0xa2, (byte)0xf6, (byte)0xe1,
+        (byte)0x8e, (byte)0xc7, (byte)0x63, (byte)0xd8,
+        (byte)0x2f, (byte)0x12, (byte)0x30, (byte)0x99,
+        (byte)0x2e, (byte)0xb0, (byte)0xf2, (byte)0x8f,
+        (byte)0xf8, (byte)0x27, (byte)0x2d, (byte)0x24,
+        (byte)0x78, (byte)0x28, (byte)0x84, (byte)0xf7,
+        (byte)0x01, (byte)0xbf, (byte)0x8d, (byte)0x44,
+        (byte)0x79, (byte)0xdd, (byte)0x3b, (byte)0xd2,
+        (byte)0x55, (byte)0xf3, (byte)0xce, (byte)0x3c,
+        (byte)0xb2, (byte)0x5b, (byte)0x21, (byte)0x7d,
+        (byte)0xef, (byte)0xfd, (byte)0x33, (byte)0x4a,
+        (byte)0xb1, (byte)0xa3, (byte)0xff, (byte)0xc6,
+        (byte)0xc8, (byte)0x9b, (byte)0xb9, (byte)0x0f,
+        (byte)0x7c, (byte)0x41, (byte)0x35, (byte)0x97,
+        (byte)0xf9, (byte)0xdb, (byte)0x3a, (byte)0x05,
+        (byte)0x60, (byte)0x05, (byte)0x15, (byte)0xaf,
+        (byte)0x59, (byte)0x17, (byte)0x92, (byte)0xa3,
+        (byte)0x10, (byte)0xad, (byte)0x16, (byte)0x1c,
+        (byte)0xe4, (byte)0x07, (byte)0x53, (byte)0xaf,
+        (byte)0xa8, (byte)0x76, (byte)0xa2, (byte)0x56,
+        (byte)0x2a, (byte)0x92, (byte)0xd3, (byte)0xf9,
+        (byte)0x28, (byte)0xe0, (byte)0x78, (byte)0xcf,
+        (byte)0x5e, (byte)0x1f, (byte)0x48, (byte)0xab,
+        (byte)0x5c, (byte)0x19, (byte)0xdd, (byte)0xe1,
+        (byte)0x67, (byte)0x43, (byte)0xba, (byte)0x75,
+        (byte)0x8d, (byte)0xf5, (byte)0x82, (byte)0xac,
+        (byte)0x43, (byte)0x92, (byte)0x44, (byte)0x1b
+    };
+
+    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 = getSSLContext(trusedCertStr, serverCertStr,
+            serverModulus, serverPrivateExponent, passphrase);
+        SSLServerSocketFactory sslssf = context.getServerSocketFactory();
+
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket) sslssf.createServerSocket(serverPort);
+        serverPort = sslServerSocket.getLocalPort();
+
+
+        // enable endpoint identification
+        // ignore, we may test the feature when known how to parse client
+        // hostname
+        //SSLParameters params = sslServerSocket.getSSLParameters();
+        //params.setEndpointIdentificationAlgorithm("HTTPS");
+        //sslServerSocket.setSSLParameters(params);
+
+        /*
+         * Signal Client, we're ready for his connect.
+         */
+        serverReady = true;
+
+        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+        sslSocket.setNeedClientAuth(true);
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslIS.read();
+        sslOS.write(85);
+        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 = getSSLContext(trusedCertStr, clientCertStr,
+            clientModulus, clientPrivateExponent, passphrase);
+
+        SSLSocketFactory sslsf = context.getSocketFactory();
+        SSLSocket sslSocket = (SSLSocket)
+            sslsf.createSocket("localhost", serverPort);
+
+        // enable endpoint identification
+        SSLParameters params = sslSocket.getSSLParameters();
+        params.setEndpointIdentificationAlgorithm("HTTPS");
+        sslSocket.setSSLParameters(params);
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslOS.write(280);
+        sslOS.flush();
+        sslIS.read();
+
+        sslSocket.close();
+
+    }
+
+    // get the ssl context
+    private static SSLContext getSSLContext(String trusedCertStr,
+            String keyCertStr, byte[] modulus,
+            byte[] privateExponent, char[] passphrase) throws Exception {
+
+        // generate certificate from cert string
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+        ByteArrayInputStream is =
+                    new ByteArrayInputStream(trusedCertStr.getBytes());
+        Certificate trusedCert = cf.generateCertificate(is);
+        is.close();
+
+        // create a key store
+        KeyStore ks = KeyStore.getInstance("JKS");
+        ks.load(null, null);
+
+        // import the trused cert
+        ks.setCertificateEntry("RSA Export Signer", trusedCert);
+
+        if (keyCertStr != null) {
+            // generate the private key.
+            RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(
+                                            new BigInteger(modulus),
+                                            new BigInteger(privateExponent));
+            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();
+
+            Certificate[] chain = new Certificate[2];
+            chain[0] = keyCert;
+            chain[1] = trusedCert;
+
+            // import the key entry.
+            ks.setKeyEntry("Whatever", priKey, passphrase, chain);
+        }
+
+        // create SSL context
+        TrustManagerFactory tmf =
+                TrustManagerFactory.getInstance("SunX509");
+        tmf.init(ks);
+
+        TrustManager tms[] = tmf.getTrustManagers();
+        if (tms == null || tms.length == 0) {
+            throw new Exception("unexpected trust manager implementation");
+        } else {
+           if (!(tms[0] instanceof X509ExtendedTrustManager)) {
+            throw new Exception("unexpected trust manager implementation: "
+                                + tms[0].getClass().getCanonicalName());
+           }
+        }
+
+
+        SSLContext ctx = SSLContext.getInstance("TLS");
+
+        if (keyCertStr != null) {
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+            kmf.init(ks, passphrase);
+
+            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+        } else {
+            ctx.init(null, tmf.getTrustManagers(), null);
+        }
+
+        return ctx;
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+
+    // 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");
+
+        /*
+         * Start the tests.
+         */
+        new SunX509ExtendedTM();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    SunX509ExtendedTM() throws Exception {
+        if (separateServerThread) {
+            startServer(true);
+            startClient(false);
+        } else {
+            startClient(true);
+            startServer(false);
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            serverThread.join();
+        } else {
+            clientThread.join();
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         *
+         * If the main thread excepted, that propagates back
+         * immediately.  If the other thread threw an exception, we
+         * should report back.
+         */
+        if (serverException != null)
+            throw serverException;
+        if (clientException != null)
+            throw clientException;
+    }
+
+    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 {
+            doServerSide();
+        }
+    }
+
+    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 {
+            doClientSide();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/X509ExtendedTMEnabled.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2010, 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 6916074
+ * @summary Add support for TLS 1.2
+ *
+ * Ensure that the SunJSSE provider enables the X509ExtendedTrustManager.
+ */
+
+import java.io.*;
+import java.net.*;
+import javax.net.ssl.*;
+import java.security.cert.*;
+import java.security.*;
+
+public class X509ExtendedTMEnabled {
+
+    /*
+     * =============================================================
+     * 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 = true;
+
+    /*
+     * Where do we find the keystores?
+     */
+    static String pathToStores = "../../../../../../../etc";
+    static String keyStoreFile = "keystore";
+    static String trustStoreFile = "truststore";
+    static String passwd = "passphrase";
+    private final static char[] cpasswd = "passphrase".toCharArray();
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    /*
+     * If the client or server is doing some kind of object creation
+     * that the other side depends on, and that thread prematurely
+     * exits, you may experience a hang.  The test harness will
+     * terminate all hung threads after its timeout has expired,
+     * currently 3 minutes by default, but you might try to be
+     * smart about it....
+     */
+
+    /*
+     * 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 {
+        SSLServerSocketFactory sslssf =
+                                getContext(true).getServerSocketFactory();
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket) sslssf.createServerSocket(serverPort);
+        serverPort = sslServerSocket.getLocalPort();
+
+        // enable endpoint identification
+        // ignore, we may test the feature when known how to parse client
+        // hostname
+        //SSLParameters params = sslServerSocket.getSSLParameters();
+        //params.setEndpointIdentificationAlgorithm("HTTPS");
+        //sslServerSocket.setSSLParameters(params);
+
+        /*
+         * Signal Client, we're ready for his connect.
+         */
+        serverReady = true;
+
+        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+        sslSocket.setNeedClientAuth(true);
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslIS.read();
+        sslOS.write(85);
+        sslOS.flush();
+
+        sslSocket.close();
+
+        if (!serverTM.wasServerChecked() && serverTM.wasClientChecked()) {
+            System.out.println("SERVER TEST PASSED!");
+        } else {
+            throw new Exception("SERVER TEST FAILED!  " +
+                !serverTM.wasServerChecked() + " " +
+                serverTM.wasClientChecked());
+        }
+    }
+
+    /*
+     * 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);
+        }
+
+        SSLSocketFactory sslsf = getContext(false).getSocketFactory();
+        SSLSocket sslSocket = (SSLSocket)
+            sslsf.createSocket("localhost", serverPort);
+
+        // enable endpoint identification
+        SSLParameters params = sslSocket.getSSLParameters();
+        params.setEndpointIdentificationAlgorithm("HTTPS");
+        sslSocket.setSSLParameters(params);
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslOS.write(280);
+        sslOS.flush();
+        sslIS.read();
+
+        sslSocket.close();
+
+        if (clientTM.wasServerChecked() && !clientTM.wasClientChecked()) {
+            System.out.println("CLIENT TEST PASSED!");
+        } else {
+            throw new Exception("CLIENT TEST FAILED!  " +
+                clientTM.wasServerChecked() + " " +
+                !clientTM.wasClientChecked());
+        }
+    }
+
+    MyExtendedX509TM serverTM;
+    MyExtendedX509TM clientTM;
+
+    private SSLContext getContext(boolean server) throws Exception {
+        String keyFilename =
+            System.getProperty("test.src", "./") + "/" + pathToStores +
+                "/" + keyStoreFile;
+        String trustFilename =
+            System.getProperty("test.src", "./") + "/" + pathToStores +
+                "/" + trustStoreFile;
+
+        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+        KeyStore ks = KeyStore.getInstance("JKS");
+        ks.load(new FileInputStream(keyFilename), cpasswd);
+        kmf.init(ks, cpasswd);
+
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+        KeyStore ts = KeyStore.getInstance("JKS");
+        ts.load(new FileInputStream(trustFilename), cpasswd);
+        tmf.init(ts);
+
+        TrustManager tms[] = tmf.getTrustManagers();
+        if (tms == null || tms.length == 0) {
+            throw new Exception("unexpected trust manager implementation");
+        } else {
+           if (!(tms[0] instanceof X509TrustManager)) {
+            throw new Exception("unexpected trust manager implementation: "
+                                + tms[0].getClass().getCanonicalName());
+           }
+        }
+
+        if (server) {
+            serverTM = new MyExtendedX509TM((X509TrustManager)tms[0]);
+
+            tms = new TrustManager[] {serverTM};
+        } else {
+            clientTM = new MyExtendedX509TM((X509TrustManager)tms[0]);
+
+            tms = new TrustManager[] {clientTM};
+        }
+
+        SSLContext ctx = SSLContext.getInstance("TLS");
+        ctx.init(kmf.getKeyManagers(), tms, null);
+
+        return ctx;
+    }
+
+    static class MyExtendedX509TM extends X509ExtendedTrustManager
+            implements X509TrustManager {
+
+        X509TrustManager tm;
+
+        boolean clientChecked;
+        boolean serverChecked;
+
+        MyExtendedX509TM(X509TrustManager tm) {
+            clientChecked = false;
+            serverChecked = false;
+
+            this.tm = tm;
+        }
+
+        public boolean wasClientChecked() {
+            return clientChecked;
+        }
+
+        public boolean wasServerChecked() {
+            return serverChecked;
+        }
+
+
+        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();
+        }
+
+        public void checkClientTrusted(X509Certificate[] chain, String authType,
+                Socket socket) throws CertificateException {
+            clientChecked = true;
+            tm.checkClientTrusted(chain, authType);
+        }
+
+        public void checkServerTrusted(X509Certificate[] chain, String authType,
+                Socket socket) throws CertificateException {
+            serverChecked = true;
+            tm.checkServerTrusted(chain, authType);
+        }
+
+        public void checkClientTrusted(X509Certificate[] chain, String authType,
+            SSLEngine engine) throws CertificateException {
+            clientChecked = true;
+            tm.checkClientTrusted(chain, authType);
+        }
+
+        public void checkServerTrusted(X509Certificate[] chain, String authType,
+            SSLEngine engine) throws CertificateException {
+            serverChecked = true;
+            tm.checkServerTrusted(chain, authType);
+        }
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+
+    // 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");
+
+        /*
+         * Start the tests.
+         */
+        new X509ExtendedTMEnabled();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    X509ExtendedTMEnabled() throws Exception {
+        if (separateServerThread) {
+            startServer(true);
+            startClient(false);
+        } else {
+            startClient(true);
+            startServer(false);
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            serverThread.join();
+        } else {
+            clientThread.join();
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         *
+         * If the main thread excepted, that propagates back
+         * immediately.  If the other thread threw an exception, we
+         * should report back.
+         */
+        if (serverException != null)
+            throw serverException;
+        if (clientException != null)
+            throw clientException;
+    }
+
+    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 {
+            doServerSide();
+        }
+    }
+
+    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 {
+            doClientSide();
+        }
+    }
+}
+
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/CheckMyTrustedKeystore.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/CheckMyTrustedKeystore.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, 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,8 @@
  * @bug 4329114
  * @summary Need better way of reflecting the reason when a chain is
  *      rejected as untrusted.
+ * @ignore JSSE supports algorithm constraints with CR 6916074,
+ *     need to update this test case in JDK 7 soon
  * This is a serious hack job!
  * @author Brad Wetmore
  */
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/Basics.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/Basics.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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,8 @@
  * @bug 4495742
  * @summary Add non-blocking SSL/TLS functionality, usable with any
  *      I/O abstraction
+ * @ignore JSSE supported cipher suites are changed with CR 6916074,
+ *     need to update this test case in JDK 7 soon
  *
  * This is intended to test many of the basic API calls to the SSLEngine
  * interface.  This doesn't really exercise much of the SSL code.
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/TestAllSuites.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/TestAllSuites.java	Wed Jul 05 17:26:57 2017 +0200
@@ -24,6 +24,8 @@
 /*
  * @test
  * @bug 4495742
+ * @ignore JSSE supported cipher suites are changed with CR 6916074,
+ *     need to update this test case in JDK 7 soon
  * @run main/timeout=180 TestAllSuites
  * @summary Add non-blocking SSL/TLS functionality, usable with any
  *      I/O abstraction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/EmptyCertificateAuthorities.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 2010, 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 4873188
+ * @summary Support TLS 1.1
+ * @run main/othervm -Djavax.net.debug=all EmptyCertificateAuthorities
+ *
+ * @author Xuelei Fan
+ */
+
+import java.io.*;
+import java.net.*;
+import java.security.*;
+import java.security.cert.*;
+import javax.net.ssl.*;
+
+public class EmptyCertificateAuthorities {
+
+    /*
+     * =============================================================
+     * 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;
+
+    /*
+     * Where do we find the keystores?
+     */
+    static String pathToStores = "/../../../../etc";
+    static String keyStoreFile = "keystore";
+    static String trustStoreFile = "truststore";
+    static String passwd = "passphrase";
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    /*
+     * If the client or server is doing some kind of object creation
+     * that the other side depends on, and that thread prematurely
+     * exits, you may experience a hang.  The test harness will
+     * terminate all hung threads after its timeout has expired,
+     * currently 3 minutes by default, but you might try to be
+     * smart about it....
+     */
+
+    /*
+     * 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 {
+        SSLServerSocketFactory sslssf = getSSLServerSF();
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket) sslssf.createServerSocket(serverPort);
+
+        // require client authentication.
+        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);
+        }
+
+        SSLSocketFactory sslsf =
+            (SSLSocketFactory) SSLSocketFactory.getDefault();
+        SSLSocket sslSocket = (SSLSocket)
+            sslsf.createSocket("localhost", serverPort);
+
+        // enable TLSv1.1 only
+        sslSocket.setEnabledProtocols(new String[] {"TLSv1.1"});
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslOS.write('B');
+        sslOS.flush();
+        sslIS.read();
+
+        sslSocket.close();
+    }
+
+    private SSLServerSocketFactory getSSLServerSF() throws Exception {
+
+        char [] password =
+            System.getProperty("javax.net.ssl.keyStorePassword").toCharArray();
+        String keyFilename = System.getProperty("javax.net.ssl.keyStore");
+
+        KeyStore ks = KeyStore.getInstance("JKS");
+        ks.load(new FileInputStream(keyFilename), password);
+
+        KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
+        kmf.init(ks, password);
+
+        KeyManager[] kms = kmf.getKeyManagers();
+        TrustManager[] tms = new MyX509TM[] {new MyX509TM()};
+
+        SSLContext ctx = SSLContext.getInstance("TLS");
+        ctx.init(kms, tms, null);
+
+        return ctx.getServerSocketFactory();
+    }
+
+
+    static class MyX509TM implements X509TrustManager {
+        X509TrustManager tm;
+
+        public void checkClientTrusted(X509Certificate[] chain,
+            String authType) throws CertificateException {
+            if (tm == null) {
+                initialize();
+            }
+            tm.checkClientTrusted(chain, authType);
+        }
+
+        public void checkServerTrusted(X509Certificate[] chain,
+            String authType) throws CertificateException {
+            if (tm == null) {
+                initialize();
+            }
+            tm.checkServerTrusted(chain, authType);
+        }
+
+        public X509Certificate[] getAcceptedIssuers() {
+            // always return empty array
+            return new X509Certificate[0];
+        }
+
+        private void initialize() throws CertificateException {
+            String passwd =
+                System.getProperty("javax.net.ssl.trustStorePassword");
+            char [] password = passwd.toCharArray();
+            String trustFilename =
+                System.getProperty("javax.net.ssl.trustStore");
+
+            try {
+                KeyStore ks = KeyStore.getInstance("JKS");
+                ks.load(new FileInputStream(trustFilename), password);
+
+                TrustManagerFactory tmf =
+                        TrustManagerFactory.getInstance("PKIX");
+                tmf.init(ks);
+                tm = (X509TrustManager)tmf.getTrustManagers()[0];
+            } catch (Exception e) {
+                throw new CertificateException("Unable to initialize TM");
+            }
+
+        }
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+
+    // 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 {
+        String keyFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + keyStoreFile;
+        String trustFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + trustStoreFile;
+
+        System.setProperty("javax.net.ssl.keyStore", keyFilename);
+        System.setProperty("javax.net.ssl.keyStorePassword", passwd);
+        System.setProperty("javax.net.ssl.trustStore", trustFilename);
+        System.setProperty("javax.net.ssl.trustStorePassword", passwd);
+
+        if (debug)
+            System.setProperty("javax.net.debug", "all");
+
+        /*
+         * Start the tests.
+         */
+        new EmptyCertificateAuthorities();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    EmptyCertificateAuthorities() 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/javax/net/ssl/TLSv11/ExportableBlockCipher.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2010, 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 4873188
+ * @summary Support TLS 1.1
+ * @run main/othervm -Djavax.net.debug=all ExportableBlockCipher
+ *
+ * @author Xuelei Fan
+ */
+
+import java.io.*;
+import java.net.*;
+import javax.net.ssl.*;
+
+public class ExportableBlockCipher {
+
+    /*
+     * =============================================================
+     * 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;
+
+    /*
+     * Where do we find the keystores?
+     */
+    static String pathToStores = "/../../../../etc";
+    static String keyStoreFile = "keystore";
+    static String trustStoreFile = "truststore";
+    static String passwd = "passphrase";
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    /*
+     * If the client or server is doing some kind of object creation
+     * that the other side depends on, and that thread prematurely
+     * exits, you may experience a hang.  The test harness will
+     * terminate all hung threads after its timeout has expired,
+     * currently 3 minutes by default, but you might try to be
+     * smart about it....
+     */
+
+    /*
+     * 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 {
+        SSLServerSocketFactory sslssf =
+            (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket) sslssf.createServerSocket(serverPort);
+
+        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();
+
+        boolean interrupted = false;
+        try {
+            sslIS.read();
+            sslOS.write('A');
+            sslOS.flush();
+        } catch (SSLException ssle) {
+            // get the expected exception
+            interrupted = true;
+        } finally {
+            sslSocket.close();
+        }
+
+        if (!interrupted) {
+            throw new SSLHandshakeException(
+                "A weak cipher suite is negotiated, " +
+                "TLSv1.1 must not negotiate the exportable cipher suites.");
+        }
+    }
+
+    /*
+     * 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);
+        }
+
+        SSLSocketFactory sslsf =
+            (SSLSocketFactory) SSLSocketFactory.getDefault();
+        SSLSocket sslSocket = (SSLSocket)
+            sslsf.createSocket("localhost", serverPort);
+
+        // enable TLSv1.1 only
+        sslSocket.setEnabledProtocols(new String[] {"TLSv1.1"});
+
+        // enable a exportable block cipher
+        sslSocket.setEnabledCipherSuites(
+            new String[] {"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"});
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        boolean interrupted = false;
+        try {
+            sslOS.write('B');
+            sslOS.flush();
+            sslIS.read();
+        } catch (SSLException ssle) {
+            // get the expected exception
+            interrupted = true;
+        } finally {
+            sslSocket.close();
+        }
+
+        if (!interrupted) {
+            throw new SSLHandshakeException(
+                "A weak cipher suite is negotiated, " +
+                "TLSv1.1 must not negotiate the exportable cipher suites.");
+        }
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+
+    // 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 {
+        String keyFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + keyStoreFile;
+        String trustFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + trustStoreFile;
+
+        System.setProperty("javax.net.ssl.keyStore", keyFilename);
+        System.setProperty("javax.net.ssl.keyStorePassword", passwd);
+        System.setProperty("javax.net.ssl.trustStore", trustFilename);
+        System.setProperty("javax.net.ssl.trustStorePassword", passwd);
+
+        if (debug)
+            System.setProperty("javax.net.debug", "all");
+
+        /*
+         * Start the tests.
+         */
+        new ExportableBlockCipher();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    ExportableBlockCipher() 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/javax/net/ssl/TLSv11/ExportableStreamCipher.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2010, 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 4873188
+ * @summary Support TLS 1.1
+ * @run main/othervm -Djavax.net.debug=all ExportableStreamCipher
+ *
+ * @author Xuelei Fan
+ */
+
+import java.io.*;
+import java.net.*;
+import javax.net.ssl.*;
+
+public class ExportableStreamCipher {
+
+    /*
+     * =============================================================
+     * 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;
+
+    /*
+     * Where do we find the keystores?
+     */
+    static String pathToStores = "/../../../../etc";
+    static String keyStoreFile = "keystore";
+    static String trustStoreFile = "truststore";
+    static String passwd = "passphrase";
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    /*
+     * If the client or server is doing some kind of object creation
+     * that the other side depends on, and that thread prematurely
+     * exits, you may experience a hang.  The test harness will
+     * terminate all hung threads after its timeout has expired,
+     * currently 3 minutes by default, but you might try to be
+     * smart about it....
+     */
+
+    /*
+     * 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 {
+        SSLServerSocketFactory sslssf =
+            (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket) sslssf.createServerSocket(serverPort);
+
+        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();
+
+        boolean interrupted = false;
+        try {
+            sslIS.read();
+            sslOS.write('A');
+            sslOS.flush();
+        } catch (SSLException ssle) {
+            // get the expected exception
+            interrupted = true;
+        } finally {
+            sslSocket.close();
+        }
+
+        if (!interrupted) {
+            throw new SSLHandshakeException(
+                "A weak cipher suite is negotiated, " +
+                "TLSv1.1 must not negotiate the exportable cipher suites.");
+        }
+    }
+
+    /*
+     * 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);
+        }
+
+        SSLSocketFactory sslsf =
+            (SSLSocketFactory) SSLSocketFactory.getDefault();
+        SSLSocket sslSocket = (SSLSocket)
+            sslsf.createSocket("localhost", serverPort);
+
+        // enable TLSv1.1 only
+        sslSocket.setEnabledProtocols(new String[] {"TLSv1.1"});
+
+        // enable a exportable stream cipher
+        sslSocket.setEnabledCipherSuites(
+            new String[] {"SSL_RSA_EXPORT_WITH_RC4_40_MD5"});
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        boolean interrupted = false;
+        try {
+            sslOS.write('B');
+            sslOS.flush();
+            sslIS.read();
+        } catch (SSLException ssle) {
+            // get the expected exception
+            interrupted = true;
+        } finally {
+            sslSocket.close();
+        }
+
+        if (!interrupted) {
+            throw new SSLHandshakeException(
+                "A weak cipher suite is negotiated, " +
+                "TLSv1.1 must not negotiate the exportable cipher suites.");
+        }
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+
+    // 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 {
+        String keyFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + keyStoreFile;
+        String trustFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + trustStoreFile;
+
+        System.setProperty("javax.net.ssl.keyStore", keyFilename);
+        System.setProperty("javax.net.ssl.keyStorePassword", passwd);
+        System.setProperty("javax.net.ssl.trustStore", trustFilename);
+        System.setProperty("javax.net.ssl.trustStorePassword", passwd);
+
+        if (debug)
+            System.setProperty("javax.net.debug", "all");
+
+        /*
+         * Start the tests.
+         */
+        new ExportableStreamCipher();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    ExportableStreamCipher() 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/javax/net/ssl/TLSv11/GenericBlockCipher.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2010, 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 4873188
+ * @summary Support TLS 1.1
+ * @run main/othervm -Djavax.net.debug=all GenericBlockCipher
+ *
+ * @author Xuelei Fan
+ */
+
+import java.io.*;
+import java.net.*;
+import javax.net.ssl.*;
+
+public class GenericBlockCipher {
+
+    /*
+     * =============================================================
+     * 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;
+
+    /*
+     * Where do we find the keystores?
+     */
+    static String pathToStores = "/../../../../etc";
+    static String keyStoreFile = "keystore";
+    static String trustStoreFile = "truststore";
+    static String passwd = "passphrase";
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    /*
+     * If the client or server is doing some kind of object creation
+     * that the other side depends on, and that thread prematurely
+     * exits, you may experience a hang.  The test harness will
+     * terminate all hung threads after its timeout has expired,
+     * currently 3 minutes by default, but you might try to be
+     * smart about it....
+     */
+
+    /*
+     * 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 {
+        SSLServerSocketFactory sslssf =
+            (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket) sslssf.createServerSocket(serverPort);
+
+        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);
+        }
+
+        SSLSocketFactory sslsf =
+            (SSLSocketFactory) SSLSocketFactory.getDefault();
+        SSLSocket sslSocket = (SSLSocket)
+            sslsf.createSocket("localhost", serverPort);
+
+        // enable TLSv1.1 only
+        sslSocket.setEnabledProtocols(new String[] {"TLSv1.1"});
+
+        // enable a block cipher
+        sslSocket.setEnabledCipherSuites(
+            new String[] {"TLS_RSA_WITH_AES_128_CBC_SHA"});
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslOS.write('B');
+        sslOS.flush();
+        sslIS.read();
+
+        sslSocket.close();
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+
+    // 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 {
+        String keyFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + keyStoreFile;
+        String trustFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + trustStoreFile;
+
+        System.setProperty("javax.net.ssl.keyStore", keyFilename);
+        System.setProperty("javax.net.ssl.keyStorePassword", passwd);
+        System.setProperty("javax.net.ssl.trustStore", trustFilename);
+        System.setProperty("javax.net.ssl.trustStorePassword", passwd);
+
+        if (debug)
+            System.setProperty("javax.net.debug", "all");
+
+        /*
+         * Start the tests.
+         */
+        new GenericBlockCipher();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    GenericBlockCipher() 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/javax/net/ssl/TLSv11/GenericStreamCipher.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2010, 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 4873188
+ * @summary Support TLS 1.1
+ * @run main/othervm -Djavax.net.debug=all GenericStreamCipher
+ *
+ * @author Xuelei Fan
+ */
+
+import java.io.*;
+import java.net.*;
+import javax.net.ssl.*;
+
+public class GenericStreamCipher {
+
+    /*
+     * =============================================================
+     * 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;
+
+    /*
+     * Where do we find the keystores?
+     */
+    static String pathToStores = "/../../../../etc";
+    static String keyStoreFile = "keystore";
+    static String trustStoreFile = "truststore";
+    static String passwd = "passphrase";
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    /*
+     * If the client or server is doing some kind of object creation
+     * that the other side depends on, and that thread prematurely
+     * exits, you may experience a hang.  The test harness will
+     * terminate all hung threads after its timeout has expired,
+     * currently 3 minutes by default, but you might try to be
+     * smart about it....
+     */
+
+    /*
+     * 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 {
+        SSLServerSocketFactory sslssf =
+            (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket) sslssf.createServerSocket(serverPort);
+
+        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);
+        }
+
+        SSLSocketFactory sslsf =
+            (SSLSocketFactory) SSLSocketFactory.getDefault();
+        SSLSocket sslSocket = (SSLSocket)
+            sslsf.createSocket("localhost", serverPort);
+
+        // enable TLSv1.1 only
+        sslSocket.setEnabledProtocols(new String[] {"TLSv1.1"});
+
+        // enable a stream cipher
+        sslSocket.setEnabledCipherSuites(
+            new String[] {"SSL_RSA_WITH_RC4_128_MD5"});
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslOS.write('B');
+        sslOS.flush();
+        sslIS.read();
+
+        sslSocket.close();
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+
+    // 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 {
+        String keyFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + keyStoreFile;
+        String trustFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + trustStoreFile;
+
+        System.setProperty("javax.net.ssl.keyStore", keyFilename);
+        System.setProperty("javax.net.ssl.keyStorePassword", passwd);
+        System.setProperty("javax.net.ssl.trustStore", trustFilename);
+        System.setProperty("javax.net.ssl.trustStorePassword", passwd);
+
+        if (debug)
+            System.setProperty("javax.net.debug", "all");
+
+        /*
+         * Start the tests.
+         */
+        new GenericStreamCipher();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    GenericStreamCipher() 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;
+            }
+        }
+    }
+}
--- a/jdk/test/sun/security/ssl/sanity/ciphersuites/CheckCipherSuites.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/security/ssl/sanity/ciphersuites/CheckCipherSuites.java	Wed Jul 05 17:26:57 2017 +0200
@@ -25,6 +25,8 @@
  * @test
  * @bug 4750141 4895631
  * @summary Check enabled and supported ciphersuites are correct
+ * @ignore JSSE supported cipher suites are changed with CR 6916074,
+ *     need to update this test case in JDK 7 soon
  */
 
 import java.util.*;
--- a/jdk/test/sun/security/ssl/sanity/interop/CipherTest.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/security/ssl/sanity/interop/CipherTest.java	Wed Jul 05 17:26:57 2017 +0200
@@ -120,6 +120,13 @@
                 return false;
             }
 
+            // ignore exportable cipher suite for TLSv1.1
+            if (protocol.equals("TLSv1.1")) {
+                if(cipherSuite.indexOf("_EXPORT_") != -1) {
+                    return false;
+                }
+            }
+
             return true;
         }
 
@@ -149,18 +156,14 @@
             cipherSuites.length * protocols.length * clientAuths.length);
         for (int i = 0; i < cipherSuites.length; i++) {
             String cipherSuite = cipherSuites[i];
-            if (peerFactory.isSupported(cipherSuite) == false) {
-                continue;
-            }
-            // skip kerberos cipher suites
-            if (cipherSuite.startsWith("TLS_KRB5")) {
-                continue;
-            }
+
             for (int j = 0; j < protocols.length; j++) {
                 String protocol = protocols[j];
-                if (protocol.equals("SSLv2Hello")) {
+
+                if (!peerFactory.isSupported(cipherSuite, protocol)) {
                     continue;
                 }
+
                 for (int k = 0; k < clientAuths.length; k++) {
                     String clientAuth = clientAuths[k];
                     if ((clientAuth != null) &&
@@ -297,7 +300,7 @@
             throws Exception {
         long time = System.currentTimeMillis();
         String relPath;
-        if ((args.length > 0) && args[0].equals("sh")) {
+        if ((args != null) && (args.length > 0) && args[0].equals("sh")) {
             relPath = pathToStoresSH;
         } else {
             relPath = pathToStores;
@@ -336,7 +339,36 @@
 
         abstract Server newServer(CipherTest cipherTest) throws Exception;
 
-        boolean isSupported(String cipherSuite) {
+        boolean isSupported(String cipherSuite, String protocol) {
+            // skip kerberos cipher suites
+            if (cipherSuite.startsWith("TLS_KRB5")) {
+                System.out.println("Skipping unsupported test for " +
+                                    cipherSuite + " of " + protocol);
+                return false;
+            }
+
+            // skip SSLv2Hello protocol
+            if (protocol.equals("SSLv2Hello")) {
+                System.out.println("Skipping unsupported test for " +
+                                    cipherSuite + " of " + protocol);
+                return false;
+            }
+
+            // ignore exportable cipher suite for TLSv1.1
+            if (protocol.equals("TLSv1.1")) {
+                if (cipherSuite.indexOf("_EXPORT_WITH") != -1) {
+                    System.out.println("Skipping obsoleted test for " +
+                                        cipherSuite + " of " + protocol);
+                    return false;
+                }
+            }
+
+            // ignore obsoleted cipher suite for the specified protocol
+            // TODO
+
+            // ignore unsupported cipher suite for the specified protocol
+            // TODO
+
             return true;
         }
     }
--- a/jdk/test/sun/security/ssl/sanity/interop/ClientJSSEServerJSSE.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/security/ssl/sanity/interop/ClientJSSEServerJSSE.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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,6 +25,8 @@
  * @test
  * @bug 4496785
  * @summary Verify that all ciphersuites work in all configurations
+ * @ignore JSSE supported cipher suites are changed with CR 6916074,
+ *     need to update this test case in JDK 7 soon
  * @author Andreas Sterbenz
  * @run main/othervm/timeout=300 ClientJSSEServerJSSE
  */
--- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/IPAddressDNSIdentities.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/IPAddressDNSIdentities.java	Wed Jul 05 17:26:57 2017 +0200
@@ -713,13 +713,16 @@
             http = (HttpsURLConnection)url.openConnection();
 
             int respCode = http.getResponseCode();
-            System.out.println("respCode = "+respCode);
+            System.out.println("respCode = " + respCode);
 
             throw new Exception("Unexpectly found subject alternative name " +
                                 "matching IP address");
         } catch (SSLHandshakeException sslhe) {
             // no subject alternative names matching IP address 127.0.0.1 found
             // that's the expected exception, ignore it.
+        } catch (IOException ioe) {
+            // HttpsClient may throw IOE during checking URL spoofing,
+            // that's the expected exception, ignore it.
         } finally {
             if (http != null) {
                 http.disconnect();
--- a/jdk/test/sun/text/resources/LocaleData	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/text/resources/LocaleData	Wed Jul 05 17:26:57 2017 +0200
@@ -5468,12 +5468,12 @@
 LocaleNames/fr/GY=Guyana
 
 # bug 4225362
-FormatData/fr/DateTimePatternChars=GaMjkHmsSEDFwWahKzZ
-FormatData/fr_BE/DateTimePatternChars=GaMjkHmsSEDFwWahKzZ
-FormatData/fr_CA/DateTimePatternChars=GaMjkHmsSEDFwWahKzZ
-FormatData/fr_CH/DateTimePatternChars=GaMjkHmsSEDFwWahKzZ
-FormatData/fr_FR/DateTimePatternChars=GaMjkHmsSEDFwWahKzZ
-FormatData/fr_LU/DateTimePatternChars=GaMjkHmsSEDFwWahKzZ
+FormatData/fr/DateTimePatternChars=GaMjkHmsSEDFwWxhKzZ
+FormatData/fr_BE/DateTimePatternChars=GaMjkHmsSEDFwWxhKzZ
+FormatData/fr_CA/DateTimePatternChars=GaMjkHmsSEDFwWxhKzZ
+FormatData/fr_CH/DateTimePatternChars=GaMjkHmsSEDFwWxhKzZ
+FormatData/fr_FR/DateTimePatternChars=GaMjkHmsSEDFwWxhKzZ
+FormatData/fr_LU/DateTimePatternChars=GaMjkHmsSEDFwWxhKzZ
 
 # bug 6547501
 FormatData/fr/NumberPatterns/2=#,##0 %
--- a/jdk/test/sun/util/logging/PlatformLoggerTest.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/jdk/test/sun/util/logging/PlatformLoggerTest.java	Wed Jul 05 17:26:57 2017 +0200
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug     6882376
+ * @bug     6882376 6985460
  * @summary Test if java.util.logging.Logger is created before and after
  *          logging is enabled.  Also validate some basic PlatformLogger
  *          operations.
@@ -43,6 +43,8 @@
         final String GOO_PLATFORM_LOGGER = "test.platformlogger.goo";
         final String BAR_LOGGER = "test.logger.bar";
         PlatformLogger goo = PlatformLogger.getLogger(GOO_PLATFORM_LOGGER);
+        // test the PlatformLogger methods
+        testLogMethods(goo);
 
         // Create a platform logger using the default
         PlatformLogger foo = PlatformLogger.getLogger(FOO_PLATFORM_LOGGER);
@@ -56,6 +58,10 @@
         PlatformLogger bar = PlatformLogger.getLogger(BAR_PLATFORM_LOGGER);
         checkPlatformLogger(bar, BAR_PLATFORM_LOGGER);
 
+        // test the PlatformLogger methods
+        testLogMethods(goo);
+        testLogMethods(bar);
+
         checkLogger(FOO_PLATFORM_LOGGER, Level.FINER);
         checkLogger(BAR_PLATFORM_LOGGER, Level.FINER);
 
@@ -64,6 +70,7 @@
 
         foo.setLevel(PlatformLogger.SEVERE);
         checkLogger(FOO_PLATFORM_LOGGER, Level.SEVERE);
+
     }
 
     private static void checkPlatformLogger(PlatformLogger logger, String name) {
@@ -108,4 +115,33 @@
                 logger.getName() + " " + logger.getLevel());
         }
     }
+
+    private static void testLogMethods(PlatformLogger logger) {
+        logger.severe("Test severe(String, Object...) {0} {1}", new Long(1), "string");
+        // test Object[]
+        logger.severe("Test severe(String, Object...) {0}", (Object[]) getPoints());
+        logger.warning("Test warning(String, Throwable)", new Throwable("Testing"));
+        logger.info("Test info(String)");
+    }
+
+    static Point[] getPoints() {
+        Point[] res = new Point[3];
+        res[0] = new Point(0,0);
+        res[1] = new Point(1,1);
+        res[2] = new Point(2,2);
+        return res;
+    }
+
+    static class Point {
+        final int x;
+        final int y;
+        public Point(int x, int y) {
+            this.x = x;
+            this.y = y;
+        }
+        public String toString() {
+            return "{x="+x + ", y=" + y + "}";
+        }
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/util/logging/SourceClassName.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2010, 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     6985460
+ * @summary Test the source class name and method output by the platform
+ *          logger.
+ *
+ * @compile -XDignore.symbol.file SourceClassName.java
+ * @run main/othervm SourceClassName
+ */
+
+import java.util.logging.*;
+import java.io.*;
+import sun.util.logging.PlatformLogger;
+
+public class SourceClassName {
+    public static void main(String[] args) throws Exception {
+        File dir = new File(System.getProperty("user.dir", "."));
+        File log = new File(dir, "testlog.txt");
+        PrintStream logps = new PrintStream(log);
+        writeLogRecords(logps);
+        checkLogRecords(log);
+    }
+
+    private static void writeLogRecords(PrintStream logps) throws Exception {
+        PrintStream err = System.err;
+        try {
+            System.setErr(logps);
+
+            Object[] params = new Object[] { new Long(1), "string"};
+            PlatformLogger plog = PlatformLogger.getLogger("test.log.foo");
+            plog.severe("Log message {0} {1}", (Object[]) params);
+
+            // create a java.util.logging.Logger
+            // now java.util.logging.Logger should be created for each platform logger
+            Logger logger = Logger.getLogger("test.log.bar");
+            logger.log(Level.SEVERE, "Log message {0} {1}", params);
+
+            plog.severe("Log message {0} {1}", (Object[]) params);
+        } finally {
+            logps.flush();
+            logps.close();
+            System.setErr(err);
+        }
+    }
+
+    private static void checkLogRecords(File log) throws Exception {
+        System.out.println("Checking log records in file: " + log);
+        FileInputStream in = new FileInputStream(log);
+        String EXPECTED_LOG = "SEVERE: Log message 1 string";
+        try {
+            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+            String line;
+            String[] record = new String[2];
+            int count = 0;
+            int i = 0;
+            while ((line = reader.readLine()) != null) {
+                line = line.trim();
+                System.out.println(line);
+                record[i++] = line;
+                if (i == 2) {
+                    i = 0;
+                    count++;
+                    // check source class name and method
+                    String[] ss = record[0].split("\\s+");
+                    int len = ss.length;
+                    if (!ss[len-2].equals("SourceClassName") ||
+                        !ss[len-1].equals("writeLogRecords")) {
+                        throw new RuntimeException("Unexpected source: " +
+                            ss[len-2] + " " + ss[len-1]);
+                    }
+
+                    // check log message
+                    if (!record[1].equals(EXPECTED_LOG)) {
+                        throw new RuntimeException("Unexpected log: " + record[1]);
+                    }
+                }
+            }
+            if (count != 3) {
+                throw new RuntimeException("Unexpected number of records: " + count);
+            }
+        } finally {
+            in.close();
+        }
+    }
+}
--- a/langtools/.hgtags	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/.hgtags	Wed Jul 05 17:26:57 2017 +0200
@@ -91,3 +91,4 @@
 e4e7408cdc5b3d91d39161e1e94aad576ecc2dcd jdk7-b114
 01e8ac5fbefd35d2d9a0996213cf2390fd164e57 jdk7-b115
 857bfcea3f30cb5f4ae96f46a53ae1c772f9b0e5 jdk7-b116
+2129a046f117547fc8a5cb3397a767e6d528f5b6 jdk7-b117
--- a/langtools/src/share/classes/com/sun/source/tree/AnnotatedTypeTree.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 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.
- */
-
-package com.sun.source.tree;
-
-import java.util.List;
-
-/**
- * A tree node for an annotated type
- *
- * For example:
- * <pre>
- *    {@code @}<em>annotationType String</em>
- *    {@code @}<em>annotationType</em> ( <em>arguments</em> ) <em>Date</em>
- * </pre>
- *
- * @see "JSR 308: Annotations on Java Types"
- *
- * @author Mahmood Ali
- * @since 1.7
- */
-public interface AnnotatedTypeTree extends ExpressionTree {
-    List<? extends AnnotationTree> getAnnotations();
-    ExpressionTree getUnderlyingType();
-}
--- a/langtools/src/share/classes/com/sun/source/tree/DisjointTypeTree.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2010, 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.
- */
-
-package com.sun.source.tree;
-
-import java.util.List;
-
-/**
- * A tree node for a disjoint type expression in a multicatch var declaration.
- *
- *
- * @author Maurizio Cimadamore
- *
- * @since 1.7
- */
-public interface DisjointTypeTree extends Tree {
-    List<? extends Tree> getTypeComponents();
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/source/tree/DisjunctiveTypeTree.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+package com.sun.source.tree;
+
+import java.util.List;
+
+/**
+ * A tree node for a disjunctive type expression in a multicatch var declaration.
+ *
+ *
+ * @author Maurizio Cimadamore
+ *
+ * @since 1.7
+ */
+public interface DisjunctiveTypeTree extends Tree {
+    List<? extends Tree> getTypeAlternatives();
+}
--- a/langtools/src/share/classes/com/sun/source/tree/MethodTree.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/source/tree/MethodTree.java	Wed Jul 05 17:26:57 2017 +0200
@@ -53,7 +53,7 @@
     Tree getReturnType();
     List<? extends TypeParameterTree> getTypeParameters();
     List<? extends VariableTree> getParameters();
-    List<? extends AnnotationTree> getReceiverAnnotations();
+//308    List<? extends AnnotationTree> getReceiverAnnotations();
     List<? extends ExpressionTree> getThrows();
     BlockTree getBody();
     Tree getDefaultValue(); // for annotation types
--- a/langtools/src/share/classes/com/sun/source/tree/Tree.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/source/tree/Tree.java	Wed Jul 05 17:26:57 2017 +0200
@@ -46,7 +46,7 @@
      */
     public enum Kind {
 
-        ANNOTATED_TYPE(AnnotatedTypeTree.class),
+//308        ANNOTATED_TYPE(AnnotatedTypeTree.class),
 
         /**
          * Used for instances of {@link AnnotationTree}.
@@ -234,9 +234,9 @@
         PARAMETERIZED_TYPE(ParameterizedTypeTree.class),
 
         /**
-         * Used for instances of {@link DisjointTypeTree}.
+         * Used for instances of {@link DisjunctiveTypeTree}.
          */
-        DISJOINT_TYPE(DisjointTypeTree.class),
+        DISJUNCTIVE_TYPE(DisjunctiveTypeTree.class),
 
         /**
          * Used for instances of {@link TypeCastTree}.
--- a/langtools/src/share/classes/com/sun/source/tree/TreeVisitor.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/source/tree/TreeVisitor.java	Wed Jul 05 17:26:57 2017 +0200
@@ -57,7 +57,7 @@
  * @since 1.6
  */
 public interface TreeVisitor<R,P> {
-    R visitAnnotatedType(AnnotatedTypeTree node, P p);
+//308    R visitAnnotatedType(AnnotatedTypeTree node, P p);
     R visitAnnotation(AnnotationTree node, P p);
     R visitMethodInvocation(MethodInvocationTree node, P p);
     R visitAssert(AssertTree node, P p);
@@ -96,7 +96,7 @@
     R visitCompilationUnit(CompilationUnitTree node, P p);
     R visitTry(TryTree node, P p);
     R visitParameterizedType(ParameterizedTypeTree node, P p);
-    R visitDisjointType(DisjointTypeTree node, P p);
+    R visitDisjunctiveType(DisjunctiveTypeTree node, P p);
     R visitArrayType(ArrayTypeTree node, P p);
     R visitTypeCast(TypeCastTree node, P p);
     R visitPrimitiveType(PrimitiveTypeTree node, P p);
--- a/langtools/src/share/classes/com/sun/source/tree/TypeParameterTree.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/source/tree/TypeParameterTree.java	Wed Jul 05 17:26:57 2017 +0200
@@ -47,5 +47,5 @@
 public interface TypeParameterTree extends Tree {
     Name getName();
     List<? extends Tree> getBounds();
-    List<? extends AnnotationTree> getAnnotations();
+//308    List<? extends AnnotationTree> getAnnotations();
 }
--- a/langtools/src/share/classes/com/sun/source/util/AbstractTypeProcessor.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,245 +0,0 @@
-/*
- * Copyright (c) 2009, 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.
- */
-
-package com.sun.source.util;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.Name;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.util.ElementFilter;
-
-import com.sun.tools.javac.processing.JavacProcessingEnvironment;
-import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.Log;
-
-import com.sun.source.tree.ClassTree;
-
-/**
- * This class is an abstract annotation processor designed to be a
- * convenient superclass for concrete "type processors", processors that
- * require the type information in the processed source.
- *
- * <p>Type processing occurs in one round after the tool (e.g. java compiler)
- * analyzes the source (all sources taken as input to the tool and sources
- * generated by other annotation processors).
- *
- * <p>The tool infrastructure will interact with classes extending this abstract
- * class as follows:
- *
- * <ol>
- * [1-3: Identical to {@link Processor} life cycle]
- *
- * <li>If an existing {@code Processor} object is not being used, to
- * create an instance of a processor the tool calls the no-arg
- * constructor of the processor class.
- *
- * <li>Next, the tool calls the {@link #init init} method with
- * an appropriate {@code ProcessingEnvironment}.
- *
- * <li>Afterwards, the tool calls {@link #getSupportedAnnotationTypes
- * getSupportedAnnotationTypes}, {@link #getSupportedOptions
- * getSupportedOptions}, and {@link #getSupportedSourceVersion
- * getSupportedSourceVersion}.  These methods are only called once per
- * run, not on each round.
- *
- * [4-5Unique to {@code AbstractTypeProcessor} subclasses]
- *
- * <li>For each class containing a supported annotation, the tool calls
- * {@link #typeProcess(TypeElement, TreePath) typeProcess} method on the
- * {@code Processor}.  The class is guaranteed to be type-checked Java code
- * and all the tree type and symbol information is resolved.
- *
- * <li>Finally, the tools calls the
- * {@link #typeProcessingOver() typeProcessingOver} method
- * on the {@code Processor}.
- *
- * </ol>
- *
- * <p>The tool is permitted to ask type processors to process a class once
- * it is analyzed before the rest of classes are analyzed.  The tool is also
- * permitted to stop type processing immediately if any errors are raised,
- * without invoking {@code typeProcessingOver}
- *
- * <p>A subclass may override any of the methods in this class, as long as the
- * general {@link javax.annotation.processing.Processor Processor}
- * contract is obeyed, with one notable exception.
- * {@link #process(Set, RoundEnvironment)} may not be overridden, as it
- * is called during the regular annotation phase before classes are analyzed.
- *
- * @author Mahmood Ali
- * @since 1.7
- */
-public abstract class AbstractTypeProcessor extends AbstractProcessor {
-    private final Set<Name> elements = new HashSet<Name>();
-    private boolean hasInvokedTypeProcessingOver = false;
-    private JavacProcessingEnvironment env;
-    private final AttributionTaskListener listener = new AttributionTaskListener();
-
-    /**
-     * Constructor for subclasses to call.
-     */
-    protected AbstractTypeProcessor() { }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void init(ProcessingEnvironment env) {
-        super.init(env);
-        this.env = (JavacProcessingEnvironment)env;
-        prepareContext(this.env.getContext());
-    }
-
-    /**
-     * The use of this method is obsolete in type processors.  The method is
-     * called during regular annotation processing phase only.
-     */
-    @Override
-    public final boolean process(Set<? extends TypeElement> annotations,
-            RoundEnvironment roundEnv) {
-        for (TypeElement elem : ElementFilter.typesIn(roundEnv.getRootElements())) {
-            elements.add(elem.getQualifiedName());
-        }
-        return false;
-    }
-
-    /**
-     * Processes a fully analyzed class that contains a supported annotation
-     * (look {@link #getSupportedAnnotationTypes()}).
-     *
-     * <p>The passed class is always a valid type-checked Java code.
-     *
-     * @param element       element of the analyzed class
-     * @param tree  the tree path to the element, with the leaf being a
-     *              {@link ClassTree}
-     */
-    public abstract void typeProcess(TypeElement element, TreePath tree);
-
-    /**
-     * A method to be called once all the classes are processed and no error
-     * is reported.
-     *
-     * <p>Subclasses may override this method to do any aggregate analysis
-     * (e.g. generate report, persistence) or resource deallocation.
-     *
-     * <p>If an error (a Java error or a processor error) is reported, this
-     * method is not guaranteed to be invoked.
-     */
-    public void typeProcessingOver() { }
-
-    /**
-     * adds a listener for attribution.
-     */
-    private void prepareContext(Context context) {
-        TaskListener otherListener = context.get(TaskListener.class);
-        if (otherListener == null) {
-            context.put(TaskListener.class, listener);
-        } else {
-            // handle cases of multiple listeners
-            context.put(TaskListener.class, (TaskListener)null);
-            TaskListeners listeners = new TaskListeners();
-            listeners.add(otherListener);
-            listeners.add(listener);
-            context.put(TaskListener.class, listeners);
-        }
-    }
-
-    /**
-     * A task listener that invokes the processor whenever a class is fully
-     * analyzed.
-     */
-    private final class AttributionTaskListener implements TaskListener {
-
-        @Override
-        public void finished(TaskEvent e) {
-            Log log = Log.instance(env.getContext());
-
-            if (!hasInvokedTypeProcessingOver && elements.isEmpty() && log.nerrors == 0) {
-                typeProcessingOver();
-                hasInvokedTypeProcessingOver = true;
-            }
-
-            if (e.getKind() != TaskEvent.Kind.ANALYZE)
-                return;
-
-            if (e.getTypeElement() == null)
-                throw new AssertionError("event task without a type element");
-            if (e.getCompilationUnit() == null)
-                throw new AssertionError("even task without compilation unit");
-
-            if (!elements.remove(e.getTypeElement().getQualifiedName()))
-                return;
-
-            if (log.nerrors != 0)
-                return;
-
-            TypeElement elem = e.getTypeElement();
-            TreePath p = Trees.instance(env).getPath(elem);
-
-            typeProcess(elem, p);
-
-            if (!hasInvokedTypeProcessingOver && elements.isEmpty() && log.nerrors == 0) {
-                typeProcessingOver();
-                hasInvokedTypeProcessingOver = true;
-            }
-        }
-
-        @Override
-        public void started(TaskEvent e) { }
-
-    }
-
-    /**
-     * A task listener multiplexer.
-     */
-    private static class TaskListeners implements TaskListener {
-        private final List<TaskListener> listeners = new ArrayList<TaskListener>();
-
-        public void add(TaskListener listener) {
-            listeners.add(listener);
-        }
-
-        public void remove(TaskListener listener) {
-            listeners.remove(listener);
-        }
-
-        @Override
-        public void finished(TaskEvent e) {
-            for (TaskListener listener : listeners)
-                listener.finished(e);
-        }
-
-        @Override
-        public void started(TaskEvent e) {
-            for (TaskListener listener : listeners)
-                listener.started(e);
-        }
-    }
-}
--- a/langtools/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java	Wed Jul 05 17:26:57 2017 +0200
@@ -228,7 +228,7 @@
         return defaultAction(node, p);
     }
 
-    public R visitDisjointType(DisjointTypeTree node, P p) {
+    public R visitDisjunctiveType(DisjunctiveTypeTree node, P p) {
         return defaultAction(node, p);
     }
 
@@ -248,9 +248,9 @@
         return defaultAction(node, p);
     }
 
-    public R visitAnnotatedType(AnnotatedTypeTree node, P p) {
-        return defaultAction(node, p);
-    }
+//308    public R visitAnnotatedType(AnnotatedTypeTree node, P p) {
+//308        return defaultAction(node, p);
+//308    }
 
     public R visitErroneous(ErroneousTree node, P p) {
         return defaultAction(node, p);
--- a/langtools/src/share/classes/com/sun/source/util/TreeScanner.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/source/util/TreeScanner.java	Wed Jul 05 17:26:57 2017 +0200
@@ -138,7 +138,7 @@
         r = scanAndReduce(node.getReturnType(), p, r);
         r = scanAndReduce(node.getTypeParameters(), p, r);
         r = scanAndReduce(node.getParameters(), p, r);
-        r = scanAndReduce(node.getReceiverAnnotations(), p, r);
+//308        r = scanAndReduce(node.getReceiverAnnotations(), p, r);
         r = scanAndReduce(node.getThrows(), p, r);
         r = scanAndReduce(node.getBody(), p, r);
         r = scanAndReduce(node.getDefaultValue(), p, r);
@@ -356,13 +356,13 @@
         return r;
     }
 
-    public R visitDisjointType(DisjointTypeTree node, P p) {
-        return scan(node.getTypeComponents(), p);
+    public R visitDisjunctiveType(DisjunctiveTypeTree node, P p) {
+        return scan(node.getTypeAlternatives(), p);
     }
 
     public R visitTypeParameter(TypeParameterTree node, P p) {
-        R r = scan(node.getAnnotations(), p);
-        r = scanAndReduce(node.getBounds(), p, r);
+        R r = scan(node.getBounds(), p);
+//308        R r = scanAndReduce(node.getAnnotations(), p, r);
         return r;
     }
 
@@ -380,11 +380,11 @@
         return r;
     }
 
-   public R visitAnnotatedType(AnnotatedTypeTree node, P p) {
-       R r = scan(node.getAnnotations(), p);
-       r = scanAndReduce(node.getUnderlyingType(), p, r);
-       return r;
-   }
+//308   public R visitAnnotatedType(AnnotatedTypeTree node, P p) {
+//308       R r = scan(node.getAnnotations(), p);
+//308       r = scanAndReduce(node.getUnderlyingType(), p, r);
+//308       return r;
+//308   }
 
     public R visitOther(Tree node, P p) {
         return null;
--- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java	Wed Jul 05 17:26:57 2017 +0200
@@ -282,9 +282,10 @@
 //                    System.err.println("COMP: " + ((JCCompilationUnit)tree).sourcefile);
                     env = enter.getTopLevelEnv((JCCompilationUnit)tree);
                     break;
+                case ANNOTATION_TYPE:
                 case CLASS:
+                case ENUM:
                 case INTERFACE:
-                case ENUM:
 //                    System.err.println("CLASS: " + ((JCClassDecl)tree).sym.getSimpleName());
                     env = enter.getClassEnv(((JCClassDecl)tree).sym);
                     break;
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java	Wed Jul 05 17:26:57 2017 +0200
@@ -231,9 +231,9 @@
     public static final long PROPRIETARY = 1L<<38;
 
     /**
-     * Flag that marks a disjoint var in a multi-catch clause
+     * Flag that marks a disjunction var in a multi-catch clause
      */
-    public static final long DISJOINT = 1L<<39;
+    public static final long DISJUNCTION = 1L<<39;
 
     /**
      * Flag that marks a signature-polymorphic invoke method.
--- a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java	Wed Jul 05 17:26:57 2017 +0200
@@ -55,8 +55,8 @@
     }
 
     public void taFillAndLift(JCClassDecl tree, boolean visitBodies) {
-        new TypeAnnotationPositions().scan(tree);
-        new TypeAnnotationLift().scan(tree);
+//308        new TypeAnnotationPositions().scan(tree);
+//308        new TypeAnnotationLift().scan(tree);
     }
 
     private static class TypeAnnotationPositions extends TreeScanner {
@@ -113,9 +113,10 @@
                     p.pos = frame.pos;
                     return p;
 
+                case ANNOTATION_TYPE:
                 case CLASS:
+                case ENUM:
                 case INTERFACE:
-                case ENUM:
                     p.pos = frame.pos;
                     if (((JCClassDecl)frame).extending == tree) {
                         p.type = TargetType.CLASS_EXTENDS;
@@ -208,11 +209,11 @@
                     }
                     return p;
 
-                case ANNOTATED_TYPE: {
-                    List<JCTree> newPath = path.tail;
-                    return resolveFrame(newPath.head, newPath.tail.head,
-                            newPath, p);
-                }
+//308                case ANNOTATED_TYPE: {
+//308                    List<JCTree> newPath = path.tail;
+//308                    return resolveFrame(newPath.head, newPath.tail.head,
+//308                            newPath, p);
+//308                }
 
                 case METHOD_INVOCATION: {
                     JCMethodInvocation invocation = (JCMethodInvocation)frame;
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Jul 05 17:26:57 2017 +0200
@@ -121,6 +121,8 @@
         sourceName = source.name;
         relax = (options.isSet("-retrofit") ||
                  options.isSet("-relax"));
+        findDiamonds = options.get("findDiamond") != null &&
+                 source.allowDiamond();
         useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning");
         enableSunApiLintControl = options.isSet("enableSunApiLintControl");
     }
@@ -154,6 +156,16 @@
      */
     boolean allowAnonOuterThis;
 
+    /** Switch: generates a warning if diamond can be safely applied
+     *  to a given new expression
+     */
+    boolean findDiamonds;
+
+    /**
+     * Internally enables/disables diamond finder feature
+     */
+    static final boolean allowDiamondFinder = true;
+
     /**
      * Switch: warn about use of variable before declaration?
      * RFE: 6425594
@@ -1053,9 +1065,9 @@
                 if ((c.param.sym.flags() & FINAL) == 0) {
                     log.error(c.param.pos(), "multicatch.param.must.be.final", c.param.sym);
                 }
-                c.param.sym.flags_field = c.param.sym.flags() | DISJOINT;
+                c.param.sym.flags_field = c.param.sym.flags() | DISJUNCTION;
             }
-            if (c.param.type.tsym.kind == Kinds.VAR) {
+            if (c.param.sym.kind == Kinds.VAR) {
                 c.param.sym.setData(ElementKind.EXCEPTION_PARAMETER);
             }
             chk.checkType(c.param.vartype.pos(),
@@ -1572,6 +1584,24 @@
         if (TreeInfo.isDiamond(tree)) {
             clazztype = attribDiamond(localEnv, tree, clazztype, mapping, argtypes, typeargtypes);
             clazz.type = clazztype;
+        } else if (allowDiamondFinder &&
+                clazztype.getTypeArguments().nonEmpty() &&
+                findDiamonds) {
+            Type inferred = attribDiamond(localEnv,
+                    tree,
+                    clazztype,
+                    mapping,
+                    argtypes,
+                    typeargtypes);
+            if (!inferred.isErroneous() &&
+                    inferred.tag == CLASS &&
+                    types.isAssignable(inferred, pt.tag == NONE ? clazztype : pt, Warner.noWarnings) &&
+                    chk.checkDiamond((ClassType)inferred).isEmpty()) {
+                String key = types.isSameType(clazztype, inferred) ?
+                    "diamond.redundant.args" :
+                    "diamond.redundant.args.1";
+                log.warning(tree.clazz.pos(), key, clazztype, inferred);
+            }
         }
 
         // If we have made no mistakes in the class type...
@@ -2839,9 +2869,9 @@
         result = check(tree, owntype, TYP, pkind, pt);
     }
 
-    public void visitTypeDisjoint(JCTypeDisjoint tree) {
-        List<Type> componentTypes = attribTypes(tree.components, env);
-        tree.type = result = check(tree, types.lub(componentTypes), TYP, pkind, pt);
+    public void visitTypeDisjunction(JCTypeDisjunction tree) {
+        List<Type> alternatives = attribTypes(tree.alternatives, env);
+        tree.type = result = check(tree, types.lub(alternatives), TYP, pkind, pt);
     }
 
     public void visitTypeParameter(JCTypeParameter tree) {
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java	Wed Jul 05 17:26:57 2017 +0200
@@ -371,7 +371,7 @@
         if (sym.adr >= firstadr && trackable(sym)) {
             if ((sym.flags() & FINAL) != 0) {
                 if ((sym.flags() & PARAMETER) != 0) {
-                    if ((sym.flags() & DISJOINT) != 0) { //multi-catch parameter
+                    if ((sym.flags() & DISJUNCTION) != 0) { //multi-catch parameter
                         log.error(pos, "multicatch.parameter.may.not.be.assigned",
                                   sym);
                     }
@@ -983,7 +983,7 @@
         thrown = List.nil();
         for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
             List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
-                    ((JCTypeDisjoint)l.head.param.vartype).components :
+                    ((JCTypeDisjunction)l.head.param.vartype).alternatives :
                     List.of(l.head.param.vartype);
             for (JCExpression ct : subClauses) {
                 caught = chk.incl(ct.type, caught);
@@ -1049,7 +1049,7 @@
             alive = true;
             JCVariableDecl param = l.head.param;
             List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
-                    ((JCTypeDisjoint)l.head.param.vartype).components :
+                    ((JCTypeDisjunction)l.head.param.vartype).alternatives :
                     List.of(l.head.param.vartype);
             List<Type> ctypes = List.nil();
             List<Type> rethrownTypes = chk.diff(thrownInTry, caughtInTry);
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Wed Jul 05 17:26:57 2017 +0200
@@ -876,7 +876,8 @@
                 make.at(tree.pos);
                 if (addBridges) {
                     ListBuffer<JCTree> bridges = new ListBuffer<JCTree>();
-                    bridges.appendList(addOverrideBridgesIfNeeded(tree, c));
+                    if (false) //see CR: 6996415
+                        bridges.appendList(addOverrideBridgesIfNeeded(tree, c));
                     if ((tree.sym.flags() & INTERFACE) == 0)
                         addBridges(tree.pos(), tree.sym, bridges);
                     tree.defs = bridges.toList().prependList(tree.defs);
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1456,7 +1456,7 @@
                       List<Integer> gaps) {
             if (startpc != endpc) {
                 List<JCExpression> subClauses = TreeInfo.isMultiCatch(tree) ?
-                        ((JCTypeDisjoint)tree.param.vartype).components :
+                        ((JCTypeDisjunction)tree.param.vartype).alternatives :
                         List.of(tree.param.vartype);
                 while (gaps.nonEmpty()) {
                     for (JCExpression subCatch : subClauses) {
--- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1090,7 +1090,7 @@
 
     private boolean unrecoverableError() {
         for (JCDiagnostic d: log.deferredDiagnostics) {
-            if (d.getKind() == JCDiagnostic.Kind.ERROR && !d.isFlagSet(RESOLVE_ERROR))
+            if (d.getKind() == JCDiagnostic.Kind.ERROR && !d.isFlagSet(RECOVERABLE))
                 return true;
         }
         return false;
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Wed Jul 05 17:26:57 2017 +0200
@@ -30,6 +30,7 @@
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
 import com.sun.tools.javac.util.List;
 import static com.sun.tools.javac.util.ListBuffer.lb;
 
@@ -75,42 +76,6 @@
     /** The name table. */
     private Names names;
 
-    // Because of javac's limited lookahead, some contexts are ambiguous in
-    // the presence of type annotations even though they are not ambiguous
-    // in the absence of type annotations.  Consider this code:
-    //   void m(String [] m) { }
-    //   void m(String ... m) { }
-    // After parsing "String", javac calls bracketsOpt which immediately
-    // returns if the next character is not '['.  Similarly, javac can see
-    // if the next token is ... and in that case parse an ellipsis.  But in
-    // the presence of type annotations:
-    //   void m(String @A [] m) { }
-    //   void m(String @A ... m) { }
-    // no finite lookahead is enough to determine whether to read array
-    // levels or an ellipsis.  Furthermore, if you call bracketsOpt, then
-    // bracketsOpt first reads all the leading annotations and only then
-    // discovers that it needs to fail.  bracketsOpt needs a way to push
-    // back the extra annotations that it read.  (But, bracketsOpt should
-    // not *always* be allowed to push back extra annotations that it finds
-    // -- in most contexts, any such extra annotation is an error.
-    // Another similar case occurs with arrays and receiver annotations:
-    //   String b() @Array [] @Receiver { }
-    //   String b() @Receiver { }
-    //
-    // The following two variables permit type annotations that have
-    // already been read to be stored for later use.  Alternate
-    // implementations are possible but would cause much larger changes to
-    // the parser.
-    /** Type annotations that have already been read but have not yet been used. **/
-    private List<JCTypeAnnotation> typeAnnotationsPushedBack = null;
-    /**
-     * If the parser notices extra annotations, then it either immediately
-     * issues an error (if this variable is false) or places the extra
-     * annotations in variable typeAnnotationsPushedBack (if this variable
-     * is true).
-     */
-    private boolean permitTypeAnnotationsPushBack = false;
-
     /** Construct a parser from a given scanner, tree factory and log.
      */
     protected JavacParser(ParserFactory fac,
@@ -134,19 +99,13 @@
         this.allowTWR = source.allowTryWithResources();
         this.allowDiamond = source.allowDiamond();
         this.allowMulticatch = source.allowMulticatch();
-        this.allowTypeAnnotations = source.allowTypeAnnotations();
         this.keepDocComments = keepDocComments;
         if (keepDocComments)
             docComments = new HashMap<JCTree,String>();
         this.keepLineMap = keepLineMap;
         this.errorTree = F.Erroneous();
-        this.debugJSR308 = fac.options.get("TA:parser") != null;
     }
 
-    /** Switch: debug output for type-annotations operations
-     */
-    boolean debugJSR308;
-
     /** Switch: Should generics be recognized?
      */
     boolean allowGenerics;
@@ -183,10 +142,6 @@
      */
     boolean allowAnnotations;
 
-    /** Switch: should we recognize type annotations?
-     */
-    boolean allowTypeAnnotations;
-
     /** Switch: should we recognize automatic resource management?
      */
     boolean allowTWR;
@@ -312,9 +267,9 @@
     private void reportSyntaxError(int pos, String key, Object... args) {
         if (pos > S.errPos() || pos == Position.NOPOS) {
             if (S.token() == EOF)
-                log.error(pos, "premature.eof");
+                error(pos, "premature.eof");
             else
-                log.error(pos, key, args);
+                error(pos, key, args);
         }
         S.errPos(pos);
         if (S.pos() == errorPos)
@@ -370,7 +325,7 @@
     void checkNoMods(long mods) {
         if (mods != 0) {
             long lowestMod = mods & -mods;
-            log.error(S.pos(), "mod.not.allowed.here",
+            error(S.pos(), "mod.not.allowed.here",
                       Flags.asFlagSet(lowestMod));
         }
     }
@@ -464,22 +419,22 @@
             return name;
         } else if (S.token() == ASSERT) {
             if (allowAsserts) {
-                log.error(S.pos(), "assert.as.identifier");
+                error(S.pos(), "assert.as.identifier");
                 S.nextToken();
                 return names.error;
             } else {
-                log.warning(S.pos(), "assert.as.identifier");
+                warning(S.pos(), "assert.as.identifier");
                 Name name = S.name();
                 S.nextToken();
                 return name;
             }
         } else if (S.token() == ENUM) {
             if (allowEnums) {
-                log.error(S.pos(), "enum.as.identifier");
+                error(S.pos(), "enum.as.identifier");
                 S.nextToken();
                 return names.error;
             } else {
-                log.warning(S.pos(), "enum.as.identifier");
+                warning(S.pos(), "enum.as.identifier");
                 Name name = S.name();
                 S.nextToken();
                 return name;
@@ -525,7 +480,7 @@
                     TypeTags.INT,
                     Convert.string2int(strval(prefix), S.radix()));
             } catch (NumberFormatException ex) {
-                log.error(S.pos(), "int.number.too.large", strval(prefix));
+                error(S.pos(), "int.number.too.large", strval(prefix));
             }
             break;
         case LONGLITERAL:
@@ -534,7 +489,7 @@
                     TypeTags.LONG,
                     new Long(Convert.string2long(strval(prefix), S.radix())));
             } catch (NumberFormatException ex) {
-                log.error(S.pos(), "int.number.too.large", strval(prefix));
+                error(S.pos(), "int.number.too.large", strval(prefix));
             }
             break;
         case FLOATLITERAL: {
@@ -547,9 +502,9 @@
                 n = Float.NaN;
             }
             if (n.floatValue() == 0.0f && !isZero(proper))
-                log.error(S.pos(), "fp.number.too.small");
+                error(S.pos(), "fp.number.too.small");
             else if (n.floatValue() == Float.POSITIVE_INFINITY)
-                log.error(S.pos(), "fp.number.too.large");
+                error(S.pos(), "fp.number.too.large");
             else
                 t = F.at(pos).Literal(TypeTags.FLOAT, n);
             break;
@@ -564,9 +519,9 @@
                 n = Double.NaN;
             }
             if (n.doubleValue() == 0.0d && !isZero(proper))
-                log.error(S.pos(), "fp.number.too.small");
+                error(S.pos(), "fp.number.too.small");
             else if (n.doubleValue() == Double.POSITIVE_INFINITY)
-                log.error(S.pos(), "fp.number.too.large");
+                error(S.pos(), "fp.number.too.large");
             else
                 t = F.at(pos).Literal(TypeTags.DOUBLE, n);
             break;
@@ -620,33 +575,7 @@
         return term(EXPR);
     }
 
-    /**
-     * parses (optional) type annotations followed by a type. If the
-     * annotations are present before the type and are not consumed during array
-     * parsing, this method returns a {@link JCAnnotatedType} consisting of
-     * these annotations and the underlying type. Otherwise, it returns the
-     * underlying type.
-     *
-     * <p>
-     *
-     * Note that this method sets {@code mode} to {@code TYPE} first, before
-     * parsing annotations.
-     */
     public JCExpression parseType() {
-        List<JCTypeAnnotation> annotations = typeAnnotationsOpt();
-        return parseType(annotations);
-    }
-
-    public JCExpression parseType(List<JCTypeAnnotation> annotations) {
-        JCExpression result = unannotatedType();
-
-        if (!annotations.isEmpty())
-            result = F.AnnotatedType(annotations, result);
-
-        return result;
-    }
-
-    public JCExpression unannotatedType() {
         return term(TYPE);
     }
 
@@ -895,8 +824,8 @@
      *                 | [TypeArguments] THIS [Arguments]
      *                 | [TypeArguments] SUPER SuperSuffix
      *                 | NEW [TypeArguments] Creator
-     *                 | [Annotations] Ident { "." Ident }
-     *                   [ [Annotations] "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
+     *                 | Ident { "." Ident }
+     *                   [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
      *                   | Arguments
      *                   | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
      *                   ]
@@ -1047,62 +976,23 @@
                 typeArgs = null;
             } else return illegal();
             break;
-        case MONKEYS_AT:
-
-            // only annotated targetting class literals or cast types are valid
-            List<JCTypeAnnotation> typeAnnos = typeAnnotationsOpt();
-            if (typeAnnos.isEmpty()) {
-                // else there would be no '@'
-                throw new AssertionError("type annos is empty");
-            }
-
-            JCExpression expr = term3();
-
-            // Type annotations: If term3 just parsed a non-type, expect a
-            // class literal (and issue a syntax error if there is no class
-            // literal). Otherwise, create a JCAnnotatedType.
-            if ((mode & TYPE) == 0) {
-                if (expr.getTag() != JCTree.SELECT)
-                    return illegal(typeAnnos.head.pos);
-                JCFieldAccess sel = (JCFieldAccess)expr;
-                if (sel.name != names._class)
-                    return illegal();
-                else {
-                    sel.selected = F.AnnotatedType(typeAnnos, sel.selected);
-                    t = expr;
-                }
-            } else {
-                // type annotation targeting a cast
-                t = toP(F.at(S.pos()).AnnotatedType(typeAnnos, expr));
-            }
-            break;
         case IDENTIFIER: case ASSERT: case ENUM:
             if (typeArgs != null) return illegal();
             t = toP(F.at(S.pos()).Ident(ident()));
             loop: while (true) {
                 pos = S.pos();
-                final List<JCTypeAnnotation> annos = typeAnnotationsOpt();
-
-                // need to report an error later if LBRACKET is for array
-                // index access rather than array creation level
-                if (!annos.isEmpty() && S.token() != LBRACKET && S.token() != ELLIPSIS)
-                    return illegal(annos.head.pos);
                 switch (S.token()) {
                 case LBRACKET:
                     S.nextToken();
-
                     if (S.token() == RBRACKET) {
-
                         S.nextToken();
-
-                        t = bracketsOpt(t, annos);
+                        t = bracketsOpt(t);
                         t = toP(F.at(pos).TypeArray(t));
                         t = bracketsSuffix(t);
                     } else {
                         if ((mode & EXPR) != 0) {
                             mode = EXPR;
                             JCExpression t1 = term();
-                            if (!annos.isEmpty()) t = illegal(annos.head.pos);
                             t = to(F.at(pos).Indexed(t, t1));
                         }
                         accept(RBRACKET);
@@ -1155,14 +1045,6 @@
                     // typeArgs saved for next loop iteration.
                     t = toP(F.at(pos).Select(t, ident()));
                     break;
-                case ELLIPSIS:
-                    if (this.permitTypeAnnotationsPushBack) {
-                        this.typeAnnotationsPushedBack = annos;
-                    } else if (annos.nonEmpty()) {
-                        // Don't return here -- error recovery attempt
-                        illegal(annos.head.pos);
-                    }
-                    break loop;
                 default:
                     break loop;
                 }
@@ -1201,18 +1083,14 @@
         if (typeArgs != null) illegal();
         while (true) {
             int pos1 = S.pos();
-
-            final List<JCTypeAnnotation> annos = typeAnnotationsOpt();
-
             if (S.token() == LBRACKET) {
                 S.nextToken();
-
                 if ((mode & TYPE) != 0) {
                     int oldmode = mode;
                     mode = TYPE;
                     if (S.token() == RBRACKET) {
                         S.nextToken();
-                        t = bracketsOpt(t, annos);
+                        t = bracketsOpt(t);
                         t = toP(F.at(pos1).TypeArray(t));
                         return t;
                     }
@@ -1247,12 +1125,6 @@
                     typeArgs = null;
                 }
             } else {
-                if (!annos.isEmpty()) {
-                    if (permitTypeAnnotationsPushBack)
-                        typeAnnotationsPushedBack = annos;
-                    else
-                        return illegal(annos.head.pos);
-                }
                 break;
             }
         }
@@ -1262,7 +1134,6 @@
                   S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
             S.nextToken();
         }
-
         return toP(t);
     }
 
@@ -1400,26 +1271,24 @@
     }
 
     /** TypeArgument = Type
-     *               | [Annotations] "?"
-     *               | [Annotations] "?" EXTENDS Type {"&" Type}
-     *               | [Annotations] "?" SUPER Type
+     *               | "?"
+     *               | "?" EXTENDS Type {"&" Type}
+     *               | "?" SUPER Type
      */
     JCExpression typeArgument() {
-        List<JCTypeAnnotation> annotations = typeAnnotationsOpt();
-        if (S.token() != QUES) return parseType(annotations);
+        if (S.token() != QUES) return parseType();
         int pos = S.pos();
         S.nextToken();
-        JCExpression result;
         if (S.token() == EXTENDS) {
             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
             S.nextToken();
             JCExpression bound = parseType();
-            result = F.at(pos).Wildcard(t, bound);
+            return F.at(pos).Wildcard(t, bound);
         } else if (S.token() == SUPER) {
             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
             S.nextToken();
             JCExpression bound = parseType();
-            result = F.at(pos).Wildcard(t, bound);
+            return F.at(pos).Wildcard(t, bound);
         } else if (S.token() == IDENTIFIER) {
             //error recovery
             reportSyntaxError(S.prevEndPos(), "expected3",
@@ -1427,14 +1296,11 @@
             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
             JCIdent id = toP(F.at(S.pos()).Ident(ident()));
-            result = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
+            return F.at(pos).Erroneous(List.<JCTree>of(wc, id));
         } else {
             TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND));
-            result = toP(F.at(pos).Wildcard(t, null));
+            return toP(F.at(pos).Wildcard(t, null));
         }
-        if (!annotations.isEmpty())
-            result = toP(F.at(annotations.head.pos).AnnotatedType(annotations,result));
-        return result;
     }
 
     JCTypeApply typeArguments(JCExpression t) {
@@ -1443,47 +1309,21 @@
         return toP(F.at(pos).TypeApply(t, args));
     }
 
-    /**
-     * BracketsOpt = { [Annotations] "[" "]" }
-     *
-     * <p>
-     *
-     * <code>annotations</code> is the list of annotations targeting
-     * the expression <code>t</code>.
+    /** BracketsOpt = {"[" "]"}
      */
-    private JCExpression bracketsOpt(JCExpression t,
-            List<JCTypeAnnotation> annotations) {
-        List<JCTypeAnnotation> nextLevelAnnotations = typeAnnotationsOpt();
-
+    private JCExpression bracketsOpt(JCExpression t) {
         if (S.token() == LBRACKET) {
             int pos = S.pos();
             S.nextToken();
-
-            JCExpression orig = t;
-            t = bracketsOptCont(t, pos, nextLevelAnnotations);
-        } else if (!nextLevelAnnotations.isEmpty()) {
-            if (permitTypeAnnotationsPushBack) {
-                this.typeAnnotationsPushedBack = nextLevelAnnotations;
-            } else
-                return illegal(nextLevelAnnotations.head.pos);
+            t = bracketsOptCont(t, pos);
+            F.at(pos);
         }
-
-        int apos = S.pos();
-        if (!annotations.isEmpty())
-            t = F.at(apos).AnnotatedType(annotations, t);
         return t;
     }
 
-    /** BracketsOpt = {"[" TypeAnnotations "]"}
-     */
-    private JCExpression bracketsOpt(JCExpression t) {
-        return bracketsOpt(t, List.<JCTypeAnnotation>nil());
-    }
-
-    private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos,
-            List<JCTypeAnnotation> annotations) {
+    private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
         accept(RBRACKET);
-        t = bracketsOpt(t, annotations);
+        t = bracketsOpt(t);
         return toP(F.at(pos).TypeArray(t));
     }
 
@@ -1517,29 +1357,18 @@
         return t;
     }
 
-    /** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
+    /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
      */
     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
-
-        List<JCTypeAnnotation> newAnnotations = typeAnnotationsOpt();
-
         switch (S.token()) {
         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
         case DOUBLE: case BOOLEAN:
-            if (typeArgs == null) {
-                if (newAnnotations.isEmpty())
-                    return arrayCreatorRest(newpos, basicType());
-                else
-                    return arrayCreatorRest(newpos, F.AnnotatedType(newAnnotations, basicType()));
-            }
+            if (typeArgs == null)
+                return arrayCreatorRest(newpos, basicType());
             break;
         default:
         }
         JCExpression t = qualident();
-        // handle type annotations for non primitive arrays
-        if (!newAnnotations.isEmpty())
-            t = F.AnnotatedType(newAnnotations, t);
-
         int oldmode = mode;
         mode = TYPE | DIAMOND;
         if (S.token() == LT) {
@@ -1556,7 +1385,7 @@
             }
         }
         mode = oldmode;
-        if (S.token() == LBRACKET || S.token() == MONKEYS_AT) {
+        if (S.token() == LBRACKET) {
             JCExpression e = arrayCreatorRest(newpos, t);
             if (typeArgs != null) {
                 int pos = newpos;
@@ -1572,15 +1401,7 @@
             }
             return e;
         } else if (S.token() == LPAREN) {
-            JCNewClass newClass = classCreatorRest(newpos, null, typeArgs, t);
-            if (newClass.def != null) {
-                assert newClass.def.mods.annotations.isEmpty();
-                if (newAnnotations.nonEmpty()) {
-                    newClass.def.mods.pos = earlier(newClass.def.mods.pos, newAnnotations.head.pos);
-                    newClass.def.mods.annotations = List.convert(JCAnnotation.class, newAnnotations);
-                }
-            }
-            return newClass;
+            return classCreatorRest(newpos, null, typeArgs, t);
         } else {
             reportSyntaxError(S.pos(), "expected2",
                                LPAREN, LBRACKET);
@@ -1603,67 +1424,34 @@
         return classCreatorRest(newpos, encl, typeArgs, t);
     }
 
-    /** ArrayCreatorRest = [Annotations] "[" ( "]" BracketsOpt ArrayInitializer
-     *                         | Expression "]" {[Annotations]  "[" Expression "]"} BracketsOpt )
+    /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
+     *                         | Expression "]" {"[" Expression "]"} BracketsOpt )
      */
     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
-
-        List<JCTypeAnnotation> topAnnos = List.nil();
-        if (elemtype.getTag() == JCTree.ANNOTATED_TYPE) {
-            JCAnnotatedType atype = (JCAnnotatedType) elemtype;
-            topAnnos = atype.annotations;
-            elemtype = atype.underlyingType;
-        }
-
-        List<JCTypeAnnotation> annos = typeAnnotationsOpt();
-
         accept(LBRACKET);
-
         if (S.token() == RBRACKET) {
             accept(RBRACKET);
-
-            elemtype = bracketsOpt(elemtype, annos);
-
+            elemtype = bracketsOpt(elemtype);
             if (S.token() == LBRACE) {
-                JCNewArray na = (JCNewArray)arrayInitializer(newpos, elemtype);
-
-                na.annotations = topAnnos;
-
-                return na;
+                return arrayInitializer(newpos, elemtype);
             } else {
                 return syntaxError(S.pos(), "array.dimension.missing");
             }
         } else {
             ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
-
-            // maintain array dimension type annotations
-            ListBuffer<List<JCTypeAnnotation>> dimAnnotations = ListBuffer.lb();
-            dimAnnotations.append(annos);
-
             dims.append(parseExpression());
             accept(RBRACKET);
-            while (S.token() == LBRACKET
-                    || (S.token() == MONKEYS_AT)) {
-                List<JCTypeAnnotation> maybeDimAnnos = typeAnnotationsOpt();
+            while (S.token() == LBRACKET) {
                 int pos = S.pos();
                 S.nextToken();
                 if (S.token() == RBRACKET) {
-                    elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos);
+                    elemtype = bracketsOptCont(elemtype, pos);
                 } else {
-                    if (S.token() == RBRACKET) { // no dimension
-                        elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos);
-                    } else {
-                        dimAnnotations.append(maybeDimAnnos);
-                        dims.append(parseExpression());
-                        accept(RBRACKET);
-                    }
+                    dims.append(parseExpression());
+                    accept(RBRACKET);
                 }
             }
-
-            JCNewArray na = toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
-            na.annotations = topAnnos;
-            na.dimAnnotations = dimAnnotations.toList();
-            return na;
+            return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
         }
     }
 
@@ -1794,7 +1582,7 @@
             case ENUM:
             case ASSERT:
                 if (allowEnums && S.token() == ENUM) {
-                    log.error(S.pos(), "local.enum");
+                    error(S.pos(), "local.enum");
                     stats.
                         append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
                                                                  S.docComment()));
@@ -1941,9 +1729,9 @@
             } else {
                 if (allowTWR) {
                     if (resources.isEmpty())
-                        log.error(pos, "try.without.catch.finally.or.resource.decls");
+                        error(pos, "try.without.catch.finally.or.resource.decls");
                 } else
-                    log.error(pos, "try.without.catch.or.finally");
+                    error(pos, "try.without.catch.or.finally");
             }
             return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
         }
@@ -2040,7 +1828,7 @@
         JCModifiers mods = optFinal(Flags.PARAMETER);
         List<JCExpression> catchTypes = catchTypes();
         JCExpression paramType = catchTypes.size() > 1 ?
-                toP(F.at(catchTypes.head.getStartPosition()).TypeDisjoint(catchTypes)) :
+                toP(F.at(catchTypes.head.getStartPosition()).TypeDisjunction(catchTypes)) :
                 catchTypes.head;
         JCVariableDecl formal = variableDeclaratorId(mods, paramType);
         accept(RPAREN);
@@ -2142,32 +1930,17 @@
                                         new ListBuffer<JCExpressionStatement>()).toList();
     }
 
-    enum AnnotationKind { DEFAULT_ANNO, TYPE_ANNO };
-
     /** AnnotationsOpt = { '@' Annotation }
      */
-    List<JCAnnotation> annotationsOpt(AnnotationKind kind) {
+    List<JCAnnotation> annotationsOpt() {
         if (S.token() != MONKEYS_AT) return List.nil(); // optimization
         ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
-        int prevmode = mode;
         while (S.token() == MONKEYS_AT) {
             int pos = S.pos();
             S.nextToken();
-            buf.append(annotation(pos, kind));
+            buf.append(annotation(pos));
         }
-        lastmode = mode;
-        mode = prevmode;
-        List<JCAnnotation> annotations = buf.toList();
-
-        if (debugJSR308 && kind == AnnotationKind.TYPE_ANNO)
-            System.out.println("TA: parsing " + annotations
-                    + " in " + log.currentSourceFile());
-        return annotations;
-    }
-
-    List<JCTypeAnnotation> typeAnnotationsOpt() {
-        List<JCAnnotation> annotations = annotationsOpt(AnnotationKind.TYPE_ANNO);
-        return List.convert(JCTypeAnnotation.class, annotations);
+        return buf.toList();
     }
 
     /** ModifiersOpt = { Modifier }
@@ -2213,13 +1986,13 @@
             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
             default: break loop;
             }
-            if ((flags & flag) != 0) log.error(S.pos(), "repeated.modifier");
+            if ((flags & flag) != 0) error(S.pos(), "repeated.modifier");
             lastPos = S.pos();
             S.nextToken();
             if (flag == Flags.ANNOTATION) {
                 checkAnnotations();
                 if (S.token() != INTERFACE) {
-                    JCAnnotation ann = annotation(lastPos, AnnotationKind.DEFAULT_ANNO);
+                    JCAnnotation ann = annotation(lastPos);
                     // if first modifier is an annotation, set pos to annotation's.
                     if (flags == 0 && annotations.isEmpty())
                         pos = ann.pos;
@@ -2250,18 +2023,12 @@
     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
      * @param pos position of "@" token
      */
-    JCAnnotation annotation(int pos, AnnotationKind kind) {
+    JCAnnotation annotation(int pos) {
         // accept(AT); // AT consumed by caller
         checkAnnotations();
-        if (kind == AnnotationKind.TYPE_ANNO)
-            checkTypeAnnotations();
         JCTree ident = qualident();
         List<JCExpression> fieldValues = annotationFieldValuesOpt();
-        JCAnnotation ann;
-        if (kind == AnnotationKind.DEFAULT_ANNO)
-            ann = F.at(pos).Annotation(ident, fieldValues);
-        else
-            ann = F.at(pos).TypeAnnotation(ident, fieldValues);
+        JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
         storeEnd(ann, S.prevEndPos());
         return ann;
     }
@@ -2314,7 +2081,7 @@
         case MONKEYS_AT:
             pos = S.pos();
             S.nextToken();
-            return annotation(pos, AnnotationKind.DEFAULT_ANNO);
+            return annotation(pos);
         case LBRACE:
             pos = S.pos();
             accept(LBRACE);
@@ -2565,7 +2332,7 @@
             }
         } else {
             if (S.token() == ENUM) {
-                log.error(S.pos(), "enums.not.supported.in.source", source.name);
+                error(S.pos(), "enums.not.supported.in.source", source.name);
                 allowEnums = true;
                 return enumDeclaration(mods, dc);
             }
@@ -2705,7 +2472,7 @@
             S.resetDeprecatedFlag();
         }
         int pos = S.pos();
-        List<JCAnnotation> annotations = annotationsOpt(AnnotationKind.DEFAULT_ANNO);
+        List<JCAnnotation> annotations = annotationsOpt();
         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
         List<JCExpression> typeArgs = typeArgumentsOpt();
         int identPos = S.pos();
@@ -2802,29 +2569,19 @@
             } else {
                 pos = S.pos();
                 List<JCTypeParameter> typarams = typeParametersOpt();
-                List<JCAnnotation> annosAfterParams = annotationsOpt(AnnotationKind.DEFAULT_ANNO);
-
                 Name name = S.name();
                 pos = S.pos();
                 JCExpression type;
                 boolean isVoid = S.token() == VOID;
                 if (isVoid) {
-                    if (annosAfterParams.nonEmpty())
-                        illegal(annosAfterParams.head.pos);
                     type = to(F.at(pos).TypeIdent(TypeTags.VOID));
                     S.nextToken();
                 } else {
-                    if (annosAfterParams.nonEmpty()) {
-                        mods.annotations = mods.annotations.appendList(annosAfterParams);
-                        if (mods.pos == Position.NOPOS)
-                            mods.pos = mods.annotations.head.pos;
-                    }
-                    // method returns types are un-annotated types
-                    type = unannotatedType();
+                    type = parseType();
                 }
                 if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
                     if (isInterface || name != className)
-                        log.error(pos, "invalid.meth.decl.ret.type.req");
+                        error(pos, "invalid.meth.decl.ret.type.req");
                     return List.of(methodDeclaratorRest(
                         pos, mods, null, names.init, typarams,
                         isInterface, true, dc));
@@ -2856,15 +2613,15 @@
     }
 
     /** MethodDeclaratorRest =
-     *      FormalParameters BracketsOpt [Annotations] [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
+     *      FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
      *  VoidMethodDeclaratorRest =
-     *      FormalParameters [Annotations] [Throws TypeList] ( MethodBody | ";")
+     *      FormalParameters [Throws TypeList] ( MethodBody | ";")
      *  InterfaceMethodDeclaratorRest =
-     *      FormalParameters BracketsOpt [Annotations] [THROWS TypeList] ";"
+     *      FormalParameters BracketsOpt [THROWS TypeList] ";"
      *  VoidInterfaceMethodDeclaratorRest =
-     *      FormalParameters [Annotations] [THROWS TypeList] ";"
+     *      FormalParameters [THROWS TypeList] ";"
      *  ConstructorDeclaratorRest =
-     *      "(" FormalParameterListOpt ")" [Annotations] [THROWS TypeList] MethodBody
+     *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
      */
     JCTree methodDeclaratorRest(int pos,
                               JCModifiers mods,
@@ -2874,22 +2631,7 @@
                               boolean isInterface, boolean isVoid,
                               String dc) {
         List<JCVariableDecl> params = formalParameters();
-
-        List<JCTypeAnnotation> receiverAnnotations;
-        if (!isVoid) {
-            // need to distinguish between receiver anno and array anno
-            // look at typeAnnotationsPushedBack comment
-            this.permitTypeAnnotationsPushBack = true;
-            type = methodReturnArrayRest(type);
-            this.permitTypeAnnotationsPushBack = false;
-            if (typeAnnotationsPushedBack == null)
-                receiverAnnotations = List.nil();
-            else
-                receiverAnnotations = typeAnnotationsPushedBack;
-            typeAnnotationsPushedBack = null;
-        } else
-            receiverAnnotations = typeAnnotationsOpt();
-
+        if (!isVoid) type = bracketsOpt(type);
         List<JCExpression> thrown = List.nil();
         if (S.token() == THROWS) {
             S.nextToken();
@@ -2919,51 +2661,20 @@
 
         JCMethodDecl result =
             toP(F.at(pos).MethodDef(mods, name, type, typarams,
-                                    params, receiverAnnotations, thrown,
+                                    params, thrown,
                                     body, defaultValue));
         attach(result, dc);
         return result;
     }
 
-    /** Parses the array levels after the format parameters list, and append
-     * them to the return type, while preseving the order of type annotations
-     */
-    private JCExpression methodReturnArrayRest(JCExpression type) {
-        if (type.getTag() != JCTree.TYPEARRAY)
-            return bracketsOpt(type);
-
-        JCArrayTypeTree baseArray = (JCArrayTypeTree)type;
-        while (TreeInfo.typeIn(baseArray.elemtype) instanceof JCArrayTypeTree)
-            baseArray = (JCArrayTypeTree)TreeInfo.typeIn(baseArray.elemtype);
-
-        if (baseArray.elemtype.getTag() == JCTree.ANNOTATED_TYPE) {
-            JCAnnotatedType at = (JCAnnotatedType)baseArray.elemtype;
-            at.underlyingType = bracketsOpt(at.underlyingType);
-        } else {
-            baseArray.elemtype = bracketsOpt(baseArray.elemtype);
-        }
-
-        return type;
-    }
-
-    /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident}
+    /** QualidentList = Qualident {"," Qualident}
      */
     List<JCExpression> qualidentList() {
         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
-
-        List<JCTypeAnnotation> typeAnnos = typeAnnotationsOpt();
-        if (!typeAnnos.isEmpty())
-            ts.append(F.AnnotatedType(typeAnnos, qualident()));
-        else
-            ts.append(qualident());
+        ts.append(qualident());
         while (S.token() == COMMA) {
             S.nextToken();
-
-            typeAnnos = typeAnnotationsOpt();
-            if (!typeAnnos.isEmpty())
-                ts.append(F.AnnotatedType(typeAnnos, qualident()));
-            else
-                ts.append(qualident());
+            ts.append(qualident());
         }
         return ts.toList();
     }
@@ -2987,13 +2698,12 @@
         }
     }
 
-    /** TypeParameter = [Annotations] TypeVariable [TypeParameterBound]
+    /** TypeParameter = TypeVariable [TypeParameterBound]
      *  TypeParameterBound = EXTENDS Type {"&" Type}
      *  TypeVariable = Ident
      */
     JCTypeParameter typeParameter() {
         int pos = S.pos();
-        List<JCTypeAnnotation> annos = typeAnnotationsOpt();
         Name name = ident();
         ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
         if (S.token() == EXTENDS) {
@@ -3004,7 +2714,7 @@
                 bounds.append(parseType());
             }
         }
-        return toP(F.at(pos).TypeParameter(name, bounds.toList(), annos));
+        return toP(F.at(pos).TypeParameter(name, bounds.toList()));
     }
 
     /** FormalParameters = "(" [ FormalParameterList ] ")"
@@ -3038,37 +2748,26 @@
      */
     JCVariableDecl formalParameter() {
         JCModifiers mods = optFinal(Flags.PARAMETER);
-        // need to distinguish between vararg annos and array annos
-        // look at typeAnnotaitonsPushedBack comment
-        this.permitTypeAnnotationsPushBack = true;
         JCExpression type = parseType();
-        this.permitTypeAnnotationsPushBack = false;
-
         if (S.token() == ELLIPSIS) {
-            List<JCTypeAnnotation> varargsAnnos = typeAnnotationsPushedBack;
-            typeAnnotationsPushedBack = null;
             checkVarargs();
             mods.flags |= Flags.VARARGS;
-            // insert var arg type annotations
-            if (varargsAnnos != null && varargsAnnos.nonEmpty())
-                type = F.at(S.pos()).AnnotatedType(varargsAnnos, type);
             type = to(F.at(S.pos()).TypeArray(type));
-
             S.nextToken();
-        } else {
-            // if not a var arg, then typeAnnotationsPushedBack should be null
-            if (typeAnnotationsPushedBack != null
-                    && !typeAnnotationsPushedBack.isEmpty()) {
-                reportSyntaxError(typeAnnotationsPushedBack.head.pos,
-                        "illegal.start.of.type");
-            }
-            typeAnnotationsPushedBack = null;
         }
         return variableDeclaratorId(mods, type);
     }
 
 /* ---------- auxiliary methods -------------- */
 
+    void error(int pos, String key, Object ... args) {
+        log.error(DiagnosticFlag.SYNTAX, pos, key, args);
+    }
+
+    void warning(int pos, String key, Object ... args) {
+        log.warning(pos, key, args);
+    }
+
     /** Check that given tree is a legal expression statement.
      */
     protected JCExpression checkExprStat(JCExpression t) {
@@ -3084,7 +2783,7 @@
         case JCTree.ERRONEOUS:
             return t;
         default:
-            log.error(t.pos, "not.stmt");
+            error(t.pos, "not.stmt");
             return F.at(t.pos).Erroneous(List.<JCTree>of(t));
         }
     }
@@ -3231,55 +2930,49 @@
 
     void checkGenerics() {
         if (!allowGenerics) {
-            log.error(S.pos(), "generics.not.supported.in.source", source.name);
+            error(S.pos(), "generics.not.supported.in.source", source.name);
             allowGenerics = true;
         }
     }
     void checkVarargs() {
         if (!allowVarargs) {
-            log.error(S.pos(), "varargs.not.supported.in.source", source.name);
+            error(S.pos(), "varargs.not.supported.in.source", source.name);
             allowVarargs = true;
         }
     }
     void checkForeach() {
         if (!allowForeach) {
-            log.error(S.pos(), "foreach.not.supported.in.source", source.name);
+            error(S.pos(), "foreach.not.supported.in.source", source.name);
             allowForeach = true;
         }
     }
     void checkStaticImports() {
         if (!allowStaticImport) {
-            log.error(S.pos(), "static.import.not.supported.in.source", source.name);
+            error(S.pos(), "static.import.not.supported.in.source", source.name);
             allowStaticImport = true;
         }
     }
     void checkAnnotations() {
         if (!allowAnnotations) {
-            log.error(S.pos(), "annotations.not.supported.in.source", source.name);
+            error(S.pos(), "annotations.not.supported.in.source", source.name);
             allowAnnotations = true;
         }
     }
-    void checkTypeAnnotations() {
-        if (!allowTypeAnnotations) {
-            log.error(S.pos(), "type.annotations.not.supported.in.source", source.name);
-            allowTypeAnnotations = true;
-        }
-    }
     void checkDiamond() {
         if (!allowDiamond) {
-            log.error(S.pos(), "diamond.not.supported.in.source", source.name);
+            error(S.pos(), "diamond.not.supported.in.source", source.name);
             allowDiamond = true;
         }
     }
     void checkMulticatch() {
         if (!allowMulticatch) {
-            log.error(S.pos(), "multicatch.not.supported.in.source", source.name);
+            error(S.pos(), "multicatch.not.supported.in.source", source.name);
             allowMulticatch = true;
         }
     }
     void checkAutomaticResourceManagement() {
         if (!allowTWR) {
-            log.error(S.pos(), "automatic.resource.management.not.supported.in.source", source.name);
+            error(S.pos(), "automatic.resource.management.not.supported.in.source", source.name);
             allowTWR = true;
         }
     }
--- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Wed Jul 05 17:26:57 2017 +0200
@@ -49,11 +49,11 @@
 import javax.tools.JavaFileObject;
 import javax.tools.DiagnosticListener;
 
-import com.sun.tools.javac.api.JavacTrees;
-import com.sun.source.util.AbstractTypeProcessor;
+//308 import com.sun.source.util.AbstractTypeProcessor;
 import com.sun.source.util.TaskEvent;
 import com.sun.source.util.TaskListener;
 import com.sun.tools.javac.api.JavacTaskImpl;
+import com.sun.tools.javac.api.JavacTrees;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.file.JavacFileManager;
@@ -712,7 +712,7 @@
             }
 
             if (matchedNames.size() > 0 || ps.contributed) {
-                foundTypeProcessors = foundTypeProcessors || (ps.processor instanceof AbstractTypeProcessor);
+//308                foundTypeProcessors = foundTypeProcessors || (ps.processor instanceof AbstractTypeProcessor);
                 boolean processingResult = callProcessor(ps.processor, typeElements, renv);
                 ps.contributed = true;
                 ps.removeSupportedOptions(unmatchedProcessorOptions);
@@ -939,7 +939,7 @@
                         break;
 
                     case ERROR:
-                        if (fatalErrors || !d.isFlagSet(RESOLVE_ERROR))
+                        if (fatalErrors || !d.isFlagSet(RECOVERABLE))
                             return true;
                         break;
                 }
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Wed Jul 05 17:26:57 2017 +0200
@@ -873,6 +873,13 @@
     found raw type: {0}\n\
     missing type parameters for generic class {1}
 
+compiler.warn.diamond.redundant.args=\
+    redundant type arguments in new expression (use diamond operator instead).
+compiler.warn.diamond.redundant.args.1=\
+    redundant type arguments in new expression (use diamond operator instead).\n\
+    explicit: {0}\n\
+    inferred: {1}
+
 #####
 
 ## The following are tokens which are non-terminals in the language. They should
@@ -1299,9 +1306,9 @@
     annotations are not supported in -source {0}\n\
 (use -source 5 or higher to enable annotations)
 
-compiler.err.type.annotations.not.supported.in.source=\
-    type annotations are not supported in -source {0}\n\
-(use -source 7 or higher to enable type annotations)
+#308 compiler.err.type.annotations.not.supported.in.source=\
+#308     type annotations are not supported in -source {0}\n\
+#308 (use -source 7 or higher to enable type annotations)
 
 compiler.err.foreach.not.supported.in.source=\
     for-each loops are not supported in -source {0}\n\
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Wed Jul 05 17:26:57 2017 +0200
@@ -236,13 +236,13 @@
      */
     public static final int TYPEAPPLY = TYPEARRAY + 1;
 
-    /** Disjunctive types, of type TypeDisjoint.
+    /** Disjunction types, of type TypeDisjunction
      */
-    public static final int TYPEDISJOINT = TYPEAPPLY + 1;
+    public static final int TYPEDISJUNCTION = TYPEAPPLY + 1;
 
     /** Formal type parameters, of type TypeParameter.
      */
-    public static final int TYPEPARAMETER = TYPEDISJOINT + 1;
+    public static final int TYPEPARAMETER = TYPEDISJUNCTION + 1;
 
     /** Type argument.
      */
@@ -1888,30 +1888,30 @@
     }
 
     /**
-     * A disjoint type, T1 | T2 | ... Tn (used in multicatch statements)
+     * A disjunction type, T1 | T2 | ... Tn (used in multicatch statements)
      */
-    public static class JCTypeDisjoint extends JCExpression implements DisjointTypeTree {
+    public static class JCTypeDisjunction extends JCExpression implements DisjunctiveTypeTree {
 
-        public List<JCExpression> components;
+        public List<JCExpression> alternatives;
 
-        protected JCTypeDisjoint(List<JCExpression> components) {
-            this.components = components;
+        protected JCTypeDisjunction(List<JCExpression> components) {
+            this.alternatives = components;
         }
         @Override
-        public void accept(Visitor v) { v.visitTypeDisjoint(this); }
+        public void accept(Visitor v) { v.visitTypeDisjunction(this); }
 
-        public Kind getKind() { return Kind.DISJOINT_TYPE; }
+        public Kind getKind() { return Kind.DISJUNCTIVE_TYPE; }
 
-        public List<JCExpression> getTypeComponents() {
-            return components;
+        public List<JCExpression> getTypeAlternatives() {
+            return alternatives;
         }
         @Override
         public <R,D> R accept(TreeVisitor<R,D> v, D d) {
-            return v.visitDisjointType(this, d);
+            return v.visitDisjunctiveType(this, d);
         }
         @Override
         public int getTag() {
-            return TYPEDISJOINT;
+            return TYPEDISJUNCTION;
         }
     }
 
@@ -2067,17 +2067,23 @@
         }
     }
 
-    public static class JCAnnotatedType extends JCExpression implements com.sun.source.tree.AnnotatedTypeTree {
+    public static class JCAnnotatedType extends JCExpression
+//308            implements com.sun.source.tree.AnnotatedTypeTree
+    {
         public List<JCTypeAnnotation> annotations;
         public JCExpression underlyingType;
         protected JCAnnotatedType(List<JCTypeAnnotation> annotations, JCExpression underlyingType) {
-            this.annotations = annotations;
-            this.underlyingType = underlyingType;
+            throw new UnsupportedOperationException();
+//308            this.annotations = annotations;
+//308            this.underlyingType = underlyingType;
         }
         @Override
         public void accept(Visitor v) { v.visitAnnotatedType(this); }
 
-        public Kind getKind() { return Kind.ANNOTATED_TYPE; }
+        public Kind getKind() {
+            throw new UnsupportedOperationException();
+//308            return Kind.ANNOTATED_TYPE;
+        }
         public List<JCTypeAnnotation> getAnnotations() {
             return annotations;
         }
@@ -2086,7 +2092,8 @@
         }
         @Override
         public <R,D> R accept(TreeVisitor<R,D> v, D d) {
-            return v.visitAnnotatedType(this, d);
+            throw new UnsupportedOperationException();
+//308            return v.visitAnnotatedType(this, d);
         }
         @Override
         public int getTag() {
@@ -2277,7 +2284,7 @@
         public void visitTypeIdent(JCPrimitiveTypeTree that) { visitTree(that); }
         public void visitTypeArray(JCArrayTypeTree that)     { visitTree(that); }
         public void visitTypeApply(JCTypeApply that)         { visitTree(that); }
-        public void visitTypeDisjoint(JCTypeDisjoint that)   { visitTree(that); }
+        public void visitTypeDisjunction(JCTypeDisjunction that)   { visitTree(that); }
         public void visitTypeParameter(JCTypeParameter that) { visitTree(that); }
         public void visitWildcard(JCWildcard that)           { visitTree(that); }
         public void visitTypeBoundKind(TypeBoundKind that)   { visitTree(that); }
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java	Wed Jul 05 17:26:57 2017 +0200
@@ -1195,9 +1195,9 @@
         }
     }
 
-    public void visitTypeDisjoint(JCTypeDisjoint tree) {
+    public void visitTypeDisjunction(JCTypeDisjunction tree) {
         try {
-            printExprs(tree.components, " | ");
+            printExprs(tree.alternatives, " | ");
         } catch (IOException e) {
             throw new UncheckedIOException(e);
         }
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Wed Jul 05 17:26:57 2017 +0200
@@ -71,12 +71,12 @@
         return lb.toList();
     }
 
-    public JCTree visitAnnotatedType(AnnotatedTypeTree node, P p) {
-        JCAnnotatedType t = (JCAnnotatedType) node;
-        List<JCTypeAnnotation> annotations = copy(t.annotations, p);
-        JCExpression underlyingType = copy(t.underlyingType, p);
-        return M.at(t.pos).AnnotatedType(annotations, underlyingType);
-    }
+//308    public JCTree visitAnnotatedType(AnnotatedTypeTree node, P p) {
+//308        JCAnnotatedType t = (JCAnnotatedType) node;
+//308        List<JCTypeAnnotation> annotations = copy(t.annotations, p);
+//308        JCExpression underlyingType = copy(t.underlyingType, p);
+//308        return M.at(t.pos).AnnotatedType(annotations, underlyingType);
+//308    }
 
     public JCTree visitAnnotation(AnnotationTree node, P p) {
         JCAnnotation t = (JCAnnotation) node;
@@ -346,10 +346,10 @@
         return M.at(t.pos).TypeApply(clazz, arguments);
     }
 
-    public JCTree visitDisjointType(DisjointTypeTree node, P p) {
-        JCTypeDisjoint t = (JCTypeDisjoint) node;
-        List<JCExpression> components = copy(t.components, p);
-        return M.at(t.pos).TypeDisjoint(components);
+    public JCTree visitDisjunctiveType(DisjunctiveTypeTree node, P p) {
+        JCTypeDisjunction t = (JCTypeDisjunction) node;
+        List<JCExpression> components = copy(t.alternatives, p);
+        return M.at(t.pos).TypeDisjunction(components);
     }
 
     public JCTree visitArrayType(ArrayTypeTree node, P p) {
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Wed Jul 05 17:26:57 2017 +0200
@@ -119,7 +119,7 @@
     }
 
     public static boolean isMultiCatch(JCCatch catchClause) {
-        return catchClause.param.vartype.getTag() == JCTree.TYPEDISJOINT;
+        return catchClause.param.vartype.getTag() == JCTree.TYPEDISJUNCTION;
     }
 
     /** Is statement an initializer for a synthetic field?
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Wed Jul 05 17:26:57 2017 +0200
@@ -451,8 +451,8 @@
         return tree;
     }
 
-    public JCTypeDisjoint TypeDisjoint(List<JCExpression> components) {
-        JCTypeDisjoint tree = new JCTypeDisjoint(components);
+    public JCTypeDisjunction TypeDisjunction(List<JCExpression> components) {
+        JCTypeDisjunction tree = new JCTypeDisjunction(components);
         tree.pos = pos;
         return tree;
     }
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java	Wed Jul 05 17:26:57 2017 +0200
@@ -276,8 +276,8 @@
         scan(tree.arguments);
     }
 
-    public void visitTypeDisjoint(JCTypeDisjoint tree) {
-        scan(tree.components);
+    public void visitTypeDisjunction(JCTypeDisjunction tree) {
+        scan(tree.alternatives);
     }
 
     public void visitTypeParameter(JCTypeParameter tree) {
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java	Wed Jul 05 17:26:57 2017 +0200
@@ -368,8 +368,8 @@
         result = tree;
     }
 
-    public void visitTypeDisjoint(JCTypeDisjoint tree) {
-        tree.components = translate(tree.components);
+    public void visitTypeDisjunction(JCTypeDisjunction tree) {
+        tree.alternatives = translate(tree.alternatives);
         result = tree;
     }
 
--- a/langtools/src/share/classes/com/sun/tools/javac/util/AbstractLog.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/AbstractLog.java	Wed Jul 05 17:26:57 2017 +0200
@@ -30,6 +30,7 @@
 import javax.tools.JavaFileObject;
 
 import com.sun.tools.javac.code.Lint.LintCategory;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
 
@@ -103,6 +104,19 @@
         report(diags.error(source, wrap(pos), key, args));
     }
 
+    /** Report an error, unless another error was already reported at same
+     *  source position.
+     *  @param flag   A flag to set on the diagnostic
+     *  @param pos    The source position at which to report the error.
+     *  @param key    The key for the localized error message.
+     *  @param args   Fields of the error message.
+     */
+    public void error(DiagnosticFlag flag, int pos, String key, Object ... args) {
+        JCDiagnostic d = diags.error(source, wrap(pos), key, args);
+        d.setFlag(flag);
+        report(d);
+    }
+
     /** Report a warning, unless suppressed by the  -nowarn option or the
      *  maximum number of warnings has been reached.
      *  @param pos    The source position at which to report the warning.
--- a/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java	Wed Jul 05 17:26:57 2017 +0200
@@ -63,17 +63,23 @@
 
         DiagnosticFormatter<JCDiagnostic> formatter;
         final String prefix;
+        final Set<DiagnosticFlag> defaultErrorFlags;
 
         /** Create a new diagnostic factory. */
         protected Factory(Context context) {
             this(JavacMessages.instance(context), "compiler");
             context.put(diagnosticFactoryKey, this);
+
+            Options options = Options.instance(context);
+            if (options.isSet("onlySyntaxErrorsUnrecoverable"))
+                defaultErrorFlags.add(DiagnosticFlag.RECOVERABLE);
         }
 
         /** Create a new diagnostic factory. */
         public Factory(JavacMessages messages, String prefix) {
             this.prefix = prefix;
             this.formatter = new BasicDiagnosticFormatter(messages);
+            defaultErrorFlags = EnumSet.of(DiagnosticFlag.MANDATORY);
         }
 
         /**
@@ -85,7 +91,7 @@
          */
         public JCDiagnostic error(
                 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
-            return create(ERROR, null, EnumSet.of(DiagnosticFlag.MANDATORY), source, pos, key, args);
+            return create(ERROR, null, defaultErrorFlags, source, pos, key, args);
         }
 
         /**
@@ -331,7 +337,9 @@
 
     public enum DiagnosticFlag {
         MANDATORY,
-        RESOLVE_ERROR
+        RESOLVE_ERROR,
+        SYNTAX,
+        RECOVERABLE
     }
 
     private final DiagnosticType type;
@@ -547,6 +555,17 @@
 
     public void setFlag(DiagnosticFlag flag) {
         flags.add(flag);
+
+        if (type == DiagnosticType.ERROR) {
+            switch (flag) {
+                case SYNTAX:
+                    flags.remove(DiagnosticFlag.RECOVERABLE);
+                    break;
+                case RESOLVE_ERROR:
+                    flags.add(DiagnosticFlag.RECOVERABLE);
+                    break;
+            }
+        }
     }
 
     public boolean isFlagSet(DiagnosticFlag flag) {
--- a/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java	Wed Jul 05 17:26:57 2017 +0200
@@ -850,6 +850,12 @@
                                        String[] paramTypes, Set<ClassDocImpl> searched) {
         //### Note that this search is not necessarily what the compiler would do!
 
+        Names names = tsym.name.table.names;
+        // do not match constructors
+        if (names.init.contentEquals(methodName)) {
+            return null;
+        }
+
         ClassDocImpl cdi;
         MethodDocImpl mdi;
 
@@ -876,7 +882,6 @@
          *---------------------------------*/
 
         // search current class
-        Names names = tsym.name.table.names;
         Scope.Entry e = tsym.members().lookup(names.fromString(methodName));
 
         //### Using modifier filter here isn't really correct,
--- a/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java	Wed Jul 05 17:26:57 2017 +0200
@@ -637,6 +637,7 @@
      * Should be called only on symbols representing methods.
      */
     public MethodDocImpl getMethodDoc(MethodSymbol meth) {
+        assert !meth.isConstructor() : "not expecting a constructor symbol";
         MethodDocImpl result = (MethodDocImpl)methodMap.get(meth);
         if (result != null) return result;
         result = new MethodDocImpl(this, meth);
@@ -665,6 +666,7 @@
      * Should be called only on symbols representing constructors.
      */
     public ConstructorDocImpl getConstructorDoc(MethodSymbol meth) {
+        assert meth.isConstructor() : "expecting a constructor symbol";
         ConstructorDocImpl result = (ConstructorDocImpl)methodMap.get(meth);
         if (result != null) return result;
         result = new ConstructorDocImpl(this, meth);
--- a/langtools/src/share/classes/com/sun/tools/javah/JavahTask.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javah/JavahTask.java	Wed Jul 05 17:26:57 2017 +0200
@@ -26,6 +26,7 @@
 package com.sun.tools.javah;
 
 import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintWriter;
@@ -74,6 +75,7 @@
 import static javax.tools.Diagnostic.Kind.*;
 
 import com.sun.tools.javac.code.Symbol.CompletionFailure;
+import com.sun.tools.javac.main.CommandLine;
 
 /**
  * Javah generates support files for native methods.
@@ -362,7 +364,7 @@
         if (fileManager == null)
             fileManager = getDefaultFileManager(diagnosticListener, log);
 
-        Iterator<String> iter = args.iterator();
+        Iterator<String> iter = expandAtArgs(args).iterator();
         noArgs = !iter.hasNext();
 
         while (iter.hasNext()) {
@@ -416,6 +418,18 @@
         throw new BadArgs("err.unknown.option", name).showUsage(true);
     }
 
+    private Iterable<String> expandAtArgs(Iterable<String> args) throws BadArgs {
+        try {
+            List<String> l = new ArrayList<String>();
+            for (String arg: args) l.add(arg);
+            return Arrays.asList(CommandLine.parse(l.toArray(new String[l.size()])));
+        } catch (FileNotFoundException e) {
+            throw new BadArgs("at.args.file.not.found", e.getLocalizedMessage());
+        } catch (IOException e) {
+            throw new BadArgs("at.args.io.exception", e.getLocalizedMessage());
+        }
+    }
+
     public Boolean call() {
         return run();
     }
@@ -607,8 +621,8 @@
             }
 
         };
+    }
 
-    }
     private String getMessage(String key, Object... args) {
         return getMessage(task_locale, key, args);
     }
--- a/langtools/src/share/classes/com/sun/tools/javah/resources/l10n.properties	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javah/resources/l10n.properties	Wed Jul 05 17:26:57 2017 +0200
@@ -30,6 +30,8 @@
         The directory {0} could not be create for output.
 at.args.cant.read=\
         Can''t read command line arguments from file {1}.
+at.args.file.not.found=\
+        Can''t find file {0}.
 at.args.io.exception=\
         The following I/O problem was encountered when processing an @ \
         argument on the command line: {0}.
--- a/langtools/test/tools/javac/T6985181.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2010, 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 6985181
- * @summary Annotations lost from classfile
- */
-
-import java.io.*;
-import java.util.*;
-
-public class T6985181 {
-    public static void main(String... args) throws Exception{
-        new T6985181().run();
-    }
-
-    public void run() throws Exception {
-        String code = "@interface Simple { }\ninterface Test<@Simple T> { }";
-
-        File srcFile = writeFile("Test.java", code);
-        File classesDir = new File("classes");
-        classesDir.mkdirs();
-        compile("-d", classesDir.getPath(), srcFile.getPath());
-        String out = javap(new File(classesDir, srcFile.getName().replace(".java", ".class")));
-        if (!out.contains("RuntimeInvisibleTypeAnnotations"))
-            throw new Exception("RuntimeInvisibleTypeAnnotations not found");
-    }
-
-    void compile(String... args) throws Exception {
-        StringWriter sw = new StringWriter();
-        PrintWriter pw = new PrintWriter(sw);
-        int rc = com.sun.tools.javac.Main.compile(args, pw);
-        pw.close();
-        String out = sw.toString();
-        if (out.length() > 0)
-            System.err.println(out);
-        if (rc != 0)
-            throw new Exception("Compilation failed: rc=" + rc);
-    }
-
-    String javap(File classFile) throws Exception {
-        StringWriter sw = new StringWriter();
-        PrintWriter pw = new PrintWriter(sw);
-        String[] args = { "-v", classFile.getPath() };
-        int rc = com.sun.tools.javap.Main.run(args, pw);
-        pw.close();
-        String out = sw.toString();
-        if (out.length() > 0)
-            System.err.println(out);
-        if (rc != 0)
-            throw new Exception("javap failed: rc=" + rc);
-        return out;
-    }
-
-    File writeFile(String path, String body) throws IOException {
-        File f = new File(path);
-        FileWriter out = new FileWriter(f);
-        try {
-            out.write(body);
-        } finally {
-            out.close();
-        }
-        return f;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/T6993301.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2010, 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 6993301
+ * @summary catch parameters do not have correct kind (i.e. ElementKind.EXCEPTION_PARAMETER)
+ */
+
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.IdentifierTree;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.TreePathScanner;
+import com.sun.source.util.Trees;
+import com.sun.tools.javac.api.JavacTaskImpl;
+import java.io.IOException;
+import java.net.URI;
+import java.util.Arrays;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.ToolProvider;
+
+/**
+ *
+ * @author Jan Lahoda
+ */
+public class T6993301 {
+    public static void main(String... args) throws Exception {
+        new T6993301().testExceptionParameterCorrectKind();
+    }
+
+    static class MyFileObject extends SimpleJavaFileObject {
+        private String text;
+        public MyFileObject(String text) {
+            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+            this.text = text;
+        }
+        @Override
+        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+            return text;
+        }
+    }
+
+    public void testExceptionParameterCorrectKind() throws IOException {
+        final String bootPath = System.getProperty("sun.boot.class.path");
+        final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
+        assert tool != null;
+
+        String code = "package test; public class Test { { try { } catch (NullPointerException ex) {} } }";
+
+        final JavacTaskImpl ct = (JavacTaskImpl)tool.getTask(null, null, null,
+                Arrays.asList("-bootclasspath",  bootPath),
+                null, Arrays.asList(new MyFileObject(code)));
+        CompilationUnitTree cut = ct.parse().iterator().next();
+
+        ct.analyze();
+
+        new TreePathScanner<Void, Void>() {
+            @Override
+            public Void visitVariable(VariableTree node, Void p) {
+                Element el = Trees.instance(ct).getElement(getCurrentPath());
+
+                assertNotNull(el);
+                assertEquals(ElementKind.EXCEPTION_PARAMETER, el.getKind());
+
+                return super.visitVariable(node, p);
+            }
+        }.scan(cut, null);
+    }
+
+    private void assertNotNull(Object o) {
+        if (o == null)
+            throw new AssertionError();
+    }
+
+    private <T> void assertEquals(T expected, T actual) {
+        if (expected == null ? actual == null : expected.equals(actual))
+            return;
+        throw new AssertionError("expected: " + expected + ", actual: " + actual);
+    }
+
+}
--- a/langtools/test/tools/javac/annotations/6881115/T6881115.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/test/tools/javac/annotations/6881115/T6881115.java	Wed Jul 05 17:26:57 2017 +0200
@@ -16,5 +16,5 @@
 }
 @A(b = @B(b2 = 1, b2 = 2),
    b_arr = {@B(), @B(b2 = 1, b2 = 2)})
-class T6881115<@A(b = @B(b2 = 1, b2 = 2),
-                  b_arr = {@B(), @B(b2 = 1, b2 = 2)}) X> {}
+class T6881115</*308 @A(b = @B(b2 = 1, b2 = 2),
+                  b_arr = {@B(), @B(b2 = 1, b2 = 2)})*/ X> {}
--- a/langtools/test/tools/javac/annotations/6881115/T6881115.out	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/test/tools/javac/annotations/6881115/T6881115.out	Wed Jul 05 17:26:57 2017 +0200
@@ -8,9 +8,4 @@
 T6881115.java:18:13: compiler.err.annotation.missing.default.value.1: B, b1,b2
 T6881115.java:18:30: compiler.err.duplicate.annotation.member.value: b2, B
 T6881115.java:18:19: compiler.err.annotation.missing.default.value: B, b1
-T6881115.java:19:34: compiler.err.duplicate.annotation.member.value: b2, B
-T6881115.java:19:23: compiler.err.annotation.missing.default.value: B, b1
-T6881115.java:20:28: compiler.err.annotation.missing.default.value.1: B, b1,b2
-T6881115.java:20:45: compiler.err.duplicate.annotation.member.value: b2, B
-T6881115.java:20:34: compiler.err.annotation.missing.default.value: B, b1
-15 errors
+10 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DiamondRedundantArgs.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+// key: compiler.warn.diamond.redundant.args
+// options: -XDfindDiamond
+
+class Foo<X> {
+   Foo<String> fs = new Foo<String>();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DiamondRedundantArgs1.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+// key: compiler.warn.diamond.redundant.args.1
+// options: -XDfindDiamond
+
+class Foo<X> {
+   Foo<?> fs = new Foo<String>();
+}
--- a/langtools/test/tools/javac/diags/examples/TypeAnnotationsNotSupported.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2010, 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.
- */
-
-// key: compiler.err.type.annotations.not.supported.in.source
-// options: -source 6
-
-@interface Anno { }
-
-class TypeAnnotationsNotSupported {
-    void m() {
-        int i = (@Anno int) 3.14;
-    }
-}
--- a/langtools/test/tools/javac/generics/OverrideBridge.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/test/tools/javac/generics/OverrideBridge.java	Wed Jul 05 17:26:57 2017 +0200
@@ -23,7 +23,8 @@
 
 /*
  * @test
- * @bug 6337171
+ * @bug 6337171 6996415
+ * @ignore fix has been disabled as a consequence of 6996415
  * @summary  javac should create bridge methods when type variable bounds restricted
  * @run main OverrideBridge
  */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/diamond/T6939780.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,25 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 6939780
+ *
+ * @summary  add a warning to detect diamond sites
+ * @author mcimadamore
+ * @compile/ref=T6939780.out T6939780.java -XDrawDiagnostics -XDfindDiamond
+ *
+ */
+
+class T6939780 {
+
+    void test() {
+        class Foo<X extends Number> {
+            Foo() {}
+            Foo(X x) {}
+        }
+        Foo<Number> f1 = new Foo<Number>(1);
+        Foo<?> f2 = new Foo<Number>();
+        Foo<?> f3 = new Foo<Integer>();
+        Foo<Number> f4 = new Foo<Number>(1) {};
+        Foo<?> f5 = new Foo<Number>() {};
+        Foo<?> f6 = new Foo<Integer>() {};
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/diamond/T6939780.out	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,5 @@
+T6939780.java:19:28: compiler.warn.diamond.redundant.args: Foo<java.lang.Number>, Foo<java.lang.Number>
+T6939780.java:20:28: compiler.warn.diamond.redundant.args.1: Foo<java.lang.Integer>, Foo<java.lang.Number>
+T6939780.java:22:28: compiler.warn.diamond.redundant.args: Foo<java.lang.Number>, Foo<java.lang.Number>
+T6939780.java:23:28: compiler.warn.diamond.redundant.args.1: Foo<java.lang.Integer>, Foo<java.lang.Number>
+4 warnings
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/6994946/SemanticErrorTest.1.out	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,2 @@
+SemanticErrorTest.java:11:46: compiler.err.repeated.interface
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/6994946/SemanticErrorTest.2.out	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,4 @@
+SemanticErrorTest.java:11:46: compiler.err.repeated.interface
+- compiler.err.proc.messager: Deliberate Error
+SemanticErrorTest.java:11:46: compiler.err.repeated.interface
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/6994946/SemanticErrorTest.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,13 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 6994946
+ * @summary option to specify only syntax errors as unrecoverable
+ * @library ../../lib
+ * @build JavacTestingAbstractProcessor TestProcessor
+ * @compile/fail/ref=SemanticErrorTest.1.out -XDrawDiagnostics                                  -processor TestProcessor SemanticErrorTest.java
+ * @compile/fail/ref=SemanticErrorTest.2.out -XDrawDiagnostics -XDonlySyntaxErrorsUnrecoverable -processor TestProcessor SemanticErrorTest.java
+ */
+
+class SemanticErrorTest implements Runnable, Runnable {
+    public void run() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/6994946/SyntaxErrorTest.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,13 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 6994946
+ * @summary option to specify only syntax errors as unrecoverable
+ * @library ../../lib
+ * @build JavacTestingAbstractProcessor TestProcessor
+ * @compile/fail/ref=SyntaxErrorTest.out -XDrawDiagnostics                                  -processor TestProcessor SyntaxErrorTest.java
+ * @compile/fail/ref=SyntaxErrorTest.out -XDrawDiagnostics -XDonlySyntaxErrorsUnrecoverable -processor TestProcessor SyntaxErrorTest.java
+ */
+
+class SyntaxErrorTest {
+    int i
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/6994946/SyntaxErrorTest.out	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,2 @@
+SyntaxErrorTest.java:12:10: compiler.err.expected: ';'
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/6994946/TestProcessor.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2010, 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.util.*;
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+import static javax.tools.Diagnostic.Kind.*;
+
+public class TestProcessor extends JavacTestingAbstractProcessor {
+   private int round = 0;
+
+   public boolean process(Set<? extends TypeElement> annotations,
+                  RoundEnvironment roundEnv) {
+        if (++round == 1)
+            messager.printMessage(ERROR, "Deliberate Error");
+        return false;
+   }
+}
+
--- a/langtools/test/tools/javac/processing/model/element/TestAnonClassNames.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/test/tools/javac/processing/model/element/TestAnonClassNames.java	Wed Jul 05 17:26:57 2017 +0200
@@ -78,7 +78,7 @@
         @Nesting(LOCAL)
         class LocalClass{};
 
-        Object o =  new @Nesting(ANONYMOUS) Object() { // An anonymous annotated class
+        Object o =  new /*@Nesting(ANONYMOUS)*/ Object() { // An anonymous annotated class
                 public String toString() {
                     return "I have no name!";
                 }
@@ -95,9 +95,10 @@
 
         for(Class<?> clazz : classes) {
             String name = clazz.getName();
+            Nesting anno = clazz.getAnnotation(Nesting.class);
             System.out.format("%s is %s%n",
                               clazz.getName(),
-                              clazz.getAnnotation(Nesting.class).value());
+                              anno == null ? "(unset/ANONYMOUS)" : anno.value());
             testClassName(name);
         }
     }
@@ -161,8 +162,8 @@
                                   typeElt.getQualifiedName().toString(),
                                   typeElt.getKind().toString(),
                                   nestingKind.toString());
-
-                if (typeElt.getAnnotation(Nesting.class).value() != nestingKind) {
+                Nesting anno = typeElt.getAnnotation(Nesting.class);
+                if ((anno == null ? NestingKind.ANONYMOUS : anno.value()) != nestingKind) {
                     throw new RuntimeException("Mismatch of expected and reported nesting kind.");
                 }
             }
--- a/langtools/test/tools/javac/tree/TreePosTest.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/test/tools/javac/tree/TreePosTest.java	Wed Jul 05 17:26:57 2017 +0200
@@ -357,7 +357,9 @@
                     check("encl.start <= start", encl, self, encl.start <= self.start);
                     check("start <= pos", encl, self, self.start <= self.pos);
                     if (!(self.tag == JCTree.TYPEARRAY
-                            && (encl.tag == JCTree.VARDEF || encl.tag == JCTree.TYPEARRAY))) {
+                            && (encl.tag == JCTree.VARDEF ||
+                                encl.tag == JCTree.METHODDEF ||
+                                encl.tag == JCTree.TYPEARRAY))) {
                         check("encl.pos <= start || end <= encl.pos",
                                 encl, self, encl.pos <= self.start || self.end <= encl.pos);
                     }
--- a/langtools/test/tools/javac/treeannotests/AnnoTreeTests.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2010, 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
- * @build DA TA Test TestProcessor
- * @compile -proc:only -processor TestProcessor AnnoTreeTests.java
- */
-
-@Test(6)
-class AnnoTreeTests {
-    // primitive types
-    @DA("int") int i1;
-    int i2 = (@TA("int") int) 0;
-
-    // simple array types
-    @DA("int[]") int[] a1;
-    int @TA("int") [] a2;
-    int[] a3 = (@TA("int[]") int[]) a1;
-    int[] a4 = (int @TA("int") []) a1;
-
-    // multi-dimensional array types
-    // (still to come)
-}
--- a/langtools/test/tools/javac/typeAnnotations/6967002/T6967002.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2010, 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 6967002
- * @summary JDK7 b99 javac compilation error (java.lang.AssertionError)
- * @author Maurizio Cimadamore
- * @compile/fail/ref=T6967002.out -XDrawDiagnostics T6967002.java
- */
-class Test {
-   private static void m(byte[] octets) {
-      return m(octets..., ?);
-   }
-}
--- a/langtools/test/tools/javac/typeAnnotations/6967002/T6967002.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-T6967002.java:33:22: compiler.err.expected: ')'
-T6967002.java:33:25: compiler.err.illegal.start.of.expr
-T6967002.java:33:28: compiler.err.illegal.start.of.expr
-T6967002.java:33:29: compiler.err.illegal.start.of.expr
-T6967002.java:33:27: compiler.err.not.stmt
-T6967002.java:33:30: compiler.err.expected: ';'
-T6967002.java:35:2: compiler.err.premature.eof
-7 errors
--- a/langtools/test/tools/javac/typeAnnotations/InnerClass.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2009, 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 6843077
- * @summary compiler crashes when visiting inner classes
- * @author Mahmood Ali
- * @compile -source 1.7 InnerClass.java
- */
-
-class InnerClass {
-
-    InnerClass() {}
-    InnerClass(Object o) {}
-
-    private void a() {
-        new Object() {
-            public <R> void method() { }
-        };
-    }
-
-    Object f1 = new InnerClass() {
-            <R> void method() { }
-        };
-
-    Object f2 = new InnerClass() {
-            <@A R> void method() { }
-        };
-
-    Object f3 = new InnerClass(null) {
-            <R> void method() { }
-        };
-
-    Object f4 = new InnerClass(null) {
-            <@A R> void method() { }
-        };
-    @interface A { }
-}
--- a/langtools/test/tools/javac/typeAnnotations/MultipleTargets.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary check that type annotations may appear on void method if it is a
- *          method annotation too.
- * @author Mahmood Ali
- * @compile -source 1.7 MultipleTargets.java
- */
-
-import java.lang.annotation.Target;
-import java.lang.annotation.ElementType;
-
-class TypeUseTarget<K extends @A Object> {
-  @A void voidMethod() { }
-}
-
-@Target({ElementType.TYPE_USE, ElementType.METHOD})
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/TypeParameterTarget.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary check that type annotations may appear on all type parameter
- * @author Mahmood Ali
- * @compile -source 1.7 TypeParameterTarget.java
- */
-
-import java.lang.annotation.Target;
-import java.lang.annotation.ElementType;
-
-class TypeUseTarget<@A K extends Object> {
-  String[] field;
-
-  <@A K, @A V> String genericMethod(K k) { return null; }
-}
-
-interface MyInterface { }
-
-@interface MyAnnotation { }
-
-@Target(ElementType.TYPE_PARAMETER)
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/TypeUseTarget.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary check that type annotations may appear on all type declarations
- * @author Mahmood Ali
- * @compile -source 1.7 TypeUseTarget.java
- */
-
-import java.lang.annotation.Target;
-import java.lang.annotation.ElementType;
-
-@A
-class TypeUseTarget<K extends @A Object> {
-  @A String @A [] field;
-
-  @A String test(@A String param, @A String @A ... vararg) @A {
-    @A Object o = new @A String @A [3];
-    TypeUseTarget<@A String> target;
-    return (@A String) null;
-  }
-
-  <K> @A String genericMethod(K k) { return null; }
-}
-
-@A
-interface MyInterface { }
-
-@A
-@interface MyAnnotation { }
-
-@Target(ElementType.TYPE_USE)
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/attribution/Scopes.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary test scopes of attribution
- * @author Mahmood Ali
- * @compile -source 1.7 Scopes.java
- */
-class Scopes {
-
-  void test() @A(VALUE) { }
-  void test1() @A(value=VALUE) { }
-
-  private static final int VALUE = 1;
-  @interface A { int value(); }
-}
--- a/langtools/test/tools/javac/typeAnnotations/classfile/DeadCode.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,181 +0,0 @@
-/*
- * Copyright (c) 2009, 2010, 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.io.*;
-import java.net.URL;
-import java.util.List;
-
-import com.sun.tools.classfile.*;
-
-/*
- * @test
- * @bug 6917130
- * @summary test that optimized away annotations are not emited to classfile
- */
-
-public class DeadCode {
-    public static void main(String[] args) throws Exception {
-        new DeadCode().run();
-    }
-
-    public void run() throws Exception {
-        ClassFile cf = getClassFile("DeadCode$Test.class");
-        test(cf);
-        for (Field f : cf.fields) {
-            test(cf, f);
-        }
-        for (Method m: cf.methods) {
-            test(cf, m);
-        }
-
-        countAnnotations();
-
-        if (errors > 0)
-            throw new Exception(errors + " errors found");
-        System.out.println("PASSED");
-    }
-
-    ClassFile getClassFile(String name) throws IOException, ConstantPoolException {
-        URL url = getClass().getResource(name);
-        InputStream in = url.openStream();
-        try {
-            return ClassFile.read(in);
-        } finally {
-            in.close();
-        }
-    }
-
-    /************ Helper annotations counting methods ******************/
-    void test(ClassFile cf) {
-        test(cf, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    void test(ClassFile cf, Method m) {
-        test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    void test(ClassFile cf, Field m) {
-        test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, String name, boolean visible) {
-        int index = cf.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = cf.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-        }
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, Method m, String name, boolean visible) {
-        int index = m.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = m.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-        }
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, Field m, String name, boolean visible) {
-        int index = m.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = m.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-        }
-    }
-
-    void countAnnotations() {
-        int expected_all = expected_visibles + expected_invisibles;
-
-        if (expected_all != all) {
-            errors++;
-            System.err.println("expected " + expected_all
-                    + " annotations but found " + all);
-        }
-
-        if (expected_visibles != visibles) {
-            errors++;
-            System.err.println("expected " + expected_visibles
-                    + " visibles annotations but found " + visibles);
-        }
-
-        if (expected_invisibles != invisibles) {
-            errors++;
-            System.err.println("expected " + expected_invisibles
-                    + " invisibles annotations but found " + invisibles);
-        }
-
-    }
-
-    int errors;
-    int all;
-    int visibles;
-    int invisibles;
-
-    /*********************** Test class *************************/
-    static int expected_invisibles = 1;
-    static int expected_visibles = 0;
-    static class Test {
-        @interface A {}
-
-        void test() {
-            List<? extends @A Object> o = null;
-            o.toString();
-
-            @A String m;
-            if (false) {
-                @A String a;
-                @A String b = "m";
-                b.toString();
-                List<? extends @A Object> c = null;
-                c.toString();
-            }
-        }
-    }
-
-}
--- a/langtools/test/tools/javac/typeAnnotations/failures/AnnotationVersion.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary test that only java 7 allows type annotations
- * @author Mahmood Ali
- * @compile/fail/ref=AnnotationVersion.out -XDrawDiagnostics -source 1.6 AnnotationVersion.java
- */
-class AnnotationVersion {
-  public void method() @A { }
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/AnnotationVersion.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-AnnotationVersion.java:9:25: compiler.err.type.annotations.not.supported.in.source: 1.6
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/IncompleteArray.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary test incomplete array declaration
- * @author Mahmood Ali
- * @compile/fail/ref=IncompleteArray.out -XDrawDiagnostics -source 1.7 IncompleteArray.java
- */
-class IncompleteArray {
-  int @A [] @A var;
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/IncompleteArray.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-IncompleteArray.java:9:13: compiler.err.illegal.start.of.type
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/IncompleteVararg.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary test incomplete vararg declaration
- * @author Mahmood Ali
- * @compile/fail/ref=IncompleteVararg.out -XDrawDiagnostics -source 1.7 IncompleteVararg.java
- */
-class IncompleteArray {
-  // the last variable may be vararg
-  void method(int @A test) { }
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/IncompleteVararg.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-IncompleteVararg.java:10:19: compiler.err.illegal.start.of.type
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/IndexArray.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary test indexing of an array
- * @author Mahmood Ali
- * @compile/fail/ref=IndexArray.out -XDrawDiagnostics -source 1.7 IndexArray.java
- */
-class IndexArray {
-  int[] var;
-  int a = var @A [1];
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/IndexArray.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-IndexArray.java:10:15: compiler.err.illegal.start.of.expr
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/LintCast.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-import java.util.List;
-
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary test that compiler doesn't warn about annotated redundant casts
- * @author Mahmood Ali
- * @compile/ref=LintCast.out -Xlint:cast -XDrawDiagnostics -source 1.7 LintCast.java
- */
-class LintCast {
-    void unparameterized() {
-        String s = "m";
-        String s1 = (String)s;
-        String s2 = (@A String)s;
-    }
-
-    void parameterized() {
-        List<String> l = null;
-        List<String> l1 = (List<String>)l;
-        List<String> l2 = (List<@A String>)l;
-    }
-
-    void array() {
-        int @A [] a = null;
-        int[] a1 = (int[])a;
-        int[] a2 = (int @A [])a;
-    }
-
-    void sameAnnotations() {
-        @A String annotated = null;
-        String unannotated = null;
-
-        // compiler ignore annotated casts even if redundant
-        @A String anno1 = (@A String)annotated;
-
-        // warn if redundant without an annotation
-        String anno2 = (String)annotated;
-        String unanno2 = (String)unannotated;
-    }
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/LintCast.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-LintCast.java:13:21: compiler.warn.redundant.cast: java.lang.String
-LintCast.java:19:27: compiler.warn.redundant.cast: java.util.List<java.lang.String>
-LintCast.java:25:20: compiler.warn.redundant.cast: int[]
-LintCast.java:37:24: compiler.warn.redundant.cast: java.lang.String
-LintCast.java:38:26: compiler.warn.redundant.cast: java.lang.String
-5 warnings
--- a/langtools/test/tools/javac/typeAnnotations/failures/OldArray.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 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 6843077
- * @summary test old array syntax
- * @author Mahmood Ali
- * @compile/fail -XDrawDiagnostics -source 1.7 OldArray.java
- */
-class OldArray {
-  String [@A]  s() { return null; }
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/Scopes.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check that A is accessible in the class type parameters
- * @author Mahmood Ali
- * @compile/fail/ref=Scopes.out -XDrawDiagnostics -source 1.7 Scopes.java
- */
-class Scopes<T extends @UniqueInner Object> {
-  @interface UniqueInner { };
-}
--- a/langtools/test/tools/javac/typeAnnotations/failures/Scopes.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-Scopes.java:8:25: compiler.err.cant.resolve: kindname.class, UniqueInner, , 
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/StaticFields.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary static field access isn't a valid location
- * @author Mahmood Ali
- * @compile/fail/ref=StaticFields.out -XDrawDiagnostics -source 1.7 StaticFields.java
- */
-class C {
-  int f;
-  int a = @A C.f;
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/StaticFields.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-StaticFields.java:10:17: compiler.err.illegal.start.of.expr
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/StaticMethods.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary static methods don't have receivers
- * @author Mahmood Ali
- * @compile/fail/ref=StaticMethods.out -XDrawDiagnostics -source 1.7 StaticMethods.java
- */
-class StaticMethods {
-  static void main() @A { }
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/StaticMethods.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-StaticMethods.java:9:22: compiler.err.annotation.type.not.applicable
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/VoidGenericMethod.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary test type annotation on void generic methods
- * @author Mahmood Ali
- * @compile/fail -source 1.7 VoidGenericMethod.java
- */
-class VoidGenericMethod {
-  public <T> @A void method() { }
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/arrayclass/DuplicateAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077 6919944
- * @summary check for duplicate annotation values
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics -source 1.7 DuplicateAnnotationValue.java
- */
-class DuplicateAnnotationValue {
-  void test() {
-    Object a = String @A(value = 2, value = 1) [].class;
-  }
-}
-
-@interface A { int value(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/arrayclass/DuplicateAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateAnnotationValue.java:10:37: compiler.err.duplicate.annotation.member.value: value, A
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/arrayclass/DuplicateTypeAnnotation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for duplicate annotations
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics -source 1.7 DuplicateTypeAnnotation.java
- */
-
-class DuplicateTypeAnnotation {
-  void test() {
-    Object a = String @A @A [].class;
-  }
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/arrayclass/DuplicateTypeAnnotation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateTypeAnnotation.java:11:26: compiler.err.duplicate.annotation
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/arrayclass/InvalidLocation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for invalid annotatins given the target
- * @author Mahmood Ali
- * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics -source 1.7 InvalidLocation.java
- */
-
-class InvalidLocation {
-  void test() {
-    Object a = String @A [].class;
-  }
-}
-
-@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE)
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/arrayclass/InvalidLocation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-InvalidLocation.java:11:23: compiler.err.annotation.type.not.applicable
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/arrayclass/MissingAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for missing annotation value
- * @author Mahmood Ali
- * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics -source 1.7 MissingAnnotationValue.java
- */
-class MissingAnnotationValue {
-  void test() {
-    Object a = String @A [].class;
-  }
-}
-
-@interface A { int field(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/arrayclass/MissingAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-MissingAnnotationValue.java:10:23: compiler.err.annotation.missing.default.value: A, field
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077 6919944
- * @summary check for duplicate annotation values
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics -source 1.7 DuplicateAnnotationValue.java
- */
-class DuplicateAnnotationValue {
-  void test() {
-    String @A(value = 2, value = 1) [] s;
-  }
-}
-
-@interface A { int value(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateAnnotationValue.java:10:26: compiler.err.duplicate.annotation.member.value: value, A
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/arrays/DuplicateTypeAnnotation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for duplicate annotations
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics -source 1.7 DuplicateTypeAnnotation.java
- */
-
-class DuplicateTypeAnnotation {
-  void test() {
-    String @A @A [] s;
-  }
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/arrays/DuplicateTypeAnnotation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateTypeAnnotation.java:11:15: compiler.err.duplicate.annotation
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/arrays/InvalidLocation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for invalid annotatins given the target
- * @author Mahmood Ali
- * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics -source 1.7 InvalidLocation.java
- */
-
-class InvalidLocation {
-  void test() {
-    String @A [] s;
-  }
-}
-
-@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE)
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/arrays/InvalidLocation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-InvalidLocation.java:11:12: compiler.err.annotation.type.not.applicable
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/arrays/MissingAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for missing annotation value
- * @author Mahmood Ali
- * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics -source 1.7 MissingAnnotationValue.java
- */
-class MissingAnnotationValue {
-  void test() {
-    String @A [] s;
-  }
-}
-
-@interface A { int field(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/arrays/MissingAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-MissingAnnotationValue.java:10:12: compiler.err.annotation.missing.default.value: A, field
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077 6919944
- * @summary check for duplicate annotation values for type parameter
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics -source 1.7 DuplicateAnnotationValue.java
- */
-class DuplicateAnnotationValue {
-  void method() {
-    class Inner<@A(value = 2, value = 1) K> {}
-  }
-}
-
-@interface A { int value(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateAnnotationValue.java:10:31: compiler.err.duplicate.annotation.member.value: value, A
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/innertypeparams/DuplicateTypeAnnotation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for duplicate annotations
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics -source 1.7 DuplicateTypeAnnotation.java
- */
-class DuplicateTypeAnno {
-  void innermethod() {
-    class Inner<@A @A K> { }
-  }
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/innertypeparams/DuplicateTypeAnnotation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateTypeAnnotation.java:10:20: compiler.err.duplicate.annotation
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/innertypeparams/InvalidLocation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for invalid annotatins given the target
- * @author Mahmood Ali
- * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics -source 1.7 InvalidLocation.java
- */
-class InvalidLocation {
-  void innermethod() {
-    class Inner<@A K> {}
-  }
-}
-
-@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE)
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/innertypeparams/InvalidLocation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-InvalidLocation.java:10:17: compiler.err.annotation.type.not.applicable
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/innertypeparams/MissingAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for missing annotation value
- * @author Mahmood Ali
- * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics -source 1.7 MissingAnnotationValue.java
- */
-class MissingAnnotationValue {
-  void innermethod() {
-    class Inner<@A K> { }
-  }
-}
-
-@interface A { int field(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/innertypeparams/MissingAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-MissingAnnotationValue.java:10:17: compiler.err.annotation.missing.default.value: A, field
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077 6919944
- * @summary check for duplicate annotation values
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics -source 1.7 DuplicateAnnotationValue.java
- */
-class DuplicateAnnotationValue {
-  void test() {
-    String[] a = new String @A(value = 2, value = 1) [5] ;
-  }
-}
-
-@interface A { int value(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateAnnotationValue.java:10:43: compiler.err.duplicate.annotation.member.value: value, A
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/newarray/DuplicateTypeAnnotation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for duplicate annotations
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics -source 1.7 DuplicateTypeAnnotation.java
- */
-
-class DuplicateTypeAnnotation {
-  void test() {
-    String[] a = new String @A @A [5] ;
-  }
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/newarray/DuplicateTypeAnnotation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateTypeAnnotation.java:11:32: compiler.err.duplicate.annotation
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/newarray/InvalidLocation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for invalid annotatins given the target
- * @author Mahmood Ali
- * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics -source 1.7 InvalidLocation.java
- */
-
-class InvalidLocation {
-  void test() {
-    String[] s = new String @A [5] ;
-  }
-}
-
-@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE)
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/newarray/InvalidLocation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-InvalidLocation.java:11:29: compiler.err.annotation.type.not.applicable
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/newarray/MissingAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for missing annotation value
- * @author Mahmood Ali
- * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics -source 1.7 MissingAnnotationValue.java
- */
-class MissingAnnotationValue {
-  void test() {
-    String[] a = new String @A [5];
-  }
-}
-
-@interface A { int field(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/newarray/MissingAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-MissingAnnotationValue.java:10:29: compiler.err.annotation.missing.default.value: A, field
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077 6919944
- * @summary check for duplicate annotation values for type parameter
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics -source 1.7 DuplicateAnnotationValue.java
- */
-class DuplicateAnnotationValue<K extends @A(value = 2, value = 1) Object> {
-}
-
-@interface A { int value(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateAnnotationValue.java:8:56: compiler.err.duplicate.annotation.member.value: value, A
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/parambounds/DuplicateTypeAnnotation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for duplicate annotations
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics -source 1.7 DuplicateTypeAnnotation.java
- */
-
-class DuplicateTypeAnno<K extends @A @A Object> {
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/parambounds/DuplicateTypeAnnotation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateTypeAnnotation.java:9:38: compiler.err.duplicate.annotation
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/parambounds/InvalidLocation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for invalid annotatins given the target
- * @author Mahmood Ali
- * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics -source 1.7 InvalidLocation.java
- */
-
-class InvalidLocation<K extends @A Object> {
-}
-
-@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE)
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/parambounds/InvalidLocation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-InvalidLocation.java:9:33: compiler.err.annotation.type.not.applicable
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/parambounds/MissingAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for missing annotation value
- * @author Mahmood Ali
- * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics -source 1.7 MissingAnnotationValue.java
- */
-class MissingAnnotationValue<K extends @A Object> {
-}
-
-@interface A { int field(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/parambounds/MissingAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-MissingAnnotationValue.java:8:40: compiler.err.annotation.missing.default.value: A, field
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077 6919944
- * @summary check for duplicate annotation values in receiver
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics -source 1.7 DuplicateAnnotationValue.java
- */
-class DuplicateAnnotationValue {
-  void test() @A(value = 2, value = 1) { }
-}
-
-@interface A { int value(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateAnnotationValue.java:9:29: compiler.err.duplicate.annotation.member.value: value, A
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/receiver/DuplicateTypeAnnotation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for duplicate annotations in receiver
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics -source 1.7 DuplicateTypeAnnotation.java
- */
-
-class DuplicateTypeAnnotation {
-  void test() @A @A { }
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/receiver/DuplicateTypeAnnotation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateTypeAnnotation.java:10:18: compiler.err.duplicate.annotation
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/receiver/InvalidLocation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for invalid annotatins given the target
- * @author Mahmood Ali
- * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics -source 1.7 InvalidLocation.java
- */
-
-class InvalidLocation {
-  void test() @A {
-  }
-}
-
-@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE)
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/receiver/InvalidLocation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-InvalidLocation.java:10:15: compiler.err.annotation.type.not.applicable
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/receiver/MissingAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for missing annotation value
- * @author Mahmood Ali
- * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics -source 1.7 MissingAnnotationValue.java
- */
-class MissingAnnotationValue {
-  void test() @A { }
-}
-
-@interface A { int field(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/receiver/MissingAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-MissingAnnotationValue.java:9:15: compiler.err.annotation.missing.default.value: A, field
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/rest/DuplicateAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for Duplicate annotation value
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics -source 1.7 DuplicateAnnotationValue.java
- */
-class DuplicateAnnotationValue {
-  void test() {
-    new @A String();
-  }
-}
-
-@interface A { int field(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/rest/DuplicateAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateAnnotationValue.java:10:9: compiler.err.annotation.missing.default.value: A, field
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/rest/DuplicateTypeAnnotation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for duplicate annotations
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics -source 1.7 DuplicateTypeAnnotation.java
- */
-
-class DuplicateTypeAnnotation {
-  void test() {
-    new @A @A String();
-  }
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/rest/DuplicateTypeAnnotation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateTypeAnnotation.java:11:12: compiler.err.duplicate.annotation
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/rest/InvalidLocation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for invalid annotatins given the target
- * @author Mahmood Ali
- * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics -source 1.7 InvalidLocation.java
- */
-
-class InvalidLocation {
-  void test() {
-    new @A String();
-  }
-}
-
-@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE)
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/rest/InvalidLocation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-InvalidLocation.java:11:9: compiler.err.annotation.type.not.applicable
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/rest/MissingAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for missing annotation value
- * @author Mahmood Ali
- * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics -source 1.7 MissingAnnotationValue.java
- */
-class MissingAnnotationValue {
-  void test() {
-    new @A String();
-  }
-}
-
-@interface A { int field(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/rest/MissingAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-MissingAnnotationValue.java:10:9: compiler.err.annotation.missing.default.value: A, field
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077 6919944
- * @summary check for duplicate annotation values for type parameter
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics -source 1.7 DuplicateAnnotationValue.java
- */
-class DuplicateAnnotationValue<K> {
-  DuplicateAnnotationValue<@A(value = 2, value = 1) String> l;
-}
-
-@interface A { int value(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateAnnotationValue.java:9:42: compiler.err.duplicate.annotation.member.value: value, A
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/typeArgs/DuplicateTypeAnnotation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for duplicate annotations
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics -source 1.7 DuplicateTypeAnnotation.java
- */
-
-class DuplicateTypeAnno<K> {
-  DuplicateTypeAnno<@A @A String> l;
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/typeArgs/DuplicateTypeAnnotation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateTypeAnnotation.java:10:24: compiler.err.duplicate.annotation
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/typeArgs/InvalidLocation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for invalid annotatins given the target
- * @author Mahmood Ali
- * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics -source 1.7 InvalidLocation.java
- */
-
-class InvalidLocation<K> {
-  InvalidLocation<@A String> l;
-}
-
-@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE)
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/typeArgs/InvalidLocation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-InvalidLocation.java:10:19: compiler.err.annotation.type.not.applicable
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/typeArgs/MissingAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for missing annotation value
- * @author Mahmood Ali
- * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics -source 1.7 MissingAnnotationValue.java
- */
-class MissingAnnotationValue<K> {
-  MissingAnnotationValue<@A String> l;
-}
-
-@interface A { int field(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/typeArgs/MissingAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-MissingAnnotationValue.java:9:26: compiler.err.annotation.missing.default.value: A, field
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077 6919944
- * @summary check for duplicate annotation values for type parameter
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics -source 1.7 DuplicateAnnotationValue.java
- */
-class DuplicateAnnotationValue<@A(value = 2, value = 1) K> {
-}
-
-@interface A { int value(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateAnnotationValue.java:8:46: compiler.err.duplicate.annotation.member.value: value, A
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/typeparams/DuplicateTypeAnnotation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for duplicate annotations
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics -source 1.7 DuplicateTypeAnnotation.java
- */
-
-class DuplicateTypeAnno<@A @A K> {
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/typeparams/DuplicateTypeAnnotation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateTypeAnnotation.java:9:28: compiler.err.duplicate.annotation
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/typeparams/InvalidLocation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for invalid annotatins given the target
- * @author Mahmood Ali
- * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics -source 1.7 InvalidLocation.java
- */
-
-class InvalidLocation<@A K> {
-}
-
-@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE)
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/typeparams/InvalidLocation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-InvalidLocation.java:9:23: compiler.err.annotation.type.not.applicable
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/typeparams/MissingAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for missing annotation value
- * @author Mahmood Ali
- * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics -source 1.7 MissingAnnotationValue.java
- */
-class MissingAnnotationValue<@A K> {
-}
-
-@interface A { int field(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/typeparams/MissingAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-MissingAnnotationValue.java:8:30: compiler.err.annotation.missing.default.value: A, field
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077 6919944
- * @summary check for duplicate annotation values for type parameter
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics -source 1.7 DuplicateAnnotationValue.java
- */
-class DuplicateAnnotationValue<K> {
-  DuplicateAnnotationValue<@A(value = 2, value = 1) ?> l;
-}
-
-@interface A { int value(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateAnnotationValue.java:9:42: compiler.err.duplicate.annotation.member.value: value, A
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/wildcards/DuplicateTypeAnnotation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for duplicate annotations
- * @author Mahmood Ali
- * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics -source 1.7 DuplicateTypeAnnotation.java
- */
-
-class DuplicateTypeAnno<K> {
-  DuplicateTypeAnno<@A @A ?> l;
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/wildcards/DuplicateTypeAnnotation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-DuplicateTypeAnnotation.java:10:24: compiler.err.duplicate.annotation
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/wildcards/InvalidLocation.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for invalid annotatins given the target
- * @author Mahmood Ali
- * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics -source 1.7 InvalidLocation.java
- */
-
-class InvalidLocation<K> {
-  InvalidLocation<@A ?> l;
-}
-
-@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE)
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/wildcards/InvalidLocation.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-InvalidLocation.java:10:19: compiler.err.annotation.type.not.applicable
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/wildcards/MissingAnnotationValue.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary check for missing annotation value
- * @author Mahmood Ali
- * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics -source 1.7 MissingAnnotationValue.java
- */
-class MissingAnnotationValue<K> {
-  MissingAnnotationValue<@A ?> l;
-}
-
-@interface A { int field(); }
--- a/langtools/test/tools/javac/typeAnnotations/failures/common/wildcards/MissingAnnotationValue.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-MissingAnnotationValue.java:9:26: compiler.err.annotation.missing.default.value: A, field
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/target/Constructor.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary test invalid location of TypeUse
- * @author Mahmood Ali
- * @compile/fail/ref=Constructor.out -XDrawDiagnostics -source 1.7 Constructor.java
- */
-
-import java.lang.annotation.Target;
-import java.lang.annotation.ElementType;
-
-class Constructor {
-  @A Constructor() { }
-}
-
-@Target(ElementType.TYPE_USE)
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/target/Constructor.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-Constructor.java:13:3: compiler.err.annotation.type.not.applicable
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/target/IncompleteArray.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary test incomplete array declaration
- * @author Mahmood Ali
- * @compile/fail/ref=IncompleteArray.out -XDrawDiagnostics -source 1.7 IncompleteArray.java
- */
-class IncompleteArray {
-  int @A [] @A var;
-}
-
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/target/IncompleteArray.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-IncompleteArray.java:9:13: compiler.err.illegal.start.of.type
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/target/NotTypeParameter.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary test invalid location of TypeUse
- * @author Mahmood Ali
- * @compile/fail/ref=NotTypeParameter.out -XDrawDiagnostics -source 1.7 NotTypeParameter.java
- */
-
-import java.lang.annotation.Target;
-import java.lang.annotation.ElementType;
-
-class VoidMethod<@A K> {
-  @A void test() { }
-}
-
-@Target(ElementType.TYPE_USE)
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/target/NotTypeParameter.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-NotTypeParameter.java:13:3: compiler.err.annotation.type.not.applicable
-NotTypeParameter.java:12:18: compiler.err.annotation.type.not.applicable
-2 errors
--- a/langtools/test/tools/javac/typeAnnotations/failures/target/NotTypeUse.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary test invalid location of TypeUse
- * @author Mahmood Ali
- * @compile/fail/ref=NotTypeUse.out -XDrawDiagnostics -source 1.7 NotTypeUse.java
- */
-
-import java.lang.annotation.Target;
-import java.lang.annotation.ElementType;
-
-class VoidMethod {
-  @A void test() { }
-}
-
-@Target(ElementType.TYPE)
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/target/NotTypeUse.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-NotTypeUse.java:13:3: compiler.err.annotation.type.not.applicable
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/failures/target/VoidMethod.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6843077
- * @summary test invalid location of TypeUse
- * @author Mahmood Ali
- * @compile/fail/ref=VoidMethod.out -XDrawDiagnostics -source 1.7 VoidMethod.java
- */
-
-import java.lang.annotation.Target;
-import java.lang.annotation.ElementType;
-
-class VoidMethod {
-  @A void test() { }
-}
-
-@Target(ElementType.TYPE_USE)
-@interface A { }
--- a/langtools/test/tools/javac/typeAnnotations/failures/target/VoidMethod.out	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-VoidMethod.java:13:3: compiler.err.annotation.type.not.applicable
-1 error
--- a/langtools/test/tools/javac/typeAnnotations/newlocations/BasicTest.java	Wed Jul 05 17:26:05 2017 +0200
+++ b/langtools/test/tools/javac/typeAnnotations/newlocations/BasicTest.java	Wed Jul 05 17:26:57 2017 +0200
@@ -27,7 +27,7 @@
  * @bug 6843077
  * @summary random tests for new locations
  * @author Matt Papi
- * @compile -source 1.7 BasicTest.java
+ * @compile/fail/ref=BasicTest.out -XDrawDiagnostics BasicTest.java
  */
 
 import java.util.*;
@@ -38,6 +38,8 @@
 @interface C {}
 @interface D {}
 
+//308: Test inverted to verify that type annotations can not be parsed yet.
+
 /**
  * Tests basic JSR 308 parser functionality. We don't really care about what
  * the parse tree looks like, just that these annotations can be parsed.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/typeAnnotations/newlocations/BasicTest.out	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,66 @@
+BasicTest.java:47:27: compiler.err.illegal.start.of.type
+BasicTest.java:47:28: compiler.err.expected: '{'
+BasicTest.java:47:36: compiler.err.expected: token.identifier
+BasicTest.java:47:38: compiler.err.illegal.start.of.type
+BasicTest.java:47:45: compiler.err.expected: token.identifier
+BasicTest.java:47:47: compiler.err.expected: ';'
+BasicTest.java:47:62: compiler.err.expected: token.identifier
+BasicTest.java:47:84: compiler.err.expected: token.identifier
+BasicTest.java:52:22: compiler.err.illegal.start.of.expr
+BasicTest.java:52:31: compiler.err.expected: ';'
+BasicTest.java:52:37: compiler.err.expected: token.identifier
+BasicTest.java:53:21: compiler.err.illegal.start.of.expr
+BasicTest.java:53:23: compiler.err.expected: ';'
+BasicTest.java:53:30: compiler.err.expected: token.identifier
+BasicTest.java:53:32: compiler.err.illegal.start.of.type
+BasicTest.java:53:37: compiler.err.expected: token.identifier
+BasicTest.java:53:38: compiler.err.expected: ';'
+BasicTest.java:56:17: compiler.err.expected: token.identifier
+BasicTest.java:56:23: compiler.err.expected: token.identifier
+BasicTest.java:56:24: compiler.err.expected2: '(', '['
+BasicTest.java:56:25: compiler.err.expected: ';'
+BasicTest.java:56:27: compiler.err.invalid.meth.decl.ret.type.req
+BasicTest.java:56:34: compiler.err.illegal.start.of.type
+BasicTest.java:58:34: compiler.err.illegal.start.of.type
+BasicTest.java:61:16: compiler.err.illegal.start.of.type
+BasicTest.java:61:18: compiler.err.expected: ';'
+BasicTest.java:61:24: compiler.err.illegal.start.of.type
+BasicTest.java:61:26: compiler.err.expected: ';'
+BasicTest.java:61:33: compiler.err.expected: token.identifier
+BasicTest.java:61:34: compiler.err.illegal.start.of.type
+BasicTest.java:61:35: compiler.err.expected: token.identifier
+BasicTest.java:61:37: compiler.err.expected: ';'
+BasicTest.java:61:45: compiler.err.expected: token.identifier
+BasicTest.java:61:50: compiler.err.expected: token.identifier
+BasicTest.java:62:16: compiler.err.expected: token.identifier
+BasicTest.java:62:17: compiler.err.expected2: '(', '['
+BasicTest.java:62:18: compiler.err.expected: ';'
+BasicTest.java:62:28: compiler.err.illegal.start.of.type
+BasicTest.java:62:30: compiler.err.expected: ';'
+BasicTest.java:62:36: compiler.err.illegal.start.of.type
+BasicTest.java:62:38: compiler.err.expected: ';'
+BasicTest.java:62:45: compiler.err.expected: token.identifier
+BasicTest.java:62:46: compiler.err.illegal.start.of.type
+BasicTest.java:62:47: compiler.err.expected: token.identifier
+BasicTest.java:62:49: compiler.err.expected: ';'
+BasicTest.java:62:57: compiler.err.expected: token.identifier
+BasicTest.java:62:58: compiler.err.illegal.start.of.type
+BasicTest.java:62:59: compiler.err.expected: token.identifier
+BasicTest.java:64:25: compiler.err.illegal.start.of.type
+BasicTest.java:64:27: compiler.err.expected: ';'
+BasicTest.java:64:34: compiler.err.expected: token.identifier
+BasicTest.java:64:38: compiler.err.expected: token.identifier
+BasicTest.java:64:41: compiler.err.illegal.start.of.expr
+BasicTest.java:64:50: compiler.err.expected: ';'
+BasicTest.java:64:56: compiler.err.expected: token.identifier
+BasicTest.java:69:17: compiler.err.expected: ';'
+BasicTest.java:69:24: compiler.err.illegal.start.of.type
+BasicTest.java:69:30: compiler.err.expected: ';'
+BasicTest.java:69:59: compiler.err.expected: token.identifier
+BasicTest.java:69:74: compiler.err.expected: ';'
+BasicTest.java:74:22: compiler.err.expected: token.identifier
+BasicTest.java:74:24: compiler.err.expected: ';'
+BasicTest.java:74:25: compiler.err.illegal.start.of.type
+BasicTest.java:74:33: compiler.err.expected: ';'
+BasicTest.java:77:2: compiler.err.premature.eof
+65 errors
--- a/langtools/test/tools/javac/typeAnnotations/newlocations/ClassExtends.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary new type annotation location: class extends/implements
- * @author Mahmood Ali
- * @compile -source 1.7 ClassExtends.java
- */
-abstract class MyClass extends @A ParameterizedClass<@B String>
-  implements @B CharSequence, @A ParameterizedInterface<@B String> { }
-
-interface MyInterface extends @A ParameterizedInterface<@A String>,
-                              @B CharSequence { }
-
-class ParameterizedClass<K> {}
-interface ParameterizedInterface<K> {}
-@interface A {}
-@interface B {}
--- a/langtools/test/tools/javac/typeAnnotations/newlocations/ClassLiterals.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary new type annotation location: class literals
- * @author Mahmood Ali
- * @compile -source 1.7 ClassLiterals.java
- */
-
-class ClassLiterals {
-
-  public static void main(String[] args) {
-    if (String.class != @A String.class) throw new Error();
-    if (@A int.class != int.class) throw new Error();
-    if (@A int.class != Integer.TYPE) throw new Error();
-    if (@A int @B(0) [].class != int[].class) throw new Error();
-
-    if (String[].class != @A String[].class) throw new Error();
-    if (String[].class != String @A [].class) throw new Error();
-    if (@A int[].class != int[].class) throw new Error();
-    if (@A int @B(0) [].class != int[].class) throw new Error();
-  }
-}
-
-@interface A {}
-@interface B { int value(); }
--- a/langtools/test/tools/javac/typeAnnotations/newlocations/ClassParameters.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary new type annotation location: class type parameter bounds
- * @author Mahmood Ali
- * @compile -source 1.7 ClassParameters.java
- */
-class Unannotated<K> { }
-
-class ExtendsBound<K extends @A String> { }
-class ExtendsGeneric<K extends @A Unannotated<@B String>> { }
-class TwoBounds<K extends @A String, V extends @B String> { }
-
-class Complex1<K extends @A String&Runnable> { }
-class Complex2<K extends String & @B Runnable> { }
-class ComplexBoth<K extends @A String & @A Runnable> { }
-
-class Outer {
-  void inner() {
-    class Unannotated<K> { }
-
-    class ExtendsBound<K extends @A String> { }
-    class ExtendsGeneric<K extends @A Unannotated<@B String>> { }
-    class TwoBounds<K extends @A String, V extends @B String> { }
-
-    class Complex1<K extends @A String&Runnable> { }
-    class Complex2<K extends String & @B Runnable> { }
-    class ComplexBoth<K extends @A String & @A Runnable> { }
-  }
-}
-
-@interface A { }
-@interface B { }
--- a/langtools/test/tools/javac/typeAnnotations/newlocations/ConstructorTypeArgs.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary new type annotation location: constructor type args
- * @author Mahmood Ali
- * @compile -source 1.7 ConstructorTypeArgs.java
- */
-
-class ConstructorTypeArgs {
-  void oneArg() {
-    new @A MyList<@A String>();
-    new MyList<@A MyList<@B(0) String>>();
-  }
-
-  void twoArg() {
-    new MyMap<String, String>();
-    new MyMap<@A String, @B(0) MyList<@A String>>();
-  }
-
-  void withArraysIn() {
-    new MyList<String[]>();
-    new MyList<@A String @B(0) [] @A []>();
-
-    new MyMap<@A String[], @B(0) MyList<@A String> @A []>();
-  }
-}
-
-class MyList<E> { }
-class MyMap<K, V> { }
-
-@interface A { }
-@interface B { int value(); }
--- a/langtools/test/tools/javac/typeAnnotations/newlocations/Expressions.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary new type annotation location: expressions
- * @author Mahmood Ali
- * @compile -source 1.7 Expressions.java
- */
-class Expressions {
-  void instanceOf() {
-    Object o = null;
-    boolean a = o instanceof @A String;
-    boolean b = o instanceof @B(0) String;
-  }
-
-  void instanceOfArray() {
-    Object o = null;
-    boolean a1 = o instanceof @A String [];
-    boolean a2 = o instanceof @B(0) String [];
-
-    boolean b1 = o instanceof String @A [];
-    boolean b2 = o instanceof String @B(0) [];
-  }
-
-  void objectCreation() {
-    new @A String();
-    new @B(0) String();
-  }
-
-  void objectCreationArray() {
-    Object a1 = new @A String [] [] { };
-    Object a2 = new @A String [1] [];
-    Object a3 = new @A String [1] [2];
-
-    Object b1 = new @A String @B(0) [] [] { };
-    Object b2 = new @A String @B(0) [1] [];
-    Object b3 = new @A String @B(0) [1] [2];
-
-    Object c1 = new @A String []  @B(0) [] { };
-    Object c2 = new @A String [1] @B(0) [];
-    Object c3 = new @A String [1] @B(0) [2];
-
-    Object d1 = new @A String @B(0) []  @B(0) [] { };
-    Object d2 = new @A String @B(0) [1] @B(0) [];
-    Object d3 = new @A String @B(0) [1] @B(0) [2];
-
-    Object rand = new @A String @B(value = 0) [1] @B(value = 0) [2];
-
-  }
-}
-
-@interface A { }
-@interface B { int value(); }
--- a/langtools/test/tools/javac/typeAnnotations/newlocations/Fields.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary new type annotation location: field type array/generics
- * @author Mahmood Ali
- * @compile -source 1.7 Fields.java
- */
-
-class DefaultScope {
-  Parameterized<String, String> unannotated;
-  Parameterized<@A String, String> firstTypeArg;
-  Parameterized<String, @A String> secondTypeArg;
-  Parameterized<@A String, @B String> bothTypeArgs;
-
-  Parameterized<@A Parameterized<@A String, @B String>, @B String>
-    nestedParameterized;
-
-  @A String [] array1;
-  @A String @B [] array1Deep;
-  @A String [] [] array2;
-  @A String @A [] @B [] array2Deep;
-  String @A [] [] array2First;
-  String [] @B [] array2Second;
-}
-
-class ModifiedScoped {
-  public final Parameterized<String, String> unannotated = null;
-  public final Parameterized<@A String, String> firstTypeArg = null;
-  public final Parameterized<String, @A String> secondTypeArg = null;
-  public final Parameterized<@A String, @B String> bothTypeArgs = null;
-
-  public final Parameterized<@A Parameterized<@A String, @B String>, @B String>
-    nestedParameterized = null;
-
-  public final @A String [] array1 = null;
-  public final @A String @B [] array1Deep = null;
-  public final @A String [] [] array2 = null;
-  public final @A String @A [] @B [] array2Deep = null;
-  public final String @A [] [] array2First = null;
-  public final String [] @B [] array2Second = null;
-}
-
-class Parameterized<K, V> { }
-
-@interface A { }
-@interface B { }
--- a/langtools/test/tools/javac/typeAnnotations/newlocations/LocalVariables.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary new type annotation location: local variables array/generics
- * @author Mahmood Ali
- * @compile -source 1.7 LocalVariables.java
- */
-
-class DefaultScope {
-  void parameterized() {
-    Parameterized<String, String> unannotated;
-    Parameterized<@A String, String> firstTypeArg;
-    Parameterized<String, @A String> secondTypeArg;
-    Parameterized<@A String, @B String> bothTypeArgs;
-
-    Parameterized<@A Parameterized<@A String, @B String>, @B String>
-      nestedParameterized;
-  }
-
-  void arrays() {
-    @A String [] array1;
-    @A String @B [] array1Deep;
-    @A String [] [] array2;
-    @A String @A [] @B [] array2Deep;
-    String @A [] [] array2First;
-    String [] @B [] array2Second;
-  }
-}
-
-class ModifiedVars {
-  void parameterized() {
-    final Parameterized<String, String> unannotated = null;
-    final Parameterized<@A String, String> firstTypeArg = null;
-    final Parameterized<String, @A String> secondTypeArg = null;
-    final Parameterized<@A String, @B String> bothTypeArgs = null;
-
-    final Parameterized<@A Parameterized<@A String, @B String>, @B String>
-      nestedParameterized = null;
-  }
-
-  void arrays() {
-    final @A String [] array1 = null;
-    final @A String @B [] array1Deep = null;
-    final @A String [] [] array2 = null;
-    final @A String @A [] @B [] array2Deep = null;
-    final String @A [] [] array2First = null;
-    final String [] @B [] array2Second = null;
-  }
-}
-
-class Parameterized<K, V> { }
-
-@interface A { }
-@interface B { }
--- a/langtools/test/tools/javac/typeAnnotations/newlocations/MethodReturnType.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary new type annotation location: method return type array/generics
- * @author Mahmood Ali
- * @compile -source 1.7 MethodReturnType.java
- */
-
-class DefaultScope {
-  Parameterized<String, String> unannotated() { return null; }
-  Parameterized<@A String, String> firstTypeArg() { return null; }
-  Parameterized<String, @A String> secondTypeArg() { return null; }
-  Parameterized<@A String, @B String> bothTypeArgs() { return null; }
-
-  Parameterized<@A Parameterized<@A String, @B String>, @B String>
-    nestedParameterized() { return null; }
-
-  public <T> @A String method() { return null; }
-
-  @A String [] array1() { return null; }
-  @A String @B [] array1Deep() { return null; }
-  @A String [] [] array2() { return null; }
-  @A String @A [] @B [] array2Deep() { return null; }
-  String @A [] [] array2First() { return null; }
-  String [] @B [] array2Second() { return null; }
-}
-
-class ModifiedScoped {
-  public final Parameterized<String, String> unannotated() { return null; }
-  public final Parameterized<@A String, String> firstTypeArg() { return null; }
-  public final Parameterized<String, @A String> secondTypeArg() { return null; }
-  public final Parameterized<@A String, @B String> bothTypeArgs() { return null; }
-
-  public final Parameterized<@A Parameterized<@A String, @B String>, @B String>
-    nestedParameterized() { return null; }
-
-  public final @A String [] array1() { return null; }
-  public final @A String @B [] array1Deep() { return null; }
-  public final @A String [] [] array2() { return null; }
-  public final @A String @A [] @B [] array2Deep() { return null; }
-  public final String @A [] [] array2First() { return null; }
-  public final String [] @B [] array2Second() { return null; }
-}
-
-class Parameterized<K, V> { }
-
-@interface A { }
-@interface B { }
--- a/langtools/test/tools/javac/typeAnnotations/newlocations/MethodTypeArgs.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary new type annotation location: method type args
- * @author Mahmood Ali
- * @compile -source 1.7 MethodTypeArgs.java
- */
-
-class MethodTypeArgs {
-  void oneArg() {
-    this.<@A String>newList();
-    this.<@A MyList<@B(0) String>>newList();
-
-    MethodTypeArgs.<@A String>newList();
-    MethodTypeArgs.<@A MyList<@B(0) String>>newList();
-  }
-
-  void twoArg() {
-    this.<String, String>newMap();
-    this.<@A String, @B(0) MyList<@A String>>newMap();
-
-    MethodTypeArgs.<String, String>newMap();
-    MethodTypeArgs.<@A String, @B(0) MyList<@A String>>newMap();
-  }
-
-  void withArraysIn() {
-    this.<String[]>newList();
-    this.<@A String @B(0) [] @A []>newList();
-
-    this.<@A String[], @B(0) MyList<@A String> @A []>newMap();
-  }
-
-  static <E> void newList() { }
-  static <K, V> void newMap() { }
-}
-
-class MyList<E> { }
-@interface A { }
-@interface B { int value(); }
--- a/langtools/test/tools/javac/typeAnnotations/newlocations/MethodTypeParameters.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary new type annotation location: method type parameter bounds
- * @author Mahmood Ali
- * @compile -source 1.7 MethodTypeParameters.java
- */
-
-class UnscopedUnmodified {
-  <K extends @A String> void methodExtends() {}
-  <K extends @A Parameterized<@B String>> void nestedExtends() {}
-  <K extends @A String, V extends @A Parameterized<@B String>> void dual() {}
-  <K extends String, V extends Parameterized<@B String>> void dualOneAnno() {}
-}
-
-class PublicModifiedMethods {
-  public final <K extends @A String> void methodExtends() {}
-  public final <K extends @A Parameterized<@B String>> void nestedExtends() {}
-  public final <K extends @A String, V extends @A Parameterized<@B String>> void dual() {}
-  public final <K extends String, V extends Parameterized<@B String>> void dualOneAnno() {}
-}
-
-class Parameterized<K> { }
-@interface A { }
-@interface B { }
--- a/langtools/test/tools/javac/typeAnnotations/newlocations/Parameters.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary new type annotation location: parameter type array/generics
- * @author Mahmood Ali
- * @compile -source 1.7 Parameters.java
- */
-
-class Parameters {
-  void unannotated(Parameterized<String, String> a) {}
-  void firstTypeArg(Parameterized<@A String, String> a) {}
-  void secondTypeArg(Parameterized<String, @A String> a) {}
-  void bothTypeArgs(Parameterized<@A String, @B String> both) {}
-
-  void nestedParameterized(Parameterized<@A Parameterized<@A String, @B String>, @B String> a) {}
-
-  void array1(@A String [] a) {}
-  void array1Deep(@A String @B [] a) {}
-  void array2(@A String [] [] a) {}
-  void array2Deep(@A String @A [] @B [] a) {}
-  void array2First(String @A [] [] a) {}
-  void array2Second(String [] @B [] a) {}
-}
-
-class Parameterized<K, V> { }
-
-@interface A { }
-@interface B { }
--- a/langtools/test/tools/javac/typeAnnotations/newlocations/Receivers.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary new type annotation location: receivers
- * @author Mahmood Ali
- * @compile -source 1.7 Receivers.java
- */
-class DefaultUnmodified {
-  void plain() @A { }
-  <T> void generic() @A { }
-  void withException() @A throws Exception { }
-  String nonVoid() @A { return null; }
-  <T extends Runnable> void accept(T r) @A throws Exception { }
-}
-
-class PublicModified {
-  public final void plain() @A { }
-  public final <T> void generic() @A { }
-  public final void withException() @A throws Exception { }
-  public final String nonVoid() @A { return null; }
-  public final <T extends Runnable> void accept(T r) @A throws Exception { }
-}
-
-class WithValue {
-  void plain() @B("m") { }
-  <T> void generic() @B("m") { }
-  void withException() @B("m") throws Exception { }
-  String nonVoid() @B("m") { return null; }
-  <T extends Runnable> void accept(T r) @B("m") throws Exception { }
-}
-
-@interface A {}
-@interface B { String value(); }
--- a/langtools/test/tools/javac/typeAnnotations/newlocations/Throws.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary new type annotation location: throw clauses
- * @author Mahmood Ali
- * @compile -source 1.7 Throws.java
- */
-class DefaultUnmodified {
-  void oneException() throws @A Exception {}
-  void twoExceptions() throws @A RuntimeException, @A Exception {}
-}
-
-class PublicModified {
-  public final void oneException(String a) throws @A Exception {}
-  public final void twoExceptions(String a) throws @A RuntimeException, @A Exception {}
-}
-
-class WithValue {
-  void oneException() throws @B("m") Exception {}
-  void twoExceptions() throws @B(value="m") RuntimeException, @A Exception {}
-}
-
-@interface A {}
-@interface B { String value(); }
--- a/langtools/test/tools/javac/typeAnnotations/newlocations/TypeCasts.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary new type annotation location: type casts
- * @author Mahmood Ali
- * @compile -source 1.7 TypeCasts.java
- */
-class TypeCasts {
-  void methodA() {
-    String s = (@A String) null;
-    Object o = (@A Class<@A String>) null;
-  }
-
-  void methodB() {
-    String s = (@B("m") String) null;
-    Object o = (@B("m") Class<@B("m") String>) null;
-  }
-}
-
-@interface A { }
-@interface B { String value(); }
--- a/langtools/test/tools/javac/typeAnnotations/newlocations/TypeParameters.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary new type annotation location: class and method type parameters
- * @author Mahmood Ali
- * @compile -source 1.7 TypeParameters.java
- */
-
-class Unannotated<K> { }
-class OneAnnotated<@A K> { }
-class TwoAnnotated<@A K, @A V> { }
-class SecondAnnotated<K, @A V extends String> { }
-
-class TestMethods {
-  <K> void unannotated() { }
-  <@A K> void oneAnnotated() { }
-  <@A K, @B("m") V> void twoAnnotated() { }
-  <K, @A V extends @A String> void secondAnnotated() { }
-}
-
-class UnannotatedB<K> { }
-class OneAnnotatedB<@B("m") K> { }
-class TwoAnnotatedB<@B("m") K, @B("m") V> { }
-class SecondAnnotatedB<K, @B("m") V extends @B("m") String> { }
-
-@interface A { }
-@interface B { String value(); }
--- a/langtools/test/tools/javac/typeAnnotations/newlocations/Wildcards.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6843077
- * @summary new type annotation location: wildcard bound
- * @author Mahmood Ali
- * @compile -source 1.7 Wildcards.java
- */
-class BoundTest {
-  void wcExtends(MyList<? extends @A String> l) { }
-  void wcSuper(MyList<? super @A String> l) { }
-
-  MyList<? extends @A String> returnWcExtends() { return null; }
-  MyList<? super @A String> returnWcSuper() { return null; }
-  MyList<? extends @A MyList<? super @B("m") String>> complex() { return null; }
-}
-
-class BoundWithValue {
-  void wcExtends(MyList<? extends @B("m") String> l) { }
-  void wcSuper(MyList<? super @B(value="m") String> l) { }
-
-  MyList<? extends @B("m") String> returnWcExtends() { return null; }
-  MyList<? super @B(value="m") String> returnWcSuper() { return null; }
-  MyList<? extends @B("m") MyList<? super @B("m") String>> complex() { return null; }
-}
-
-class SelfTest {
-  void wcExtends(MyList<@A ?> l) { }
-  void wcSuper(MyList<@A ?> l) { }
-
-  MyList<@A ?> returnWcExtends() { return null; }
-  MyList<@A ?> returnWcSuper() { return null; }
-  MyList<@A ? extends @A MyList<@B("m") ?>> complex() { return null; }
-}
-
-class SelfWithValue {
-  void wcExtends(MyList<@B("m") ?> l) { }
-  void wcSuper(MyList<@B(value="m") ?> l) { }
-
-  MyList<@B("m") ?> returnWcExtends() { return null; }
-  MyList<@B(value="m") ?> returnWcSuper() { return null; }
-  MyList<@B("m") ? extends MyList<@B("m") ? super String>> complex() { return null; }
-}
-
-class MyList<K> { }
-
-@interface A { }
-@interface B { String value(); }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/T6551367.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2010, 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     6551367
+ * @summary javadoc throws ClassCastException when an link tag tries to reference constructor.
+ * @author  A. Sundararajan
+ * @run main T6551367 T6551367.java
+ */
+
+import com.sun.javadoc.*;
+import java.io.File;
+import static com.sun.tools.javadoc.Main.execute;
+
+public class T6551367 extends com.sun.tools.doclets.standard.Standard {
+    public T6551367() {}
+
+    /** Here, in the javadoc for this method, I try to link to
+     *  {@link #<init> a constructor}.
+     */
+    public static void main(String... args) {
+        File testSrc = new File(System.getProperty("test.src", "."));
+        File destDir = new File(System.getProperty("user.dir", "."));
+        for (String file : args) {
+            File source = new File(testSrc, file);
+            int rc = execute("javadoc", "T6551367",
+              T6551367.class.getClassLoader(),
+              new String[]{source.getPath(), "-d", destDir.getAbsolutePath()});
+            if (rc != 0)
+                throw new Error("unexpected exit from javadoc: " + rc);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javah/T6994608.java	Wed Jul 05 17:26:57 2017 +0200
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2010, 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 6994608
+ * @summary javah no longer accepts parameter files as input
+ */
+
+import java.io.*;
+import java.util.*;
+
+public class T6994608 {
+    public static void main(String... args) throws Exception {
+        new T6994608().run();
+    }
+
+    void run() throws Exception {
+        Locale prev = Locale.getDefault();
+        Locale.setDefault(Locale.ENGLISH);
+        try {
+            File f = writeFile(new File("classList"), "java.lang.Object");
+            test(Arrays.asList("@" + f.getPath()), 0, null);
+            test(Arrays.asList("@badfile"), 1, "Can't find file badfile");
+            if (errors > 0)
+                throw new Exception(errors + " errors occurred");
+        } finally {
+            Locale.setDefault(prev);
+        }
+    }
+
+    void test(List<String> args, int expectRC, String expectOut) {
+        System.err.println("Test: " + args
+                + " rc:" + expectRC
+                + ((expectOut != null) ? " out:" + expectOut : ""));
+
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        int rc = com.sun.tools.javah.Main.run(args.toArray(new String[args.size()]), pw);
+        pw.close();
+        String out = sw.toString();
+        if (!out.isEmpty())
+            System.err.println(out);
+
+        if (rc != expectRC)
+            error("Unexpected exit code: " + rc + "; expected: " + expectRC);
+        if (expectOut != null && !out.contains(expectOut))
+            error("Expected string not found: " + expectOut);
+
+        System.err.println();
+    }
+
+    File writeFile(File f, String s) throws IOException {
+        if (f.getParentFile() != null)
+            f.getParentFile().mkdirs();
+        try (FileWriter out = new FileWriter(f)) {
+            out.write(s);
+        }
+        return f;
+    }
+
+    void error(String msg) {
+        System.err.println(msg);
+        errors++;
+    }
+
+    int errors;
+}
+
--- a/langtools/test/tools/javap/typeAnnotations/ArrayClassLiterals.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,183 +0,0 @@
-/*
- * Copyright (c) 2009, 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.io.*;
-import com.sun.tools.classfile.*;
-
-/*
- * @test ArrayClassLiterals
- * @bug 6863814
- * @summary test that class literals array doesn't crash javap
- */
-
-public class ArrayClassLiterals {
-    public static void main(String[] args) throws Exception {
-        new ArrayClassLiterals().run();
-    }
-
-    public void run() throws Exception {
-        File javaFile = writeTestFile();
-        File classFile = compileTestFile(javaFile);
-
-        ClassFile cf = ClassFile.read(classFile);
-        test(cf);
-        for (Field f : cf.fields) {
-            test(cf, f);
-        }
-        for (Method m: cf.methods) {
-            test(cf, m);
-        }
-
-        countAnnotations();
-
-        if (errors > 0)
-            throw new Exception(errors + " errors found");
-        System.out.println("PASSED");
-    }
-
-    void test(ClassFile cf) {
-        test(cf, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    void test(ClassFile cf, Method m) {
-        test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    void test(ClassFile cf, Field m) {
-        test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, String name, boolean visible) {
-        int index = cf.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = cf.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-
-            for (ExtendedAnnotation anno : tAttr.annotations)
-                anno.position.toString();
-        }
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, Method m, String name, boolean visible) {
-        int index = m.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = m.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-
-            for (ExtendedAnnotation anno : tAttr.annotations)
-                anno.position.toString();
-        }
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, Field m, String name, boolean visible) {
-        int index = m.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = m.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-
-            for (ExtendedAnnotation anno : tAttr.annotations)
-                anno.position.toString();
-        }
-    }
-
-    File writeTestFile() throws IOException {
-      File f = new File("Testa.java");
-        PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f)));
-        out.println("import java.util.*;");
-        out.println("class Testa { ");
-        out.println("  @interface A { }");
-
-        out.println(" void test() {");
-        out.println("  Object a = @A String.class;");
-        out.println("  Object b = @A String @A [] @A [].class;");
-        out.println(" }");
-        out.println("}");
-
-        out.close();
-        return f;
-    }
-
-    File compileTestFile(File f) {
-      int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.7", "-g", f.getPath() });
-        if (rc != 0)
-            throw new Error("compilation failed. rc=" + rc);
-        String path = f.getPath();
-        return new File(path.substring(0, path.length() - 5) + ".class");
-    }
-
-    void countAnnotations() {
-        int expected_visibles = 0, expected_invisibles = 4;
-        int expected_all = expected_visibles + expected_invisibles;
-
-        if (expected_all != all) {
-            errors++;
-            System.err.println("expected " + expected_all
-                    + " annotations but found " + all);
-        }
-
-        if (expected_visibles != visibles) {
-            errors++;
-            System.err.println("expected " + expected_visibles
-                    + " visibles annotations but found " + visibles);
-        }
-
-        if (expected_invisibles != invisibles) {
-            errors++;
-            System.err.println("expected " + expected_invisibles
-                    + " invisibles annotations but found " + invisibles);
-        }
-
-    }
-
-    int errors;
-    int all;
-    int visibles;
-    int invisibles;
-}
--- a/langtools/test/tools/javap/typeAnnotations/ArrayClassLiterals2.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2009, 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 6918625
- * @summary javap dumps type information of array class literals
- */
-
-import java.io.*;
-
-public class ArrayClassLiterals2 {
-    public static void main(String[] args) throws Exception {
-        new ArrayClassLiterals2().run();
-    }
-
-    public void run() throws IOException {
-        File classFile = new File(System.getProperty("test.classes"), "ArrayClassLiterals2$Test.class");
-
-        verify(classFile,
-               "RuntimeInvisibleTypeAnnotations:",
-               "CLASS_LITERAL_GENERIC_OR_ARRAY"
-               );
-
-        if (errors > 0)
-            throw new Error(errors + " found.");
-    }
-
-    String javap(File f) {
-        StringWriter sw = new StringWriter();
-        PrintWriter out = new PrintWriter(sw);
-        int rc = com.sun.tools.javap.Main.run(new String[] { "-v", f.getPath() }, out);
-        if (rc != 0)
-            throw new Error("javap failed. rc=" + rc);
-        out.close();
-        return sw.toString();
-    }
-
-    void verify(File classFile, String... expects) {
-        String output = javap(classFile);
-        for (String expect: expects) {
-            if (output.indexOf(expect)< 0)
-                error(expect + " not found");
-        }
-    }
-
-    void error(String msg) {
-        System.err.println(msg);
-        errors++;
-    }
-
-    int errors;
-
-
-    /*********************** Test class *************************/
-    static class Test {
-        @interface A { }
-        void test() {
-            Object a = @A String @A [] @A [].class;
-        }
-    }
-}
--- a/langtools/test/tools/javap/typeAnnotations/ClassLiterals.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +0,0 @@
-/*
- * Copyright (c) 2008, 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.io.*;
-import com.sun.tools.classfile.*;
-
-/*
- * @test ClassLiterals
- * @bug 6843077
- * @summary test that all type annotations are present in the classfile
- */
-
-public class ClassLiterals {
-    public static void main(String[] args) throws Exception {
-        new ClassLiterals().run();
-    }
-
-    public void run() throws Exception {
-        File javaFile = writeTestFile();
-        File classFile = compileTestFile(javaFile);
-
-        ClassFile cf = ClassFile.read(classFile);
-        test(cf);
-        for (Field f : cf.fields) {
-            test(cf, f);
-        }
-        for (Method m: cf.methods) {
-            test(cf, m);
-        }
-
-        countAnnotations();
-
-        if (errors > 0)
-            throw new Exception(errors + " errors found");
-        System.out.println("PASSED");
-    }
-
-    void test(ClassFile cf) {
-        test(cf, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    void test(ClassFile cf, Method m) {
-        test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    void test(ClassFile cf, Field m) {
-        test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, String name, boolean visible) {
-        int index = cf.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = cf.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-        }
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, Method m, String name, boolean visible) {
-        int index = m.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = m.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-        }
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, Field m, String name, boolean visible) {
-        int index = m.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = m.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-        }
-    }
-
-    File writeTestFile() throws IOException {
-      File f = new File("Testa.java");
-        PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f)));
-        out.println("import java.util.*;");
-        out.println("class Testa { ");
-        out.println("  @interface A { }");
-
-        out.println(" void test() {");
-        out.println("  Object a = @A String.class;");
-        out.println("  Object b = @A String @A [] @A [].class;");
-        out.println(" }");
-        out.println("}");
-
-        out.close();
-        return f;
-    }
-
-    File compileTestFile(File f) {
-      int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.7", "-g", f.getPath() });
-        if (rc != 0)
-            throw new Error("compilation failed. rc=" + rc);
-        String path = f.getPath();
-        return new File(path.substring(0, path.length() - 5) + ".class");
-    }
-
-    void countAnnotations() {
-        int expected_visibles = 0, expected_invisibles = 4;
-        int expected_all = expected_visibles + expected_invisibles;
-
-        if (expected_all != all) {
-            errors++;
-            System.err.println("expected " + expected_all
-                    + " annotations but found " + all);
-        }
-
-        if (expected_visibles != visibles) {
-            errors++;
-            System.err.println("expected " + expected_visibles
-                    + " visibles annotations but found " + visibles);
-        }
-
-        if (expected_invisibles != invisibles) {
-            errors++;
-            System.err.println("expected " + expected_invisibles
-                    + " invisibles annotations but found " + invisibles);
-        }
-
-    }
-
-    int errors;
-    int all;
-    int visibles;
-    int invisibles;
-}
--- a/langtools/test/tools/javap/typeAnnotations/JSR175Annotations.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-/*
- * Copyright (c) 2008, 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.io.*;
-import com.sun.tools.classfile.*;
-
-/*
- * @test JSR175Annotations
- * @bug 6843077
- * @summary test that only type annotations are recorded as such in classfile
- */
-
-public class JSR175Annotations {
-    public static void main(String[] args) throws Exception {
-        new JSR175Annotations().run();
-    }
-
-    public void run() throws Exception {
-        File javaFile = writeTestFile();
-        File classFile = compileTestFile(javaFile);
-
-        ClassFile cf = ClassFile.read(classFile);
-        for (Field f : cf.fields) {
-            test(cf, f);
-        }
-        for (Method m: cf.methods) {
-            test(cf, m);
-        }
-
-        countAnnotations();
-
-        if (errors > 0)
-            throw new Exception(errors + " errors found");
-        System.out.println("PASSED");
-    }
-
-    void test(ClassFile cf, Method m) {
-        test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    void test(ClassFile cf, Field m) {
-        test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, Method m, String name, boolean visible) {
-        int index = m.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = m.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-        }
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, Field m, String name, boolean visible) {
-        int index = m.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = m.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-        }
-    }
-
-    File writeTestFile() throws IOException {
-        File f = new File("Test.java");
-        PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f)));
-        out.println("import java.lang.annotation.Retention;");
-        out.println("import java.lang.annotation.RetentionPolicy;");
-        out.println("abstract class Test { ");
-        out.println("  @Retention(RetentionPolicy.RUNTIME)");
-        out.println("  @interface A { }");
-        out.println("  @A String m;");
-        out.println("  @A String method(@A String a) {");
-        out.println("    return a;");
-        out.println("  }");
-        out.println("}");
-        out.close();
-        return f;
-    }
-
-    File compileTestFile(File f) {
-        int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.7", "-g", f.getPath() });
-        if (rc != 0)
-            throw new Error("compilation failed. rc=" + rc);
-        String path = f.getPath();
-        return new File(path.substring(0, path.length() - 5) + ".class");
-    }
-
-    void countAnnotations() {
-        int expected_visibles = 0, expected_invisibles = 0;
-        int expected_all = expected_visibles + expected_invisibles;
-
-        if (expected_all != all) {
-            errors++;
-            System.err.println("expected " + expected_all
-                    + " annotations but found " + all);
-        }
-
-        if (expected_visibles != visibles) {
-            errors++;
-            System.err.println("expected " + expected_visibles
-                    + " visibles annotations but found " + visibles);
-        }
-
-        if (expected_invisibles != invisibles) {
-            errors++;
-            System.err.println("expected " + expected_invisibles
-                    + " invisibles annotations but found " + invisibles);
-        }
-
-    }
-
-    int errors;
-    int all;
-    int visibles;
-    int invisibles;
-}
--- a/langtools/test/tools/javap/typeAnnotations/NewArray.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-/*
- * Copyright (c) 2008, 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.io.*;
-import com.sun.tools.classfile.*;
-
-/*
- * @test NewArray
- * @bug 6843077
- * @summary test that all type annotations are present in the classfile
- */
-
-public class NewArray {
-    public static void main(String[] args) throws Exception {
-        new NewArray().run();
-    }
-
-    public void run() throws Exception {
-        File javaFile = writeTestFile();
-        File classFile = compileTestFile(javaFile);
-
-        ClassFile cf = ClassFile.read(classFile);
-        test(cf);
-        for (Field f : cf.fields) {
-            test(cf, f);
-        }
-        for (Method m: cf.methods) {
-            test(cf, m);
-        }
-
-        countAnnotations();
-
-        if (errors > 0)
-            throw new Exception(errors + " errors found");
-        System.out.println("PASSED");
-    }
-
-    void test(ClassFile cf) {
-        test(cf, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    void test(ClassFile cf, Method m) {
-        test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    void test(ClassFile cf, Field m) {
-        test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, String name, boolean visible) {
-        int index = cf.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = cf.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-        }
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, Method m, String name, boolean visible) {
-        int index = m.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = m.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-        }
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, Field m, String name, boolean visible) {
-        int index = m.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = m.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-        }
-    }
-
-    File writeTestFile() throws IOException {
-      File f = new File("Test.java");
-        PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f)));
-        out.println("import java.util.*;");
-        out.println("class Test { ");
-        out.println("  @interface A { }");
-
-        out.println(" void test() {");
-        out.println("  Object a = new @A String @A [5] @A  [];");
-        out.println("  Object b = new @A String @A [5] @A [3];");
-        out.println("  Object c = new @A String @A [] @A [] {};");
-        out.println(" }");
-        out.println("}");
-
-        out.close();
-        return f;
-    }
-
-    File compileTestFile(File f) {
-        int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.7", "-g", f.getPath() });
-        if (rc != 0)
-            throw new Error("compilation failed. rc=" + rc);
-        String path = f.getPath();
-        return new File(path.substring(0, path.length() - 5) + ".class");
-    }
-
-    void countAnnotations() {
-        int expected_visibles = 0, expected_invisibles = 9;
-        int expected_all = expected_visibles + expected_invisibles;
-
-        if (expected_all != all) {
-            errors++;
-            System.err.println("expected " + expected_all
-                    + " annotations but found " + all);
-        }
-
-        if (expected_visibles != visibles) {
-            errors++;
-            System.err.println("expected " + expected_visibles
-                    + " visibles annotations but found " + visibles);
-        }
-
-        if (expected_invisibles != invisibles) {
-            errors++;
-            System.err.println("expected " + expected_invisibles
-                    + " invisibles annotations but found " + invisibles);
-        }
-
-    }
-
-    int errors;
-    int all;
-    int visibles;
-    int invisibles;
-}
--- a/langtools/test/tools/javap/typeAnnotations/Presence.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,189 +0,0 @@
-/*
- * Copyright (c) 2008, 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.io.*;
-import com.sun.tools.classfile.*;
-
-/*
- * @test Presence
- * @bug 6843077
- * @summary test that all type annotations are present in the classfile
- */
-
-public class Presence {
-    public static void main(String[] args) throws Exception {
-        new Presence().run();
-    }
-
-    public void run() throws Exception {
-        File javaFile = writeTestFile();
-        File classFile = compileTestFile(javaFile);
-
-        ClassFile cf = ClassFile.read(classFile);
-        test(cf);
-        for (Field f : cf.fields) {
-            test(cf, f);
-        }
-        for (Method m: cf.methods) {
-            test(cf, m);
-        }
-
-        countAnnotations();
-
-        if (errors > 0)
-            throw new Exception(errors + " errors found");
-        System.out.println("PASSED");
-    }
-
-    void test(ClassFile cf) {
-        test(cf, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    void test(ClassFile cf, Method m) {
-        test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    void test(ClassFile cf, Field m) {
-        test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, String name, boolean visible) {
-        int index = cf.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = cf.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-        }
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, Method m, String name, boolean visible) {
-        int index = m.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = m.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-        }
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, Field m, String name, boolean visible) {
-        int index = m.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = m.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-        }
-    }
-
-    File writeTestFile() throws IOException {
-        File f = new File("Test.java");
-        PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f)));
-        out.println("import java.util.*;");
-        out.println("class Test<@Test.A T extends @Test.A List<@Test.A String>> { ");
-        out.println("  @interface A { }");
-
-        out.println("  Map<@A String, Map<@A String, @A String>> f1;");
-
-        out.println("  <@A T extends @A List<@A String>>");
-        out.println("  Map<@A String, @A List<@A String>>");
-        out.println("  method(List<@A String> @A [] param1, String @A [] @A ... param2) @A");
-        out.println("  throws @A Exception {");
-        out.println("    @A String lc1 = null;");
-        out.println("    @A List<@A String> lc2 = null;");
-        out.println("    @A String @A [] [] @A[] lc3 = null;");
-        out.println("    List<? extends @A List<@A String>> lc4 = null;");
-        out.println("    Object lc5 = (@A List<@A String>) null;");
-        out.println("    boolean lc6 = lc1 instanceof @A String;");
-        out.println("    boolean lc7 = lc5 instanceof @A String @A [] @A [];");
-        out.println("    new @A ArrayList<@A String>();");
-        out.println("    Object lc8 = new @A String @A [4];");
-        out.println("    Object lc9 = @A String.class;");
-        out.println("    Object lc10 = @A int.class;");
-        out.println("    return null;");
-        out.println("  }");
-        out.println("  void vararg1(String @A ... t) { } ");
-        out.println("}");
-        out.close();
-        return f;
-    }
-
-    File compileTestFile(File f) {
-        int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.7", "-g", f.getPath() });
-        if (rc != 0)
-            throw new Error("compilation failed. rc=" + rc);
-        String path = f.getPath();
-        return new File(path.substring(0, path.length() - 5) + ".class");
-    }
-
-    void countAnnotations() {
-        int expected_visibles = 0, expected_invisibles = 39;
-        int expected_all = expected_visibles + expected_invisibles;
-
-        if (expected_all != all) {
-            errors++;
-            System.err.println("expected " + expected_all
-                    + " annotations but found " + all);
-        }
-
-        if (expected_visibles != visibles) {
-            errors++;
-            System.err.println("expected " + expected_visibles
-                    + " visibles annotations but found " + visibles);
-        }
-
-        if (expected_invisibles != invisibles) {
-            errors++;
-            System.err.println("expected " + expected_invisibles
-                    + " invisibles annotations but found " + invisibles);
-        }
-
-    }
-
-    int errors;
-    int all;
-    int visibles;
-    int invisibles;
-}
--- a/langtools/test/tools/javap/typeAnnotations/PresenceInner.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-/*
- * Copyright (c) 2009, 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.io.*;
-import com.sun.tools.classfile.*;
-
-/*
- * @test PresenceInner
- * @bug 6843077
- * @summary test that annotations in inner types count only once
- */
-
-public class PresenceInner {
-    public static void main(String[] args) throws Exception {
-        new PresenceInner().run();
-    }
-
-    public void run() throws Exception {
-        File javaFile = writeTestFile();
-        File classFile = compileTestFile(javaFile);
-
-        ClassFile cf = ClassFile.read(classFile);
-        test(cf);
-        for (Field f : cf.fields) {
-            test(cf, f);
-        }
-        for (Method m: cf.methods) {
-            test(cf, m);
-        }
-
-        // counts are zero when vising outer class
-        countAnnotations(0);
-
-        // visit inner class
-        File innerFile = new File("Test$1Inner.class");
-        ClassFile icf = ClassFile.read(innerFile);
-        test(icf);
-        for (Field f : icf.fields) {
-            test(cf, f);
-        }
-        for (Method m: icf.methods) {
-            test(cf, m);
-        }
-
-        countAnnotations(1);
-        if (errors > 0)
-            throw new Exception(errors + " errors found");
-        System.out.println("PASSED");
-    }
-
-    void test(ClassFile cf) {
-        test(cf, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    void test(ClassFile cf, Method m) {
-        test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    void test(ClassFile cf, Field m) {
-        test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, String name, boolean visible) {
-        int index = cf.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = cf.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-        }
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, Method m, String name, boolean visible) {
-        int index = m.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = m.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-        }
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, Field m, String name, boolean visible) {
-        int index = m.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = m.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-        }
-    }
-
-    File writeTestFile() throws IOException {
-        File f = new File("Test.java");
-        PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f)));
-
-        out.println("class Test {");
-        out.println("  void method() {");
-        out.println("    class Inner<T extends @A Object> { }");
-        out.println("  }");
-        out.println("}");
-        out.println("@interface A { }");
-        out.close();
-        System.out.println(f.getAbsolutePath());
-        return f;
-    }
-
-    File compileTestFile(File f) {
-        int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.7", "-g", f.getPath() });
-        if (rc != 0)
-            throw new Error("compilation failed. rc=" + rc);
-        String path = f.getPath();
-        return new File(path.substring(0, path.length() - 5) + ".class");
-    }
-
-    void countAnnotations(int expected_invisibles) {
-        int expected_visibles = 0;
-        int expected_all = expected_visibles + expected_invisibles;
-
-        if (expected_all != all) {
-            errors++;
-            System.err.println("expected " + expected_all
-                    + " annotations but found " + all);
-        }
-
-        if (expected_visibles != visibles) {
-            errors++;
-            System.err.println("expected " + expected_visibles
-                    + " visibles annotations but found " + visibles);
-        }
-
-        if (expected_invisibles != invisibles) {
-            errors++;
-            System.err.println("expected " + expected_invisibles
-                    + " invisibles annotations but found " + invisibles);
-        }
-
-    }
-
-    int errors;
-    int all;
-    int visibles;
-    int invisibles;
-}
--- a/langtools/test/tools/javap/typeAnnotations/T6855990.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2009, 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.io.*;
-
-/*
- * @test
- * @bug 6855990
- * @summary InstructionDetailWriter should support new 308 annotations attribute
- */
-
-public class T6855990 {
-    public static void main(String[] args) throws Exception {
-        new T6855990().run();
-    }
-
-    public void run() throws Exception {
-        @Simple String[] args = { "-c", "-XDdetails:typeAnnotations", "T6855990" };
-        StringWriter sw = new StringWriter();
-        PrintWriter pw = new PrintWriter(sw);
-        int rc = com.sun.tools.javap.Main.run(args, pw);
-        pw.close();
-        String out = sw.toString();
-        System.out.println(out);
-        if (out.indexOf("@Simple: LOCAL_VARIABLE") == -1)
-            throw new Exception("expected output not found");
-    }
-}
-
-@interface Simple { }
-
--- a/langtools/test/tools/javap/typeAnnotations/Visibility.java	Wed Jul 05 17:26:05 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2008, 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.io.*;
-import com.sun.tools.classfile.*;
-
-/*
- * @test Visibility
- * @bug 6843077
- * @summary test that type annotations are recorded in the classfile
- */
-
-public class Visibility {
-    public static void main(String[] args) throws Exception {
-        new Visibility().run();
-    }
-
-    public void run() throws Exception {
-        File javaFile = writeTestFile();
-        File classFile = compileTestFile(javaFile);
-
-        ClassFile cf = ClassFile.read(classFile);
-        for (Method m: cf.methods) {
-            test(cf, m);
-        }
-
-        countAnnotations();
-
-        if (errors > 0)
-            throw new Exception(errors + " errors found");
-        System.out.println("PASSED");
-    }
-
-    void test(ClassFile cf, Method m) {
-        test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true);
-        test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
-    }
-
-    // test the result of Attributes.getIndex according to expectations
-    // encoded in the method's name
-    void test(ClassFile cf, Method m, String name, boolean visible) {
-        int index = m.attributes.getIndex(cf.constant_pool, name);
-        if (index != -1) {
-            Attribute attr = m.attributes.get(index);
-            assert attr instanceof RuntimeTypeAnnotations_attribute;
-            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
-            all += tAttr.annotations.length;
-            if (visible)
-                visibles += tAttr.annotations.length;
-            else
-                invisibles += tAttr.annotations.length;
-        }
-    }
-
-    File writeTestFile() throws IOException {
-        File f = new File("Test.java");
-        PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f)));
-        out.println("import java.lang.annotation.Retention;");
-        out.println("import java.lang.annotation.RetentionPolicy;");
-        out.println("abstract class Test { ");
-        // visible annotations: RUNTIME
-        out.println("  @Retention(RetentionPolicy.RUNTIME)");
-        out.println("  @interface A { }");
-        out.println("  void visible() @A { }");
-
-        // invisible annotations: CLASS
-        out.println("  @Retention(RetentionPolicy.CLASS)");
-        out.println("  @interface B { }");
-        out.println("  void invisible() @B { }");
-
-        // source annotations
-        out.println("  @Retention(RetentionPolicy.SOURCE)");
-        out.println("  @interface C { }");
-        out.println("  void source() @C { }");
-
-        // default visibility: CLASS
-        out.println("  @interface D { }");
-        out.println("  void def() @D { }");
-        out.println("}");
-        out.close();
-        return f;
-    }
-
-    File compileTestFile(File f) {
-      int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.7", "-g", f.getPath() });
-        if (rc != 0)
-            throw new Error("compilation failed. rc=" + rc);
-        String path = f.getPath();
-        return new File(path.substring(0, path.length() - 5) + ".class");
-    }
-
-    void countAnnotations() {
-        int expected_all = 3, expected_visibles = 1, expected_invisibles = 2;
-
-        if (expected_all != all) {
-            errors++;
-            System.err.println("expected " + expected_all
-                    + " annotations but found " + all);
-        }
-
-        if (expected_visibles != visibles) {
-            errors++;
-            System.err.println("expected " + expected_visibles
-                    + " visibles annotations but found " + visibles);
-        }
-
-        if (expected_invisibles != invisibles) {
-            errors++;
-            System.err.println("expected " + expected_invisibles
-                    + " invisibles annotations but found " + invisibles);
-        }
-
-    }
-
-    int errors;
-    int all;
-    int visibles;
-    int invisibles;
-}