diff options
author | Eric Blake <ebb9@byu.net> | 2002-02-23 09:19:52 +0000 |
---|---|---|
committer | Eric Blake <ebb9@byu.net> | 2002-02-23 09:19:52 +0000 |
commit | 70f6e1ec80b4ffc5370564b2710ee194054da42f (patch) | |
tree | 9f2b7ce9aa35a53393b9876f6492f2ec90cfde62 /vm | |
parent | e746a862de38f2e1a5d53b17e633ad2400a7e6c8 (diff) | |
download | classpath-70f6e1ec80b4ffc5370564b2710ee194054da42f.tar.gz |
2002-02-23 Eric Blake <ebb9@email.byu.edu>
* java/lang/Makefile.am (EXTRA_DIST): Add AssertionError.java and
StackTraceElement.java.
* java/lang/AssertionError.java: New file.
* java/lang/ClassLoader.java: Add some synchronization and code
cleanups to use improved VMClassLoader.
Add assertion status fields and methods.
* java/lang/StackTraceElement.java: New file.
* vm/reference/java/lang/Class.java (desiredAssertionStatus): Add.
Other locations: clean up code.
* vm/reference/java/lang/Throwable.java (cause, stackTrace): Add
exception chaining, and Java code for stack traces (native code
unimplemented).
* vm/reference/java/lang/VMClassLoader.java: Add (unimplemented)
hooks to compile assertion status.
(defineClass, loadClass): Add prototypes for missing native hooks.
* vm/reference/java/lang/VMSecurityManager.java: Formatting.
* gnu/java/lang/ClassHelper.java (getAllMethodsAtDeclaration),
(getAllFieldsAtDeclaration): Delete, as they were just duplicates.
(getAllMethods, getAllFields): Optimize.
* gnu/java/lang/ArrayHelper.java: Formatting and Javadoc.
(equalsArray): Delete, it duplicates java.util.Arrays.equals.
* gnu/java/beans/BeanInfoEmbryo.java (hasMethod): Use
Arrays.equals instead of ArrayHelper.equalsArray.
Diffstat (limited to 'vm')
-rwxr-xr-x | vm/reference/java/lang/Class.java | 35 | ||||
-rw-r--r-- | vm/reference/java/lang/Throwable.java | 162 | ||||
-rw-r--r-- | vm/reference/java/lang/VMClassLoader.java | 131 | ||||
-rw-r--r-- | vm/reference/java/lang/VMSecurityManager.java | 57 |
4 files changed, 268 insertions, 117 deletions
diff --git a/vm/reference/java/lang/Class.java b/vm/reference/java/lang/Class.java index 211b17fad..837d410a7 100755 --- a/vm/reference/java/lang/Class.java +++ b/vm/reference/java/lang/Class.java @@ -38,6 +38,7 @@ exception statement from your version. */ package java.lang; import java.io.Serializable; +import java.io.InputStream; import java.lang.reflect.*; import java.security.*; import java.net.URL; @@ -117,7 +118,8 @@ public final class Class implements Serializable */ public String toString() { - //XXX Fix for primitive types. + if (isPrimitive()) + return getName(); return (isInterface() ? "interface " : "class ") + getName(); } @@ -134,15 +136,11 @@ public final class Class implements Serializable * @throws ExceptionInInitializerError if the class loads, but an exception * occurs during initialization */ - //XXX This does not need to be native. - public static native Class forName(String name) - throws ClassNotFoundException; - /* + public static Class forName(String name) throws ClassNotFoundException { return forName(name, true, VMSecurityManager.getClassContext()[1].getClassLoader()); } - */ /** * Use the specified classloader to load and link a class. If the loader @@ -211,27 +209,21 @@ public final class Class implements Serializable { try { - //XXX What about getConstructor(null).newInstance(null)? - return getConstructor(new Class[0]).newInstance(new Object[0]); - } - catch(SecurityException e) - { - //XXX Why is this trapped? - throw new IllegalAccessException("Cannot access no-arg constructor"); + return getConstructor(null).newInstance(null); } catch(IllegalArgumentException e) { - throw new UnknownError("IllegalArgumentException thrown from Constructor.newInstance(). Something is rotten in Denmark."); + throw (Error) new InternalError("Should not happen").initCause(e); } catch(InvocationTargetException e) { - //XXX Chain this. - throw new InstantiationException("Target threw an exception."); + throw (InstantiationException) + new InstantiationException(e.toString()).initCause(e); } catch(NoSuchMethodException e) { - //XXX Chain this. - throw new InstantiationException("Method not found"); + throw (InstantiationException) + new InstantiationException(e.toString()).initCause(e); } } @@ -387,8 +379,8 @@ public final class Class implements Serializable if(isArray()) try { - //XXX This should not initialize the component type. - return Class.forName(getName().substring(1)); + return Class.forName(getName().substring(1), false, + getClassLoader()); } catch(ClassNotFoundException e) { @@ -772,7 +764,7 @@ public final class Class implements Serializable * @see ClassLoader#setPackageAssertionStatus(String, boolean) * @see ClassLoader#setDefaultAssertionStatus(boolean) * @since 1.4 - * @XXX For 1.4 compliance, implement this method. + */ public boolean desiredAssertionStatus() { ClassLoader c = getClassLoader(); @@ -825,6 +817,5 @@ public final class Class implements Serializable } return c.defaultAssertionStatus; } - */ } diff --git a/vm/reference/java/lang/Throwable.java b/vm/reference/java/lang/Throwable.java index 79877f2ee..16a24e07e 100644 --- a/vm/reference/java/lang/Throwable.java +++ b/vm/reference/java/lang/Throwable.java @@ -107,6 +107,7 @@ import java.io.IOException; * * @author Brian Jones * @author John Keiser + * @author Mark Wielaard * @author Eric Blake <ebb9@email.byu.edu> * @since 1.0 * @status still missing 1.4 functionality @@ -122,9 +123,8 @@ public class Throwable extends Object implements Serializable * The detail message. * * @serial specific details about the exception, may be null - * @XXX for serialization, renaming this detailMessage would be nice */ - private String message = null; + private String detailMessage; /** * The cause of the throwable, including null for an unknown or non-chained @@ -133,9 +133,8 @@ public class Throwable extends Object implements Serializable * * @serial the cause, or null if unknown, or this if not yet set * @since 1.4 - * @XXX for 1.4 compatibility, add this field - private Throwable cause = this; */ + private Throwable cause = this; /** * The stack trace, in a serialized form. @@ -143,9 +142,9 @@ public class Throwable extends Object implements Serializable * @serial the elements of the stack trace; this is non-null, and has * no null entries * @since 1.4 - * @XXX for 1.4 compatibility, add this field - private StackTraceElement[] stackTrace; */ + // XXX Don't initialize this, once fillInStackTrace() does it. + private StackTraceElement[] stackTrace = {}; /** * Instantiate this Throwable with an empty message. The cause remains @@ -154,7 +153,7 @@ public class Throwable extends Object implements Serializable */ public Throwable() { - this(null); + this((String) null); } /** @@ -167,7 +166,7 @@ public class Throwable extends Object implements Serializable public Throwable(String message) { fillInStackTrace(); - this.message = message; + detailMessage = message; } /** @@ -178,13 +177,12 @@ public class Throwable extends Object implements Serializable * @param message the message to associate with the Throwable * @param cause the cause, may be null * @since 1.4 - * @XXX for 1.4 compatibility, add this constructor + */ public Throwable(String message, Throwable cause) { this(message); initCause(cause); } - */ /** * Instantiate this Throwable with the given cause. The message is then @@ -193,12 +191,11 @@ public class Throwable extends Object implements Serializable * * @param cause the cause, may be null * @since 1.4 - * @XXX for 1.4 compatibility, add this constructor + */ public Throwable(Throwable cause) { this(cause == null ? null : cause.toString(), cause); } - */ /** * Get the message associated with this Throwable. @@ -207,7 +204,7 @@ public class Throwable extends Object implements Serializable */ public String getMessage() { - return message; + return detailMessage; } /** @@ -232,12 +229,11 @@ public class Throwable extends Object implements Serializable * * @return the cause of this Throwable * @since 1.4 - * @XXX for 1.4 compatibility, add this method + */ public Throwable getCause() { return cause == this ? null : cause; } - */ /** * Initialize the cause of this Throwable. This may only be called once @@ -250,7 +246,7 @@ public class Throwable extends Object implements Serializable * its own cause!) * @throws IllegalStateException if the cause has already been set * @since 1.4 - * @XXX for 1.4 compatibility, add this method + */ public Throwable initCause(Throwable cause) { if (cause == this) @@ -260,7 +256,6 @@ public class Throwable extends Object implements Serializable this.cause = cause; return this; } - */ /** * Get a human-readable representation of this Throwable. With a null @@ -272,7 +267,8 @@ public class Throwable extends Object implements Serializable */ public String toString() { - return getClass().getName() + (message != null ? ": " + message : ""); + return getClass().getName() + + (detailMessage == null ? "" : ": " + detailMessage); } /** @@ -310,7 +306,7 @@ public class Throwable extends Object implements Serializable * static void b() throws MidLevelException * { * c(); - * } + * } * static void c() throws MidLevelException * { * try @@ -373,8 +369,7 @@ public class Throwable extends Object implements Serializable */ public void printStackTrace(PrintStream s) { - s.println(toString()); - printStackTrace0(s); + printStackTrace(new PrintWriter(s)); } /** @@ -386,16 +381,99 @@ public class Throwable extends Object implements Serializable */ public void printStackTrace(PrintWriter w) { - w.println(toString()); + //XXX - should be printStackTrace1(w); printStackTrace0(w); } /** * The implentation for printing a stack trace. * - * @param stream either a PrintStream or PrintWriter + * @param stream the destination stream + */ + private native void printStackTrace0(PrintWriter stream); + + /** + * Alternative printStackTrace that uses <code>getStrackTrace0()</code> + * to print the exception, stack trace and cause (recursively). Not used + * since <code>getStackTrace()</code> does not yet work. + * + * <p>Prints the exception, the detailed message and the stack trace + * associated with this Throwable to the given <code>PrintWriter</code>. + * The actual output written is implemention specific. Use the result of + * <code>getStackTrace()</code> when more precise information is needed. + * + * <p>This implementation first prints a line with the result of this + * object's <code>toString()</code> method. + * <br> + * Then for all elements given by <code>getStackTrace</code> it prints + * a line containing a tab, the string "at " and the result of calling the + * <code>toString()</code> method on the <code>StackTraceElement</code> + * object. If <code>getStackTrace()</code> returns an empty array it prints + * a line containing a tab and the string "<<No stacktrace available>>". + * <br> + * Then if <code>getCause()</code> doesn't return null it adds a line + * starting with "Caused by: " and the result of calling + * <code>toString()</code> on the cause. + * <br> + * Then for every cause (of a cause, etc) the stacktrace is printed the + * same as for the top level <code>Throwable</code> except that as soon + * as all the remaining stack frames of the cause are the same as the + * the last stack frames of the throwable that the cause is wrapped in + * then a line starting with a tab and the string "... X more" is printed, + * where X is the number of remaining stackframes. */ - private native void printStackTrace0 (Object stream); + private void printStackTrace1(PrintWriter pw) + { + // First line + pw.println(toString()); + + // The stacktrace + StackTraceElement[] stack = getStackTrace(); + for (int i = 0; i < stack.length; i++) + pw.println("\tat " + stack[i]); + + // The cause(s) + Throwable cause = getCause(); + while (cause != null) + { + // Cause first line + pw.println("Caused by: " + cause); + + // Cause stacktrace + StackTraceElement[] parentStack = stack; + stack = cause.getStackTrace(); + boolean equal = false; // Is rest of stack equal to parent frame? + for (int i = 0; i < stack.length && ! equal; i++) + { + // Check if we already printed the rest of the stack + // since it was the tail of the parent stack + int remaining = stack.length - i; + int element = i; + int parentElement = parentStack.length - remaining; + equal = parentElement >= 0 + && parentElement < parentStack.length; // be optimistic + while (equal && element < stack.length) + { + if (stack[element].equals(parentStack[parentElement])) + { + element++; + parentElement++; + } + else + equal = false; + } + // Print stacktrace element or indicate the rest is equal + if (! equal) + pw.println("\tat " + stack[i]); + else + { + pw.println("\t..." + remaining + " more"); + break; // from stack printing for loop + } + } + cause = cause.getCause(); + } + } /** * Fill in the stack trace with the current execution stack. @@ -417,12 +495,11 @@ public class Throwable extends Object implements Serializable * * @return an array of stack trace information, as available from the VM * @since 1.4 - * @XXX for 1.4 compatibility, add this method + */ public StackTraceElement[] getStackTrace() { return stackTrace; } - */ /** * Change the stack trace manually. This method is designed for remote @@ -432,7 +509,7 @@ public class Throwable extends Object implements Serializable * @param stackTrace the new trace to use * @throws NullPointerException if stackTrace is null or has null elements * @since 1.4 - * @XXX for 1.4 compatibility, add this method + */ public void setStackTrace(StackTraceElement[] stackTrace) { for (int i = stackTrace.length; --i >= 0; ) @@ -440,35 +517,4 @@ public class Throwable extends Object implements Serializable throw new NullPointerException(); this.stackTrace = stackTrace; } - */ - - /** - * Serialize the object in a manner binary compatible with the JDK 1.2. - * - * @param s the stream to write to - * @throws IOException if the write fails - */ - private void writeObject(ObjectOutputStream s) - throws IOException - { - ObjectOutputStream.PutField oFields; - oFields = s.putFields(); - oFields.put("detailMessage", message); - s.writeFields(); - } - - /** - * Deserialize the object in a manner binary compatible with the JDK 1.2. - * - * @param s the stream to read from - * @throws IOException if the read fails - * @throws ClassNotFoundException if deserialization fails - */ - private void readObject(ObjectInputStream s) - throws IOException, ClassNotFoundException - { - ObjectInputStream.GetField oFields; - oFields = s.readFields(); - message = (String)oFields.get("detailMessage", (String)null); - } } diff --git a/vm/reference/java/lang/VMClassLoader.java b/vm/reference/java/lang/VMClassLoader.java index ce55b8dd4..ded080e9d 100644 --- a/vm/reference/java/lang/VMClassLoader.java +++ b/vm/reference/java/lang/VMClassLoader.java @@ -38,6 +38,13 @@ exception statement from your version. */ package java.lang; +import java.security.ProtectionDomain; +import java.net.URL; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Map; +import java.util.HashMap; + /** * java.lang.VMClassLoader is a package-private helper for VMs to implement * on behalf of java.lang.ClassLoader. @@ -49,7 +56,10 @@ package java.lang; final class VMClassLoader { /** - * Helper to define a class using a string of bytes. + * Helper to define a class using a string of bytes. This assumes that + * the security checks have already been performed, if necessary. + * <strong>This method will be removed in a future version of GNU + * Classpath</strong>. * * @param name the name to give the class, or null if unknown * @param data the data representing the classfile, in classfile format @@ -57,13 +67,39 @@ final class VMClassLoader * @param len the length of the classfile data in the array * @return the class that was defined * @throws ClassFormatError if data is not in proper classfile format - * @XXX This should also have a ProtectionDomain argument. + * @deprecated Implement + * {@link #defineClass(ClassLoader, String, byte[], int, int, ProtectionDomain)} + * instead. */ static final native Class defineClass(ClassLoader cl, String name, byte[] data, int offset, int len) throws ClassFormatError; /** + * Helper to define a class using a string of bytes. This assumes that + * the security checks have already been performed, if necessary. + * + * <strong>For backward compatibility, this just ignores the protection + * domain; that is the wrong behavior, and you should directly implement + * this method natively if you can.</strong> + * + * @param name the name to give the class, or null if unknown + * @param data the data representing the classfile, in classfile format + * @param offset the offset into the data where the classfile starts + * @param len the length of the classfile data in the array + * @param pd the protection domain + * @return the class that was defined + * @throws ClassFormatError if data is not in proper classfile format + */ + static final Class defineClass(ClassLoader cl, String name, + byte[] data, int offset, int len, + ProtectionDomain pd) + throws ClassFormatError + { + return defineClass(cl, name, data, offset, len); + } + + /** * Helper to resolve all references to other classes from this class. * * @param c the class to resolve @@ -71,6 +107,73 @@ final class VMClassLoader static final native void resolveClass(Class c); /** + * Helper to load a class from the bootstrap class loader. + * + * XXX - Not implemented yet; this requires native help. + * + * @param name the class name to load + * @param resolve whether to resolve it + * @return the class, loaded by the bootstrap classloader + */ + static final Class loadClass(String name, boolean resolve) + throws ClassNotFoundException + { + return Class.forName(name, resolve, ClassLoader.getSystemClassLoader()); + } + + /** + * Helper to load a resource from the bootstrap class loader. + * + * XXX - Not implemented yet; this requires native help. + * + * @param name the resource to find + * @return the URL to the resource + */ + static URL getResource(String name) + { + return ClassLoader.getSystemResource(name); + } + + /** + * Helper to get a list of resources from the bootstrap class loader. + * + * XXX - Not implemented yet; this requires native help. + * + * @param name the resource to find + * @return an enumeration of resources + * @throws IOException if one occurs + */ + static Enumeration getResources(String name) throws IOException + { + return ClassLoader.getSystemResources(name); + } + + /** + * Helper to get a package from the bootstrap class loader. The default + * implementation of returning null may be adequate, or you may decide + * that this needs some native help. + * + * @param name the name to find + * @return the named package, if it exists + */ + static Package getPackage(String name) + { + return null; + } + + /** + * Helper to get all packages from the bootstrap class loader. The default + * implementation of returning an empty array may be adequate, or you may + * decide that this needs some native help. + * + * @return all named packages, if any exist + */ + static Package[] getPackages() + { + return new Package[0]; + } + + /** * Helper for java.lang.Integer, Byte, etc to get the TYPE class * at initialization time. The type code is one of the chars that * represents the primitive type as in JNI. @@ -153,10 +256,14 @@ final class VMClassLoader * classes (those with a null ClassLoader), as well as the initial value for * every ClassLoader's default assertion status. * + * XXX - Not implemented yet; this requires native help. + * * @return the system-wide default assertion status - * @XXX Implement this for 1.4 compatibility. - static final native boolean defaultAssertionStatus(); */ + static final boolean defaultAssertionStatus() + { + return true; + } /** * The system default for package assertion status. This is used for all @@ -164,18 +271,26 @@ final class VMClassLoader * package names to Boolean.TRUE or Boolean.FALSE, with the unnamed package * represented as a null key. * + * XXX - Not implemented yet; this requires native help. + * * @return a (read-only) map for the default packageAssertionStatus - * @XXX Implement this for 1.4 compatibility. - static final native Map packageAssertionStatus(); */ + static final Map packageAssertionStatus() + { + return new HashMap(); + } /** * The system default for class assertion status. This is used for all * ClassLoader's classAssertionStatus defaults. It must be a map of * class names to Boolean.TRUE or Boolean.FALSE * + * XXX - Not implemented yet; this requires native help. + * * @return a (read-only) map for the default classAssertionStatus - * @XXX Implement this for 1.4 compatibility. - static final native Map classAssertionStatus(); */ + static final Map classAssertionStatus() + { + return new HashMap(); + } } diff --git a/vm/reference/java/lang/VMSecurityManager.java b/vm/reference/java/lang/VMSecurityManager.java index bc2ef1382..a70d049d9 100644 --- a/vm/reference/java/lang/VMSecurityManager.java +++ b/vm/reference/java/lang/VMSecurityManager.java @@ -1,5 +1,5 @@ -/* VMSecurityManager.java - Copyright (C) 1998 Free Software Foundation +/* VMSecurityManager.java -- Reference implementation of VM hooks for security + Copyright (C) 1998, 2002 Free Software Foundation This file is part of GNU Classpath. @@ -37,33 +37,32 @@ exception statement from your version. */ package java.lang; -import java.net.*; -import java.util.*; -import java.io.*; - /** - ** VMSecurityManager is a helper class for SecurityManager the VM must - ** implement. - ** - ** @author John Keiser - ** @version 1.1.0, 31 May 1998 - **/ -class VMSecurityManager { - /** Get a list of all the classes currently executing - ** methods on the Java stack. getClassContext()[0] is - ** the currently executing method - ** <STRONG>Spec Note:</STRONG> does not say whether - ** the stack will include the getClassContext() call or - ** the one just before it. - ** - ** @return an array containing all the methods on classes - ** on the Java execution stack. - **/ - static native Class[] getClassContext(); + * VMSecurityManager is a helper class for SecurityManager the VM must + * implement. + * + * @author John Keiser + * @author Eric Blake <ebb9@email.byu.edu> + */ +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--the one nearest to the - ** top of the stack. - ** @return the current ClassLoader. - **/ - static native ClassLoader currentClassLoader(); + /** + * Get the current ClassLoader--the one nearest to the top of the stack. + * + * @return the current ClassLoader + */ + static native ClassLoader currentClassLoader(); } |