5088398: 3/2 java.lang.instrument TCK test deadlock (test11)

Add regression test for single-threaded bootstrap classloader.

Reviewed-by: sspitsyn
diff --git a/jdk/test/java/lang/instrument/ParallelTransformerLoader.sh b/jdk/test/java/lang/instrument/ParallelTransformerLoader.sh
new file mode 100644
index 0000000..cab081a
--- /dev/null
+++ b/jdk/test/java/lang/instrument/ParallelTransformerLoader.sh
@@ -0,0 +1,72 @@
+#
+# Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+# @test
+# @bug 5088398
+# @summary Test parallel class loading by parallel transformers.
+# @author Daniel D. Daugherty as modified from the code of Daryl Puryear @ Wily
+#
+# @run shell MakeJAR3.sh ParallelTransformerLoaderAgent
+# @run build ParallelTransformerLoaderApp
+# @run shell/timeout=240 ParallelTransformerLoader.sh
+#
+
+if [ "${TESTJAVA}" = "" ]
+then
+  echo "TESTJAVA not set.  Test cannot execute.  Failed."
+  exit 1
+fi
+
+if [ "${TESTSRC}" = "" ]
+then
+  echo "TESTSRC not set.  Test cannot execute.  Failed."
+  exit 1
+fi
+
+if [ "${TESTCLASSES}" = "" ]
+then
+  echo "TESTCLASSES not set.  Test cannot execute.  Failed."
+  exit 1
+fi
+
+JAR="${TESTJAVA}"/bin/jar
+JAVAC="${TESTJAVA}"/bin/javac
+JAVA="${TESTJAVA}"/bin/java
+
+"${JAVAC}" -d . \
+    "${TESTSRC}"/TestClass1.java \
+    "${TESTSRC}"/TestClass2.java \
+    "${TESTSRC}"/TestClass3.java
+
+"${JAR}" cvf Test.jar Test*.class
+# Removing the test class files is important. If these
+# .class files are available on the classpath other
+# than via Test.jar, then the deadlock will not reproduce.
+rm -f Test*.class
+
+"${JAVA}" ${TESTVMOPTS} -javaagent:ParallelTransformerLoaderAgent.jar=Test.jar \
+    -classpath "${TESTCLASSES}" ParallelTransformerLoaderApp
+result=$?
+echo "result=$result"
+
+exit $result
diff --git a/jdk/test/java/lang/instrument/ParallelTransformerLoaderAgent.java b/jdk/test/java/lang/instrument/ParallelTransformerLoaderAgent.java
new file mode 100644
index 0000000..9b707eb
--- /dev/null
+++ b/jdk/test/java/lang/instrument/ParallelTransformerLoaderAgent.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.lang.instrument.*;
+import java.net.*;
+import java.io.*;
+import java.security.*;
+
+/**
+ *      Test Java Agent
+ *
+ *      @author Daryl Puryear
+ *      @copyright 1999-2004 Wily Technology, Inc.  All rights reserved.
+ */
+public class ParallelTransformerLoaderAgent
+{
+        private static URL sURL;
+        private static ClassLoader sClassLoader;
+
+        public static synchronized ClassLoader
+        getClassLoader()
+        {
+                return sClassLoader;
+        }
+
+        public static synchronized void
+        generateNewClassLoader()
+        {
+                sClassLoader = new URLClassLoader(new URL[] {sURL});
+        }
+
+        public static void
+        premain(        String agentArgs,
+                        Instrumentation instrumentation)
+                throws Exception
+        {
+                if (agentArgs == null || agentArgs == "")
+                {
+                        System.err.println("Error: No jar file name provided, test will not run.");
+                        return;
+                }
+
+                sURL = (new File(agentArgs)).toURL();
+                System.out.println("Using jar file: " + sURL);
+                generateNewClassLoader();
+
+                instrumentation.addTransformer(new TestTransformer());
+        }
+
+        private static class TestTransformer
+                implements ClassFileTransformer
+        {
+                public byte[]
+                transform(      ClassLoader loader,
+                                String className,
+                                Class classBeingRedefined,
+                                ProtectionDomain protectionDomain,
+                                byte[] classfileBuffer)
+                        throws IllegalClassFormatException
+                {
+                        String tName = Thread.currentThread().getName();
+                        // In 160_03 and older, transform() is called
+                        // with the "system_loader_lock" held and that
+                        // prevents the bootstrap class loaded from
+                        // running in parallel. If we add a slight sleep
+                        // delay here when the transform() call is not
+                        // main or TestThread, then the deadlock in
+                        // 160_03 and older is much more reproducible.
+                        if (!tName.equals("main") && !tName.equals("TestThread")) {
+                            System.out.println("Thread '" + tName +
+                                "' has called transform()");
+                            try {
+                                Thread.sleep(500);
+                            } catch (InterruptedException ie) {
+                            }
+                        }
+
+                        // load additional classes when called from other threads
+                        if (!tName.equals("main"))
+                        {
+                                loadClasses(3);
+                        }
+                        return null;
+                }
+
+                public static void
+                loadClasses( int index)
+                {
+                        ClassLoader loader = ParallelTransformerLoaderAgent.getClassLoader();
+                        try
+                        {
+                                Class.forName("TestClass" + index, true, loader);
+                        }
+                        catch (Exception e)
+                        {
+                                e.printStackTrace();
+                        }
+                }
+        }
+}
diff --git a/jdk/test/java/lang/instrument/ParallelTransformerLoaderApp.java b/jdk/test/java/lang/instrument/ParallelTransformerLoaderApp.java
new file mode 100644
index 0000000..62216e2
--- /dev/null
+++ b/jdk/test/java/lang/instrument/ParallelTransformerLoaderApp.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ *      Test Java Program
+ *
+ *      @author Daryl Puryear
+ *      @copyright 1999-2004 Wily Technology, Inc.  All rights reserved.
+ */
+public class ParallelTransformerLoaderApp
+{
+        private static final int kNumIterations = 1000;
+
+        public static void
+        main(   String[] args)
+                throws Exception
+        {
+                System.out.println();
+                System.out.print("Starting test with " + kNumIterations + " iterations");
+                for (int i = 0; i < kNumIterations; i++)
+                {
+                        // load some classes from multiple threads (this thread and one other)
+                        Thread testThread = new TestThread(2);
+                        testThread.start();
+                        loadClasses(1);
+
+                        // log that it completed and reset for the next iteration
+                        testThread.join();
+                        System.out.print(".");
+                        ParallelTransformerLoaderAgent.generateNewClassLoader();
+                }
+
+                System.out.println();
+                System.out.println("Test completed successfully");
+        }
+
+        private static class TestThread
+                extends Thread
+        {
+                private final int fIndex;
+
+                public
+                TestThread(     int index)
+                {
+                        super("TestThread");
+
+                        fIndex = index;
+                }
+
+                public void
+                run()
+                {
+                        loadClasses(fIndex);
+                }
+        }
+
+        public static void
+        loadClasses( int index)
+        {
+                ClassLoader loader = ParallelTransformerLoaderAgent.getClassLoader();
+                try
+                {
+                        Class.forName("TestClass" + index, true, loader);
+                }
+                catch (Exception e)
+                {
+                        e.printStackTrace();
+                }
+        }
+}
diff --git a/jdk/test/java/lang/instrument/TestClass1.java b/jdk/test/java/lang/instrument/TestClass1.java
new file mode 100644
index 0000000..7089527
--- /dev/null
+++ b/jdk/test/java/lang/instrument/TestClass1.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ *      Test Java Program
+ *
+ *      @author Daryl Puryear
+ *      @copyright 1999-2004 Wily Technology, Inc.  All rights reserved.
+ */
+public class TestClass1
+{
+        public
+        TestClass1()
+        {
+        }
+}
diff --git a/jdk/test/java/lang/instrument/TestClass2.java b/jdk/test/java/lang/instrument/TestClass2.java
new file mode 100644
index 0000000..145ac59
--- /dev/null
+++ b/jdk/test/java/lang/instrument/TestClass2.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ *      Test Java Program
+ *
+ *      @author Daryl Puryear
+ *      @copyright 1999-2004 Wily Technology, Inc.  All rights reserved.
+ */
+public class TestClass2
+{
+        public
+        TestClass2()
+        {
+        }
+}
diff --git a/jdk/test/java/lang/instrument/TestClass3.java b/jdk/test/java/lang/instrument/TestClass3.java
new file mode 100644
index 0000000..0189ee1
--- /dev/null
+++ b/jdk/test/java/lang/instrument/TestClass3.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ *      Test Java Program
+ *
+ *      @author Daryl Puryear
+ *      @copyright 1999-2004 Wily Technology, Inc.  All rights reserved.
+ */
+public class TestClass3
+{
+        public
+        TestClass3()
+        {
+        }
+}