From 4923c01b66f2e49e3735d067f8e4e671399abd25 Mon Sep 17 00:00:00 2001 From: Archie Cobbs Date: Tue, 4 Jan 2005 17:45:49 +0000 Subject: * NEWS: Document changes. * java/lang/Class.java (newInstance(), getClassLoader(), forName(String), forName(String, boolean, ClassLoader)): Use new VMStackWalker methods. * java/lang/ClassLoader.java (getParent(), getSystemClassLoader()): Likewise. * java/lang/Package.java (getPackages()): Likewise. * java/lang/SecurityManager.java (getClassContext()): Likewise. * java/util/ResourceBundle.java (getBundle()): Likewise. * java/lang/Runtime.java (load(), loadLibrary()): Load the native library using the calling class' class loader. * java/lang/System.java (load(), loadLibrary()): Likewise. (currentClassLoader()): implement via currentLoadedClass(). * vm/reference/gnu/classpath/VMStackWalker.java: New class. * vm/reference/java/lang/VMRuntime.java (nativeLoad()): Add a ClassLoader parameter. * vm/reference/java/lang/VMSecurityManager.java: Removed. --- ChangeLog | 20 +++++ NEWS | 5 ++ java/lang/Class.java | 19 ++--- java/lang/ClassLoader.java | 7 +- java/lang/Package.java | 7 +- java/lang/Runtime.java | 72 ++++++++++++----- java/lang/SecurityManager.java | 10 ++- java/lang/System.java | 14 +++- java/util/ResourceBundle.java | 47 +---------- vm/reference/gnu/classpath/VMStackWalker.java | 108 ++++++++++++++++++++++++++ vm/reference/java/lang/VMRuntime.java | 3 +- vm/reference/java/lang/VMSecurityManager.java | 73 ----------------- 12 files changed, 226 insertions(+), 159 deletions(-) create mode 100644 vm/reference/gnu/classpath/VMStackWalker.java delete mode 100644 vm/reference/java/lang/VMSecurityManager.java diff --git a/ChangeLog b/ChangeLog index 27b9d30b0..4992eac34 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2005-01-04 Archie Cobbs + + * NEWS: Document changes. + * java/lang/Class.java (newInstance(), getClassLoader(), + forName(String), forName(String, boolean, ClassLoader)): + Use new VMStackWalker methods. + * java/lang/ClassLoader.java (getParent(), getSystemClassLoader()): + Likewise. + * java/lang/Package.java (getPackages()): Likewise. + * java/lang/SecurityManager.java (getClassContext()): Likewise. + * java/util/ResourceBundle.java (getBundle()): Likewise. + * java/lang/Runtime.java (load(), loadLibrary()): Load the native + library using the calling class' class loader. + * java/lang/System.java (load(), loadLibrary()): Likewise. + (currentClassLoader()): implement via currentLoadedClass(). + * vm/reference/gnu/classpath/VMStackWalker.java: New class. + * vm/reference/java/lang/VMRuntime.java (nativeLoad()): + Add a ClassLoader parameter. + * vm/reference/java/lang/VMSecurityManager.java: Removed. + 2005-01-03 Michael Koch * javax/swing/plaf/metal/MetalLookAndFeel.java diff --git a/NEWS b/NEWS index 80a2e38d6..87f8654e7 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,11 @@ Runtime interface changes: implementation, but it is a generic implementation that ignores the nano-seconds argument. Runtime hackers are encouraged to provide a more efficient version. +* VMRuntime.nativeLoad() now takes an additional ClassLoader parameter. +* VMSecurityManager has been replaced by gnu.classpath.VMStackWalker. + currentClassLoader() is no longer needed, and there are also two new + methods with non-native implementations. VM implementors are encouraged + to provide more efficient versions. New in release 0.12 (Nov 14, 2004) diff --git a/java/lang/Class.java b/java/lang/Class.java index 7bd3a3b09..d3bc1dea4 100644 --- a/java/lang/Class.java +++ b/java/lang/Class.java @@ -38,6 +38,8 @@ exception statement from your version. */ package java.lang; +import gnu.classpath.VMStackWalker; + import java.io.InputStream; import java.io.Serializable; import java.lang.reflect.Constructor; @@ -157,7 +159,7 @@ public final class Class implements Serializable Class result = VMClass.forName (name); if (result == null) result = Class.forName(name, true, - VMSecurityManager.getClassContext()[1].getClassLoader()); + VMStackWalker.getCallingClassLoader()); return result; } @@ -198,9 +200,8 @@ public final class Class implements Serializable SecurityManager sm = SecurityManager.current; if (sm != null) { - // Get the calling class and classloader - Class c = VMSecurityManager.getClassContext()[1]; - ClassLoader cl = c.getClassLoader(); + // Get the calling classloader + ClassLoader cl = VMStackWalker.getCallingClassLoader(); if (cl != null) sm.checkPermission(new RuntimePermission("getClassLoader")); } @@ -278,9 +279,8 @@ public final class Class implements Serializable SecurityManager sm = SecurityManager.current; if (sm != null) { - // Get the calling class and classloader - Class c = VMSecurityManager.getClassContext()[1]; - ClassLoader cl = VMClass.getClassLoader(c); + // Get the calling classloader + ClassLoader cl = VMStackWalker.getCallingClassLoader(); if (cl != null && !cl.isAncestorOf(loader)) sm.checkPermission(new RuntimePermission("getClassLoader")); } @@ -1132,8 +1132,9 @@ public final class Class implements Serializable int modifiers = constructor.getModifiers(); if (!Modifier.isPublic(modifiers)) { - Class caller = VMSecurityManager.getClassContext()[1]; - if (caller != this && + Class caller = VMStackWalker.getCallingClass(); + if (caller != null && + caller != this && (Modifier.isPrivate(modifiers) || getClassLoader() != caller.getClassLoader() || !getPackagePortion(getName()) diff --git a/java/lang/ClassLoader.java b/java/lang/ClassLoader.java index 9cd3b81d9..f2a0ac161 100644 --- a/java/lang/ClassLoader.java +++ b/java/lang/ClassLoader.java @@ -39,6 +39,7 @@ exception statement from your version. */ package java.lang; import gnu.classpath.SystemProperties; +import gnu.classpath.VMStackWalker; import gnu.java.util.DoubleEnumeration; import gnu.java.util.EmptyEnumeration; @@ -520,8 +521,7 @@ public abstract class ClassLoader SecurityManager sm = SecurityManager.current; if (sm != null) { - Class c = VMSecurityManager.getClassContext()[1]; - ClassLoader cl = c.getClassLoader(); + ClassLoader cl = VMStackWalker.getCallingClassLoader(); if (cl != null && ! cl.isAncestorOf(this)) sm.checkPermission(new RuntimePermission("getClassLoader")); } @@ -763,8 +763,7 @@ public abstract class ClassLoader SecurityManager sm = SecurityManager.current; if (sm != null) { - Class c = VMSecurityManager.getClassContext()[1]; - ClassLoader cl = c.getClassLoader(); + ClassLoader cl = VMStackWalker.getCallingClassLoader(); if (cl != null && cl != StaticData.systemClassLoader) sm.checkPermission(new RuntimePermission("getClassLoader")); } diff --git a/java/lang/Package.java b/java/lang/Package.java index 89945cadd..23838d681 100644 --- a/java/lang/Package.java +++ b/java/lang/Package.java @@ -37,6 +37,8 @@ exception statement from your version. */ package java.lang; +import gnu.classpath.VMStackWalker; + import java.net.URL; import java.util.NoSuchElementException; import java.util.StringTokenizer; @@ -273,7 +275,7 @@ public class Package public static Package getPackage(String name) { // Get the caller's classloader - ClassLoader cl = VMSecurityManager.currentClassLoader(); + ClassLoader cl = VMStackWalker.getCallingClassLoader(); return cl != null ? cl.getPackage(name) : null; } @@ -286,8 +288,7 @@ public class Package public static Package[] getPackages() { // Get the caller's classloader - Class c = VMSecurityManager.getClassContext()[1]; - ClassLoader cl = c.getClassLoader(); + ClassLoader cl = VMStackWalker.getCallingClassLoader(); // Sun's implementation returns the packages loaded by the bootstrap // classloader if cl is null, but right now our bootstrap classloader // does not create any Packages. diff --git a/java/lang/Runtime.java b/java/lang/Runtime.java index 58d1f5c0d..d0e7ac593 100644 --- a/java/lang/Runtime.java +++ b/java/lang/Runtime.java @@ -39,6 +39,7 @@ exception statement from your version. */ package java.lang; import gnu.classpath.SystemProperties; +import gnu.classpath.VMStackWalker; import java.io.File; import java.io.IOException; @@ -628,16 +629,33 @@ public class Runtime * before the final ".so" if the VM was invoked by the name "java_g". There * may be a security check, of checkLink. * + *

+ * The library is loaded using the class loader associated with the + * class associated with the invoking method. + * * @param filename the file to load * @throws SecurityException if permission is denied * @throws UnsatisfiedLinkError if the library is not found */ public void load(String filename) + { + load(filename, VMStackWalker.getCallingClassLoader()); + } + + /** + * Same as load(String) but using the given loader. + * + * @param filename the file to load + * @param loader class loader, or null for the boot loader + * @throws SecurityException if permission is denied + * @throws UnsatisfiedLinkError if the library is not found + */ + void load(String filename, ClassLoader loader) { SecurityManager sm = SecurityManager.current; // Be thread-safe! if (sm != null) sm.checkLink(filename); - if (loadLib(filename) == 0) + if (loadLib(filename, loader) == 0) throw new UnsatisfiedLinkError("Could not load library " + filename); } @@ -645,15 +663,16 @@ public class Runtime * Do a security check on the filename and then load the native library. * * @param filename the file to load + * @param loader class loader, or null for the boot loader * @return 0 on failure, nonzero on success * @throws SecurityException if file read permission is denied */ - private static int loadLib(String filename) + private static int loadLib(String filename, ClassLoader loader) { SecurityManager sm = SecurityManager.current; // Be thread-safe! if (sm != null) sm.checkRead(filename); - return VMRuntime.nativeLoad(filename); + return VMRuntime.nativeLoad(filename, loader); } /** @@ -668,6 +687,10 @@ public class Runtime * System.mapLibraryName(libname). There may be a security * check, of checkLink. * + *

+ * The library is loaded using the class loader associated with the + * class associated with the invoking method. + * * @param libname the library to load * * @throws SecurityException if permission is denied @@ -677,31 +700,38 @@ public class Runtime * @see ClassLoader#findLibrary(String) */ public void loadLibrary(String libname) + { + loadLibrary(libname, VMStackWalker.getCallingClassLoader()); + } + + /** + * Same as loadLibrary(String) but using the given loader. + * + * @param libname the library to load + * @param loader class loader, or null for the boot loader + * @throws SecurityException if permission is denied + * @throws UnsatisfiedLinkError if the library is not found + */ + void loadLibrary(String libname, ClassLoader loader) { SecurityManager sm = SecurityManager.current; // Be thread-safe! if (sm != null) sm.checkLink(libname); - String filename; - ClassLoader cl = VMSecurityManager.currentClassLoader(); - if (cl != null) + if (loader != null && (filename = loader.findLibrary(libname)) != null) { - filename = cl.findLibrary(libname); - if (filename != null) - { - if (loadLib(filename) != 0) - return; - else - throw new UnsatisfiedLinkError("Could not load library " + filename); - } + if (loadLib(filename, loader) != 0) + return; } - - filename = VMRuntime.mapLibraryName(libname); - for (int i = 0; i < libpath.length; i++) - if (loadLib(libpath[i] + filename) != 0) - return; - - throw new UnsatisfiedLinkError("Could not find library " + libname + "."); + else + { + filename = VMRuntime.mapLibraryName(libname); + for (int i = 0; i < libpath.length; i++) + if (loadLib(libpath[i] + filename, loader) != 0) + return; + } + throw new UnsatisfiedLinkError("Native library `" + libname + + "' not found (as file `" + filename + "')"); } /** diff --git a/java/lang/SecurityManager.java b/java/lang/SecurityManager.java index d5c47a8d8..f47b2ff83 100644 --- a/java/lang/SecurityManager.java +++ b/java/lang/SecurityManager.java @@ -38,6 +38,8 @@ exception statement from your version. */ package java.lang; +import gnu.classpath.VMStackWalker; + import java.awt.AWTPermission; import java.io.File; import java.io.FileDescriptor; @@ -179,7 +181,10 @@ public class SecurityManager */ protected Class[] getClassContext() { - return VMSecurityManager.getClassContext(); + Class[] stack1 = VMStackWalker.getClassContext(); + Class[] stack2 = new Class[stack1.length - 1]; + System.arraycopy(stack1, 1, stack2, 0, stack1.length - 1); + return stack2; } /** @@ -201,7 +206,8 @@ public class SecurityManager */ protected ClassLoader currentClassLoader() { - return VMSecurityManager.currentClassLoader(); + Class cl = currentLoadedClass(); + return cl != null ? cl.getClassLoader() : null; } /** diff --git a/java/lang/System.java b/java/lang/System.java index a639cac40..d0e32a3e5 100644 --- a/java/lang/System.java +++ b/java/lang/System.java @@ -39,6 +39,7 @@ exception statement from your version. */ package java.lang; +import gnu.classpath.VMStackWalker; import gnu.classpath.SystemProperties; import java.io.InputStream; @@ -480,6 +481,10 @@ public final class System * check may be performed, checkLink. This just calls * Runtime.getRuntime().load(filename). * + *

+ * The library is loaded using the class loader associated with the + * class associated with the invoking method. + * * @param filename the code file to load * @throws SecurityException if permission is denied * @throws UnsatisfiedLinkError if the file cannot be loaded @@ -487,7 +492,7 @@ public final class System */ public static void load(String filename) { - Runtime.getRuntime().load(filename); + Runtime.getRuntime().load(filename, VMStackWalker.getCallingClassLoader()); } /** @@ -495,6 +500,10 @@ public final class System * check may be performed, checkLink. This just calls * Runtime.getRuntime().load(filename). * + *

+ * The library is loaded using the class loader associated with the + * class associated with the invoking method. + * * @param libname the library file to load * @throws SecurityException if permission is denied * @throws UnsatisfiedLinkError if the file cannot be loaded @@ -502,7 +511,8 @@ public final class System */ public static void loadLibrary(String libname) { - Runtime.getRuntime().loadLibrary(libname); + Runtime.getRuntime().loadLibrary(libname, + VMStackWalker.getCallingClassLoader()); } /** diff --git a/java/util/ResourceBundle.java b/java/util/ResourceBundle.java index 8432b9a46..16dfed9e8 100644 --- a/java/util/ResourceBundle.java +++ b/java/util/ResourceBundle.java @@ -39,6 +39,7 @@ exception statement from your version. */ package java.util; +import gnu.classpath.VMStackWalker; import java.io.IOException; import java.io.InputStream; import java.security.AccessController; @@ -103,48 +104,6 @@ public abstract class ResourceBundle */ private Locale locale; - /** - * We override SecurityManager in order to access getClassContext(). - */ - private static final class Security extends SecurityManager - { - /** - * Avoid accessor method of private constructor. - */ - Security() - { - } - - /** - * Return the ClassLoader of the class which called into this - * ResourceBundle, or null if it cannot be determined. - */ - ClassLoader getCallingClassLoader() - { - Class[] stack = getClassContext(); - for (int i = 0; i < stack.length; i++) - { - if (stack[i] != Security.class && stack[i] != ResourceBundle.class) - return stack[i].getClassLoader(); - } - - return null; - } - } - - /** A security context for grabbing the correct class loader. */ - private static final Security security - = (Security) AccessController.doPrivileged(new PrivilegedAction() - { - // This will always work since java.util classes have (all) system - // permissions. - public Object run() - { - return new Security(); - } - } - ); - /** * The resource bundle cache. */ @@ -256,7 +215,7 @@ public abstract class ResourceBundle */ public static ResourceBundle getBundle(String baseName) { - ClassLoader cl = security.getCallingClassLoader(); + ClassLoader cl = VMStackWalker.getCallingClassLoader(); if (cl == null) cl = ClassLoader.getSystemClassLoader(); return getBundle(baseName, Locale.getDefault(), cl); @@ -276,7 +235,7 @@ public abstract class ResourceBundle */ public static ResourceBundle getBundle(String baseName, Locale locale) { - ClassLoader cl = security.getCallingClassLoader(); + ClassLoader cl = VMStackWalker.getCallingClassLoader(); if (cl == null) cl = ClassLoader.getSystemClassLoader(); return getBundle(baseName, locale, cl); diff --git a/vm/reference/gnu/classpath/VMStackWalker.java b/vm/reference/gnu/classpath/VMStackWalker.java new file mode 100644 index 000000000..72e41d8c7 --- /dev/null +++ b/vm/reference/gnu/classpath/VMStackWalker.java @@ -0,0 +1,108 @@ +/* VMStackWalker.java -- Reference implementation of VM hooks for stack access + Copyright (C) 2005 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.classpath; + +/** + * This class provides access to the classes on the Java stack + * for reflection and security purposes. + * + *

+ * This class is only available to priviledged code (i.e., code loaded + * by the bootstrap loader). + * + * @author John Keiser + * @author Eric Blake + * @author Archie Cobbs + */ +public final class VMStackWalker +{ + /** + * Get a list of all the classes currently executing methods on the + * Java stack. getClassContext()[0] is the class associated + * with the currently executing method, i.e., the method that called + * VMStackWalker.getClassContext() (possibly through + * reflection). So you may need to pop off these stack frames from + * the top of the stack: + *

    + *
  • VMStackWalker.getClassContext() + *
  • Method.invoke() + *
+ * + * @return an array of the declaring classes of each stack frame + */ + public static native Class[] getClassContext(); + + /** + * Get the class associated with the method invoking the method + * invoking this method, or null if the stack is not + * that deep (e.g., invoked via JNI invocation API). This method + * is an optimization for the expression getClassContext()[1] + * and should return the same result. + * + *

+ * VM implementers are encouraged to provide a more efficient + * version of this method. + */ + public static Class getCallingClass() + { + Class[] ctx = getClassContext(); + if (ctx.length < 3) + return null; + return ctx[2]; + } + + /** + * Get the class loader associated with the Class returned by + * getCallingClass(), or null if no + * such class exists or it is the boot loader. This method is an optimization + * for the expression getClassContext()[1].getClassLoader() + * and should return the same result. + * + *

+ * VM implementers are encouraged to provide a more efficient + * version of this method. + */ + public static ClassLoader getCallingClassLoader() + { + Class[] ctx = getClassContext(); + if (ctx.length < 3) + return null; + return ctx[2].getClassLoader(); + } +} + diff --git a/vm/reference/java/lang/VMRuntime.java b/vm/reference/java/lang/VMRuntime.java index 72e22390d..8da217f15 100644 --- a/vm/reference/java/lang/VMRuntime.java +++ b/vm/reference/java/lang/VMRuntime.java @@ -151,9 +151,10 @@ final class VMRuntime * already been mapped to a true filename. * * @param filename the file to load + * @param loader class loader, or null for the boot loader * @return 0 on failure, nonzero on success */ - static native int nativeLoad(String filename); + static native int nativeLoad(String filename, ClassLoader loader); /** * Map a system-independent "short name" to the full file name. diff --git a/vm/reference/java/lang/VMSecurityManager.java b/vm/reference/java/lang/VMSecurityManager.java deleted file mode 100644 index 3d95c8a96..000000000 --- a/vm/reference/java/lang/VMSecurityManager.java +++ /dev/null @@ -1,73 +0,0 @@ -/* VMSecurityManager.java -- Reference implementation of VM hooks for security - Copyright (C) 1998, 2002 Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath 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 for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package java.lang; - -/** - * VMSecurityManager is a helper class for SecurityManager the VM must - * implement. - * - * @author John Keiser - * @author Eric Blake - */ -final class VMSecurityManager -{ - /** - * Get a list of all the classes currently executing methods on the - * Java stack. getClassContext()[0] is the currently executing method, ie. - * the method which called SecurityManager.getClassContext(). (Hint: you - * may need to pop off one or more frames: don't include SecurityManager - * or VMSecurityManager.getClassContext in your result. Also, be sure that - * you correctly handle the context if SecurityManager.getClassContext - * was invoked by reflection). - * - * @return an array of the declaring classes of each stack frame - */ - static native Class[] getClassContext(); - - /** - * Get the current ClassLoader. This is the first non-null class loader - * on the stack, if one exists, stopping either at the end of the stack - * or the first instance of a PrivilegedAction. In other words, this call - * automatically unwinds past all classes loaded by the bootstrap loader, - * where getClassLoader() returns null, to get to the user class that - * really invoked the call that needs a classloader. - * - * @return the current ClassLoader - */ - static native ClassLoader currentClassLoader(); -} -- cgit v1.2.1