aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/lang
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/java/lang')
-rw-r--r--libjava/java/lang/Class.h6
-rw-r--r--libjava/java/lang/Class.java93
-rw-r--r--libjava/java/lang/Math.java176
-rw-r--r--libjava/java/lang/Thread.java149
-rw-r--r--libjava/java/lang/natMath.cc5
-rw-r--r--libjava/java/lang/reflect/Constructor.java25
-rw-r--r--libjava/java/lang/reflect/Field.java5
-rw-r--r--libjava/java/lang/reflect/Method.java25
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;