Initial load
diff --git a/test/java/lang/System/Available.java b/test/java/lang/System/Available.java
new file mode 100644
index 0000000..beff558
--- /dev/null
+++ b/test/java/lang/System/Available.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 1998 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.
+ */
+
+/*
+ * This class tests to see if System.in.available starts
+ * with an appropriate value
+ *
+ * @test
+ * @bug 4104888
+ * @summary Test for System.in.available
+ */
+
+public class Available {
+    public static void main(String args[]) throws Exception {
+        int bytesAvailable = System.in.available();
+        if (bytesAvailable != 0)
+            throw new RuntimeException("System.in.available returned non-zero");
+        }
+}
diff --git a/test/java/lang/System/ExitFinalizersAndJIT.java b/test/java/lang/System/ExitFinalizersAndJIT.java
new file mode 100644
index 0000000..619b036
--- /dev/null
+++ b/test/java/lang/System/ExitFinalizersAndJIT.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 1998-2007 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 4119554
+   @summary runFinalizersOnExit(true) causes JIT to be unloaded and
+            crashes the VM.  Interim fix for 1.2 beta4 -- don't unload
+            native libraries loaded by system classes.
+*/
+
+public class ExitFinalizersAndJIT {
+    public static void main(String[] args) throws Exception {
+        System.runFinalizersOnExit(true);
+    }
+}
diff --git a/test/java/lang/System/IHashCode.java b/test/java/lang/System/IHashCode.java
new file mode 100644
index 0000000..d90ebc7
--- /dev/null
+++ b/test/java/lang/System/IHashCode.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 1999 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 4228188
+ * @summary test System.identityHashCode(null)
+ */
+
+public class IHashCode {
+  public static void main (String argv[]) throws Exception {
+       int test = System.identityHashCode(null);
+       if (test != 0)
+           throw new RuntimeException("identityHashCode(null) is "+test);
+  }
+}
diff --git a/test/java/lang/System/IgnoreNullSecurityManager.java b/test/java/lang/System/IgnoreNullSecurityManager.java
new file mode 100644
index 0000000..949ef29
--- /dev/null
+++ b/test/java/lang/System/IgnoreNullSecurityManager.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 1999 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 4213876
+ * @summary Make sure "null" security manager is ignored, as specified in the
+ * javadocs
+ */
+
+public class IgnoreNullSecurityManager {
+
+    public static void main(String argv[]) throws Exception {
+        System.setSecurityManager(null);
+    }
+}
diff --git a/test/java/lang/System/SecurityRace.java b/test/java/lang/System/SecurityRace.java
new file mode 100644
index 0000000..c563d34
--- /dev/null
+++ b/test/java/lang/System/SecurityRace.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2005 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 6302839
+ * @summary SecurityRace System field accesses in two threads
+ * @author Pete Soper
+ * @build SecurityRace
+ * @run main/othervm/policy=System.policy SecurityRace
+ */
+
+/*
+ * By default the test runs for a very short time.  Use main arg "stress"
+ * to have a real chance of exposing races. Use main arg "time" to report
+ * the average nanoseconds per invocation of System.setSecurityManager and
+ * System.getSecurityManager. No testing for access races is performed with
+ * argument "time."
+ *
+ * Requires security permissions "setSecurityManager" and
+ * "createSecurityManager."
+ */
+
+
+
+public class SecurityRace implements Runnable {
+
+    // Number of iterations to "warm up" and get methods compiled/inlined.
+    // (this is conservative)
+    static final int WARMUP_LOOPS = 100000;
+
+    // Number of timing trials
+    static final int TIMING_TRIALS = 10;
+
+    // Seconds to run this in "stress" mode. This is double the average
+    // time to expose the races of bug 6302839 on a Blade 1000. Invoke
+    // the program with the "stress" option multiple times for more
+    // confidence.
+    static final int STRESS_MILLISECONDS = 300000;
+    static final int SET_TIMING_LOOPS    = 10000;
+
+    // Max seconds to run before terminating the test ("declaring victory").
+    static int MAX_MILLISECONDS = 100;
+
+    // Number of iterations to time
+    static final int GET_TIMING_LOOPS = 10000000;
+
+    // Set true by main thread when NPE caught or time to terminate.
+    // Set true by other thread when NPE caught. It makes
+    // no difference where the NPE is thrown.
+    static volatile boolean stopthreads = false;
+
+    // Number of getProperty invocations between main loop checks
+    static final int       GETPROPERTY_LOOPS = 30000;
+
+    // Used by race and timing tests. Must get set non-null at lease once.
+    static SecurityManager sm = new SecurityManager();
+
+    public static void main(String[] argv) throws Exception {
+        String s;
+
+        if (argv.length > 0) {
+            if (argv[0].equals("time")) {
+
+                // Run the timing method
+                // First warm up the method to make sure it gets compiled
+                for (int i = 0; i < WARMUP_LOOPS; i++) {
+                    timeit(1, 1, 1);
+                }
+
+                System.out.println("boo");
+
+                // Now do the actual timing
+                timeit(TIMING_TRIALS, GET_TIMING_LOOPS, SET_TIMING_LOOPS);
+            } else if (argv[0].equals("stress")) {
+
+                // For stress test the test duration is boosted
+                MAX_MILLISECONDS = STRESS_MILLISECONDS;
+            } else {
+                throw new RuntimeException(
+                    "SecurityRace: " + argv[0]
+                    + " argument to main not recognized");
+            }    // if argv
+        }        // if length
+
+        long start = System.currentTimeMillis(),
+             end   = start + MAX_MILLISECONDS;
+
+        // Create and start racing thread
+        (new Thread(new SecurityRace())).start();
+
+        // main thread alternates batches of getProperty() with time checks
+        try {
+            do {
+                if (stopthreads) {
+
+                    // other thread suffered an NPE
+                    throw new RuntimeException("SecurityRace failed with NPE");
+                }
+
+                for (int i = 0; i < GETPROPERTY_LOOPS; i++) {
+                    s = System.getProperty("java.version");
+                }
+            } while (System.currentTimeMillis() < end);
+        } catch (NullPointerException e) {
+            throw new RuntimeException("SecurityRace failed with NPE");
+        } finally {
+
+            // make sure other thread terminates
+            stopthreads = true;
+        }
+    }    // main
+
+    // System.security mutator.
+    public void run() {
+        try {
+            while (true) {
+                if (stopthreads) {
+                    return;
+                }
+
+                System.setSecurityManager(sm);
+
+                // The goal is to catch another thread testing the
+                // value set above and trying to use it after it's
+                // nulled below.
+                System.setSecurityManager(null);
+            }
+        } catch (NullPointerException e) {
+            stopthreads = true;
+
+            return;
+        }
+    }
+
+    // Time method execution. Collects trials number of timings
+    // for the number of accessor and mutator invocation loops
+    // specified.
+    public static void timeit(int timing_trials, int get_timing_loops,
+                              int set_timing_loops) {
+        try {
+            long start;
+
+            // Time the methods and report average.
+            // Time multiple trials so noise is apparent and a
+            // T test can be used to establish significance.
+            for (int j = 0; j < timing_trials; j++) {
+                start = System.nanoTime();
+
+                for (int i = 0; i < get_timing_loops; i++) {
+                    sm = System.getSecurityManager();
+                }
+
+                // Don't print for "warmup" case. This might mean that
+                // the compiler fails to compile the println (setting it
+                // up to execute via interpretation using an "uncommon trap")
+                // but we don't care if this println runs slowly!
+                if (timing_trials > 1) {
+                    System.out.println((float) (System.nanoTime() - start)
+                                       / (float) get_timing_loops);
+                }
+            }
+
+            for (int j = 0; j < timing_trials; j++) {
+                start = System.nanoTime();
+
+                for (int i = 0; i < set_timing_loops; i++) {
+                    System.setSecurityManager(sm);
+                }
+
+                if (timing_trials > 1) {
+                    System.out.println((float) (System.nanoTime() - start)
+                                       / (float) set_timing_loops);
+                }
+            }
+
+            return;
+        } catch (Exception e) {
+            throw new RuntimeException("SecurityRace got unexpected: " + e);
+        }
+    }    // timeit
+}    // SecurityRace
diff --git a/test/java/lang/System/System.policy b/test/java/lang/System/System.policy
new file mode 100644
index 0000000..9ce33d1
--- /dev/null
+++ b/test/java/lang/System/System.policy
@@ -0,0 +1,55 @@
+//
+// Used by SecurityRace.java 
+// Standard extensions get all permissions by default
+
+grant codeBase "file:${{java.ext.dirs}}/*" {
+	permission java.security.AllPermission;
+};
+
+// default permissions granted to all domains
+
+grant { 
+	// Allows any thread to stop itself using the java.lang.Thread.stop()
+	// method that takes no argument.
+	// Note that this permission is granted by default only to remain
+	// backwards compatible.
+	// It is strongly recommended that you either remove this permission
+	// from this policy file or further restrict it to code sources
+	// that you specify, because Thread.stop() is potentially unsafe.
+	// See "http://java.sun.com/notes" for more information.
+	permission java.lang.RuntimePermission "stopThread";
+
+	// These two added for SecurityRace test
+
+	permission java.lang.RuntimePermission "setSecurityManager";
+	permission java.lang.RuntimePermission "createSecurityManager";
+
+	// allows anyone to listen on un-privileged ports
+	permission java.net.SocketPermission "localhost:1024-", "listen";
+
+	// "standard" properies that can be read by anyone
+
+	permission java.util.PropertyPermission "java.version", "read";
+	permission java.util.PropertyPermission "java.vendor", "read";
+	permission java.util.PropertyPermission "java.vendor.url", "read";
+	permission java.util.PropertyPermission "java.class.version", "read";
+	permission java.util.PropertyPermission "os.name", "read";
+	permission java.util.PropertyPermission "os.version", "read";
+	permission java.util.PropertyPermission "os.arch", "read";
+	permission java.util.PropertyPermission "file.separator", "read";
+	permission java.util.PropertyPermission "path.separator", "read";
+	permission java.util.PropertyPermission "line.separator", "read";
+
+	permission java.util.PropertyPermission "java.specification.version", "read";
+	permission java.util.PropertyPermission "java.specification.vendor", "read";
+	permission java.util.PropertyPermission "java.specification.name", "read";
+
+	permission java.util.PropertyPermission "java.vm.specification.version", "read";
+	permission java.util.PropertyPermission "java.vm.specification.vendor", "read";
+	permission java.util.PropertyPermission "java.vm.specification.name", "read";
+	permission java.util.PropertyPermission "java.vm.version", "read";
+	permission java.util.PropertyPermission "java.vm.vendor", "read";
+	permission java.util.PropertyPermission "java.vm.name", "read";
+	permission java.util.PropertyPermission "java.vm.name", "read";
+};
+
diff --git a/test/java/lang/System/Versions.java b/test/java/lang/System/Versions.java
new file mode 100644
index 0000000..d94d3b4
--- /dev/null
+++ b/test/java/lang/System/Versions.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2004-2005 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 4989690 6259855
+ * @summary Check that version-related system property invariants hold.
+ * @author Martin Buchholz
+ */
+
+import java.io.*;
+import java.net.URLClassLoader;
+import java.net.URL;
+
+public class Versions {
+    static String getProperty(String prop) throws Exception {
+        String value = System.getProperty(prop);
+        if (value == null)
+            throw new Exception("No such system property: " + prop);
+        System.out.printf("%s=%s%n", prop, value);
+        return value;
+    }
+
+    static ClassLoader cl;
+
+    static void checkClassVersion(int major, int minor, boolean expectSupported)
+        throws Exception
+    {
+        final String className  = "ClassVersionTest";
+        final String classFile  = className + ".class";
+
+        // We create an invalid class file, (only magic and version info),
+        // but the version info must be checked before the body.
+        final DataOutputStream dos =
+            new DataOutputStream(new FileOutputStream(classFile));
+        dos.writeLong((0xCafeBabel << 32) + (minor << 16) + major);
+        dos.close();
+
+        boolean supported = true;
+        try {
+            Class.forName(className, false, cl);
+        } catch (UnsupportedClassVersionError e) {
+            supported = false;
+        } catch (Throwable t) {
+            // We expect an Exception indicating invalid class file
+        }
+        new File(classFile).delete();
+        if (supported != expectSupported)
+            throw new Exception("Forgot to update java.class.version?");
+    }
+
+    public static void main(String [] args) throws Exception {
+        String classVersion   = getProperty("java.class.version");
+        String javaVersion    = getProperty("java.version");
+        String VMVersion      = getProperty("java.vm.version");
+        String runtimeVersion = getProperty("java.runtime.version");
+        String specVersion    = getProperty("java.specification.version");
+
+        if (! (javaVersion.startsWith(specVersion) &&
+               runtimeVersion.startsWith(specVersion)))
+            throw new Exception("Invalid version-related system properties");
+
+        //----------------------------------------------------------------
+        // Check that java.class.version is correct.
+        // Injecting a larger major or minor version number into a
+        // .class file should result in UnsupportedClassVersionError.
+        //----------------------------------------------------------------
+        String[] versions = classVersion.split("\\.");
+        int majorVersion = Integer.parseInt(versions[0]);
+        int minorVersion = Integer.parseInt(versions[1]);
+        System.out.printf("majorVersion=%s%n",majorVersion);
+        System.out.printf("minorVersion=%s%n",minorVersion);
+
+        // Look in ".", and *not* in CLASSPATH
+        cl = new URLClassLoader(new URL[]{new File("./").toURL()}, null);
+
+        checkClassVersion(majorVersion    , minorVersion    , true );
+        checkClassVersion(majorVersion + 1, minorVersion    , false);
+        checkClassVersion(majorVersion    , minorVersion + 1, false);
+    }
+}
diff --git a/test/java/lang/System/finalization/FinExit.java b/test/java/lang/System/finalization/FinExit.java
new file mode 100644
index 0000000..26664f2
--- /dev/null
+++ b/test/java/lang/System/finalization/FinExit.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 1998 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 4116016
+   @summary Ensure that finalizers are not invoked more than once when on-exit
+            finalization is enabled and a finalizer invokes System.exit after
+            System.exit has already been invoked
+   @build FinExit
+   @run shell FinExit.sh
+ */
+
+
+public class FinExit {
+
+    boolean finalized = false;
+
+    public void finalize() {
+        if (finalized) {
+            System.out.println("2");
+        } else {
+            finalized = true;
+            System.out.println("1");
+            System.exit(0);
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        System.runFinalizersOnExit(true);
+        Object o = new FinExit();
+        System.exit(0);
+    }
+
+}
diff --git a/test/java/lang/System/finalization/FinExit.sh b/test/java/lang/System/finalization/FinExit.sh
new file mode 100644
index 0000000..d2e48da
--- /dev/null
+++ b/test/java/lang/System/finalization/FinExit.sh
@@ -0,0 +1,34 @@
+#! /bin/sh
+
+#
+# Copyright 1998 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.
+#
+
+#
+x=`$TESTJAVA/bin/java -cp $TESTCLASSES FinExit`
+echo $x
+if [ "x$x" != "x1" ]; then
+  echo On-exit finalizer invoked twice
+  exit 1
+else
+  exit 0
+fi
diff --git a/test/java/lang/System/finalization/FinThreads.java b/test/java/lang/System/finalization/FinThreads.java
new file mode 100644
index 0000000..fd91c1b
--- /dev/null
+++ b/test/java/lang/System/finalization/FinThreads.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 1998 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 4026895
+   @summary Ensure that System.runFinalization does not run finalizers in the
+            thread that invokes it
+ */
+
+
+public class FinThreads {
+
+    static Thread mainThread;
+
+    static Object lock = new Object();    /* Protects following two fields */
+    static Thread finalizerThread = null;
+    static Thread finalizedBy = null;
+
+
+    static class Foo {
+
+        boolean catchFinalizer = false;
+
+        /* Instances are only created in an auxiliary thread, in order to
+           guard against stray references from the current thread's stack
+         */
+        static public void create(final boolean catchFinalizer)
+            throws InterruptedException
+        {
+            Thread t = new Thread(new Runnable() {
+                public void run() {
+                    new Foo(catchFinalizer);
+                }});
+            t.start();
+            t.join();
+        }
+
+        public Foo(boolean catchFinalizer) {
+            this.catchFinalizer = catchFinalizer;
+        }
+
+        public void finalize() throws InterruptedException {
+            if (catchFinalizer) {
+                boolean gotFinalizer = false;
+                synchronized (lock) {
+                    if (finalizerThread == null) {
+                        finalizerThread = Thread.currentThread();
+                        gotFinalizer = true;
+                    }
+                }
+                if (gotFinalizer) {
+                    System.err.println("Caught finalizer thread; sleeping...");
+                    Thread.sleep(Long.MAX_VALUE);
+                }
+            } else {
+                synchronized (lock) {
+                    finalizedBy = Thread.currentThread();
+                }
+                System.err.println("Test object finalized by " + finalizedBy);
+            }
+        }
+
+    }
+
+
+    static void alarm(final Thread sleeper, final long delay)
+        throws InterruptedException
+    {
+        Thread t = new Thread(new Runnable() {
+            public void run() {
+                try {
+                    Thread.sleep(delay);
+                    System.err.println("Waking " + sleeper);
+                    sleeper.interrupt();
+                } catch (InterruptedException x) { }
+            }});
+        t.setDaemon(true);
+        t.start();
+    }
+
+
+    public static void main(String[] args) throws Exception {
+
+        mainThread = Thread.currentThread();
+
+        /* Find the finalizer thread and put it to sleep */
+        for (;;) {
+            Foo.create(true);
+            System.gc();
+            synchronized (lock) {
+                if (finalizerThread != null) break;
+            }
+        }
+
+        /* Now create a finalizable object and run finalization */
+        alarm(finalizerThread, 5000);
+        Foo.create(false);
+        for (;;) {
+            System.gc();
+            System.runFinalization();
+            synchronized (lock) {
+                if (finalizedBy != null) break;
+            }
+        }
+
+        if (finalizedBy == mainThread)
+            throw new Exception("Finalizer run in main thread");
+
+    }
+
+}