classpath-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[cp-patches] Some VMStackWalker cleanups/simplifications


From: Mark Wielaard
Subject: [cp-patches] Some VMStackWalker cleanups/simplifications
Date: Sun, 16 Jan 2005 18:40:28 +0100

Hi,

Here are a couple of cleanups/simplifications for the new VMStackWalker.
It fixes a nasty recursion in Class.getClassLoader() and it adds the
Class that is interested in the actual calling class or classloader as
argument to the VMStackWalker methods. This way it is much easier to
generically check for skipping this class and the Method.invoke() call
on the stack without depending on the actual stack depth.

Thanks to Robert Robert Lougher for pointing out the endless recursion
between VMStackWalker and Class and thanks to Michael Koch for adding
security checks to mauve that pointed these issues out. 

2005-01-16  Mark Wielaard  <address@hidden>

        * vm/reference/gnu/classpath/VMStackWalker.java: Add Class to skip as
        argument to all public methods. Actually skip Method.invoke() class
        frame.
        * java/lang/SecurityManager.java (getClassContext): Use result of
        VMStackWalker.getClassContext(Class) directly.
        * java/lang/Class.java (forName): Add class to skip as argument to
        VMStackWalker invocation.
        (getClassLoader): Use VMStackWalker.getCallingClass() and
        VMClass.getClassLoader() to avoid endless recursion.
        * java/lang/ClassLoader.java (getParent): Add class to skip as
        argument to VMStackWalker invocation.
        (getSystemClassLoader): Likewise
        * java/lang/Package.java (getPackage): Likewise.
        (getPackages): Likewise.
        * java/lang/Runtime.java (load): Likewise.
        (loadLibrary): Likewise.
        * java/lang/System.java (load): Likewise.
        (loadLibrary): Likewise.
        * java/util/ResourceBundle.java (getBundle): Likewise.

Comments?

Cheers,

Mark

P.S. I have not yet really thought about how this would/should interact
with the proposed VMStackBrowser from Steven Augart. Comment welcome of
course.
Index: vm/reference/gnu/classpath/VMStackWalker.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/vm/reference/gnu/classpath/VMStackWalker.java,v
retrieving revision 1.3
diff -u -r1.3 VMStackWalker.java
--- vm/reference/gnu/classpath/VMStackWalker.java       7 Jan 2005 15:08:23 
-0000       1.3
+++ vm/reference/gnu/classpath/VMStackWalker.java       16 Jan 2005 17:25:50 
-0000
@@ -40,10 +40,13 @@
 /**
  * This class provides access to the classes on the Java stack
  * for reflection and security purposes.
- *
  * <p>
  * This class is only available to priviledged code (i.e., code loaded
  * by the bootstrap loader).
+ * <p>
+ * VM runtime implementers only need to implement the native getClassContext()
+ * method. But are encouraged to implement the other methods more efficiently
+ * when possible.
  *
  * @author John Keiser
  * @author Eric Blake <address@hidden>
@@ -65,44 +68,65 @@
    *
    * @return an array of the declaring classes of each stack frame
    */
-  public static native Class[] getClassContext();
+  public static Class[] getClassContext(Class c)
+  {
+    Class[] stack = getClassContext();
+    int skip = 0;
+    while (skip < stack.length && stack[skip] != c)
+      skip++;
+
+    // Did we find the class to skip and is there anything left?
+    if (skip < stack.length && stack[skip] == c)
+      {
+       skip++;
+       if (skip < stack.length
+           && stack[skip] == java.lang.reflect.Method.class)
+         skip++;
+       Class[] stack2 = new Class[stack.length - skip];
+       System.arraycopy(stack, skip, stack2, 0, stack2.length);
+       stack = stack2;
+      }
+
+    return stack;
+  }
+
+  /**
+   * Returns a "raw" stack of all classes on the call stack.
+   */
+  static native Class[] getClassContext();
 
   /**
    * Get the class associated with the method invoking the method
    * invoking this method, or <code>null</code> if the stack is not
    * that deep (e.g., invoked via JNI invocation API). This method
-   * is an optimization for the expression <code>getClassContext()[1]</code>
+   * is an optimization for the expression <code>getClassContext(c)[0]</code>
    * and should return the same result.
    *
    * <p>
    * VM implementers are encouraged to provide a more efficient
    * version of this method.
    */
-  public static Class getCallingClass()
+  public static Class getCallingClass(Class c)
   {
-    Class[] ctx = getClassContext();
-    if (ctx.length < 3)
-      return null;
-    return ctx[2];
+    Class[] ctx = getClassContext(c);
+    return ctx.length > 0 ? ctx[0] : null;
   }
 
   /**
    * Get the class loader associated with the Class returned by
    * <code>getCallingClass()</code>, or <code>null</code> if no
    * such class exists or it is the boot loader. This method is an optimization
-   * for the expression <code>getClassContext()[1].getClassLoader()</code>
+   * for the expression <code>getCallingClass().getClassLoader()</code>
    * and should return the same result.
    *
    * <p>
    * VM implementers are encouraged to provide a more efficient
    * version of this method.
    */
-  public static ClassLoader getCallingClassLoader()
+  public static ClassLoader getCallingClassLoader(Class c)
   {
-    Class[] ctx = getClassContext();
-    if (ctx.length < 3)
-      return null;
-    return ctx[2].getClassLoader();
+    Class cc = getCallingClass(c);
+    return cc != null ? cc.getClassLoader() : null;
   }
 }
 
Index: java/lang/Class.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/lang/Class.java,v
retrieving revision 1.31
diff -u -r1.31 Class.java
--- java/lang/Class.java        7 Jan 2005 15:08:23 -0000       1.31
+++ java/lang/Class.java        16 Jan 2005 17:25:50 -0000
@@ -1,5 +1,5 @@
 /* Class.java -- Representation of a Java class.
-   Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004
+   Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005
    Free Software Foundation
 
 This file is part of GNU Classpath.
@@ -159,7 +159,7 @@
     Class result = VMClass.forName (name);
     if (result == null)
       result = Class.forName(name, true,
-       VMStackWalker.getCallingClassLoader());
+       VMStackWalker.getCallingClassLoader(Class.class));
     return result;
   }
 
@@ -196,12 +196,12 @@
   {
     if (classloader == null)
       {
-        // Check if we may access the bootstrap classloader
-        SecurityManager sm = SecurityManager.current;
+       // Check if we may access the bootstrap classloader
+       SecurityManager sm = SecurityManager.current;
         if (sm != null)
           {
-            // Get the calling classloader
-            ClassLoader cl = VMStackWalker.getCallingClassLoader();
+           // Get the calling classloader
+           ClassLoader cl = VMStackWalker.getCallingClassLoader(Class.class);
             if (cl != null)
               sm.checkPermission(new RuntimePermission("getClassLoader"));
           }
@@ -279,10 +279,16 @@
     SecurityManager sm = SecurityManager.current;
     if (sm != null)
       {
-        // Get the calling classloader
-       ClassLoader cl = VMStackWalker.getCallingClassLoader();
-        if (cl != null && !cl.isAncestorOf(loader))
-          sm.checkPermission(new RuntimePermission("getClassLoader"));
+        // Get the calling classloader. Note that we cannot use
+       // VMStackWalker.getCallingClassLoader() here since
+       // the default implementation will call use again.
+        Class cc = VMStackWalker.getCallingClass(Class.class);
+        if (cc != null)
+         {
+           ClassLoader cl = VMClass.getClassLoader(cc);
+           if (cl != null && !cl.isAncestorOf(loader))
+             sm.checkPermission(new RuntimePermission("getClassLoader"));
+         }
       }
     return loader;
   }
@@ -1132,7 +1138,7 @@
     int modifiers = constructor.getModifiers();
     if (!Modifier.isPublic(modifiers))
       {
-       Class caller = VMStackWalker.getCallingClass();
+       Class caller = VMStackWalker.getCallingClass(Class.class);
        if (caller != null &&
            caller != this &&
            (Modifier.isPrivate(modifiers)
Index: java/lang/ClassLoader.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/lang/ClassLoader.java,v
retrieving revision 1.45
diff -u -r1.45 ClassLoader.java
--- java/lang/ClassLoader.java  16 Jan 2005 15:24:35 -0000      1.45
+++ java/lang/ClassLoader.java  16 Jan 2005 17:25:50 -0000
@@ -521,7 +521,7 @@
     SecurityManager sm = SecurityManager.current;
     if (sm != null)
       {
-       ClassLoader cl = VMStackWalker.getCallingClassLoader();
+       ClassLoader cl = VMStackWalker.getCallingClassLoader(ClassLoader.class);
        if (cl != null && ! cl.isAncestorOf(this))
           sm.checkPermission(new RuntimePermission("getClassLoader"));
       }
@@ -763,7 +763,7 @@
     SecurityManager sm = SecurityManager.current;
     if (sm != null)
       {
-       ClassLoader cl = VMStackWalker.getCallingClassLoader();
+       ClassLoader cl = VMStackWalker.getCallingClassLoader(ClassLoader.class);
        if (cl != null && cl != StaticData.systemClassLoader)
          sm.checkPermission(new RuntimePermission("getClassLoader"));
       }
Index: java/lang/Package.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/lang/Package.java,v
retrieving revision 1.16
diff -u -r1.16 Package.java
--- java/lang/Package.java      7 Jan 2005 22:01:00 -0000       1.16
+++ java/lang/Package.java      16 Jan 2005 17:25:50 -0000
@@ -275,7 +275,7 @@
   public static Package getPackage(String name)
   {
     // Get the caller's classloader
-    ClassLoader cl = VMStackWalker.getCallingClassLoader();
+    ClassLoader cl = VMStackWalker.getCallingClassLoader(Package.class);
     return cl != null ? cl.getPackage(name) : VMClassLoader.getPackage(name);
   }
 
@@ -288,7 +288,7 @@
   public static Package[] getPackages()
   {
     // Get the caller's classloader
-    ClassLoader cl = VMStackWalker.getCallingClassLoader();
+    ClassLoader cl = VMStackWalker.getCallingClassLoader(Package.class);
     return cl != null ? cl.getPackages() : VMClassLoader.getPackages();
   }
 
Index: java/lang/Runtime.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/lang/Runtime.java,v
retrieving revision 1.18
diff -u -r1.18 Runtime.java
--- java/lang/Runtime.java      7 Jan 2005 15:08:23 -0000       1.18
+++ java/lang/Runtime.java      16 Jan 2005 17:25:51 -0000
@@ -639,7 +639,7 @@
    */
   public void load(String filename)
   {
-    load(filename, VMStackWalker.getCallingClassLoader());
+    load(filename, VMStackWalker.getCallingClassLoader(Runtime.class));
   }
 
   /**
@@ -701,7 +701,7 @@
    */
   public void loadLibrary(String libname)
   {
-    loadLibrary(libname, VMStackWalker.getCallingClassLoader());
+    loadLibrary(libname, VMStackWalker.getCallingClassLoader(Runtime.class));
   }
 
   /**
Index: java/lang/SecurityManager.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/lang/SecurityManager.java,v
retrieving revision 1.26
diff -u -r1.26 SecurityManager.java
--- java/lang/SecurityManager.java      7 Jan 2005 15:08:23 -0000       1.26
+++ java/lang/SecurityManager.java      16 Jan 2005 17:25:51 -0000
@@ -181,10 +181,8 @@
    */
   protected Class[] getClassContext()
   {
-    Class[] stack1 = VMStackWalker.getClassContext();
-    Class[] stack2 = new Class[stack1.length - 1];
-    System.arraycopy(stack1, 1, stack2, 0, stack1.length - 1);
-    return stack2;
+    Class[] stack = VMStackWalker.getClassContext(this.getClass());
+    return stack;
   }
 
   /**
Index: java/lang/System.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/lang/System.java,v
retrieving revision 1.50
diff -u -r1.50 System.java
--- java/lang/System.java       11 Jan 2005 09:44:31 -0000      1.50
+++ java/lang/System.java       16 Jan 2005 17:25:51 -0000
@@ -492,7 +492,8 @@
    */
   public static void load(String filename)
   {
-    Runtime.getRuntime().load(filename, VMStackWalker.getCallingClassLoader());
+    Runtime runtime = Runtime.getRuntime();
+    runtime.load(filename, VMStackWalker.getCallingClassLoader(System.class));
   }
 
   /**
@@ -511,8 +512,9 @@
    */
   public static void loadLibrary(String libname)
   {
-    Runtime.getRuntime().loadLibrary(libname,
-      VMStackWalker.getCallingClassLoader());
+    Runtime runtime = Runtime.getRuntime();
+    runtime.loadLibrary(libname,
+                       VMStackWalker.getCallingClassLoader(System.class));
   }
 
   /**
Index: java/util/ResourceBundle.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/util/ResourceBundle.java,v
retrieving revision 1.31
diff -u -r1.31 ResourceBundle.java
--- java/util/ResourceBundle.java       11 Jan 2005 09:44:32 -0000      1.31
+++ java/util/ResourceBundle.java       16 Jan 2005 17:25:51 -0000
@@ -214,7 +214,7 @@
    */
   public static ResourceBundle getBundle(String baseName)
   {
-    ClassLoader cl = VMStackWalker.getCallingClassLoader();
+    ClassLoader cl = VMStackWalker.getCallingClassLoader(ResourceBundle.class);
     if (cl == null)
       cl = ClassLoader.getSystemClassLoader();
     return getBundle(baseName, Locale.getDefault(), cl);
@@ -234,7 +234,7 @@
    */
   public static ResourceBundle getBundle(String baseName, Locale locale)
   {
-    ClassLoader cl = VMStackWalker.getCallingClassLoader();
+    ClassLoader cl = VMStackWalker.getCallingClassLoader(ResourceBundle.class);
     if (cl == null)
       cl = ClassLoader.getSystemClassLoader();
     return getBundle(baseName, locale, cl);

Attachment: signature.asc
Description: This is a digitally signed message part


reply via email to

[Prev in Thread] Current Thread [Next in Thread]