From: <ls...@us...> - 2009-04-02 19:01:08
|
Revision: 5210 http://jnode.svn.sourceforge.net/jnode/?rev=5210&view=rev Author: lsantha Date: 2009-04-02 19:01:01 +0000 (Thu, 02 Apr 2009) Log Message: ----------- Separating jnode os code from classlib. Modified Paths: -------------- trunk/all/conf/openjdk-annotations.properties trunk/core/src/core/org/jnode/debugger/DebuggerUtils.java trunk/core/src/core/org/jnode/debugger/ThreadListState.java trunk/core/src/core/org/jnode/debugger/ThreadState.java trunk/core/src/core/org/jnode/vm/isolate/VmIsolate.java trunk/core/src/core/org/jnode/vm/scheduler/IRQThread.java trunk/core/src/openjdk/vm/java/lang/reflect/NativeProxy.java trunk/core/src/openjdk/vm/sun/misc/NativeUnsafe.java trunk/core/src/test/org/jnode/test/core/StackView.java trunk/shell/src/shell/org/jnode/shell/command/ThreadCommand.java Added Paths: ----------- trunk/core/src/classpath/java/java/lang/ClassLoader.java trunk/core/src/classpath/java/java/lang/Thread.java trunk/core/src/classpath/vm/java/lang/NativeClassLoader.java trunk/core/src/classpath/vm/java/lang/NativeThread.java trunk/core/src/classpath/vm/java/lang/ThreadHelper.java Removed Paths: ------------- trunk/core/src/classpath/vm/java/lang/ClassLoader.java trunk/core/src/classpath/vm/java/lang/Thread.java Modified: trunk/all/conf/openjdk-annotations.properties =================================================================== --- trunk/all/conf/openjdk-annotations.properties 2009-04-01 18:57:30 UTC (rev 5209) +++ trunk/all/conf/openjdk-annotations.properties 2009-04-02 19:01:01 UTC (rev 5210) @@ -9,6 +9,7 @@ java/awt/image/DataBuffer.class=SharedStatics java/awt/KeyboardFocusManager.class=SharedStatics java/awt/Toolkit.class=SharedStatics +java/lang/Thread.class=SharedStatics java/lang/ThreadLocal.class=SharedStatics java/lang/Throwable.class=MagicPermission java/net/InetAddress.class=SharedStatics Copied: trunk/core/src/classpath/java/java/lang/ClassLoader.java (from rev 5209, trunk/core/src/classpath/vm/java/lang/ClassLoader.java) =================================================================== --- trunk/core/src/classpath/java/java/lang/ClassLoader.java (rev 0) +++ trunk/core/src/classpath/java/java/lang/ClassLoader.java 2009-04-02 19:01:01 UTC (rev 5210) @@ -0,0 +1,950 @@ +/* + * $Id$ + * + * Copyright (C) 2003-2009 JNode.org + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package java.lang; + +import gnu.classpath.SystemProperties; +import gnu.java.util.EmptyEnumeration; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.ByteBuffer; +import java.security.AccessController; +import java.security.CodeSource; +import java.security.PermissionCollection; +import java.security.Policy; +import java.security.PrivilegedAction; +import java.security.ProtectionDomain; +import java.security.cert.Certificate; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import sun.reflect.Reflection; + +public abstract class ClassLoader { + + private final ClassLoader parent; + + //this is always a VmClassLoaderInstance + final Object vmClassLoader; + + private ProtectionDomain defaultProtectionDomain; + + /** + * All packages defined by this classloader. It is not private in order to + * allow native code (and trusted subclasses) access to this field. + */ + final HashMap<String, Package> definedPackages = new HashMap<String, Package>(); + + /** + * The desired assertion status of classes loaded by this loader, if not + * overridden by package or class instructions. + */ + // Package visible for use by Class. + boolean defaultAssertionStatus = VMClassLoader.defaultAssertionStatus(); + + /** + * The map of package assertion status overrides, or null if no package + * overrides have been specified yet. The values of the map should be + * Boolean.TRUE or Boolean.FALSE, and the unnamed package is represented by + * the null key. This map must be synchronized on this instance. + */ + // Package visible for use by Class. + Map<String, Boolean> packageAssertionStatus; + + /** + * The map of class assertion status overrides, or null if no class + * overrides have been specified yet. The values of the map should be + * Boolean.TRUE or Boolean.FALSE. This map must be synchronized on this + * instance. + */ + // Package visible for use by Class. + Map<String, Boolean> classAssertionStatus; + + static class StaticData { + /** + * The System Class Loader (a.k.a. Application Class Loader). The one + * returned by ClassLoader.getSystemClassLoader. + */ + static final ClassLoader systemClassLoader = VMClassLoader + .getSystemClassLoader(); + static { + // Find out if we have to install a default security manager. Note + // that + // this is done here because we potentially need the system class + // loader + // to load the security manager and note also that we don't need the + // security manager until the system class loader is created. + // If the runtime chooses to use a class loader that doesn't have + // the + // system class loader as its parent, it is responsible for setting + // up a security manager before doing so. + String secman = SystemProperties + .getProperty("java.security.manager"); + if (secman != null && SecurityManager.current == null) { + if (secman.equals("") || secman.equals("default")) { + SecurityManager.current = new SecurityManager(); + } else { + try { + Class< ? > cl = Class.forName(secman, false, + StaticData.systemClassLoader); + SecurityManager.current = (SecurityManager) cl + .newInstance(); + } catch (Exception x) { + throw (InternalError) new InternalError( + "Unable to create SecurityManager") + .initCause(x); + } + } + } + } + + /** + * The default protection domain, used when defining a class with a null + * parameter for the domain. + */ + static final ProtectionDomain defaultProtectionDomain; + static { + final CodeSource cs = new CodeSource(null, (Certificate[])null); + PermissionCollection perm = AccessController + .doPrivileged(new PrivilegedAction<PermissionCollection>() { + public PermissionCollection run() { + return Policy.getPolicy().getPermissions(cs); + } + }); + defaultProtectionDomain = new ProtectionDomain(cs, perm); + } + + /** + * The command-line state of the package assertion status overrides. + * This map is never modified, so it does not need to be synchronized. + */ + // Package visible for use by Class. + static final Map<String, Boolean> systemPackageAssertionStatus = VMClassLoader + .packageAssertionStatus(); + + /** + * The command-line state of the class assertion status overrides. This + * map is never modified, so it does not need to be synchronized. + */ + // Package visible for use by Class. + static final Map<String, Boolean> systemClassAssertionStatus = VMClassLoader + .classAssertionStatus(); + } + + /** + * Create a new ClassLoader with the specified parent. The parent will be + * consulted when a class or resource is requested through + * <code>loadClass()</code> or <code>getResource()</code>. Only when + * the parent classloader cannot provide the requested class or resource the + * <code>findClass()</code> or <code>findResource()</code> method of + * this classloader will be called. There may be a security check for + * <code>checkCreateClassLoader</code>. + * + * @param parent + * the classloader's parent + * @throws SecurityException + * if the security check fails + * @since 1.2 + */ + protected ClassLoader(ClassLoader parent) { + /* May we create a new classloader? */ + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkCreateClassLoader(); + } + this.parent = parent; + this.vmClassLoader = createVmJavaClassLoader0(this); + } + + private static native Object createVmJavaClassLoader0(ClassLoader instance); + + /** + * Create a new instance + * + */ + protected ClassLoader() { + this(getSystemClassLoader()); + } + + /** + * Create a new classloader wrapped around a given VmClassLoader. + * + * @param vmClassLoader + */ + protected ClassLoader(Object vmClassLoader, int discriminator) { + /* May we create a new classloader? */ + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkCreateClassLoader(); + } + if (vmClassLoader == null) { + throw new IllegalArgumentException("vmClassLoader cannot be null"); + } + checkArg0(vmClassLoader); + this.parent = null; + this.vmClassLoader = vmClassLoader; + } + + private static native void checkArg0(Object vmClassLoader); + + /** + * Create a new classloader wrapped around a given VmClassLoader, + * with a given parent loader. + * + * @param vmClassLoader + */ + protected ClassLoader(ClassLoader parent, Object vmClassLoader) { + /* May we create a new classloader? */ + checkArgs0(vmClassLoader); + this.parent = parent; + this.vmClassLoader = vmClassLoader; + } + + private static native void checkArgs0(Object vmClassLoader); + + /** + * Gets the VmClassLoader that is used by this classloader. + * This method requires special permission. + * @return + */ + public final Object getVmClassLoader() { + return getVmClassLoader0(); + } + + private native Object getVmClassLoader0(); + + /** + * Load and resolve a class with a given name. + * + * @param name + * @return Class + * @throws ClassNotFoundException + */ + public Class loadClass(String name) throws ClassNotFoundException { + // return vmClassLoader.loadClass(name, true).asClass(); + return loadClass(name, true); + } + + /** + * Load and optionally resolve a class with a given name. + * + * @param name + * @param resolve + * @return Class + * @throws ClassNotFoundException + */ + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException { + + /* Have we already loaded this class? */ + final Class cls = findLoadedClass(name); + if (cls != null) { + return cls; + } + + /* Can the class been loaded by a parent? */ + try { + if ((parent == null) || skipParentLoader(name)) { + return loadClass0(name, resolve); + } else { + return parent.loadClass(name, resolve); + } + } catch (ClassNotFoundException e) { + // e.printStackTrace(); + } + /* Still not found, we have to do it ourself. */ + final Class c = findClass(name); + if (resolve) { + resolveClass(c); + } + return c; + } + + private static native Class loadClass0(String name, boolean resolve) throws ClassNotFoundException; + + /** + * Define a byte-array of class data into a loaded class. + * + * @param data + * @param offset + * @param length + * @return Class + * @deprecated Replaced by {@link #defineClass(String, byte[], int, int)} + */ + protected final Class defineClass(byte[] data, int offset, int length) { + return defineClass(null, data, offset, length, null); + } + + /** + * Define a byte-array of class data into a loaded class. + * + * @param name + * @param data + * @param offset + * @param length + * @return Class + */ + protected final Class defineClass(String name, byte[] data, int offset, + int length) { + return defineClass(name, data, offset, length, null); + } + + /** + * Defines a new package and creates a Package object. The package should be + * defined before any class in the package is defined with + * <code>defineClass()</code>. The package should not yet be defined + * before in this classloader or in one of its parents (which means that + * <code>getPackage()</code> should return <code>null</code>). All + * parameters except the <code>name</code> of the package may be + * <code>null</code>. + * + * <p> + * Subclasses should call this method from their <code>findClass()</code> + * implementation before calling <code>defineClass()</code> on a Class in + * a not yet defined Package (which can be checked by calling + * <code>getPackage()</code>). + * + * @param name + * the name of the Package + * @param specTitle + * the name of the specification + * @param specVendor + * the name of the specification designer + * @param specVersion + * the version of this specification + * @param implTitle + * the name of the implementation + * @param implVendor + * the vendor that wrote this implementation + * @param implVersion + * the version of this implementation + * @param sealed + * if sealed the origin of the package classes + * @return the Package object for the specified package + * @throws IllegalArgumentException + * if the package name is null or it was already defined by this + * classloader or one of its parents + * @see Package + * @since 1.2 + */ + protected Package definePackage(String name, String specTitle, + String specVendor, String specVersion, String implTitle, + String implVendor, String implVersion, URL sealed) { + if (getPackage(name) != null) + throw new IllegalArgumentException("Package " + name + + " already defined"); + Package p = new Package(name, specTitle, specVendor, specVersion, + implTitle, implVendor, implVersion, sealed, this); + synchronized (definedPackages) { + definedPackages.put(name, p); + } + return p; + } + + /** + * Define a byte-array of class data into a loaded class. + * + * @param name + * @param data + * @param offset + * @param length + * @param protDomain + * @return Class + */ + protected final Class defineClass(String name, byte[] data, int offset, + int length, ProtectionDomain protDomain) { + if (data == null) { + throw new NullPointerException(); + } + if (offset < 0 || length < 0 || (offset + length) > data.length) { + throw new IndexOutOfBoundsException(); + } + if (protDomain == null) { + + protDomain = AccessController + .doPrivileged(new PrivilegedAction<ProtectionDomain>() { + + public ProtectionDomain run() { + return getDefaultProtectionDomain(); + } + }); + } + return defineClass0(name, data, offset, length, protDomain); + } + + private native Class defineClass0(String name, byte[] data, int offset, int length, ProtectionDomain protDomain); + + /** + * Define a byte-array of class data into a loaded class. + * + * @param name + * @param data + * @param protDomain + * @return Class + */ + protected final Class defineClass(String name, ByteBuffer data, ProtectionDomain protDomain) { + if (data == null) { + throw new NullPointerException(); + } + if (protDomain == null) { + protDomain = AccessController.doPrivileged( + new PrivilegedAction<ProtectionDomain>() { + public ProtectionDomain run() { + return getDefaultProtectionDomain(); + } + }); + } + return defineClass0(name, data, protDomain); + } + + private native Class defineClass0(String name, ByteBuffer data, ProtectionDomain protDomain); + + private ProtectionDomain getDefaultProtectionDomain() { + if (defaultProtectionDomain == null) { + final CodeSource cs = new CodeSource(null, (Certificate[])null); + defaultProtectionDomain = new ProtectionDomain(cs, Policy + .getPolicy().getPermissions(cs)); + } + return defaultProtectionDomain; + } + + /** + * Resolve all references in the given class. + * + * @param c + */ + protected final void resolveClass(Class c) { + if (c == null) { + throw new NullPointerException(); + } + } + + /** + * Finds the class with the given name if it had been previously loaded + * through this class loader. + * + * @param name + * @return the Class object, or null if the class has not been loaded + */ + protected native final Class findLoadedClass(String name); + + /** + * Finds the specified class. This method should be overridden by class + * loader implementations that follow the new delegation model for loading + * classes, and will be called by the loadClass method after checking the + * parent class loader for the requested class. The default implementation + * throws ClassNotFoundException. + * + * @param name + * @return Class + * @throws ClassNotFoundException + */ + protected Class findClass(String name) throws ClassNotFoundException { + throw new ClassNotFoundException(name); + } + + /** + * Find a system class. + * + * @param name + * @return Class + * @throws ClassNotFoundException + */ + protected final Class findSystemClass(String name) + throws ClassNotFoundException { + if (name == null) { + throw new NullPointerException(); + } else { + return loadClass0(name, true); + } + } + + /** + * Gets a system resource as stream by name. + * + * @param name + * @return InputStream + */ + public static final InputStream getSystemResourceAsStream(String name) { + try { + return getSystemResourceAsStream0(name); + } catch (IOException ex) { + return null; + } + } + + private static native InputStream getSystemResourceAsStream0(String name) throws IOException; + + /** + * Gets a resource as stream by name. + * + * @param name + * @return InputStream + */ + public InputStream getResourceAsStream(String name) { + URL url = getResource(name); + if (url != null) { + try { + return url.openStream(); + } catch (IOException ex) { + // Syslog.debug("Cannot load resource " + name, ex); + return null; + } + } else { + return null; + } + } + + /** + * Gets a URL to a system resource by name. + * + * @param name + * @return URL + */ + public static final URL getSystemResource(String name) { + try { + if (name.startsWith("/")) { + return new URL("system://" + name); + } else { + return new URL("system:///" + name); + } + } catch (MalformedURLException ex) { + ex.printStackTrace(); + return null; + } + } + + /** + * Gets an URL to a resource by name. + * + * @param name + * @return URL + */ + public URL getResource(String name) { + URL result = null; + + if (parent == null) { + if (resourceExists0(name)) { + try { + if (name.startsWith("/")) { + result = new URL("system://" + name); + } else { + result = new URL("system:///" + name); + } + } catch (MalformedURLException ex) { + ex.printStackTrace(); + result = null; + } + } + } else { + result = parent.getResource(name); + } + + if (result == null) { + result = findResource(name); + } + return result; + } + + private native boolean resourceExists0(String name); + + public Enumeration getResources(String name) throws IOException { + final List<URL> urls = new ArrayList<URL>(); + getResourcesImpl(name, urls); + + return new Enumeration<URL>() + { + private Iterator<URL> it = urls.iterator(); + + public boolean hasMoreElements() { + return it.hasNext(); + } + + public URL nextElement() { + return it.next(); + } + }; + } + + protected boolean getResourcesImpl(String name, List<URL> urls) throws IOException { + URL result = null; + if (parent == null) { + if (resourceExists0(name)) { + try { + if (name.startsWith("/")) { + //todo: adjust the rt.jar path to match the future configurations + //todo: one possibility is ${java.home}/lib/rt.jar + result = new URL("jar:file:/jifs/lib/rt.jar!" + name); + //result = new URL("system://" + name); + } else { + //todo: adjust the rt.jar path to match the future configurations + //todo: one possibility is ${java.home}/lib/rt.jar + result = new URL("jar:file:/jifs/lib/rt.jar!/" + name); + //result = new URL("system:///" + name); + } + } catch (MalformedURLException ex) { + ex.printStackTrace(); + result = null; + } + if(result != null) + { + if(!urls.contains(result)) urls.add(result); + } + } + } else { + parent.getResourcesImpl(name, urls); + } + + if (result == null) { + result = findResource(name); + if(result != null) + { + if(!urls.contains(result)) urls.add(result); + } + } + + return (result != null); + } + + /** + * Finds the resource with the given name. Class loader implementations + * should override this method to specify where to find resources. + * + * @param name + * @return URL + */ + protected URL findResource(String name) { + return null; + } + + /** + * Called whenever all locations of a named resource are needed. + * It is called by <code>getResources()</code> after it has called + * <code>parent.getResources()</code>. The results are combined by + * the <code>getResources()</code> method. + * + * <p>The default implementation always returns an empty Enumeration. + * Subclasses should override it when they can provide an Enumeration of + * URLs (possibly just one element) to the named resource. + * The first URL of the Enumeration should be the same as the one + * returned by <code>findResource</code>. + * + * @param name the name of the resource to be found + * @return a possibly empty Enumeration of URLs to the named resource + * @throws IOException if I/O errors occur in the process + * @since 1.2 + */ + protected Enumeration findResources(String name) throws IOException + { + return EmptyEnumeration.getInstance(); + } + + + /** + * Returns the Package object for the requested package name. It returns + * null when the package is not defined by this classloader or one of its + * parents. + * + * @param name + * the package name to find + * @return the package, if defined + * @since 1.2 + */ + protected Package getPackage(String name) { + Package p; + if (parent == null) { + p = VMClassLoader.getPackage(name); + } else { + p = parent.getPackage(name); + } + + if (p == null) { + synchronized (definedPackages) { + p = definedPackages.get(name); + } + } + return p; + } + + /** + * Returns all Package objects defined by this classloader and its parents. + * + * @return an array of all defined packages + * @since 1.2 + */ + protected Package[] getPackages() { + // Get all our packages. + Package[] packages; + synchronized (definedPackages) { + packages = new Package[definedPackages.size()]; + definedPackages.values().toArray(packages); + } + + // If we have a parent get all packages defined by our parents. + Package[] parentPackages; + if (parent == null) + parentPackages = VMClassLoader.getPackages(); + else + parentPackages = parent.getPackages(); + + Package[] allPackages = new Package[parentPackages.length + + packages.length]; + System.arraycopy(parentPackages, 0, allPackages, 0, + parentPackages.length); + System.arraycopy(packages, 0, allPackages, parentPackages.length, + packages.length); + return allPackages; + } + + /** + * Avoid trying to load the given class via its parent classloader? + * + * @param name + * @return {@code true} if the parent classloader should be skipped. + */ + public boolean skipParentLoader(String name) { + return false; + } + + /** + * Gets the system classloader. + * + * @return ClassLoader + */ + public static native ClassLoader getSystemClassLoader(); + + public static Enumeration getSystemResources(String name) + throws IOException { + return EmptyEnumeration.getInstance(); + } + + /** + * @return + */ + public ClassLoader getParent() { + return parent; + } + + /** + * Called by <code>Runtime.loadLibrary()</code> to get an absolute path to + * a (system specific) library that was requested by a class loaded by this + * classloader. The default implementation returns <code>null</code>. It + * should be implemented by subclasses when they have a way to find the + * absolute path to a library. If this method returns null the library is + * searched for in the default locations (the directories listed in the + * <code>java.library.path</code> system property). + * + * @param name + * the (system specific) name of the requested library + * @return the full pathname to the requested library, or null + * @see Runtime#loadLibrary(String) + * @since 1.2 + */ + protected String findLibrary(String name) { + return null; + } + + /** + * Sets the signers of a class. This should be invoked after defining a + * class. + * + * @param clazz + * The class object. + * @param signers + * The signers. + */ + protected final void setSigners(Class clazz, Object[] signers) { + // TODO implement me + } + + /** + * Set the default assertion status for classes loaded by this classloader, + * used unless overridden by a package or class request. + * + * @param enabled + * true to set the default to enabled + * @see #setClassAssertionStatus(String, boolean) + * @see #setPackageAssertionStatus(String, boolean) + * @see #clearAssertionStatus() + * @since 1.4 + */ + public void setDefaultAssertionStatus(boolean enabled) { + defaultAssertionStatus = enabled; + } + + /** + * Set the default assertion status for packages, used unless overridden by + * a class request. This default also covers subpackages, unless they are + * also specified. The unnamed package should use null for the name. + * + * @param name + * the package (and subpackages) to affect + * @param enabled + * true to set the default to enabled + * @see #setDefaultAssertionStatus(boolean) + * @see #setClassAssertionStatus(String, boolean) + * @see #clearAssertionStatus() + * @since 1.4 + */ + public synchronized void setPackageAssertionStatus(String name, + boolean enabled) { + if (packageAssertionStatus == null) + packageAssertionStatus = new HashMap<String, Boolean>( + StaticData.systemPackageAssertionStatus); + packageAssertionStatus.put(name, Boolean.valueOf(enabled)); + } + + /** + * Set the default assertion status for a class. This only affects the + * status of top-level classes, any other string is harmless. + * + * @param name + * the class to affect + * @param enabled + * true to set the default to enabled + * @throws NullPointerException + * if name is null + * @see #setDefaultAssertionStatus(boolean) + * @see #setPackageAssertionStatus(String, boolean) + * @see #clearAssertionStatus() + * @since 1.4 + */ + public synchronized void setClassAssertionStatus(String name, + boolean enabled) { + if (classAssertionStatus == null) + classAssertionStatus = new HashMap<String, Boolean>( + StaticData.systemClassAssertionStatus); + // The toString() hack catches null, as required. + classAssertionStatus.put(name.toString(), Boolean.valueOf(enabled)); + } + + /** + * Resets the default assertion status of this classloader, its packages and + * classes, all to false. This allows overriding defaults inherited from the + * command line. + * + * @see #setDefaultAssertionStatus(boolean) + * @see #setClassAssertionStatus(String, boolean) + * @see #setPackageAssertionStatus(String, boolean) + * @since 1.4 + */ + public synchronized void clearAssertionStatus() { + defaultAssertionStatus = false; + packageAssertionStatus = null; + classAssertionStatus = null; + } + + //jnod+openjdk + // Returns the invoker's class loader, or null if none. + // NOTE: This must always be invoked when there is exactly one intervening + // frame from the core libraries on the stack between this method's + // invocation and the desired invoker. + static ClassLoader getCallerClassLoader() { + // NOTE use of more generic Reflection.getCallerClass() + Class caller = Reflection.getCallerClass(3); + // This can be null if the VM is requesting it + if (caller == null) { + return null; + } + // Circumvent security check since this is package-private + return caller.getClassLoader0(); + } + + // Returns true if the specified class loader can be found in this class + // loader's delegation chain. + boolean isAncestor(ClassLoader cl) { + ClassLoader acl = this; + do { + acl = acl.parent; + if (cl == acl) { + return true; + } + } while (acl != null); + return false; + } + +/** + * Returns the assertion status that would be assigned to the specified + * class if it were to be initialized at the time this method is invoked. + * If the named class has had its assertion status set, the most recent + * setting will be returned; otherwise, if any package default assertion + * status pertains to this class, the most recent setting for the most + * specific pertinent package default assertion status is returned; + * otherwise, this class loader's default assertion status is returned. + * </p> + * + * @param className + * The fully qualified class name of the class whose desired + * assertion status is being queried. + * + * @return The desired assertion status of the specified class. + * + * @see #setClassAssertionStatus(String, boolean) + * @see #setPackageAssertionStatus(String, boolean) + * @see #setDefaultAssertionStatus(boolean) + * + * @since 1.4 + */ + synchronized boolean desiredAssertionStatus(String className) { + Boolean result; + + // assert classAssertionStatus != null; + // assert packageAssertionStatus != null; + + // Check for a class entry + result = (Boolean)classAssertionStatus.get(className); + if (result != null) + return result.booleanValue(); + + // Check for most specific package entry + int dotIndex = className.lastIndexOf("."); + if (dotIndex < 0) { // default package + result = (Boolean)packageAssertionStatus.get(null); + if (result != null) + return result.booleanValue(); + } + while(dotIndex > 0) { + className = className.substring(0, dotIndex); + result = (Boolean)packageAssertionStatus.get(className); + if (result != null) + return result.booleanValue(); + dotIndex = className.lastIndexOf(".", dotIndex-1); + } + + // Return the classloader default + return defaultAssertionStatus; + } + + { + packageAssertionStatus = new HashMap(); + } + + public static void loadLibrary(Class fromClass, String libname, boolean b) { + //do nothing + } + +} Property changes on: trunk/core/src/classpath/java/java/lang/ClassLoader.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Copied: trunk/core/src/classpath/java/java/lang/Thread.java (from rev 5209, trunk/core/src/classpath/vm/java/lang/Thread.java) =================================================================== --- trunk/core/src/classpath/java/java/lang/Thread.java (rev 0) +++ trunk/core/src/classpath/java/java/lang/Thread.java 2009-04-02 19:01:01 UTC (rev 5210) @@ -0,0 +1,1390 @@ +/* Thread -- an independent thread of executable code + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + 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., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 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; + +import java.util.Map; +import java.util.HashMap; + + +import sun.security.util.SecurityConstants; +import sun.nio.ch.Interruptible; + +/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 +* "The Java Language Specification", ISBN 0-201-63451-1 +* plus online API docs for JDK 1.2 beta from http://www.javasoft.com. +* Status: Believed complete to version 1.4, with caveats. We do not +* implement the deprecated (and dangerous) stop, suspend, and resume +* methods. Security implementation is not complete. +*/ + +/** + * Thread represents a single thread of execution in the VM. When an + * application VM starts up, it creates a non-daemon Thread which calls the + * main() method of a particular class. There may be other Threads running, + * such as the garbage collection thread. + * + * <p>Threads have names to identify them. These names are not necessarily + * unique. Every Thread has a priority, as well, which tells the VM which + * Threads should get more running time. New threads inherit the priority + * and daemon status of the parent thread, by default. + * + * <p>There are two methods of creating a Thread: you may subclass Thread and + * implement the <code>run()</code> method, at which point you may start the + * Thread by calling its <code>start()</code> method, or you may implement + * <code>Runnable</code> in the class you want to use and then call new + * <code>Thread(your_obj).start()</code>. + * + * <p>The virtual machine runs until all non-daemon threads have died (either + * by returning from the run() method as invoked by start(), or by throwing + * an uncaught exception); or until <code>System.exit</code> is called with + * adequate permissions. + * + * <p>It is unclear at what point a Thread should be added to a ThreadGroup, + * and at what point it should be removed. Should it be inserted when it + * starts, or when it is created? Should it be removed when it is suspended + * or interrupted? The only thing that is clear is that the Thread should be + * removed when it is stopped. + * + * @author Tom Tromey + * @author John Keiser + * @author Eric Blake (eb...@em...) + * @author Andrew John Hughes (gnu...@me...) + * @see Runnable + * @see Runtime#exit(int) + * @see #run() + * @see #start() + * @see ThreadLocal + * @since 1.0 + */ +public class Thread implements Runnable +{ + /** The minimum priority for a Thread. */ + public static final int MIN_PRIORITY = 1; + + /** The priority a Thread gets by default. */ + public static final int NORM_PRIORITY = 5; + + /** The maximum priority for a Thread. */ + public static final int MAX_PRIORITY = 10; + + private static final String NONAME = "Thread"; + + /** The VM thread implementing this thread */ + final Object vmThread; + + /** The group this thread belongs to. + * + */ + ThreadGroup group; + + /** The object to run(), null if this is the target. */ + final Runnable runnable; + + /** The name of this thread */ + String name; + + /** Is this a daemon thread? */ + private boolean daemon; + + /** The context classloader of this thread */ + private ClassLoader contextClassLoader; + + /** The thread in which I was created */ + private final Thread parent; + + /** The default exception handler. */ + private static UncaughtExceptionHandler defaultHandler; + + /* ThreadLocal values pertaining to this thread. This map is maintained + * by the ThreadLocal class. */ + ThreadLocal.ThreadLocalMap threadLocals = null; + + /* + * InheritableThreadLocal values pertaining to this thread. This map is + * maintained by the InheritableThreadLocal class. + */ + ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; + + /** The uncaught exception handler. */ + UncaughtExceptionHandler exceptionHandler; + + /** + * Name and number of threads created. Used only for generating unique names. + * + * @see java.lang.Thread#autoName(String) + */ + private static final HashMap<String, Integer> nameMap = new HashMap<String, Integer>(); + + /** + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(null, null,</code> + * <i>gname</i><code>)</code>, where <b><i>gname</i></b> is + * a newly generated name. Automatically generated names are of the + * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer. + * <p> + * Threads created this way must have overridden their + * <code>run()</code> method to actually do anything. An example + * illustrating this method being used follows: + * <p><blockquote><pre> + * import java.lang.*; + * + * class plain01 implements Runnable { + * String name; + * plain01() { + * name = null; + * } + * plain01(String s) { + * name = s; + * } + * public void run() { + * if (name == null) + * System.out.println("A new thread created"); + * else + * System.out.println("A new thread with name " + name + + * " created"); + * } + * } + * class threadtest01 { + * public static void main(String args[] ) { + * int failed = 0 ; + * + * <b>Thread t1 = new Thread();</b> + * if (t1 != null) + * System.out.println("new Thread() succeed"); + * else { + * System.out.println("new Thread() failed"); + * failed++; + * } + * } + * } + * </pre></blockquote> + * + * @see java.lang.Thread#Thread(java.lang.ThreadGroup, + * java.lang.Runnable, java.lang.String) + */ + public Thread() + { + this(null, null, NONAME); + } + + /** + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(null, target,</code> + * <i>gname</i><code>)</code>, where <i>gname</i> is + * a newly generated name. Automatically generated names are of the + * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer. + * + * @param target the object whose <code>run</code> method is called. + * @see java.lang.Thread#Thread(java.lang.ThreadGroup, + * java.lang.Runnable, java.lang.String) + */ + public Thread(Runnable target) + { + this(null, target, NONAME); + } + + /** + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(null, null, name)</code>. + * + * @param name the name of the new thread. + * @see java.lang.Thread#Thread(java.lang.ThreadGroup, + * java.lang.Runnable, java.lang.String) + */ + public Thread(String name) + { + this(null, null, name); + } + + /** + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(group, target,</code> + * <i>gname</i><code>)</code>, where <i>gname</i> is + * a newly generated name. Automatically generated names are of the + * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer. + * + * @param group the group to put the Thread into + * @param target the Runnable object to execute + * @throws SecurityException if this thread cannot access <code>group</code> + * @throws IllegalThreadStateException if group is destroyed + * @see #Thread(ThreadGroup, Runnable, String) + */ + public Thread(ThreadGroup group, Runnable target) + { + this(group, target, NONAME); + } + + /** + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(group, null, name)</code> + * + * @param group the group to put the Thread into + * @param name the name for the Thread + * @throws NullPointerException if name is null + * @throws SecurityException if this thread cannot access <code>group</code> + * @throws IllegalThreadStateException if group is destroyed + * @see #Thread(ThreadGroup, Runnable, String) + */ + public Thread(ThreadGroup group, String name) + { + this(group, null, name); + } + + /** + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(null, target, name)</code>. + * + * @param target the Runnable object to execute + * @param name the name for the Thread + * @throws NullPointerException if name is null + * @see #Thread(ThreadGroup, Runnable, String) + */ + public Thread(Runnable target, String name) + { + this(null, target, name); + } + + /** + * Allocate a new Thread object, with the specified ThreadGroup and name, and + * using the specified Runnable object's <code>run()</code> method to + * execute. If the Runnable object is null, <code>this</code> (which is + * a Runnable) is used instead. + * + * <p>If the ThreadGroup is null, the security manager is checked. If a + * manager exists and returns a non-null object for + * <code>getThreadGroup</code>, that group is used; otherwise the group + * of the creating thread is used. Note that the security manager calls + * <code>checkAccess</code> if the ThreadGroup is not null. + * + * <p>The new Thread will inherit its creator's priority and daemon status. + * These can be changed with <code>setPriority</code> and + * <code>setDaemon</code>. + * + * @param group the group to put the Thread into + * @param target the Runnable object to execute + * @param name the name for the Thread + * @throws NullPointerException if name is null + * @throws SecurityException if this thread cannot access <code>group</code> + * @throws IllegalThreadStateException if group is destroyed + * @see Runnable#run() + * @see #run() + * @see #setDaemon(boolean) + * @see #setPriority(int) + * @see SecurityManager#checkAccess(ThreadGroup) + * @see ThreadGroup#checkAccess() + */ + public Thread(ThreadGroup group, Runnable target, String name) + { + Thread current = currentThread(); + + if (group != null) { + group.checkAccess(); + } else { + group = current.getThreadGroup(); + } + + if (group == null) { + throw new InternalError("Live thread has invalid group: " + name); + } + + group.addUnstarted(); + + this.group = group; + this.runnable = target; + this.name = autoName(name); + this.parent = current; + + this.daemon = current.isDaemon(); + + this.vmThread = createVmThread0(current); + setPriority(current.getPriority()); + updateName0(); + + + if (parent.inheritableThreadLocals != null) + this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); + } + + private native Object createVmThread0(Thread current); + + /** + * Allocate a new Thread object, as if by + * <code>Thread(group, null, name)</code>, and give it the specified stack + * size, in bytes. The stack size is <b>highly platform independent</b>, + * and the virtual machine is free to round up or down, or ignore it + * completely. A higher value might let you go longer before a + * <code>StackOverflowError</code>, while a lower value might let you go + * longer before an <code>OutOfMemoryError</code>. Or, it may do absolutely + * nothing! So be careful, and expect to need to tune this value if your + * virtual machine even supports it. + * + * @param group the group to put the Thread into + * @param target the Runnable object to execute + * @param name the name for the Thread + * @param size the stack size, in bytes; 0 to be ignored + * @throws NullPointerException if name is null + * @throws SecurityException if this thread cannot access <code>group</code> + * @throws IllegalThreadStateException if group is destroyed + * @since 1.4 + */ + public Thread(ThreadGroup group, Runnable target, String name, long size) + { + Thread current = currentThread(); + + if (group != null) { + group.checkAccess(); + } else { + group = current.getThreadGroup(); + } + + if (group == null) { + throw new InternalError("Live thread has invalid group: " + name); + } + + group.addUnstarted(); + + this.group = group; + this.runnable = target; + this.name = autoName(name); + this.parent = current; + + this.daemon = current.isDaemon(); + + this.vmThread = createVmThread0(current); + setPriority(current.getPriority()); + updateName0(); + + + if (parent.inheritableThreadLocals != null) + this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); + } + + /** + * Create a new instance with a given group as containing group, a runnable + * as thread runner and a given name. + * + * @param group + * @param target + * @param name + */ + protected Thread(ThreadGroup group, Runnable target, String name, Object isolatedStatics) { + /* + if (!(this instanceof IsolateThread)) { + throw new SecurityException("Constructor can only be called from IsolateThread"); + } + */ + if (!(this.getClass().getName().startsWith("org.jnode.vm.isolate"))) { + throw new SecurityException("Constructor can only be called from IsolateThread"); + } + if (group == null) { + throw new InternalError("Isolate thread has invalid group: " + name); + } + + group.addUnstarted(); + + this.group = group; + this.runnable = target; + this.name = autoName(name); + this.parent = null; + this.daemon = false; + + this.vmThread = createVmThread1(isolatedStatics); + setPriority(this.getPriority()); + updateName0(); + + //todo review it: should thread locals be inherited accorss isolates? Probably not... + ThreadLocal.ThreadLocalMap parentLocals = currentThread().inheritableThreadLocals; + if (parentLocals != null) + this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parentLocals); + } + + private native Object createVmThread1(Object isolatedStatics); + + /** + * Create a new thread from a given VmThread. Only used for the main thread. + * + * @param vmThread + * @throws IllegalArgumentException + * If the given vmThread is not the root thread or the given + * vmThread already has an associated java thread. + */ + public Thread(Object vmThread) throws IllegalArgumentException { + checkArg0(vmThread); + this.vmThread = vmThread; + this.group = ROOT_GROUP; + this.group.addUnstarted(); + this.name = autoName("System"); + this.runnable = null; + this.parent = null; + updateName0(); + } + + private static native void checkArg0(Object vmThread); + + private native void updateName0(); + /** + * Get the number of active threads in the current Thread's ThreadGroup. + * This implementation calls + * <code>currentThread().getThreadGroup().activeCount()</code>. + * + * @return the number of active threads in the current ThreadGroup + * @see ThreadGroup#activeCount() + */ + public static int activeCount() + { + return currentThread().getThreadGroup().activeCount(); + } + + /** + * Check whether the current Thread is allowed to modify this Thread. This + * passes the check on to <code>SecurityManager.checkAccess(this)</code>. + * + * @throws SecurityException if the current Thread cannot modify this Thread + * @see SecurityManager#checkAccess(Thread) + */ + public final void checkAccess() + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkAccess(this); + } + } + + /** + * Count the number of stack frames in this Thread. The Thread in question + * must be suspended when this occurs. + * + * @return the number of stack frames in this Thread + * @throws IllegalThreadStateException if this Thread is not suspended + * @deprecated pointless, since suspend is deprecated + */ + public native int countStackFrames(); + + /** + * 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 + */ + public static native Thread currentThread(); + + /** + * 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 native void destroy(); + + /** + * Print a stack trace of the current thread to stderr using the same + * format as Throwable's printStackTrace() method. + * + * @see Throwable#printStackTrace() + */ + public static void dumpStack() + { + new Throwable().printStackTrace(); + } + + /** + * Copy every active thread in the current Thread's ThreadGroup into the + * array. Extra threads are silently ignored. This implementation calls + * <code>getThreadGroup().enumerate(array)</code>, which may have a + * security check, <code>checkAccess(group)</code>. + * + * @param array the array to place the Threads into + * @return the number of Threads placed into the array + * @throws NullPointerException if array is null + * @throws SecurityException if you cannot access the ThreadGroup + * @see ThreadGroup#enumerate(Thread[]) + * @see #activeCount() + * @see SecurityManager#checkAccess(ThreadGroup) + */ + public static int enumerate(Thread[] array) + { + return currentThread().group.enumerate(array); + } + + /** + * Get this Thread's name. + * + * @return this Thread's name + */ + public final String getName() + { + return name; + } + + /** + * Get this Thread's priority. + * + * @return the Thread's priority + */ + public native final int getPriority(); + + /** + * Get the ThreadGroup this Thread belongs to. If the thread has died, this + * returns null. + * + * @return this Thread's ThreadGroup + */ + public final ThreadGroup getThreadGroup() + { + return isAlive() ? group : null; + } + + /** + * Checks whether the current thread holds the monitor on a given object. + * This allows you to do <code>assert Thread.holdsLock(obj)</code>. + * + * @param obj the object to test lock ownership on. + * @return true if the current thread is currently synchronized on obj + * @throws NullPointerException if obj is null + * @since 1.4 + */ + public static native boolean holdsLock(Object obj); + + /** + * Interrupt this Thread. First, there is a security check, + * <code>checkAccess</code>. Then, depending on the current state of the + * thread, various actions take place: + * + * <p>If the thread is waiting because of {@link #wait()}, + * {@link #sleep(long)}, or {@link #join()}, its <i>interrupt status</i> + * will be cleared, and an InterruptedException will be thrown. Notice that + * this case is only possible if an external thread called interrupt(). + * + * <p>If the thread is blocked in an interruptible I/O operation, in + * {@link java.nio.channels.InterruptibleChannel}, the <i>interrupt + * status</i> will be set, and ClosedByInterruptException will be thrown. + * + * <p>If the thread is blocked on a {@link java.nio.channels.Selector}, the + * <i>interrupt status</i> will be set, and the selection will return, with + * a possible non-zero value, as though by the wakeup() method. + * + * <p>Otherwise, the interrupt status will be set. + * + * @throws SecurityException if you cannot modify this Thread + */ + public native void interrupt(); + + /** + * Determine whether the current Thread has been interrupted, and clear + * the <i>interrupted status</i> in the process. + * + * @return whether the current Thread has been interrupted + * @see #isInterrupted() + */ + public static native boolean interrupted(); + + /** + * Determine whether the given Thread has been interrupted, but leave + * the <i>interrupted status</i> alone in the process. + * + * @return whether the Thread has been interrupted + * @see #interrupted() + */ + public native boolean isInterrupted(); + + /** + * Determine whether this Thread is alive. A thread which is alive has + * started and not yet died. + * + * @return whether this Thread is alive + */ + public native final boolean isAlive(); + + /** + * Tell whether this is a daemon Thread or not. + * + * @return whether this is a daemon Thread or not + * @see #setDaemon(boolean) + */ + public final boolean isDaemon() + { + return daemon; + } + + /** + * Wait forever for the Thread in question to die. + * + * @throws InterruptedException if the Thread is interrupted; it's + * <i>interrupted status</i> will be cleared + */ + public final synchronized void join() throws InterruptedException { + // Test interrupted status + if (isInterupted0()) { + throw new InterruptedExce... [truncated message content] |