summaryrefslogtreecommitdiff
path: root/vm
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2002-02-23 09:19:52 +0000
committerEric Blake <ebb9@byu.net>2002-02-23 09:19:52 +0000
commit70f6e1ec80b4ffc5370564b2710ee194054da42f (patch)
tree9f2b7ce9aa35a53393b9876f6492f2ec90cfde62 /vm
parente746a862de38f2e1a5d53b17e633ad2400a7e6c8 (diff)
downloadclasspath-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-xvm/reference/java/lang/Class.java35
-rw-r--r--vm/reference/java/lang/Throwable.java162
-rw-r--r--vm/reference/java/lang/VMClassLoader.java131
-rw-r--r--vm/reference/java/lang/VMSecurityManager.java57
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();
}