changeset 10023:bbece7eab49f

Merge
author lana
date Tue, 16 Sep 2014 14:16:55 -0700
parents 25788892a672 2be3555a6a37
children 083041dc0035
files
diffstat 29 files changed, 2034 insertions(+), 181 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/javax/management/remote/rmi/RMIConnector.java	Tue Sep 16 11:51:52 2014 -0700
+++ b/src/share/classes/javax/management/remote/rmi/RMIConnector.java	Tue Sep 16 14:16:55 2014 -0700
@@ -1335,66 +1335,94 @@
                 int maxNotifications,
                 long timeout)
                 throws IOException, ClassNotFoundException {
-            IOException org;
 
+            boolean retried = false;
             while (true) { // used for a successful re-connection
+                           // or a transient network problem
                 try {
                     return connection.fetchNotifications(clientSequenceNumber,
                             maxNotifications,
-                            timeout);
+                            timeout); // return normally
                 } catch (IOException ioe) {
-                    org = ioe;
+                    // Examine the chain of exceptions to determine whether this
+                    // is a deserialization issue. If so - we propagate the
+                    // appropriate exception to the caller, who will then
+                    // proceed with fetching notifications one by one
+                    rethrowDeserializationException(ioe);
 
-                    // inform of IOException
                     try {
                         communicatorAdmin.gotIOException(ioe);
+                        // reconnection OK, back to "while" to do again
+                    } catch (IOException ee) {
+                        boolean toClose = false;
 
-                        // The connection should be re-established.
-                        continue;
-                    } catch (IOException ee) {
-                        // No more fetch, the Exception will be re-thrown.
-                        break;
-                    } // never reached
-                } // never reached
+                        synchronized (this) {
+                            if (terminated) {
+                                // the connection is closed.
+                                throw ioe;
+                            } else if (retried) {
+                                toClose = true;
+                            }
+                        }
+
+                        if (toClose) {
+                            // JDK-8049303
+                            // We received an IOException - but the communicatorAdmin
+                            // did not close the connection - possibly because
+                            // the original exception was raised by a transient network
+                            // problem?
+                            // We already know that this exception is not due to a deserialization
+                            // issue as we already took care of that before involving the
+                            // communicatorAdmin. Moreover - we already made one retry attempt
+                            // at fetching the same batch of notifications - and the
+                            // problem persisted.
+                            // Since trying again doesn't seem to solve the issue, we will now
+                            // close the connection. Doing otherwise might cause the
+                            // NotifFetcher thread to die silently.
+                            final Notification failedNotif =
+                                    new JMXConnectionNotification(
+                                    JMXConnectionNotification.FAILED,
+                                    this,
+                                    connectionId,
+                                    clientNotifSeqNo++,
+                                    "Failed to communicate with the server: " + ioe.toString(),
+                                    ioe);
+
+                            sendNotification(failedNotif);
+
+                            try {
+                                close(true);
+                            } catch (Exception e) {
+                                // OK.
+                                // We are closing
+                            }
+                            throw ioe; // the connection is closed here.
+                        } else {
+                            // JDK-8049303 possible transient network problem,
+                            // let's try one more time
+                            retried = true;
+                        }
+                    }
+                }
             }
+        }
 
+        private void rethrowDeserializationException(IOException ioe)
+                throws ClassNotFoundException, IOException {
             // specially treating for an UnmarshalException
-            if (org instanceof UnmarshalException) {
-                UnmarshalException ume = (UnmarshalException)org;
-
-                if (ume.detail instanceof ClassNotFoundException)
-                    throw (ClassNotFoundException) ume.detail;
-
-                /* In Sun's RMI implementation, if a method return
-                   contains an unserializable object, then we get
-                   UnmarshalException wrapping WriteAbortedException
-                   wrapping NotSerializableException.  In that case we
-                   extract the NotSerializableException so that our
-                   caller can realize it should try to skip past the
-                   notification that presumably caused it.  It's not
-                   certain that every other RMI implementation will
-                   generate this exact exception sequence.  If not, we
-                   will not detect that the problem is due to an
-                   unserializable object, and we will stop trying to
-                   receive notifications from the server.  It's not
-                   clear we can do much better.  */
-                if (ume.detail instanceof WriteAbortedException) {
-                    WriteAbortedException wae =
-                            (WriteAbortedException) ume.detail;
-                    if (wae.detail instanceof IOException)
-                        throw (IOException) wae.detail;
-                }
-            } else if (org instanceof MarshalException) {
+            if (ioe instanceof UnmarshalException) {
+                throw ioe; // the fix of 6937053 made ClientNotifForwarder.fetchNotifs
+                           // fetch one by one with UnmarshalException
+            } else if (ioe instanceof MarshalException) {
                 // IIOP will throw MarshalException wrapping a NotSerializableException
                 // when a server fails to serialize a response.
-                MarshalException me = (MarshalException)org;
+                MarshalException me = (MarshalException)ioe;
                 if (me.detail instanceof NotSerializableException) {
                     throw (NotSerializableException)me.detail;
                 }
             }
 
-            // Not serialization problem, simply re-throw the orginal exception
-            throw org;
+            // Not serialization problem, return.
         }
 
         protected Integer addListenerForMBeanRemovedNotif()
--- a/src/share/classes/javax/swing/text/FlowView.java	Tue Sep 16 11:51:52 2014 -0700
+++ b/src/share/classes/javax/swing/text/FlowView.java	Tue Sep 16 14:16:55 2014 -0700
@@ -800,14 +800,22 @@
         @Override
         protected void forwardUpdate(DocumentEvent.ElementChange ec,
                                           DocumentEvent e, Shape a, ViewFactory f) {
-            calculateUpdateIndexes(e);
-            // Send update event to all views followed by the changed place.
-            lastUpdateIndex = Math.max((getViewCount() - 1), 0);
-            for (int i = firstUpdateIndex; i <= lastUpdateIndex; i++) {
-                View v = getView(i);
-                if (v != null) {
-                    Shape childAlloc = getChildAllocation(i, a);
-                    forwardUpdateToView(v, e, childAlloc, f);
+            // Update the view responsible for the changed element by invocation of
+            // super method.
+            super.forwardUpdate(ec, e, a, f);
+            // Re-calculate the update indexes and update the views followed by
+            // the changed place. Note: we update the views only when insertion or
+            // removal takes place.
+            DocumentEvent.EventType type = e.getType();
+            if (type == DocumentEvent.EventType.INSERT ||
+                type == DocumentEvent.EventType.REMOVE) {
+                firstUpdateIndex = Math.min((lastUpdateIndex + 1), (getViewCount() - 1));
+                lastUpdateIndex = Math.max((getViewCount() - 1), 0);
+                for (int i = firstUpdateIndex; i <= lastUpdateIndex; i++) {
+                    View v = getView(i);
+                    if (v != null) {
+                        v.updateAfterChange();
+                    }
                 }
             }
         }
--- a/src/share/classes/javax/swing/text/GlyphView.java	Tue Sep 16 11:51:52 2014 -0700
+++ b/src/share/classes/javax/swing/text/GlyphView.java	Tue Sep 16 14:16:55 2014 -0700
@@ -971,6 +971,14 @@
         }
     }
 
+    /** {@inheritDoc} */
+    @Override
+    void updateAfterChange() {
+        // Drop the break spots. They will be re-calculated during
+        // layout. It is necessary for proper line break calculation.
+        breakSpots = null;
+    }
+
     /**
      * Class to hold data needed to justify this GlyphView in a PargraphView.Row
      */
--- a/src/share/classes/javax/swing/text/View.java	Tue Sep 16 11:51:52 2014 -0700
+++ b/src/share/classes/javax/swing/text/View.java	Tue Sep 16 14:16:55 2014 -0700
@@ -1199,6 +1199,13 @@
     }
 
     /**
+     * Updates the view to reflect the changes.
+     */
+    void updateAfterChange() {
+        // Do nothing by default. Should be overridden in subclasses, if any.
+    }
+
+    /**
      * Forwards the <code>DocumentEvent</code> to the give child view.  This
      * simply messages the view with a call to <code>insertUpdate</code>,
      * <code>removeUpdate</code>, or <code>changedUpdate</code> depending
--- a/src/share/classes/sun/awt/SunToolkit.java	Tue Sep 16 11:51:52 2014 -0700
+++ b/src/share/classes/sun/awt/SunToolkit.java	Tue Sep 16 14:16:55 2014 -0700
@@ -386,7 +386,7 @@
      * null or the target can't be found, a null with be returned.
      */
     public static AppContext targetToAppContext(Object target) {
-        if (target == null || GraphicsEnvironment.isHeadless()) {
+        if (target == null) {
             return null;
         }
         AppContext context = getAppContext(target);
@@ -460,12 +460,10 @@
      * via targetToAppContext() above.
      */
     public static void insertTargetMapping(Object target, AppContext appContext) {
-        if (!GraphicsEnvironment.isHeadless()) {
-            if (!setAppContext(target, appContext)) {
-                // Target is not a Component/MenuComponent, use the private Map
-                // instead.
-                appContextMap.put(target, appContext);
-            }
+        if (!setAppContext(target, appContext)) {
+            // Target is not a Component/MenuComponent, use the private Map
+            // instead.
+            appContextMap.put(target, appContext);
         }
     }
 
--- a/src/share/classes/sun/security/ssl/Handshaker.java	Tue Sep 16 11:51:52 2014 -0700
+++ b/src/share/classes/sun/security/ssl/Handshaker.java	Tue Sep 16 14:16:55 2014 -0700
@@ -656,8 +656,15 @@
      */
     ProtocolList getActiveProtocols() {
         if (activeProtocols == null) {
+            boolean enabledSSL20Hello = false;
             ArrayList<ProtocolVersion> protocols = new ArrayList<>(4);
             for (ProtocolVersion protocol : enabledProtocols.collection()) {
+                // Need not to check the SSL20Hello protocol.
+                if (protocol.v == ProtocolVersion.SSL20Hello.v) {
+                    enabledSSL20Hello = true;
+                    continue;
+                }
+
                 boolean found = false;
                 for (CipherSuite suite : enabledCipherSuites.collection()) {
                     if (suite.isAvailable() && suite.obsoleted > protocol.v &&
@@ -684,6 +691,11 @@
                         "No available cipher suite for " + protocol);
                 }
             }
+
+            if (!protocols.isEmpty() && enabledSSL20Hello) {
+                protocols.add(ProtocolVersion.SSL20Hello);
+            }
+
             activeProtocols = new ProtocolList(protocols);
         }
 
--- a/src/solaris/classes/sun/java2d/xr/XRSolidSrcPict.java	Tue Sep 16 11:51:52 2014 -0700
+++ b/src/solaris/classes/sun/java2d/xr/XRSolidSrcPict.java	Tue Sep 16 14:16:55 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved.
 
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -31,12 +31,14 @@
 
     XRSurfaceData srcPict;
     XRColor xrCol;
-    int curPixVal = -1;
+    int curPixVal;
 
     public XRSolidSrcPict(XRBackend con, int parentXid) {
         this.con = con;
 
         xrCol = new XRColor();
+        curPixVal = 0xFF000000;
+
         int solidPixmap = con.createPixmap(parentXid, 32, 1, 1);
         int solidSrcPictXID = con.createPicture(solidPixmap, XRUtils.PictStandardARGB32);
         con.setPictureRepeat(solidSrcPictXID, XRUtils.RepeatNormal);
--- a/src/windows/native/java/net/NetworkInterface.c	Tue Sep 16 11:51:52 2014 -0700
+++ b/src/windows/native/java/net/NetworkInterface.c	Tue Sep 16 14:16:55 2014 -0700
@@ -1014,9 +1014,11 @@
       case MIB_IF_TYPE_FDDI:
       case IF_TYPE_IEEE80211:
         len = ifRowP->dwPhysAddrLen;
-        ret = (*env)->NewByteArray(env, len);
-        if (!IS_NULL(ret)) {
-          (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) ifRowP->bPhysAddr);
+        if (len > 0) {
+            ret = (*env)->NewByteArray(env, len);
+            if (!IS_NULL(ret)) {
+              (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) ifRowP->bPhysAddr);
+            }
         }
         break;
       }
--- a/test/TEST.groups	Tue Sep 16 11:51:52 2014 -0700
+++ b/test/TEST.groups	Tue Sep 16 14:16:55 2014 -0700
@@ -124,15 +124,27 @@
 
 jdk_security3 = \
     javax/security  \
+    -javax/security/auth/kerberos \
     com/sun/security \
+    -com/sun/security/jgss \
     com/sun/org/apache/xml/internal/security \
     sun/security \
+    -sun/security/krb5 \
+    -sun/security/jgss \
+    javax/net \
     lib/security
 
+jdk_security4 = \
+    com/sun/security/jgss \
+    javax/security/auth/kerberos \
+    sun/security/krb5 \
+    sun/security/jgss
+
 jdk_security = \
     :jdk_security1 \
     :jdk_security2 \
-    :jdk_security3
+    :jdk_security3 \
+    :jdk_security4
 
 jdk_text = \
     java/text \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/Graphics2D/WhiteTextColorTest.java	Tue Sep 16 14:16:55 2014 -0700
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2014, 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.awt.*;
+import java.awt.image.*;
+import javax.swing.*;
+
+/**
+ * @test
+ * @bug 8056009
+ * @summary tests whether Graphics.setColor-calls with Color.white are ignored directly
+ *          after pipeline initialization for a certain set of operations.
+ * @author ceisserer
+ */
+public class WhiteTextColorTest extends Frame {
+    public static volatile boolean success = false;
+
+    public WhiteTextColorTest() {
+        Image dstImg = getGraphicsConfiguration()
+                .createCompatibleVolatileImage(30, 20);
+        Graphics g = dstImg.getGraphics();
+
+        g.setColor(Color.BLACK);
+        g.fillRect(0, 0, dstImg.getWidth(null), dstImg.getHeight(null));
+        g.setColor(Color.WHITE);
+        g.drawString("Test", 0, 15);
+
+        BufferedImage readBackImg = new BufferedImage(dstImg.getWidth(null),
+                dstImg.getHeight(null), BufferedImage.TYPE_INT_RGB);
+        readBackImg.getGraphics().drawImage(dstImg, 0, 0, null);
+
+        for (int x = 0; x < readBackImg.getWidth(); x++) {
+            for (int y = 0; y < readBackImg.getHeight(); y++) {
+                int pixel = readBackImg.getRGB(x, y);
+
+                // In case a single white pixel is found, the
+                // setColor(Color.WHITE)
+                // call before was not ignored and the bug is not present
+                if (pixel == 0xFFFFFFFF) {
+                    return;
+                }
+            }
+        }
+
+        throw new RuntimeException("Test Failed");
+    }
+
+    public static void main(String[] args) throws Exception {
+        SwingUtilities.invokeLater(new Runnable() {
+            public void run() {
+                new WhiteTextColorTest();
+            }
+        });
+    }
+}
+
--- a/test/java/lang/instrument/NMTHelper.java	Tue Sep 16 11:51:52 2014 -0700
+++ b/test/java/lang/instrument/NMTHelper.java	Tue Sep 16 14:16:55 2014 -0700
@@ -21,8 +21,12 @@
  * questions.
  */
 
+import java.io.File;
+import java.io.FileWriter;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.Arrays;
+import java.util.stream.Collectors;
 import sun.management.ManagementFactoryHelper;
 import com.sun.management.DiagnosticCommandMBean;
 
@@ -32,8 +36,8 @@
         executeDcmd("vmNativeMemory", "baseline");
     }
 
-    // Total:  reserved=3484685KB  +293KB, committed=266629KB +293KB
-    private static Pattern totalLine = Pattern.compile("^Total:  reserved=\\d+KB  .*KB, committed=\\d+KB (.*)KB$");
+    // Total: reserved=3484685KB +293KB, committed=266629KB +293KB
+    private static Pattern totalLine = Pattern.compile("^Total: reserved=\\d+KB .*KB, committed=\\d+KB (.*)KB$");
 
     public static long committedDiff() throws Exception {
         String res = (String) executeDcmd("vmNativeMemory", "detail.diff");
@@ -53,14 +57,14 @@
         Object[] dcmdArgs = {args};
         String[] signature = {String[].class.getName()};
 
-        try {
-            System.out.print("> " + cmd + " ");
-            for (String s : args) {
-                System.out.print(s + " ");
-            }
-            System.out.println(":");
+        String cmdString = cmd + " " +
+            Arrays.stream(args).collect(Collectors.joining(" "));
+        File f = new File("dcmdoutput-" + cmd + "-" + System.currentTimeMillis() + ".txt");
+        System.out.println("Output from Dcmd '" + cmdString + "' is being written to file " + f);
+        try (FileWriter fw = new FileWriter(f)) {
+            fw.write("> " + cmdString + ":");
             String result = (String) dcmd.invoke(cmd, dcmdArgs, signature);
-            System.out.println(result);
+            fw.write(result);
             return result;
         } catch(Exception ex) {
             ex.printStackTrace();
--- a/test/java/lang/instrument/RedefineBigClass.sh	Tue Sep 16 11:51:52 2014 -0700
+++ b/test/java/lang/instrument/RedefineBigClass.sh	Tue Sep 16 14:16:55 2014 -0700
@@ -27,7 +27,7 @@
 # @author Daniel D. Daugherty
 #
 # @run shell MakeJAR3.sh RedefineBigClassAgent 'Can-Redefine-Classes: true'
-# @run build BigClass RedefineBigClassApp
+# @run build BigClass RedefineBigClassApp NMTHelper
 # @run shell/timeout=600 RedefineBigClass.sh
 #
 
--- a/test/java/lang/instrument/RetransformBigClass.sh	Tue Sep 16 11:51:52 2014 -0700
+++ b/test/java/lang/instrument/RetransformBigClass.sh	Tue Sep 16 14:16:55 2014 -0700
@@ -27,7 +27,7 @@
 # @author Daniel D. Daugherty
 #
 # @run shell MakeJAR4.sh RetransformBigClassAgent SimpleIdentityTransformer 'Can-Retransform-Classes: true'
-# @run build BigClass RetransformBigClassApp
+# @run build BigClass RetransformBigClassApp NMTHelper
 # @run shell/timeout=600 RetransformBigClass.sh
 #
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/LFCaching/LFCachingTestCase.java	Tue Sep 16 14:16:55 2014 -0700
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, 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.lang.invoke.MethodHandle;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Abstract class for lambda forms caching testing.
+ *
+ * @author kshefov
+ */
+public abstract class LFCachingTestCase extends LambdaFormTestCase {
+
+    /**
+     * Constructor for lambda forms caching test case.
+     *
+     * @param testMethod A method from {@code j.l.i.MethodHandles} class that
+     * returns a {@code j.l.i.MethodHandle} instance.
+     */
+    protected LFCachingTestCase(TestMethods testMethod) {
+        super(testMethod);
+    }
+
+    /**
+     * Checks that the lambda forms of the two adapter method handles adapter1
+     * and adapter2 are the same.
+     *
+     * @param adapter1 First method handle.
+     * @param adapter2 Second method handle.
+     */
+    public void checkLFCaching(MethodHandle adapter1, MethodHandle adapter2) {
+        try {
+
+            if (!adapter1.type().equals(adapter2.type())) {
+                throw new Error("TESTBUG: Types of the two method handles are not the same");
+            }
+
+            Object lambdaForm0 = LambdaFormTestCase.INTERNAL_FORM.invoke(adapter1);
+            Object lambdaForm1 = LambdaFormTestCase.INTERNAL_FORM.invoke(adapter2);
+
+            if (lambdaForm0 == null || lambdaForm1 == null) {
+                throw new Error("Unexpected error: One or both lambda forms of the method handles are null");
+            }
+
+            if (lambdaForm0 != lambdaForm1) {
+                System.err.println("Lambda form 0 toString is:");
+                System.err.println(lambdaForm0);
+                System.err.println("Lambda form 1 toString is:");
+                System.err.println(lambdaForm1);
+                throw new AssertionError("Error: Lambda forms of the two method handles"
+                        + " are not the same. LF cahing does not work");
+            }
+        } catch (IllegalAccessException | IllegalArgumentException |
+                SecurityException | InvocationTargetException ex) {
+            throw new Error("Unexpected exception: ", ex);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java	Tue Sep 16 14:16:55 2014 -0700
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2014, 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 LFGarbageCollectedTest
+ * @bug 8046703
+ * @summary Test verifies that lambda forms are garbage collected
+ * @author kshefov
+ * @library /lib/testlibrary/jsr292 /lib/testlibrary
+ * @build TestMethods
+ * @build LambdaFormTestCase
+ * @build LFGarbageCollectedTest
+ * @run main/othervm/timeout=600 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true -DtestLimit=150 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI LFGarbageCollectedTest
+ */
+
+import java.lang.invoke.MethodHandle;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.Map;
+
+/**
+ * Lambda forms garbage collection test class.
+ */
+public final class LFGarbageCollectedTest extends LambdaFormTestCase {
+
+    /**
+     * Constructor for a lambda forms garbage collection test case.
+     *
+     * @param testMethod A method from {@code j.l.i.MethodHandles} class that
+     * returns a {@code j.l.i.MethodHandle} instance.
+     */
+    public LFGarbageCollectedTest(TestMethods testMethod) {
+        super(testMethod);
+    }
+
+    @Override
+    public void doTest() {
+        try {
+            Map<String, Object> data = getTestMethod().getTestCaseData();
+            MethodHandle adapter;
+            try {
+                adapter = getTestMethod().getTestCaseMH(data, TestMethods.Kind.ONE);
+            } catch (NoSuchMethodException ex) {
+                throw new Error("Unexpected exception: ", ex);
+            }
+            Object lambdaForm = LambdaFormTestCase.INTERNAL_FORM.invoke(adapter);
+            if (lambdaForm == null) {
+                throw new Error("Unexpected error: Lambda form of the method handle is null");
+            }
+            ReferenceQueue rq = new ReferenceQueue();
+            PhantomReference ph = new PhantomReference(lambdaForm, rq);
+            lambdaForm = null;
+            data = null;
+            adapter = null;
+            for (int i = 0; i < 1000 && !ph.isEnqueued(); i++) {
+                System.gc();
+            }
+            if (!ph.isEnqueued()) {
+                throw new AssertionError("Error: Lambda form is not garbage collected");
+            }
+        } catch (IllegalAccessException | IllegalArgumentException |
+                InvocationTargetException ex) {
+            throw new Error("Unexpected exception: ", ex);
+        }
+    }
+
+    /**
+     * Main routine for lambda forms garbage collection test.
+     *
+     * @param args Accepts no arguments.
+     */
+    public static void main(String[] args) {
+        // The "identity" and "constant" methods should be removed from this test,
+        // because their lambda forms are stored in a static filed and are not GC'ed.
+        // There can be only 5 such LFs for each method, so no memory leak happens.
+        EnumSet<TestMethods> testMethods = EnumSet.complementOf(EnumSet.of(TestMethods.IDENTITY, TestMethods.CONSTANT));
+        LambdaFormTestCase.runTests(LFGarbageCollectedTest::new, testMethods);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java	Tue Sep 16 14:16:55 2014 -0700
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2014, 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 LFMultiThreadCachingTest
+ * @bug 8046703
+ * @summary Test verifies that lambda forms are cached when run with multiple threads
+ * @author kshefov
+ * @library /lib/testlibrary/jsr292 /lib/testlibrary
+ * @build TestMethods
+ * @build LambdaFormTestCase
+ * @build LFCachingTestCase
+ * @build LFMultiThreadCachingTest
+ * @run main/othervm/timeout=300 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true LFMultiThreadCachingTest
+ */
+
+import java.lang.invoke.MethodHandle;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.CyclicBarrier;
+
+/**
+ * Multiple threaded lambda forms caching test class.
+ */
+public final class LFMultiThreadCachingTest extends LFCachingTestCase {
+    private static final TestMethods.Kind[] KINDS;
+    static {
+        EnumSet<TestMethods.Kind> set = EnumSet.complementOf(EnumSet.of(TestMethods.Kind.EXCEPT));
+        KINDS = set.toArray(new TestMethods.Kind[set.size()]);
+        if (KINDS.length < 2) {
+            throw new Error("TESTBUG: KINDS.length[" + KINDS.length + "] should be at least 2");
+        }
+    }
+    private static final int CORES = Math.max(KINDS.length, Runtime.getRuntime().availableProcessors());
+
+    /**
+     * Constructor a for multiple threaded lambda forms caching test case.
+     *
+     * @param testMethod A method from {@code j.l.i.MethodHandles} class that
+     * returns a {@code j.l.i.MethodHandle} instance.
+     */
+    public LFMultiThreadCachingTest(TestMethods testMethod) {
+        super(testMethod);
+    }
+
+    @Override
+    public void doTest() {
+        Map<String, Object> data = getTestMethod().getTestCaseData();
+        ConcurrentLinkedQueue<MethodHandle> adapters = new ConcurrentLinkedQueue<>();
+        CyclicBarrier begin = new CyclicBarrier(CORES);
+        CountDownLatch end = new CountDownLatch(CORES);
+        for (int i = 0; i < CORES; ++i) {
+            TestMethods.Kind kind = KINDS[i % KINDS.length];
+            new Thread(() -> {
+                try {
+                    begin.await();
+                    adapters.add(getTestMethod().getTestCaseMH(data, kind));
+                } catch (InterruptedException | BrokenBarrierException | IllegalAccessException | NoSuchMethodException ex) {
+                    throw new Error("Unexpected exception: ", ex);
+                } finally {
+                    end.countDown();
+                }
+            }).start();
+        }
+        try {
+            end.await();
+        } catch (InterruptedException ex) {
+            throw new Error("Unexpected exception: ", ex);
+        }
+        if (adapters.size() < CORES) {
+            throw new Error("adapters size[" + adapters.size() + "] is less than " + CORES);
+        }
+        MethodHandle prev = adapters.poll();
+        for (MethodHandle current : adapters) {
+            checkLFCaching(prev, current);
+            prev = current;
+        }
+    }
+
+    /**
+     * Main routine for multiple threaded lambda forms caching test.
+     *
+     * @param args Accepts no arguments.
+     */
+    public static void main(String[] args) {
+        LambdaFormTestCase.runTests(LFMultiThreadCachingTest::new, EnumSet.allOf(TestMethods.class));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java	Tue Sep 16 14:16:55 2014 -0700
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, 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 LFSingleThreadCachingTest
+ * @bug 8046703
+ * @summary Test verifies that lambda forms are cached when run with single thread
+ * @author kshefov
+ * @library /lib/testlibrary/jsr292 /lib/testlibrary
+ * @build TestMethods
+ * @build LambdaFormTestCase
+ * @build LFCachingTestCase
+ * @build LFSingleThreadCachingTest
+ * @run main/othervm/timeout=300 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true LFSingleThreadCachingTest
+ */
+
+import java.lang.invoke.MethodHandle;
+import java.util.EnumSet;
+import java.util.Map;
+
+/**
+ * Single threaded lambda forms caching test class.
+ */
+public final class LFSingleThreadCachingTest extends LFCachingTestCase {
+
+    /**
+     * Constructor for a single threaded lambda forms caching test case.
+     *
+     * @param testMethod A method from {@code j.l.i.MethodHandles} class that
+     * returns a {@code j.l.i.MethodHandle} instance.
+     */
+    public LFSingleThreadCachingTest(TestMethods testMethod) {
+        super(testMethod);
+    }
+
+    @Override
+    public void doTest() {
+        MethodHandle adapter1;
+        MethodHandle adapter2;
+        Map<String, Object> data = getTestMethod().getTestCaseData();
+        try {
+            adapter1 = getTestMethod().getTestCaseMH(data, TestMethods.Kind.ONE);
+            adapter2 = getTestMethod().getTestCaseMH(data, TestMethods.Kind.TWO);
+        } catch (NoSuchMethodException | IllegalAccessException ex) {
+            throw new Error("Unexpected exception: ", ex);
+        }
+        checkLFCaching(adapter1, adapter2);
+    }
+
+    /**
+     * Main routine for single threaded lambda forms caching test.
+     *
+     * @param args Accepts no arguments.
+     */
+    public static void main(String[] args) {
+        LambdaFormTestCase.runTests(LFSingleThreadCachingTest::new, EnumSet.allOf(TestMethods.class));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/LFCaching/LambdaFormTestCase.java	Tue Sep 16 14:16:55 2014 -0700
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2014, 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 com.oracle.testlibrary.jsr292.Helper;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.function.Function;
+
+/**
+ * Lambda forms caching test case class. Contains all necessary test routines to
+ * test lambda forms caching in method handles returned by methods of
+ * MethodHandles class.
+ *
+ * @author kshefov
+ */
+public abstract class LambdaFormTestCase {
+
+    private final static String METHOD_HANDLE_CLASS_NAME = "java.lang.invoke.MethodHandle";
+    private final static String INTERNAL_FORM_METHOD_NAME = "internalForm";
+
+    /**
+     * Reflection link to {@code j.l.i.MethodHandle.internalForm} method. It is
+     * used to get a lambda form from a method handle.
+     */
+    protected final static Method INTERNAL_FORM;
+
+    static {
+        try {
+            Class mhClass = Class.forName(METHOD_HANDLE_CLASS_NAME);
+            INTERNAL_FORM = mhClass.getDeclaredMethod(INTERNAL_FORM_METHOD_NAME);
+            INTERNAL_FORM.setAccessible(true);
+        } catch (Exception ex) {
+            throw new Error("Unexpected exception: ", ex);
+        }
+    }
+
+    private final TestMethods testMethod;
+
+    /**
+     * Test case constructor. Generates test cases with random method types for
+     * given methods form {@code j.l.i.MethodHandles} class.
+     *
+     * @param testMethod A method from {@code j.l.i.MethodHandles} class which
+     * returns a {@code j.l.i.MethodHandle}.
+     */
+    protected LambdaFormTestCase(TestMethods testMethod) {
+        this.testMethod = testMethod;
+    }
+
+    public TestMethods getTestMethod() {
+        return testMethod;
+    }
+
+    /**
+     * Routine that executes a test case.
+     */
+    public abstract void doTest();
+
+    /**
+     * Runs a number of test cases defined by the size of testCases list.
+     *
+     * @param ctor constructor of LambdaFormCachingTest or its child classes
+     * object.
+     * @param testMethods list of test methods
+     */
+    public static void runTests(Function<TestMethods, LambdaFormTestCase> ctor, Collection<TestMethods> testMethods) {
+        boolean passed = true;
+        int testCounter = 0;
+        int failCounter = 0;
+        long iterations = Math.max(1, Helper.TEST_LIMIT / testMethods.size());
+        for (long i = 0; i < iterations; i++) {
+            System.err.println(String.format("Iteration %d:", i));
+            for (TestMethods testMethod : testMethods) {
+                LambdaFormTestCase testCase = ctor.apply(testMethod);
+                try {
+                    System.err.printf("Tested LF caching feature with MethodHandles.%s method.%n",
+                            testCase.getTestMethod().name);
+                    testCase.doTest();
+                    System.err.println("PASSED");
+                } catch (Throwable t) {
+                    t.printStackTrace();
+                    System.err.println("FAILED");
+                    passed = false;
+                    failCounter++;
+                }
+                testCounter++;
+            }
+        }
+        if (!passed) {
+            throw new Error(String.format("%d of %d test cases FAILED! %n"
+                    + "Rerun the test with the same \"-Dseed=\" option as in the log file!",
+                    failCounter, testCounter));
+        } else {
+            System.err.println(String.format("All %d test cases PASSED!", testCounter));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/LFCaching/TestMethods.java	Tue Sep 16 14:16:55 2014 -0700
@@ -0,0 +1,698 @@
+/*
+ * Copyright (c) 2014, 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 com.oracle.testlibrary.jsr292.Helper;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Enumeration containing information about methods from
+ * {@code j.l.i.MethodHandles} class that are used for testing lambda forms
+ * caching.
+ *
+ * @author kshefov
+ */
+public enum TestMethods {
+
+    FOLD_ARGUMENTS("foldArguments") {
+                @Override
+                public Map<String, Object> getTestCaseData() {
+                    Map<String, Object> data = new HashMap<>();
+                    int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+                    MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+                    data.put("mtTarget", mtTarget);
+                    // Arity after reducing because of long and double take 2 slots.
+                    int realArity = mtTarget.parameterCount();
+                    int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1);
+                    data.put("modifierMHArgNum", modifierMHArgNum);
+                    Class<?> combinerReturnType;
+                    if (realArity == 0) {
+                        combinerReturnType = void.class;
+                    } else {
+                        combinerReturnType = Helper.RNG.nextBoolean() ? void.class : mtTarget.parameterType(0);
+                    }
+                    data.put("combinerReturnType", combinerReturnType);
+                    return data;
+                }
+
+                @Override
+                protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+                    MethodType mtTarget = (MethodType) data.get("mtTarget");
+                    Class<?> combinerReturnType = (Class) data.get("combinerReturnType");
+                    int modifierMHArgNum = (int) data.get("modifierMHArgNum");
+                    MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+                            mtTarget.parameterList(), kind);
+                    Class<?> rType = mtTarget.returnType();
+                    int combListStart = (combinerReturnType == void.class) ? 0 : 1;
+                    if (modifierMHArgNum < combListStart) {
+                        modifierMHArgNum = combListStart;
+                    }
+                    MethodHandle combiner = TestMethods.methodHandleGenerator(combinerReturnType,
+                            mtTarget.parameterList().subList(combListStart,
+                                    modifierMHArgNum), kind);
+                    return MethodHandles.foldArguments(target, combiner);
+                }
+            },
+    DROP_ARGUMENTS("dropArguments") {
+                @Override
+                public Map<String, Object> getTestCaseData() {
+                    Map<String, Object> data = new HashMap<>();
+                    int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+                    MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+                    data.put("mtTarget", mtTarget);
+                    // Arity after reducing because of long and double take 2 slots.
+                    int realArity = mtTarget.parameterCount();
+                    int dropArgsPos = Helper.RNG.nextInt(realArity + 1);
+                    data.put("dropArgsPos", dropArgsPos);
+                    MethodType mtDropArgs = TestMethods.randomMethodTypeGenerator(
+                            Helper.RNG.nextInt(Helper.MAX_ARITY - realArity));
+                    data.put("mtDropArgs", mtDropArgs);
+                    return data;
+                }
+
+                @Override
+                protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+                    MethodType mtTarget = (MethodType) data.get("mtTarget");
+                    MethodType mtDropArgs = (MethodType) data.get("mtDropArgs");
+                    int dropArgsPos = (int) data.get("dropArgsPos");
+                    MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+                            mtTarget.parameterList(), kind);
+                    int mtTgtSlotsCount = TestMethods.argSlotsCount(mtTarget);
+                    int mtDASlotsCount = TestMethods.argSlotsCount(mtDropArgs);
+                    List<Class<?>> fakeParList;
+                    if (mtTgtSlotsCount + mtDASlotsCount > Helper.MAX_ARITY - 1) {
+                        fakeParList = TestMethods.reduceArgListToSlotsCount(mtDropArgs.parameterList(),
+                                Helper.MAX_ARITY - mtTgtSlotsCount - 1);
+                    } else {
+                        fakeParList = mtDropArgs.parameterList();
+                    }
+                    return MethodHandles.dropArguments(target, dropArgsPos, fakeParList);
+                }
+            },
+    EXPLICIT_CAST_ARGUMENTS("explicitCastArguments") {
+                @Override
+                public Map<String, Object> getTestCaseData() {
+                    Map<String, Object> data = new HashMap<>();
+                    int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY / 2);
+                    MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+                    data.put("mtTarget", mtTarget);
+                    // Arity after reducing because of long and double take 2 slots.
+                    int realArity = mtTarget.parameterCount();
+                    MethodType mtExcplCastArgs = TestMethods.randomMethodTypeGenerator(realArity);
+                    if (mtTarget.returnType() == void.class) {
+                        mtExcplCastArgs = MethodType.methodType(void.class,
+                                mtExcplCastArgs.parameterArray());
+                    }
+                    if (mtExcplCastArgs.returnType() == void.class) {
+                        mtExcplCastArgs = MethodType.methodType(mtTarget.returnType(),
+                                mtExcplCastArgs.parameterArray());
+                    }
+                    data.put("mtExcplCastArgs", mtExcplCastArgs);
+                    return data;
+                }
+
+                @Override
+                protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+                    MethodType mtTarget = (MethodType) data.get("mtTarget");
+                    MethodType mtExcplCastArgs = (MethodType) data.get("mtExcplCastArgs");
+                    MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+                            mtTarget.parameterList(), kind);
+                    return MethodHandles.explicitCastArguments(target, mtExcplCastArgs);
+                }
+            },
+    FILTER_ARGUMENTS("filterArguments") {
+                @Override
+                public Map<String, Object> getTestCaseData() {
+                    Map<String, Object> data = new HashMap<>();
+                    int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY / 2);
+                    MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+                    data.put("mtTarget", mtTarget);
+                    // Arity after reducing because of long and double take 2 slots.
+                    int realArity = mtTarget.parameterCount();
+                    int filterArgsPos = Helper.RNG.nextInt(realArity + 1);
+                    data.put("filterArgsPos", filterArgsPos);
+                    int filtersArgsArrayLength = Helper.RNG.nextInt(realArity + 1 - filterArgsPos);
+                    data.put("filtersArgsArrayLength", filtersArgsArrayLength);
+                    MethodType mtFilter = TestMethods.randomMethodTypeGenerator(filtersArgsArrayLength);
+                    data.put("mtFilter", mtFilter);
+                    return data;
+                }
+
+                @Override
+                protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+                    MethodType mtTarget = (MethodType) data.get("mtTarget");
+                    MethodType mtFilter = (MethodType) data.get("mtFilter");
+                    int filterArgsPos = (int) data.get("filterArgsPos");
+                    int filtersArgsArrayLength = (int) data.get("filtersArgsArrayLength");
+                    MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+                            mtTarget.parameterList(), kind);
+                    MethodHandle[] filters = new MethodHandle[filtersArgsArrayLength];
+                    for (int i = 0; i < filtersArgsArrayLength; i++) {
+                        filters[i] = TestMethods.filterGenerator(mtFilter.parameterType(i),
+                                mtTarget.parameterType(filterArgsPos + i), kind);
+                    }
+                    return MethodHandles.filterArguments(target, filterArgsPos, filters);
+                }
+            },
+    FILTER_RETURN_VALUE("filterReturnValue") {
+                @Override
+                public Map<String, Object> getTestCaseData() {
+                    Map<String, Object> data = new HashMap<>();
+                    int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+                    MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+                    data.put("mtTarget", mtTarget);
+                    // Arity after reducing because of long and double take 2 slots.
+                    int realArity = mtTarget.parameterCount();
+                    int filterArgsPos = Helper.RNG.nextInt(realArity + 1);
+                    int filtersArgsArrayLength = Helper.RNG.nextInt(realArity + 1 - filterArgsPos);
+                    MethodType mtFilter = TestMethods.randomMethodTypeGenerator(filtersArgsArrayLength);
+                    data.put("mtFilter", mtFilter);
+                    return data;
+                }
+
+                @Override
+                protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+                    MethodType mtTarget = (MethodType) data.get("mtTarget");
+                    MethodType mtFilter = (MethodType) data.get("mtFilter");
+                    MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+                            mtTarget.parameterList(), kind);
+                    MethodHandle filter = TestMethods.filterGenerator(mtTarget.returnType(),
+                            mtFilter.returnType(), kind);
+                    return MethodHandles.filterReturnValue(target, filter);
+                }
+            },
+    INSERT_ARGUMENTS("insertArguments") {
+                @Override
+                public Map<String, Object> getTestCaseData() {
+                    Map<String, Object> data = new HashMap<>();
+                    int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+                    MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+                    data.put("mtTarget", mtTarget);
+                    // Arity after reducing because of long and double take 2 slots.
+                    int realArity = mtTarget.parameterCount();
+                    int insertArgsPos = Helper.RNG.nextInt(realArity + 1);
+                    data.put("insertArgsPos", insertArgsPos);
+                    int insertArgsArrayLength = Helper.RNG.nextInt(realArity + 1 - insertArgsPos);
+                    MethodType mtInsertArgs = MethodType.methodType(void.class, mtTarget.parameterList()
+                            .subList(insertArgsPos, insertArgsPos + insertArgsArrayLength));
+                    data.put("mtInsertArgs", mtInsertArgs);
+                    return data;
+                }
+
+                @Override
+                protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+                    MethodType mtTarget = (MethodType) data.get("mtTarget");
+                    MethodType mtInsertArgs = (MethodType) data.get("mtInsertArgs");
+                    int insertArgsPos = (int) data.get("insertArgsPos");
+                    MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+                            mtTarget.parameterList(), kind);
+                    Object[] insertList = Helper.randomArgs(mtInsertArgs.parameterList());
+                    return MethodHandles.insertArguments(target, insertArgsPos, insertList);
+                }
+            },
+    PERMUTE_ARGUMENTS("permuteArguments") {
+                @Override
+                public Map<String, Object> getTestCaseData() {
+                    Map<String, Object> data = new HashMap<>();
+                    int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY / 2);
+                    MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+                    // Arity after reducing because of long and double take 2 slots.
+                    int realArity = mtTarget.parameterCount();
+                    int[] permuteArgsReorderArray = new int[realArity];
+                    int mtParmuteArgsNum = Helper.RNG.nextInt(Helper.MAX_ARITY);
+                    mtParmuteArgsNum = mtParmuteArgsNum == 0 ? 1 : mtParmuteArgsNum;
+                    MethodType mtPermuteArgs = TestMethods.randomMethodTypeGenerator(mtParmuteArgsNum);
+                    mtTarget = mtTarget.changeReturnType(mtPermuteArgs.returnType());
+                    for (int i = 0; i < realArity; i++) {
+                        int mtPermuteArgsParNum = Helper.RNG.nextInt(mtPermuteArgs.parameterCount());
+                        permuteArgsReorderArray[i] = mtPermuteArgsParNum;
+                        mtTarget = mtTarget.changeParameterType(
+                                i, mtPermuteArgs.parameterType(mtPermuteArgsParNum));
+                    }
+                    data.put("mtTarget", mtTarget);
+                    data.put("permuteArgsReorderArray", permuteArgsReorderArray);
+                    data.put("mtPermuteArgs", mtPermuteArgs);
+                    return data;
+                }
+
+                @Override
+                protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+                    MethodType mtTarget = (MethodType) data.get("mtTarget");
+                    MethodType mtPermuteArgs = (MethodType) data.get("mtPermuteArgs");
+                    int[] permuteArgsReorderArray = (int[]) data.get("permuteArgsReorderArray");
+                    MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+                            mtTarget.parameterList(), kind);
+                    return MethodHandles.permuteArguments(target, mtPermuteArgs, permuteArgsReorderArray);
+                }
+            },
+    THROW_EXCEPTION("throwException") {
+                @Override
+                public Map<String, Object> getTestCaseData() {
+                    Map<String, Object> data = new HashMap<>();
+                    int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+                    MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+                    data.put("mtTarget", mtTarget);
+                    return data;
+                }
+
+                @Override
+                protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
+                    MethodType mtTarget = (MethodType) data.get("mtTarget");
+                    Class<?> rType = mtTarget.returnType();
+                    return MethodHandles.throwException(rType, Exception.class
+                    );
+                }
+            },
+    GUARD_WITH_TEST("guardWithTest") {
+                @Override
+                public Map<String, Object> getTestCaseData() {
+                    Map<String, Object> data = new HashMap<>();
+                    int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+                    MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+                    data.put("mtTarget", mtTarget);
+                    // Arity after reducing because of long and double take 2 slots.
+                    int realArity = mtTarget.parameterCount();
+                    int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1);
+                    data.put("modifierMHArgNum", modifierMHArgNum);
+                    return data;
+                }
+
+                @Override
+                protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+                    MethodType mtTarget = (MethodType) data.get("mtTarget");
+                    int modifierMHArgNum = (int) data.get("modifierMHArgNum");
+                    TestMethods.Kind targetKind;
+                    TestMethods.Kind fallbackKind;
+                    if (kind.equals(TestMethods.Kind.ONE)) {
+                        targetKind = TestMethods.Kind.ONE;
+                        fallbackKind = TestMethods.Kind.TWO;
+                    } else {
+                        targetKind = TestMethods.Kind.TWO;
+                        fallbackKind = TestMethods.Kind.ONE;
+                    }
+                    MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+                            mtTarget.parameterList(), targetKind);
+                    MethodHandle fallback = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+                            mtTarget.parameterList(), fallbackKind);
+                    MethodHandle test = TestMethods.methodHandleGenerator(boolean.class,
+                            mtTarget.parameterList().subList(0, modifierMHArgNum), kind);
+                    return MethodHandles.guardWithTest(test, target, fallback);
+                }
+            },
+    CATCH_EXCEPTION("catchException") {
+                @Override
+                public Map<String, Object> getTestCaseData() {
+                    Map<String, Object> data = new HashMap<>();
+                    int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+                    MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+                    data.put("mtTarget", mtTarget);
+                    // Arity after reducing because of long and double take 2 slots.
+                    int realArity = mtTarget.parameterCount();
+                    int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1);
+                    data.put("modifierMHArgNum", modifierMHArgNum);
+                    return data;
+                }
+
+                @Override
+                protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+                    MethodType mtTarget = (MethodType) data.get("mtTarget");
+                    int modifierMHArgNum = (int) data.get("modifierMHArgNum");
+                    MethodHandle target;
+                    if (kind.equals(TestMethods.Kind.ONE)) {
+                        target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+                                mtTarget.parameterList(), TestMethods.Kind.ONE);
+                    } else {
+                        target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+                                mtTarget.parameterList(), TestMethods.Kind.EXCEPT);
+                    }
+                    List<Class<?>> handlerParamList = new ArrayList<>(mtTarget.parameterCount() + 1);
+                    handlerParamList.add(Exception.class);
+                    handlerParamList.addAll(mtTarget.parameterList().subList(0, modifierMHArgNum));
+                    MethodHandle handler = TestMethods.methodHandleGenerator(
+                            mtTarget.returnType(), handlerParamList, TestMethods.Kind.TWO);
+                    return MethodHandles.catchException(target, Exception.class, handler);
+                }
+            },
+    INVOKER("invoker") {
+                @Override
+                public Map<String, Object> getTestCaseData() {
+                    Map<String, Object> data = new HashMap<>();
+                    int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+                    MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+                    data.put("mtTarget", mtTarget);
+                    return data;
+                }
+
+                @Override
+                protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
+                    MethodType mtTarget = (MethodType) data.get("mtTarget");
+                    return MethodHandles.invoker(mtTarget);
+                }
+            },
+    EXACT_INVOKER("exactInvoker") {
+                @Override
+                public Map<String, Object> getTestCaseData() {
+                    Map<String, Object> data = new HashMap<>();
+                    int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+                    MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+                    data.put("mtTarget", mtTarget);
+                    return data;
+                }
+
+                @Override
+                protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
+                    MethodType mtTarget = (MethodType) data.get("mtTarget");
+                    return MethodHandles.exactInvoker(mtTarget);
+                }
+            },
+    SPREAD_INVOKER("spreadInvoker") {
+                @Override
+                public Map<String, Object> getTestCaseData() {
+                    Map<String, Object> data = new HashMap<>();
+                    int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+                    MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+                    data.put("mtTarget", mtTarget);
+                    // Arity after reducing because of long and double take 2 slots.
+                    int realArity = mtTarget.parameterCount();
+                    int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1);
+                    data.put("modifierMHArgNum", modifierMHArgNum);
+                    return data;
+                }
+
+                @Override
+                protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
+                    MethodType mtTarget = (MethodType) data.get("mtTarget");
+                    int modifierMHArgNum = (int) data.get("modifierMHArgNum");
+                    return MethodHandles.spreadInvoker(mtTarget, modifierMHArgNum);
+                }
+            },
+    ARRAY_ELEMENT_GETTER("arrayElementGetter") {
+                @Override
+                public Map<String, Object> getTestCaseData() {
+                    Map<String, Object> data = new HashMap<>();
+                    int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+                    MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+                    data.put("mtTarget", mtTarget);
+                    return data;
+                }
+
+                @Override
+                protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
+                    MethodType mtTarget = (MethodType) data.get("mtTarget");
+                    Class<?> rType = mtTarget.returnType();
+                    if (rType == void.class) {
+                        rType = Object.class;
+                    }
+                    return MethodHandles.arrayElementGetter(Array.newInstance(rType, 2).getClass());
+                }
+            },
+    ARRAY_ELEMENT_SETTER("arrayElementSetter") {
+                @Override
+                public Map<String, Object> getTestCaseData() {
+                    Map<String, Object> data = new HashMap<>();
+                    int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+                    MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+                    data.put("mtTarget", mtTarget);
+                    return data;
+                }
+
+                @Override
+                protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
+                    MethodType mtTarget = (MethodType) data.get("mtTarget");
+                    Class<?> rType = mtTarget.returnType();
+                    if (rType == void.class) {
+                        rType = Object.class;
+                    }
+                    return MethodHandles.arrayElementSetter(Array.newInstance(rType, 2).getClass());
+                }
+            },
+    CONSTANT("constant") {
+                @Override
+                public Map<String, Object> getTestCaseData() {
+                    Map<String, Object> data = new HashMap<>();
+                    int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+                    MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+                    data.put("mtTarget", mtTarget);
+                    return data;
+                }
+
+                @Override
+                protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
+                    MethodType mtTarget = (MethodType) data.get("mtTarget");
+                    Class<?> rType = mtTarget.returnType();
+                    if (rType == void.class) {
+                        rType = Object.class;
+                    }
+                    if (rType.equals(boolean.class)) {
+                        // There should be the same return values because for default values there are special "zero" forms
+                        return MethodHandles.constant(rType, true);
+                    } else {
+                        return MethodHandles.constant(rType, kind.getValue(rType));
+                    }
+                }
+            },
+    IDENTITY("identity") {
+                @Override
+                public Map<String, Object> getTestCaseData() {
+                    Map<String, Object> data = new HashMap<>();
+                    int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+                    MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+                    data.put("mtTarget", mtTarget);
+                    return data;
+                }
+
+                @Override
+                protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
+                    MethodType mtTarget = (MethodType) data.get("mtTarget");
+                    Class<?> rType = mtTarget.returnType();
+                    if (rType == void.class) {
+                        rType = Object.class;
+                    }
+                    return MethodHandles.identity(rType);
+                }
+            };
+
+    /**
+     * Test method's name.
+     */
+    public final String name;
+
+    private TestMethods(String name) {
+        this.name = name;
+    }
+
+    protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+        throw new UnsupportedOperationException("TESTBUG: getMH method is not implemented for test method " + this);
+    }
+
+    /**
+     * Creates an adapter method handle depending on a test method from
+     * MethodHandles class. Adapter is what is returned by the test method. This
+     * method is able to create two kinds of adapters, their type will be the
+     * same, but return values are different.
+     *
+     * @param data a Map containing data to create a method handle, can be
+     * obtained by {@link #getTestCaseData} method
+     * @param kind defines whether adapter ONE or adapter TWO will be
+     * initialized. Should be equal to TestMethods.Kind.ONE or
+     * TestMethods.Kind.TWO
+     * @return Method handle adapter that behaves according to
+     * TestMethods.Kind.ONE or TestMethods.Kind.TWO
+     * @throws java.lang.NoSuchMethodException
+     * @throws java.lang.IllegalAccessException
+     */
+    public MethodHandle getTestCaseMH(Map<String, Object> data, TestMethods.Kind kind)
+            throws NoSuchMethodException, IllegalAccessException {
+        if (data == null) {
+            throw new Error(String.format("TESTBUG: Data for test method %s is not prepared",
+                    this.name));
+        }
+        if (!kind.equals(TestMethods.Kind.ONE) && !kind.equals(TestMethods.Kind.TWO)) {
+            throw new IllegalArgumentException("TESTBUG: Wrong \"kind\" (" + kind
+                    + ") arg to getTestCaseMH function."
+                    + " Should be Kind.ONE or Kind.TWO");
+        }
+        return getMH(data, kind);
+    }
+
+    /**
+     * Returns a data Map needed for {@link #getTestCaseMH} method.
+     *
+     * @return data Map needed for {@link #getTestCaseMH} method
+     */
+    public Map<String, Object> getTestCaseData() {
+        throw new UnsupportedOperationException(
+                "TESTBUG: getTestCaseData method is not implemented for test method " + this);
+    }
+
+    /**
+     * Enumeration used in methodHandleGenerator to define whether a MH returned
+     * by this method returns "2" in different type representations, "4", or
+     * throw an Exception.
+     */
+    public static enum Kind {
+
+        ONE(2),
+        TWO(4),
+        EXCEPT(0);
+
+        private final int value;
+
+        private Object getValue(Class<?> cl) {
+            return Helper.castToWrapper(value, cl);
+        }
+
+        private MethodHandle getBasicMH(Class<?> rType) throws NoSuchMethodException, IllegalAccessException {
+            MethodHandle result = null;
+            switch (this) {
+                case ONE:
+                case TWO:
+                    if (rType.equals(void.class)) {
+                        result = MethodHandles.lookup().findVirtual(Kind.class, "returnVoid", MethodType.methodType(void.class));
+                        result = MethodHandles.insertArguments(result, 0, this);
+                    } else {
+                        result = MethodHandles.constant(rType, getValue(rType));
+                    }
+                    break;
+                case EXCEPT:
+                    result = MethodHandles.throwException(rType, Exception.class);
+                    result = MethodHandles.insertArguments(result, 0, new Exception());
+                    break;
+            }
+            return result;
+        }
+
+        private void returnVoid() {
+        }
+
+        private Kind(int value) {
+            this.value = value;
+        }
+    }
+
+    /**
+     * Routine used to obtain a randomly generated method type.
+     *
+     * @param arity Arity of returned method type.
+     * @return MethodType generated randomly.
+     */
+    private static MethodType randomMethodTypeGenerator(int arity) {
+        final Class<?>[] CLASSES = {
+            Object.class,
+            int.class,
+            boolean.class,
+            byte.class,
+            short.class,
+            char.class,
+            long.class,
+            float.class,
+            double.class
+        };
+        if (arity > Helper.MAX_ARITY) {
+            throw new IllegalArgumentException(
+                    String.format("Arity should not exceed %d!", Helper.MAX_ARITY));
+        }
+        List<Class<?>> list = Helper.randomClasses(CLASSES, arity);
+        list = Helper.getParams(list, false, arity);
+        int i = Helper.RNG.nextInt(CLASSES.length + 1);
+        Class<?> rtype = i == CLASSES.length ? void.class : CLASSES[i];
+        return MethodType.methodType(rtype, list);
+    }
+
+    /**
+     * Routine used to obtain a method handles of a given type an kind (return
+     * value).
+     *
+     * @param returnType Type of MH return value.
+     * @param argTypes Types of MH args.
+     * @param kind Defines whether the obtained MH returns "1" or "2".
+     * @return Method handle of the given type.
+     * @throws NoSuchMethodException
+     * @throws IllegalAccessException
+     */
+    private static MethodHandle methodHandleGenerator(Class<?> returnType,
+            List<Class<?>> argTypes, TestMethods.Kind kind)
+            throws NoSuchMethodException, IllegalAccessException {
+        MethodHandle result;
+        result = kind.getBasicMH(returnType);
+        return Helper.addTrailingArgs(result, argTypes.size(), argTypes);
+    }
+
+    /**
+     * Routine that generates filter method handles to test
+     * MethodHandles.filterArguments method.
+     *
+     * @param inputType Filter's argument type.
+     * @param returnType Filter's return type.
+     * @param kind Filter's return value definer.
+     * @return A filter method handle, that takes one argument.
+     * @throws NoSuchMethodException
+     * @throws IllegalAccessException
+     */
+    private static MethodHandle filterGenerator(Class<?> inputType, Class<?> returnType,
+            TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+        MethodHandle tmpMH = kind.getBasicMH(returnType);
+        if (inputType.equals(void.class)) {
+            return tmpMH;
+        }
+        ArrayList<Class<?>> inputTypeList = new ArrayList<>(1);
+        inputTypeList.add(inputType);
+        return Helper.addTrailingArgs(tmpMH, 1, inputTypeList);
+    }
+
+    private static int argSlotsCount(MethodType mt) {
+        int result = 0;
+        for (Class cl : mt.parameterArray()) {
+            if (cl.equals(long.class) || cl.equals(double.class)) {
+                result += 2;
+            } else {
+                result++;
+            }
+        }
+        return result;
+    }
+
+    private static List<Class<?>> reduceArgListToSlotsCount(List<Class<?>> list,
+            int desiredSlotCount) {
+        List<Class<?>> result = new ArrayList<>(desiredSlotCount);
+        int count = 0;
+        for (Class<?> cl : list) {
+            if (count >= desiredSlotCount) {
+                break;
+            }
+            if (cl.equals(long.class) || cl.equals(double.class)) {
+                count += 2;
+            } else {
+                count++;
+            }
+            result.add(cl);
+        }
+        return result;
+    }
+}
--- a/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java	Tue Sep 16 11:51:52 2014 -0700
+++ b/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java	Tue Sep 16 14:16:55 2014 -0700
@@ -43,6 +43,7 @@
 public class CatchExceptionTest {
     private static final List<Class<?>> ARGS_CLASSES;
     protected static final int MAX_ARITY = Helper.MAX_ARITY - 1;
+
     static {
         Class<?> classes[] = {
                 Object.class,
@@ -53,11 +54,8 @@
                 double[].class,
                 String.class,
         };
-        List<Class<?>> list = new ArrayList<>(MAX_ARITY);
-        for (int i = 0; i < MAX_ARITY; ++i) {
-            list.add(classes[Helper.RNG.nextInt(classes.length)]);
-        }
-        ARGS_CLASSES = Collections.unmodifiableList(list);
+        ARGS_CLASSES = Collections.unmodifiableList(
+                Helper.randomClasses(classes, MAX_ARITY));
     }
 
     private final TestCase testCase;
@@ -67,7 +65,6 @@
     private int dropped;
     private MethodHandle thrower;
 
-
     public CatchExceptionTest(TestCase testCase, final boolean isVararg, final int argsCount,
             final int catchDrops) {
         this.testCase = testCase;
@@ -108,37 +105,7 @@
     }
 
     private List<Class<?>> getThrowerParams(boolean isVararg, int argsCount) {
-        boolean unmodifiable = true;
-        List<Class<?>> classes;
-        classes = ARGS_CLASSES.subList(0,
-                Math.min(argsCount, (MAX_ARITY / 2) - 1));
-        int extra = 0;
-        if (argsCount >= MAX_ARITY / 2) {
-            classes = new ArrayList<>(classes);
-            unmodifiable = false;
-            extra = (int) classes.stream().filter(Helper::isDoubleCost).count();
-            int i = classes.size();
-            while (classes.size() + extra < argsCount) {
-                Class<?> aClass = ARGS_CLASSES.get(i);
-                if (Helper.isDoubleCost(aClass)) {
-                    ++extra;
-                    if (classes.size() + extra >= argsCount) {
-                        break;
-                    }
-                }
-                classes.add(aClass);
-            }
-        }
-        if (isVararg && classes.size() > 0) {
-            if (unmodifiable) {
-                classes = new ArrayList<>(classes);
-            }
-            int last = classes.size() - 1;
-            Class<?> aClass = classes.get(classes.size() - 1);
-            aClass = Array.newInstance(aClass, 2).getClass();
-            classes.set(last, aClass);
-        }
-        return classes;
+        return Helper.getParams(ARGS_CLASSES, isVararg, argsCount);
     }
 
 
--- a/test/java/net/NetworkInterface/Test.java	Tue Sep 16 11:51:52 2014 -0700
+++ b/test/java/net/NetworkInterface/Test.java	Tue Sep 16 14:16:55 2014 -0700
@@ -22,7 +22,9 @@
  */
 
 /* @test
- * @bug 4405354 6594296
+ * @bug 4405354 6594296 8058216
+ * @run main Test
+ * @run main/othervm -Djava.net.preferIPv4Stack=true Test
  * @summary Basic tests for NetworkInterface
  */
 import java.net.NetworkInterface;
--- a/test/javax/management/monitor/AttributeArbitraryDataTypeTest.java	Tue Sep 16 11:51:52 2014 -0700
+++ b/test/javax/management/monitor/AttributeArbitraryDataTypeTest.java	Tue Sep 16 14:16:55 2014 -0700
@@ -58,9 +58,9 @@
 public class AttributeArbitraryDataTypeTest implements NotificationListener {
 
     // Flag to notify that a message has been received
-    private boolean counterMessageReceived = false;
-    private boolean gaugeMessageReceived = false;
-    private boolean stringMessageReceived = false;
+    private volatile boolean counterMessageReceived = false;
+    private volatile boolean gaugeMessageReceived = false;
+    private volatile boolean stringMessageReceived = false;
 
     // Match enum
     public enum Match { do_not_match_0,
@@ -195,21 +195,33 @@
                      " has reached or exceeded the threshold");
                 echo("\t\tDerived Gauge = " + n.getDerivedGauge());
                 echo("\t\tTrigger = " + n.getTrigger());
-                counterMessageReceived = true;
+
+                synchronized (this) {
+                    counterMessageReceived = true;
+                    notifyAll();
+                }
             } else if (type.equals(MonitorNotification.
                                    THRESHOLD_HIGH_VALUE_EXCEEDED)) {
                 echo("\t\t" + n.getObservedAttribute() +
                      " has reached or exceeded the high threshold");
                 echo("\t\tDerived Gauge = " + n.getDerivedGauge());
                 echo("\t\tTrigger = " + n.getTrigger());
-                gaugeMessageReceived = true;
+
+                synchronized (this) {
+                    gaugeMessageReceived = true;
+                    notifyAll();
+                }
             } else if (type.equals(MonitorNotification.
                                    STRING_TO_COMPARE_VALUE_MATCHED)) {
                 echo("\t\t" + n.getObservedAttribute() +
                      " matches the string-to-compare value");
                 echo("\t\tDerived Gauge = " + n.getDerivedGauge());
                 echo("\t\tTrigger = " + n.getTrigger());
-                stringMessageReceived = true;
+
+                synchronized (this) {
+                    stringMessageReceived = true;
+                    notifyAll();
+                }
             } else {
                 echo("\t\tSkipping notification of type: " + type);
             }
@@ -358,6 +370,17 @@
 
             // Check if notification was received
             //
+            synchronized (this) {
+                while (!counterMessageReceived) {
+                    try {
+                        wait();
+                    } catch (InterruptedException e) {
+                        System.err.println("Got unexpected exception: " + e);
+                        e.printStackTrace();
+                        break;
+                    }
+                }
+            }
             if (counterMessageReceived) {
                 echo("\tOK: CounterMonitor notification received");
             } else {
@@ -525,6 +548,17 @@
 
             // Check if notification was received
             //
+            synchronized (this) {
+                while (!gaugeMessageReceived) {
+                    try {
+                        wait();
+                    } catch (InterruptedException e) {
+                        System.err.println("Got unexpected exception: " + e);
+                        e.printStackTrace();
+                        break;
+                    }
+                }
+            }
             if (gaugeMessageReceived) {
                 echo("\tOK: GaugeMonitor notification received");
             } else {
@@ -680,6 +714,17 @@
 
             // Check if notification was received
             //
+            synchronized (this) {
+                while (!stringMessageReceived) {
+                    try {
+                        wait();
+                    } catch (InterruptedException e) {
+                        System.err.println("Got unexpected exception: " + e);
+                        e.printStackTrace();
+                        break;
+                    }
+                }
+            }
             if (stringMessageReceived) {
                 echo("\tOK: StringMonitor notification received");
             } else {
--- a/test/javax/management/monitor/CounterMonitorTest.java	Tue Sep 16 11:51:52 2014 -0700
+++ b/test/javax/management/monitor/CounterMonitorTest.java	Tue Sep 16 14:16:55 2014 -0700
@@ -43,9 +43,6 @@
     // modulus number
     private Number modulus = new Integer(7);
 
-    // offset number
-    private int offset = 0;
-
     // difference mode flag
     private boolean differenceModeFlag = true;
 
@@ -58,9 +55,6 @@
     // counter values
     private int[] values = new int[] {4, 6, 9, 11};
 
-    // time to wait for notification (in seconds)
-    private int timeout = 5;
-
     // flag to notify that a message has been received
     private volatile boolean messageReceived = false;
 
@@ -92,8 +86,9 @@
                 echo("\t\t" + n.getObservedAttribute() +
                      " has reached or exceeded the threshold");
                 echo("\t\tDerived Gauge = " + n.getDerivedGauge());
-                messageReceived = true;
+
                 synchronized (this) {
+                    messageReceived = true;
                     notifyAll();
                 }
             } else {
@@ -205,22 +200,17 @@
     }
 
     /*
-     * Wait until timeout reached
+     * Wait messageReceived to be true
      */
-    void doWait() {
-        for (int i = 0; i < timeout; i++) {
-            echo("\tdoWait: Waiting for " + timeout + " seconds. " +
-                 "i = " + i + ", messageReceived = " + messageReceived);
-            if (messageReceived) {
+    synchronized void doWait() {
+        while (!messageReceived) {
+            try {
+                wait();
+            } catch (InterruptedException e) {
+                System.err.println("Got unexpected exception: " + e);
+                e.printStackTrace();
                 break;
             }
-            try {
-                synchronized (this) {
-                    wait(1000);
-                }
-            } catch (InterruptedException e) {
-                // OK: Ignore...
-            }
         }
     }
 
--- a/test/javax/management/monitor/NonComparableAttributeValueTest.java	Tue Sep 16 11:51:52 2014 -0700
+++ b/test/javax/management/monitor/NonComparableAttributeValueTest.java	Tue Sep 16 14:16:55 2014 -0700
@@ -39,7 +39,7 @@
 public class NonComparableAttributeValueTest implements NotificationListener {
 
     // Flag to notify that a message has been received
-    private boolean messageReceived = false;
+    private volatile boolean messageReceived = false;
 
     // MBean class
     public class ObservedObject implements ObservedObjectMBean {
@@ -69,7 +69,11 @@
                 echo("\t\t" + n.getObservedAttribute() + " is null");
                 echo("\t\tDerived Gauge = " + n.getDerivedGauge());
                 echo("\t\tTrigger = " + n.getTrigger());
-                messageReceived = true;
+
+                synchronized (this) {
+                    messageReceived = true;
+                    notifyAll();
+                }
             } else {
                 echo("\t\tSkipping notification of type: " + type);
             }
@@ -134,12 +138,9 @@
             echo(">>> START the CounterMonitor");
             counterMonitor.start();
 
-            // Wait for granularity period (multiplied by 2 for sure)
-            //
-            Thread.sleep(granularityperiod * 2);
-
             // Check if notification was received
             //
+            doWait();
             if (messageReceived) {
                 echo("\tOK: CounterMonitor notification received");
             } else {
@@ -212,12 +213,9 @@
             echo(">>> START the GaugeMonitor");
             gaugeMonitor.start();
 
-            // Wait for granularity period (multiplied by 2 for sure)
-            //
-            Thread.sleep(granularityperiod * 2);
-
             // Check if notification was received
             //
+            doWait();
             if (messageReceived) {
                 echo("\tOK: GaugeMonitor notification received");
             } else {
@@ -289,12 +287,9 @@
             echo(">>> START the StringMonitor");
             stringMonitor.start();
 
-            // Wait for granularity period (multiplied by 2 for sure)
-            //
-            Thread.sleep(granularityperiod * 2);
-
             // Check if notification was received
             //
+            doWait();
             if (messageReceived) {
                 echo("\tOK: StringMonitor notification received");
             } else {
@@ -334,6 +329,21 @@
     }
 
     /*
+     * Wait messageReceived to be true
+     */
+    synchronized void doWait() {
+        while (!messageReceived) {
+            try {
+                wait();
+            } catch (InterruptedException e) {
+                System.err.println("Got unexpected exception: " + e);
+                e.printStackTrace();
+                break;
+            }
+        }
+    }
+
+    /*
      * Standalone entry point.
      *
      * Run the test and report to stdout.
--- a/test/javax/management/monitor/ReflectionExceptionTest.java	Tue Sep 16 11:51:52 2014 -0700
+++ b/test/javax/management/monitor/ReflectionExceptionTest.java	Tue Sep 16 14:16:55 2014 -0700
@@ -87,7 +87,11 @@
                 echo("\tObservedAttribute: " + mn.getObservedAttribute());
                 echo("\tDerivedGauge: " + mn.getDerivedGauge());
                 echo("\tTrigger: " + mn.getTrigger());
-                messageReceived = true;
+
+                synchronized (this) {
+                    messageReceived = true;
+                    notifyAll();
+                }
             }
         }
     }
@@ -135,12 +139,9 @@
             echo(">>> START the CounterMonitor");
             counterMonitor.start();
 
-            // Wait for granularity period (multiplied by 2 for sure)
-            //
-            Thread.sleep(granularityperiod * 2);
-
             // Check if notification was received
             //
+            doWait();
             if (messageReceived) {
                 echo("\tOK: CounterMonitor got RUNTIME_ERROR notification!");
             } else {
@@ -203,12 +204,9 @@
             echo(">>> START the GaugeMonitor");
             gaugeMonitor.start();
 
-            // Wait for granularity period (multiplied by 2 for sure)
-            //
-            Thread.sleep(granularityperiod * 2);
-
             // Check if notification was received
             //
+            doWait();
             if (messageReceived) {
                 echo("\tOK: GaugeMonitor got RUNTIME_ERROR notification!");
             } else {
@@ -270,12 +268,9 @@
             echo(">>> START the StringMonitor");
             stringMonitor.start();
 
-            // Wait for granularity period (multiplied by 2 for sure)
-            //
-            Thread.sleep(granularityperiod * 2);
-
             // Check if notification was received
             //
+            doWait();
             if (messageReceived) {
                 echo("\tOK: StringMonitor got RUNTIME_ERROR notification!");
             } else {
@@ -349,8 +344,23 @@
         }
     }
 
+    /*
+     * Wait messageReceived to be true
+     */
+    synchronized void doWait() {
+        while (!messageReceived) {
+            try {
+                wait();
+            } catch (InterruptedException e) {
+                System.err.println("Got unexpected exception: " + e);
+                e.printStackTrace();
+                break;
+            }
+        }
+    }
+
     // Flag to notify that a message has been received
-    private boolean messageReceived = false;
+    private volatile boolean messageReceived = false;
 
     private MBeanServer server;
     private ObjectName obsObjName;
--- a/test/javax/management/monitor/RuntimeExceptionTest.java	Tue Sep 16 11:51:52 2014 -0700
+++ b/test/javax/management/monitor/RuntimeExceptionTest.java	Tue Sep 16 14:16:55 2014 -0700
@@ -86,7 +86,11 @@
                 echo("\tObservedAttribute: " + mn.getObservedAttribute());
                 echo("\tDerivedGauge: " + mn.getDerivedGauge());
                 echo("\tTrigger: " + mn.getTrigger());
-                messageReceived = true;
+
+                synchronized (this) {
+                    messageReceived = true;
+                    notifyAll();
+                }
             }
         }
     }
@@ -134,12 +138,9 @@
             echo(">>> START the CounterMonitor");
             counterMonitor.start();
 
-            // Wait for granularity period (multiplied by 2 for sure)
-            //
-            Thread.sleep(granularityperiod * 2);
-
             // Check if notification was received
             //
+            doWait();
             if (messageReceived) {
                 echo("\tOK: CounterMonitor got RUNTIME_ERROR notification!");
             } else {
@@ -202,12 +203,9 @@
             echo(">>> START the GaugeMonitor");
             gaugeMonitor.start();
 
-            // Wait for granularity period (multiplied by 2 for sure)
-            //
-            Thread.sleep(granularityperiod * 2);
-
             // Check if notification was received
             //
+            doWait();
             if (messageReceived) {
                 echo("\tOK: GaugeMonitor got RUNTIME_ERROR notification!");
             } else {
@@ -269,12 +267,9 @@
             echo(">>> START the StringMonitor");
             stringMonitor.start();
 
-            // Wait for granularity period (multiplied by 2 for sure)
-            //
-            Thread.sleep(granularityperiod * 2);
-
             // Check if notification was received
             //
+            doWait();
             if (messageReceived) {
                 echo("\tOK: StringMonitor got RUNTIME_ERROR notification!");
             } else {
@@ -347,8 +342,23 @@
         }
     }
 
+    /*
+     * Wait messageReceived to be true
+     */
+    synchronized void doWait() {
+        while (!messageReceived) {
+            try {
+                wait();
+            } catch (InterruptedException e) {
+                System.err.println("Got unexpected exception: " + e);
+                e.printStackTrace();
+                break;
+            }
+        }
+    }
+
     // Flag to notify that a message has been received
-    private boolean messageReceived = false;
+    private volatile boolean messageReceived = false;
 
     private MBeanServer server;
     private ObjectName obsObjName;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/net/ssl/TLSv12/ProtocolFilter.java	Tue Sep 16 14:16:55 2014 -0700
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+
+/*
+ * @test
+ * @bug 8052406
+ * @summary SSLv2Hello protocol may be filter out unexpectedly
+ * @run main/othervm ProtocolFilter
+ */
+
+import java.io.*;
+import java.net.*;
+import javax.net.ssl.*;
+
+public class ProtocolFilter {
+
+    /*
+     * =============================================================
+     * 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 = "../../../../sun/security/ssl/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);
+
+        // Only enable cipher suites for TLS v1.2.
+        sslServerSocket.setEnabledCipherSuites(
+            new String[]{"TLS_RSA_WITH_AES_128_CBC_SHA256"});
+
+        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(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);
+        }
+
+        SSLSocketFactory sslsf =
+            (SSLSocketFactory) SSLSocketFactory.getDefault();
+        SSLSocket sslSocket = (SSLSocket)
+            sslsf.createSocket("localhost", serverPort);
+
+        // Enable all supported protocols, including SSLv2Hello.
+        sslSocket.setEnabledProtocols(sslSocket.getSupportedProtocols());
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslOS.write(280);
+        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 ProtocolFilter();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    ProtocolFilter() throws Exception {
+        Exception startException = null;
+        try {
+            if (separateServerThread) {
+                startServer(true);
+                startClient(false);
+            } else {
+                startClient(true);
+                startServer(false);
+            }
+        } catch (Exception e) {
+            startException = e;
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            if (serverThread != null) {
+                serverThread.join();
+            }
+        } else {
+            if (clientThread != null) {
+                clientThread.join();
+            }
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         * Which side threw the error?
+         */
+        Exception local;
+        Exception remote;
+
+        if (separateServerThread) {
+            remote = serverException;
+            local = clientException;
+        } else {
+            remote = clientException;
+            local = serverException;
+        }
+
+        Exception exception = null;
+
+        /*
+         * Check various exception conditions.
+         */
+        if ((local != null) && (remote != null)) {
+            // If both failed, return the curthread's exception.
+            local.initCause(remote);
+            exception = local;
+        } else if (local != null) {
+            exception = local;
+        } else if (remote != null) {
+            exception = remote;
+        } else if (startException != null) {
+            exception = startException;
+        }
+
+        /*
+         * If there was an exception *AND* a startException,
+         * output it.
+         */
+        if (exception != null) {
+            if (exception != startException && startException != null) {
+                exception.addSuppressed(startException);
+            }
+            throw exception;
+        }
+
+        // Fall-through: no exception to throw!
+    }
+
+    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/test/javax/swing/text/View/8048110/bug8048110.java	Tue Sep 16 14:16:55 2014 -0700
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2014, 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 8048110
+ * @summary Using tables in JTextPane leads to infinite loop in FlowLayout.layoutRow
+ * @author Dmitry Markov
+ * @run main bug8048110
+ */
+
+import sun.awt.SunToolkit;
+
+import javax.swing.*;
+import javax.swing.text.Element;
+import javax.swing.text.html.HTMLDocument;
+import javax.swing.text.html.HTMLEditorKit;
+import java.awt.*;
+
+public class bug8048110 {
+    private static SunToolkit toolkit = (SunToolkit)Toolkit.getDefaultToolkit();
+    private static Object lock = new Object();
+    private static boolean isRealSyncPerformed = false;
+    private static final String htmlText = "<table width=\"100%\" cellpadding=\"10\" cellspacing=\"5\" align=\"center\">" +
+            "<tr><th align=\"left\" bgcolor=\"#bec3c6\">Devices</th><th align=\"left\" bgcolor=\"#bec3c6\">State</th></tr>" +
+            "<tr><td align=\"left\" bgcolor=\"#bec3c6\">PC</td><td align=\"left\" bgcolor=\"#46a055\">Ok</td></tr></table>";
+
+    public static void main(String[] args) throws Exception {
+        SwingUtilities.invokeAndWait(new Runnable() {
+            @Override
+            public void run() {
+                createAndShowGUI();
+            }
+        });
+
+        Thread thread = new Thread() {
+            @Override
+            public void run() {
+                toolkit.realSync();
+                synchronized (lock) {
+                    isRealSyncPerformed = true;
+                    lock.notifyAll();
+                }
+            }
+        };
+        thread.start();
+
+        synchronized (lock) {
+            if (!isRealSyncPerformed) {
+                lock.wait(5000);
+            }
+        }
+
+        if (!isRealSyncPerformed) {
+            throw new RuntimeException("Test Failed!");
+        }
+    }
+
+    private static void createAndShowGUI() {
+        try {
+            UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
+        } catch (Exception ex) {
+            throw new RuntimeException(ex);
+        }
+        HTMLEditorKit editorKit = new HTMLEditorKit();
+        JTextPane textPane = new JTextPane();
+        textPane.setContentType("text/html");
+        textPane.setEditorKit(editorKit);
+        textPane.setText("Initial text without table");
+
+        JFrame frame = new JFrame("bug8048110");
+        frame.getContentPane().add(textPane, BorderLayout.CENTER);
+        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+        frame.setSize(500, 200);
+        frame.setVisible(true);
+
+        textPane.setDocument(textPane.getEditorKit().createDefaultDocument());
+        HTMLDocument htmlDocument = (HTMLDocument) textPane.getDocument();
+        Element firstParagraph = findFirstElement(textPane.getDocument().getDefaultRootElement(), "p");
+
+        try {
+            htmlDocument.setInnerHTML(firstParagraph, htmlText);
+        } catch (Exception ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private static Element findFirstElement(Element e, String name) {
+        String elementName = e.getName();
+        if (elementName != null && elementName.equalsIgnoreCase(name)) {
+            return e;
+        }
+        for (int i = 0; i < e.getElementCount(); i++) {
+            Element result = findFirstElement(e.getElement(i), name);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+}
+
--- a/test/lib/testlibrary/jsr292/com/oracle/testlibrary/jsr292/Helper.java	Tue Sep 16 11:51:52 2014 -0700
+++ b/test/lib/testlibrary/jsr292/com/oracle/testlibrary/jsr292/Helper.java	Tue Sep 16 14:16:55 2014 -0700
@@ -52,7 +52,7 @@
     public static final long TEST_LIMIT;
     static {
         String str = System.getProperty("testLimit");
-        TEST_LIMIT = str != null ? Long.parseUnsignedLong(str) : 2_000L;
+        TEST_LIMIT = str != null ? Long.parseUnsignedLong(str) : 2000L;
         System.out.printf("-DtestLimit=%d%n", TEST_LIMIT);
     }
 
@@ -116,6 +116,48 @@
         return size <= lag ? null : calledLog.get(size - lag - 1);
     }
 
+    public static List<Class<?>> randomClasses(Class<?>[] classes, int size) {
+        List<Class<?>> result = new ArrayList<>(size);
+        for (int i = 0; i < size; ++i) {
+            result.add(classes[RNG.nextInt(classes.length)]);
+        }
+        return result;
+    }
+
+    public static List<Class<?>> getParams(List<Class<?>> classes,
+            boolean isVararg, int argsCount) {
+        boolean unmodifiable = true;
+        List<Class<?>> result = classes.subList(0,
+                Math.min(argsCount, (MAX_ARITY / 2) - 1));
+        int extra = 0;
+        if (argsCount >= MAX_ARITY / 2) {
+            result = new ArrayList<>(result);
+            unmodifiable = false;
+            extra = (int) result.stream().filter(Helper::isDoubleCost).count();
+            int i = result.size();
+            while (result.size() + extra < argsCount) {
+                Class<?> aClass = classes.get(i);
+                if (Helper.isDoubleCost(aClass)) {
+                    ++extra;
+                    if (result.size() + extra >= argsCount) {
+                        break;
+                    }
+                }
+                result.add(aClass);
+            }
+        }
+        if (isVararg && result.size() > 0) {
+            if (unmodifiable) {
+                result = new ArrayList<>(result);
+            }
+            int last = result.size() - 1;
+            Class<?> aClass = result.get(last);
+            aClass = Array.newInstance(aClass, 2).getClass();
+            result.set(last, aClass);
+        }
+        return result;
+    }
+
     public static MethodHandle addTrailingArgs(MethodHandle target, int nargs,
             List<Class<?>> classes) {
         int targetLen = target.type().parameterCount();
@@ -230,7 +272,7 @@
         return randomArgs(params.toArray(new Class<?>[params.size()]));
     }
 
-    private static Object castToWrapper(Object value, Class<?> dst) {
+    public static Object castToWrapper(Object value, Class<?> dst) {
         Object wrap = null;
         if (value instanceof Number) {
             wrap = castToWrapperOrNull(((Number) value).longValue(), dst);
@@ -268,7 +310,7 @@
         if (dst == byte.class || dst == Byte.class) {
             return (byte) (value);
         }
-        if (dst == boolean.class || dst == boolean.class) {
+        if (dst == boolean.class || dst == Boolean.class) {
             return ((value % 29) & 1) == 0;
         }
         return null;