diff options
Diffstat (limited to 'libjava/java/lang')
-rw-r--r-- | libjava/java/lang/Class.h | 6 | ||||
-rw-r--r-- | libjava/java/lang/Class.java | 93 | ||||
-rw-r--r-- | libjava/java/lang/Math.java | 176 | ||||
-rw-r--r-- | libjava/java/lang/Thread.java | 149 | ||||
-rw-r--r-- | libjava/java/lang/natMath.cc | 5 | ||||
-rw-r--r-- | libjava/java/lang/reflect/Constructor.java | 25 | ||||
-rw-r--r-- | libjava/java/lang/reflect/Field.java | 5 | ||||
-rw-r--r-- | libjava/java/lang/reflect/Method.java | 25 |
8 files changed, 481 insertions, 3 deletions
diff --git a/libjava/java/lang/Class.h b/libjava/java/lang/Class.h index 22a078d..0e5066f 100644 --- a/libjava/java/lang/Class.h +++ b/libjava/java/lang/Class.h @@ -395,6 +395,12 @@ public: jstring toString (void); jboolean desiredAssertionStatus (void); + JArray<java::lang::reflect::TypeVariable *> *getTypeParameters (void); + + java::lang::Class *getEnclosingClass (void); + java::lang::reflect::Constructor *getEnclosingConstructor (void); + java::lang::reflect::Method *getEnclosingMethod (void); + // FIXME: this probably shouldn't be public. jint size (void) { diff --git a/libjava/java/lang/Class.java b/libjava/java/lang/Class.java index db2bf72..7c3eced 100644 --- a/libjava/java/lang/Class.java +++ b/libjava/java/lang/Class.java @@ -42,8 +42,11 @@ import java.io.InputStream; import java.io.Serializable; import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.GenericDeclaration; import java.lang.reflect.Member; import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; import java.net.URL; import java.security.ProtectionDomain; import java.util.ArrayList; @@ -79,7 +82,7 @@ import java.util.HashSet; * @since 1.0 * @see ClassLoader */ -public final class Class implements Serializable +public final class Class implements Type, GenericDeclaration, Serializable { /** * Class is non-instantiable from Java code; only the VM can create @@ -928,4 +931,92 @@ public final class Class implements Serializable sm.checkPackageAccess(pkg.getName()); } } + + /** + * Returns the simple name for this class, as used in the source + * code. For normal classes, this is the content returned by + * <code>getName()</code> which follows the last ".". Anonymous + * classes have no name, and so the result of calling this method is + * "". The simple name of an array consists of the simple name of + * its component type, followed by "[]". Thus, an array with the + * component type of an anonymous class has a simple name of simply + * "[]". + * + * @return the simple name for this class. + * @since 1.5 + */ + public String getSimpleName() + { + // FIXME write real implementation + return ""; + } + + /** + * Returns the class which immediately encloses this class. If this class + * is a top-level class, this method returns <code>null</code>. + * + * @return the immediate enclosing class, or <code>null</code> if this is + * a top-level class. + * @since 1.5 + */ + /* FIXME[GENERICS]: Should return Class<?> */ + public Class getEnclosingClass() + { + // FIXME write real implementation + return null; + } + + /** + * Returns the constructor which immediately encloses this class. If + * this class is a top-level class, or a local or anonymous class + * immediately enclosed by a type definition, instance initializer + * or static initializer, then <code>null</code> is returned. + * + * @return the immediate enclosing constructor if this class is + * declared within a constructor. Otherwise, <code>null</code> + * is returned. + * @since 1.5 + */ + /* FIXME[GENERICS]: Should return Constructor<?> */ + public Constructor getEnclosingConstructor() + { + // FIXME write real implementation + return null; + } + + /** + * Returns the method which immediately encloses this class. If + * this class is a top-level class, or a local or anonymous class + * immediately enclosed by a type definition, instance initializer + * or static initializer, then <code>null</code> is returned. + * + * @return the immediate enclosing method if this class is + * declared within a method. Otherwise, <code>null</code> + * is returned. + * @since 1.5 + */ + public Method getEnclosingMethod() + { + // FIXME write real implementation + return null; + } + + /** + * Returns an array of <code>TypeVariable</code> objects that represents + * the type variables declared by this class, in declaration order. + * An array of size zero is returned if this class has no type + * variables. + * + * @return the type variables associated with this class. + * @throws GenericSignatureFormatError if the generic signature does + * not conform to the format specified in the Virtual Machine + * specification, version 3. + * @since 1.5 + */ + /* FIXME[GENERICS]: Should return TypeVariable<Class<T>> */ + public TypeVariable[] getTypeParameters() + { + // FIXME - provide real implementation. + return new TypeVariable[0]; + } } diff --git a/libjava/java/lang/Math.java b/libjava/java/lang/Math.java index 08081e2..6f68480 100644 --- a/libjava/java/lang/Math.java +++ b/libjava/java/lang/Math.java @@ -647,4 +647,180 @@ public final class Math { return (rads * 180) / PI; } + + /** + * <p> + * Returns the base 10 logarithm of the supplied value. The returned + * result is within 1 ulp of the exact result, and the results are + * semi-monotonic. + * </p> + * <p> + * Arguments of either <code>NaN</code> or less than zero return + * <code>NaN</code>. An argument of positive infinity returns positive + * infinity. Negative infinity is returned if either positive or negative + * zero is supplied. Where the argument is the result of + * <code>10<sup>n</sup</code>, then <code>n</code> is returned. + * </p> + * + * @param a the numeric argument. + * @return the base 10 logarithm of <code>a</code>. + * @since 1.5 + */ + public static native double log10(double a); + + /** + * <p> + * Returns the sign of the argument as follows: + * </p> + * <ul> + * <li>If <code>a</code> is greater than zero, the result is 1.0.</li> + * <li>If <code>a</code> is less than zero, the result is -1.0.</li> + * <li>If <code>a</code> is <code>NaN</code>, the result is <code>NaN</code>. + * <li>If <code>a</code> is positive or negative zero, the result is the + * same.</li> + * </ul> + * + * @param a the numeric argument. + * @return the sign of the argument. + * @since 1.5. + */ + public static double signum(double a) + { + if (Double.isNaN(a)) + return Double.NaN; + if (a > 0) + return 1.0; + if (a < 0) + return -1.0; + return a; + } + + /** + * <p> + * Returns the sign of the argument as follows: + * </p> + * <ul> + * <li>If <code>a</code> is greater than zero, the result is 1.0f.</li> + * <li>If <code>a</code> is less than zero, the result is -1.0f.</li> + * <li>If <code>a</code> is <code>NaN</code>, the result is <code>NaN</code>. + * <li>If <code>a</code> is positive or negative zero, the result is the + * same.</li> + * </ul> + * + * @param a the numeric argument. + * @return the sign of the argument. + * @since 1.5. + */ + public static float signum(float a) + { + if (Float.isNaN(a)) + return Float.NaN; + if (a > 0) + return 1.0f; + if (a < 0) + return -1.0f; + return a; + } + + /** + * Return the ulp for the given double argument. The ulp is the + * difference between the argument and the next larger double. Note + * that the sign of the double argument is ignored, that is, + * ulp(x) == ulp(-x). If the argument is a NaN, then NaN is returned. + * If the argument is an infinity, then +Inf is returned. If the + * argument is zero (either positive or negative), then + * {@link Double#MIN_VALUE} is returned. + * @param d the double whose ulp should be returned + * @return the difference between the argument and the next larger double + * @since 1.5 + */ + public static double ulp(double d) + { + if (Double.isNaN(d)) + return d; + if (Double.isInfinite(d)) + return Double.POSITIVE_INFINITY; + // This handles both +0.0 and -0.0. + if (d == 0.0) + return Double.MIN_VALUE; + long bits = Double.doubleToLongBits(d); + final int mantissaBits = 52; + final int exponentBits = 11; + final long mantMask = (1L << mantissaBits) - 1; + long mantissa = bits & mantMask; + final long expMask = (1L << exponentBits) - 1; + long exponent = (bits >>> mantissaBits) & expMask; + + // Denormal number, so the answer is easy. + if (exponent == 0) + { + long result = (exponent << mantissaBits) | 1L; + return Double.longBitsToDouble(result); + } + + // Conceptually we want to have '1' as the mantissa. Then we would + // shift the mantissa over to make a normal number. If this underflows + // the exponent, we will make a denormal result. + long newExponent = exponent - mantissaBits; + long newMantissa; + if (newExponent > 0) + newMantissa = 0; + else + { + newMantissa = 1L << -(newExponent - 1); + newExponent = 0; + } + return Double.longBitsToDouble((newExponent << mantissaBits) | newMantissa); + } + + /** + * Return the ulp for the given float argument. The ulp is the + * difference between the argument and the next larger float. Note + * that the sign of the float argument is ignored, that is, + * ulp(x) == ulp(-x). If the argument is a NaN, then NaN is returned. + * If the argument is an infinity, then +Inf is returned. If the + * argument is zero (either positive or negative), then + * {@link Float#MIN_VALUE} is returned. + * @param f the float whose ulp should be returned + * @return the difference between the argument and the next larger float + * @since 1.5 + */ + public static float ulp(float f) + { + if (Float.isNaN(f)) + return f; + if (Float.isInfinite(f)) + return Float.POSITIVE_INFINITY; + // This handles both +0.0 and -0.0. + if (f == 0.0) + return Float.MIN_VALUE; + int bits = Float.floatToIntBits(f); + final int mantissaBits = 23; + final int exponentBits = 8; + final int mantMask = (1 << mantissaBits) - 1; + int mantissa = bits & mantMask; + final int expMask = (1 << exponentBits) - 1; + int exponent = (bits >>> mantissaBits) & expMask; + + // Denormal number, so the answer is easy. + if (exponent == 0) + { + int result = (exponent << mantissaBits) | 1; + return Float.intBitsToFloat(result); + } + + // Conceptually we want to have '1' as the mantissa. Then we would + // shift the mantissa over to make a normal number. If this underflows + // the exponent, we will make a denormal result. + int newExponent = exponent - mantissaBits; + int newMantissa; + if (newExponent > 0) + newMantissa = 0; + else + { + newMantissa = 1 << -(newExponent - 1); + newExponent = 0; + } + return Float.intBitsToFloat((newExponent << mantissaBits) | newMantissa); + } } diff --git a/libjava/java/lang/Thread.java b/libjava/java/lang/Thread.java index 7938498..505b99b 100644 --- a/libjava/java/lang/Thread.java +++ b/libjava/java/lang/Thread.java @@ -127,11 +127,17 @@ public class Thread implements Runnable /** The context classloader for this Thread. */ private ClassLoader contextClassLoader; + /** The default exception handler. */ + private static UncaughtExceptionHandler defaultHandler; + /** Thread local storage. Package accessible for use by * InheritableThreadLocal. */ WeakIdentityHashMap locals; + /** The uncaught exception handler. */ + UncaughtExceptionHandler exceptionHandler; + // This describes the top-most interpreter frame for this thread. RawData interp_frame; @@ -935,4 +941,147 @@ public class Thread implements Runnable } return locals; } + + /** + * Assigns the given <code>UncaughtExceptionHandler</code> to this + * thread. This will then be called if the thread terminates due + * to an uncaught exception, pre-empting that of the + * <code>ThreadGroup</code>. + * + * @param h the handler to use for this thread. + * @throws SecurityException if the current thread can't modify this thread. + * @since 1.5 + */ + public void setUncaughtExceptionHandler(UncaughtExceptionHandler h) + { + SecurityManager sm = SecurityManager.current; // Be thread-safe. + if (sm != null) + sm.checkAccess(this); + exceptionHandler = h; + } + + /** + * <p> + * Returns the handler used when this thread terminates due to an + * uncaught exception. The handler used is determined by the following: + * </p> + * <ul> + * <li>If this thread has its own handler, this is returned.</li> + * <li>If not, then the handler of the thread's <code>ThreadGroup</code> + * object is returned.</li> + * <li>If both are unavailable, then <code>null</code> is returned + * (which can only happen when the thread was terminated since + * then it won't have an associated thread group anymore).</li> + * </ul> + * + * @return the appropriate <code>UncaughtExceptionHandler</code> or + * <code>null</code> if one can't be obtained. + * @since 1.5 + */ + public UncaughtExceptionHandler getUncaughtExceptionHandler() + { + return exceptionHandler != null ? exceptionHandler : group; + } + + /** + * <p> + * Sets the default uncaught exception handler used when one isn't + * provided by the thread or its associated <code>ThreadGroup</code>. + * This exception handler is used when the thread itself does not + * have an exception handler, and the thread's <code>ThreadGroup</code> + * does not override this default mechanism with its own. As the group + * calls this handler by default, this exception handler should not defer + * to that of the group, as it may lead to infinite recursion. + * </p> + * <p> + * Uncaught exception handlers are used when a thread terminates due to + * an uncaught exception. Replacing this handler allows default code to + * be put in place for all threads in order to handle this eventuality. + * </p> + * + * @param h the new default uncaught exception handler to use. + * @throws SecurityException if a security manager is present and + * disallows the runtime permission + * "setDefaultUncaughtExceptionHandler". + * @since 1.5 + */ + public static void + setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler h) + { + SecurityManager sm = SecurityManager.current; // Be thread-safe. + if (sm != null) + sm.checkPermission(new RuntimePermission("setDefaultUncaughtExceptionHandler")); + defaultHandler = h; + } + + /** + * Returns the handler used by default when a thread terminates + * unexpectedly due to an exception, or <code>null</code> if one doesn't + * exist. + * + * @return the default uncaught exception handler. + * @since 1.5 + */ + public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() + { + return defaultHandler; + } + + /** + * <p> + * This interface is used to handle uncaught exceptions + * which cause a <code>Thread</code> to terminate. When + * a thread, t, is about to terminate due to an uncaught + * exception, the virtual machine looks for a class which + * implements this interface, in order to supply it with + * the dying thread and its uncaught exception. + * </p> + * <p> + * The virtual machine makes two attempts to find an + * appropriate handler for the uncaught exception, in + * the following order: + * </p> + * <ol> + * <li> + * <code>t.getUncaughtExceptionHandler()</code> -- + * the dying thread is queried first for a handler + * specific to that thread. + * </li> + * <li> + * <code>t.getThreadGroup()</code> -- + * the thread group of the dying thread is used to + * handle the exception. If the thread group has + * no special requirements for handling the exception, + * it may simply forward it on to + * <code>Thread.getDefaultUncaughtExceptionHandler()</code>, + * the default handler, which is used as a last resort. + * </li> + * </ol> + * <p> + * The first handler found is the one used to handle + * the uncaught exception. + * </p> + * + * @author Tom Tromey <tromey@redhat.com> + * @author Andrew John Hughes <gnu_andrew@member.fsf.org> + * @since 1.5 + * @see Thread#getUncaughtExceptionHandler() + * @see Thread#setUncaughtExceptionHander(java.lang.Thread.UncaughtExceptionHandler) + * @see Thread#getDefaultUncaughtExceptionHandler() + * @see + * Thread#setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler) + */ + public interface UncaughtExceptionHandler + { + /** + * Invoked by the virtual machine with the dying thread + * and the uncaught exception. Any exceptions thrown + * by this method are simply ignored by the virtual + * machine. + * + * @param thr the dying thread. + * @param exc the uncaught exception. + */ + void uncaughtException(Thread thr, Throwable exc); + } } diff --git a/libjava/java/lang/natMath.cc b/libjava/java/lang/natMath.cc index 1903e27..bc6cf7e 100644 --- a/libjava/java/lang/natMath.cc +++ b/libjava/java/lang/natMath.cc @@ -102,6 +102,11 @@ jdouble java::lang::Math::ceil(jdouble x) return (jdouble)::ceil((double)x); } +jdouble java::lang::Math::log10(jdouble x) +{ + return (jdouble)::log10((double)x); +} + static inline int floatToIntBits (jfloat value) { diff --git a/libjava/java/lang/reflect/Constructor.java b/libjava/java/lang/reflect/Constructor.java index 980ca2a4..b789fb1 100644 --- a/libjava/java/lang/reflect/Constructor.java +++ b/libjava/java/lang/reflect/Constructor.java @@ -44,7 +44,8 @@ package java.lang.reflect; * @since 1.1 * @status updated to 1.4 */ -public final class Constructor extends AccessibleObject implements Member +public final class Constructor extends AccessibleObject + implements Member, GenericDeclaration { /** * This class is uninstantiable except from native code. @@ -203,6 +204,28 @@ public final class Constructor extends AccessibleObject implements Member throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException; + // FIXME - Write a real implementation + public boolean isSynthetic() { return false; } + + /** + * Returns an array of <code>TypeVariable</code> objects that represents + * the type variables declared by this constructor, in declaration order. + * An array of size zero is returned if this class has no type + * variables. + * + * @return the type variables associated with this class. + * @throws GenericSignatureFormatError if the generic signature does + * not conform to the format specified in the Virtual Machine + * specification, version 3. + * @since 1.5 + */ + /* FIXME[GENERICS]: Should be TypeVariable<Method>[] */ + public TypeVariable[] getTypeParameters() + { + // FIXME - write a real implementation + return new TypeVariable[0]; + } + // Update cached values from method descriptor in class. private native void getType (); diff --git a/libjava/java/lang/reflect/Field.java b/libjava/java/lang/reflect/Field.java index cb852cf..10884c1 100644 --- a/libjava/java/lang/reflect/Field.java +++ b/libjava/java/lang/reflect/Field.java @@ -262,4 +262,9 @@ public final class Field extends AccessibleObject implements Member sbuf.append(getName()); return sbuf.toString(); } + + // FIXME - Write a real implementations + public boolean isSynthetic() { return false; } + public boolean isEnumConstant() { return false; } + } diff --git a/libjava/java/lang/reflect/Method.java b/libjava/java/lang/reflect/Method.java index f93a727..a5047f5 100644 --- a/libjava/java/lang/reflect/Method.java +++ b/libjava/java/lang/reflect/Method.java @@ -46,7 +46,8 @@ import gnu.gcj.RawData; * @since 1.1 * @status updated to 1.4 */ -public final class Method extends AccessibleObject implements Member +public final class Method extends AccessibleObject + implements Member, GenericDeclaration { /** * This class is uninstantiable. @@ -262,6 +263,28 @@ public final class Method extends AccessibleObject implements Member } } + // FIXME - Write a real implementation + public boolean isSynthetic() { return false; } + + /** + * Returns an array of <code>TypeVariable</code> objects that represents + * the type variables declared by this constructor, in declaration order. + * An array of size zero is returned if this class has no type + * variables. + * + * @return the type variables associated with this class. + * @throws GenericSignatureFormatError if the generic signature does + * not conform to the format specified in the Virtual Machine + * specification, version 3. + * @since 1.5 + */ + /* FIXME[GENERICS]: Should be TypeVariable<Method>[] */ + public TypeVariable[] getTypeParameters() + { + // FIXME - write a real implementation + return new TypeVariable[0]; + } + // Declaring class. private Class declaringClass; |