[ecj] java.lang.Thread partial merge

Gary Benson gbenson@redhat.com
Thu Nov 30 09:22:00 GMT 2006


Hi all,

This commit makes java.lang.Thread use VMStackWalker to determine when
it can omit the security check when setting the context classloader.
I also merged the javadoc with Classpath to make it easier to see the
real differences between the two.

Cheers,
Gary
-------------- next part --------------
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 119314)
+++ ChangeLog	(working copy)
@@ -1,3 +1,8 @@
+2006-11-30  Gary Benson  <gbenson@redhat.com>
+
+	* java/lang/Thread.java: Merged javadoc.
+	(getContextClassLoader): Use VMStackWalker.
+
 2006-11-29  Gary Benson  <gbenson@redhat.com>
 
 	* java/lang/Package.java: Removed.
Index: java/lang/Thread.java
===================================================================
--- java/lang/Thread.java	(revision 119314)
+++ java/lang/Thread.java	(working copy)
@@ -36,9 +36,9 @@
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */
 
-
 package java.lang;
 
+import gnu.classpath.VMStackWalker;
 import gnu.gcj.RawData;
 import gnu.gcj.RawDataManaged;
 import gnu.java.util.WeakIdentityHashMap;
@@ -89,6 +89,7 @@
  * @author Tom Tromey
  * @author John Keiser
  * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
  * @see Runnable
  * @see Runtime#exit(int)
  * @see #run()
@@ -470,7 +471,10 @@
   public native int countStackFrames();
 
   /**
-   * Get the currently executing Thread.
+   * Get the currently executing Thread. In the situation that the
+   * currently running thread was created by native code and doesn't
+   * have an associated Thread object yet, a new Thread object is
+   * constructed and associated with the native thread.
    *
    * @return the currently executing Thread
    */
@@ -479,6 +483,19 @@
   /**
    * Originally intended to destroy this thread, this method was never
    * implemented by Sun, and is hence a no-op.
+   *
+   * @deprecated This method was originally intended to simply destroy
+   *             the thread without performing any form of cleanup operation.
+   *             However, it was never implemented.  It is now deprecated
+   *             for the same reason as <code>suspend()</code>,
+   *             <code>stop()</code> and <code>resume()</code>; namely,
+   *             it is prone to deadlocks.  If a thread is destroyed while
+   *             it still maintains a lock on a resource, then this resource
+   *             will remain locked and any attempts by other threads to
+   *             access the resource will result in a deadlock.  Thus, even
+   *             an implemented version of this method would be still be
+   *             deprecated, due to its unsafe nature.
+   * @throws NoSuchMethodError as this method was never implemented.
    */
   public void destroy()
   {
@@ -667,7 +684,9 @@
     throws InterruptedException;
 
   /**
-   * Resume a suspended thread.
+   * Resume this Thread.  If the thread is not suspended, this method does
+   * nothing. To mirror suspend(), there may be a security check:
+   * <code>checkAccess</code>.
    *
    * @throws SecurityException if you cannot resume the Thread
    * @see #checkAccess()
@@ -742,7 +761,7 @@
    *
    * @return the context class loader
    * @throws SecurityException when permission is denied
-   * @see setContextClassLoader(ClassLoader)
+   * @see #setContextClassLoader(ClassLoader)
    * @since 1.2
    */
   public synchronized ClassLoader getContextClassLoader()
@@ -750,24 +769,15 @@
     if (contextClassLoader == null)
       contextClassLoader = ClassLoader.getSystemClassLoader();
 
+    // Check if we may get the classloader
     SecurityManager sm = System.getSecurityManager();
-    // FIXME: we can't currently find the caller's class loader.
-    ClassLoader callers = null;
-    if (sm != null && callers != null)
+    if (contextClassLoader != null && sm != null)
       {
-	// See if the caller's class loader is the same as or an
-	// ancestor of this thread's class loader.
-	while (callers != null && callers != contextClassLoader)
-	  {
-	    // FIXME: should use some internal version of getParent
-	    // that avoids security checks.
-	    callers = callers.getParent();
-	  }
-
-	if (callers != contextClassLoader)
-	  sm.checkPermission(new RuntimePermission("getClassLoader"));
+        // Get the calling classloader
+	ClassLoader cl = VMStackWalker.getCallingClassLoader();
+        if (cl != null && !cl.isAncestorOf(contextClassLoader))
+          sm.checkPermission(new RuntimePermission("getClassLoader"));
       }
-
     return contextClassLoader;
   }
 
@@ -780,7 +790,7 @@
    *
    * @param classloader the new context class loader
    * @throws SecurityException when permission is denied
-   * @see getContextClassLoader()
+   * @see #getContextClassLoader()
    * @since 1.2
    */
   public synchronized void setContextClassLoader(ClassLoader classloader)
@@ -810,8 +820,10 @@
   }
 
   /**
-   * Causes the currently executing thread object to temporarily pause
-   * and allow other threads to execute.
+   * Yield to another thread. The Thread will not lose any locks it holds
+   * during this time. There are no guarantees which thread will be
+   * next to run, and it could even be this one, but most VMs will choose
+   * the highest priority thread that has been waiting longest.
    */
   public static native void yield();
 
@@ -822,8 +834,10 @@
    * choose the highest priority thread that has been waiting longest.
    *
    * @param ms the number of milliseconds to sleep, or 0 for forever
-   * @throws InterruptedException if the Thread is interrupted; it's
-   *         <i>interrupted status</i> will be cleared
+   * @throws InterruptedException if the Thread is (or was) interrupted;
+   *         it's <i>interrupted status</i> will be cleared
+   * @throws IllegalArgumentException if ms is negative
+   * @see #interrupt()
    * @see #notify()
    * @see #wait(long)
    */
@@ -837,18 +851,21 @@
    * time. The Thread will not lose any locks it has during this time. There
    * are no guarantees which thread will be next to run, but most VMs will
    * choose the highest priority thread that has been waiting longest.
+   * <p>
+   * Note that 1,000,000 nanoseconds == 1 millisecond, but most VMs
+   * do not offer that fine a grain of timing resolution. When ms is
+   * zero and ns is non-zero the Thread will sleep for at least one
+   * milli second. There is no guarantee that this thread can start up
+   * immediately when time expires, because some other thread may be
+   * active.  So don't expect real-time performance.
    *
-   * <p>Note that 1,000,000 nanoseconds == 1 millisecond, but most VMs do
-   * not offer that fine a grain of timing resolution. Besides, there is
-   * no guarantee that this thread can start up immediately when time expires,
-   * because some other thread may be active.  So don't expect real-time
-   * performance.
-   *
    * @param ms the number of milliseconds to sleep, or 0 for forever
    * @param ns the number of extra nanoseconds to sleep (0-999999)
-   * @throws InterruptedException if the Thread is interrupted; it's
-   *         <i>interrupted status</i> will be cleared
-   * @throws IllegalArgumentException if ns is invalid
+   * @throws InterruptedException if the Thread is (or was) interrupted;
+   *         it's <i>interrupted status</i> will be cleared
+   * @throws IllegalArgumentException if ms or ns is negative
+   *         or ns is larger than 999999.
+   * @see #interrupt()
    * @see #notify()
    * @see #wait(long, int)
    */
@@ -899,10 +916,11 @@
 
   /**
    * Cause this Thread to stop abnormally and throw the specified exception.
-   * If you stop a Thread that has not yet started, it will stop immediately
-   * when it is actually started. <b>WARNING</b>This bypasses Java security,
-   * and can throw a checked exception which the call stack is unprepared to
-   * handle. Do not abuse this power.
+   * If you stop a Thread that has not yet started, the stop is ignored
+   * (contrary to what the JDK documentation says).
+   * <b>WARNING</b>This bypasses Java security, and can throw a checked
+   * exception which the call stack is unprepared to handle. Do not abuse
+   * this power.
    *
    * <p>This is inherently unsafe, as it can interrupt synchronized blocks and
    * leave data in bad states.  Hence, there is a security check:
@@ -1124,7 +1142,7 @@
    * @author Andrew John Hughes <gnu_andrew@member.fsf.org>
    * @since 1.5
    * @see Thread#getUncaughtExceptionHandler()
-   * @see Thread#setUncaughtExceptionHander(java.lang.Thread.UncaughtExceptionHandler)
+   * @see Thread#setUncaughtExceptionHandler(UncaughtExceptionHandler)
    * @see Thread#getDefaultUncaughtExceptionHandler()
    * @see
    * Thread#setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)
@@ -1274,4 +1292,5 @@
     ThreadInfo info = bean.getThreadInfo(getId(), Integer.MAX_VALUE);
     return info.getStackTrace();
   }
+
 }


More information about the Java-patches mailing list