aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/lang
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/java/lang')
-rw-r--r--libjava/java/lang/Class.h15
-rw-r--r--libjava/java/lang/Class.java4
-rw-r--r--libjava/java/lang/ClassLoader.java52
-rw-r--r--libjava/java/lang/ExceptionInInitializerError.java28
-rw-r--r--libjava/java/lang/Integer.java14
-rw-r--r--libjava/java/lang/Long.java14
-rw-r--r--libjava/java/lang/Runtime.java6
-rw-r--r--libjava/java/lang/String.java1
-rw-r--r--libjava/java/lang/System.java2
-rw-r--r--libjava/java/lang/ThreadGroup.java37
-rw-r--r--libjava/java/lang/Throwable.java2
-rw-r--r--libjava/java/lang/natClass.cc51
-rw-r--r--libjava/java/lang/natClassLoader.cc30
-rw-r--r--libjava/java/lang/natDouble.cc48
-rw-r--r--libjava/java/lang/natRuntime.cc7
-rw-r--r--libjava/java/lang/natString.cc107
-rw-r--r--libjava/java/lang/natSystem.cc14
-rw-r--r--libjava/java/lang/natThrowable.cc17
-rw-r--r--libjava/java/lang/reflect/Constructor.java4
-rw-r--r--libjava/java/lang/reflect/Method.java4
-rw-r--r--libjava/java/lang/reflect/natConstructor.cc4
-rw-r--r--libjava/java/lang/reflect/natField.cc15
22 files changed, 300 insertions, 176 deletions
diff --git a/libjava/java/lang/Class.h b/libjava/java/lang/Class.h
index 9736b78829b..3f09a5a445b 100644
--- a/libjava/java/lang/Class.h
+++ b/libjava/java/lang/Class.h
@@ -98,6 +98,13 @@ struct _Jv_ifaces
jshort count;
};
+// Used for vtable pointer manipulation.
+union _Jv_Self
+{
+ char *vtable_ptr;
+ jclass self;
+};
+
#define JV_PRIMITIVE_VTABLE ((_Jv_VTable *) -1)
#define JV_CLASS(Obj) ((jclass) (*(_Jv_VTable **) Obj)->clas)
@@ -105,7 +112,8 @@ struct _Jv_ifaces
class java::lang::Class : public java::lang::Object
{
public:
- static jclass forName (jstring className, java::lang::ClassLoader *loader);
+ static jclass forName (jstring className, jboolean initialize,
+ java::lang::ClassLoader *loader);
static jclass forName (jstring className);
JArray<jclass> *getClasses (void);
@@ -208,9 +216,8 @@ public:
// C++ ctors set the vtbl pointer to point at an offset inside the vtable
// object. That doesn't work for Java, so this hack adjusts it back.
- void *p = ((void **)this)[0];
- ((void **)this)[0] = (void *)((char *)p-2*sizeof (void *));
-
+ ((_Jv_Self *)this)->vtable_ptr -= 2 * sizeof (void *);
+
// We must initialize every field of the class. We do this in the
// same order they are declared in Class.h, except for fields that
// are initialized to NULL.
diff --git a/libjava/java/lang/Class.java b/libjava/java/lang/Class.java
index 0f081ebbac6..e42c4be6146 100644
--- a/libjava/java/lang/Class.java
+++ b/libjava/java/lang/Class.java
@@ -30,7 +30,9 @@ public final class Class implements Serializable
{
public static native Class forName (String className)
throws ClassNotFoundException;
- public static native Class forName (String className, ClassLoader loader)
+ /** @since 1.2 */
+ public static native Class forName (String className, boolean initialize,
+ ClassLoader loader)
throws ClassNotFoundException;
public native Class[] getClasses ();
public native ClassLoader getClassLoader ();
diff --git a/libjava/java/lang/ClassLoader.java b/libjava/java/lang/ClassLoader.java
index 402e8124864..f081cc55de1 100644
--- a/libjava/java/lang/ClassLoader.java
+++ b/libjava/java/lang/ClassLoader.java
@@ -1,6 +1,6 @@
// ClassLoader.java - Define policies for loading Java classes.
-/* Copyright (C) 1998, 1999, 2000 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
This file is part of libgcj.
@@ -25,18 +25,23 @@ import java.util.Stack;
* @author Kresten Krab Thorup
*/
-public abstract class ClassLoader {
-
+public abstract class ClassLoader
+{
static private ClassLoader system;
private ClassLoader parent;
- public ClassLoader getParent ()
+ public final ClassLoader getParent ()
{
/* FIXME: security */
return parent;
}
-
- public static native ClassLoader getSystemClassLoader ();
+
+ public static ClassLoader getSystemClassLoader ()
+ {
+ if (system == null)
+ system = gnu.gcj.runtime.VMClassLoader.instance;
+ return system;
+ }
/**
* Creates a <code>ClassLoader</code> with no parent.
@@ -55,6 +60,7 @@ public abstract class ClassLoader {
* <code>checkCreateClassLoader</code> on the current
* security manager.
* @exception java.lang.SecurityException if not allowed
+ * @since 1.2
*/
protected ClassLoader(ClassLoader parent)
{
@@ -71,12 +77,12 @@ public abstract class ClassLoader {
* @see ClassLoader#loadClass(String,boolean)
* @exception java.lang.ClassNotFoundException
*/
- public Class loadClass(String name)
- throws java.lang.ClassNotFoundException, java.lang.LinkageError
+ public Class loadClass(String name)
+ throws java.lang.ClassNotFoundException
{
return loadClass (name, false);
}
-
+
/**
* Loads the class by the given name. The default implementation
* will search for the class in the following order (similar to jdk 1.2)
@@ -96,7 +102,7 @@ public abstract class ClassLoader {
* @deprecated
*/
protected Class loadClass(String name, boolean link)
- throws java.lang.ClassNotFoundException, java.lang.LinkageError
+ throws java.lang.ClassNotFoundException
{
Class c = findLoadedClass (name);
@@ -106,7 +112,7 @@ public abstract class ClassLoader {
if (parent != null)
return parent.loadClass (name, link);
else
- c = findSystemClass (name);
+ c = system.findClass (name);
} catch (ClassNotFoundException ex) {
/* ignore, we'll try findClass */;
}
@@ -130,6 +136,7 @@ public abstract class ClassLoader {
* @param name Name of the class to find.
* @return The class found.
* @exception java.lang.ClassNotFoundException
+ * @since 1.2
*/
protected Class findClass (String name)
throws ClassNotFoundException
@@ -201,7 +208,7 @@ public abstract class ClassLoader {
throw new java.lang.LinkageError ("class "
+ name
+ " already loaded");
-
+
try {
// Since we're calling into native code here,
// we better make sure that any generated
@@ -232,7 +239,6 @@ public abstract class ClassLoader {
int len)
throws ClassFormatError;
-
/**
* Link the given class. This will bring the class to a state where
* the class initializer can be run. Linking involves the following
@@ -262,13 +268,11 @@ public abstract class ClassLoader {
* @exception java.lang.LinkageError
*/
protected final void resolveClass(Class clazz)
- throws java.lang.LinkageError
{
resolveClass0(clazz);
}
static void resolveClass0(Class clazz)
- throws java.lang.LinkageError
{
synchronized (clazz)
{
@@ -288,15 +292,13 @@ public abstract class ClassLoader {
/** Internal method. Calls _Jv_PrepareClass and
* _Jv_PrepareCompiledClass. This is only called from resolveClass. */
- private static native void linkClass0(Class clazz)
- throws java.lang.LinkageError;
+ private static native void linkClass0(Class clazz);
/** Internal method. Marks the given clazz to be in an erroneous
* state, and calls notifyAll() on the class object. This should only
* be called when the caller has the lock on the class object. */
private static native void markClassErrorState0(Class clazz);
-
/**
* Returns a class found in a system-specific way, typically
* via the <code>java.class.path</code> system property. Loads the
@@ -307,14 +309,14 @@ public abstract class ClassLoader {
* @exception java.lang.LinkageError
* @exception java.lang.ClassNotFoundException
*/
- protected Class findSystemClass(String name)
- throws java.lang.ClassNotFoundException, java.lang.LinkageError
+ protected final Class findSystemClass(String name)
+ throws java.lang.ClassNotFoundException
{
return getSystemClassLoader ().loadClass (name);
}
/*
- * Does currently nothing.
+ * Does currently nothing. FIXME.
*/
protected final void setSigners(Class claz, Object[] signers) {
/* claz.setSigners (signers); */
@@ -328,13 +330,13 @@ public abstract class ClassLoader {
* @param name class to find.
* @return the class loaded, or null.
*/
- protected native Class findLoadedClass(String name);
+ protected final native Class findLoadedClass(String name);
- public static final InputStream getSystemResourceAsStream(String name) {
+ public static InputStream getSystemResourceAsStream(String name) {
return getSystemClassLoader().getResourceAsStream (name);
}
- public static final URL getSystemResource(String name) {
+ public static URL getSystemResource(String name) {
return getSystemClassLoader().getResource (name);
}
@@ -397,7 +399,7 @@ public abstract class ClassLoader {
return null;
}
- public Enumeration getResources (String name) throws IOException
+ public final Enumeration getResources (String name) throws IOException
{
// The rules say search the parent class if non-null,
// otherwise search the built-in class loader (assumed to be
diff --git a/libjava/java/lang/ExceptionInInitializerError.java b/libjava/java/lang/ExceptionInInitializerError.java
index 0aad2fc89ea..d43a8599127 100644
--- a/libjava/java/lang/ExceptionInInitializerError.java
+++ b/libjava/java/lang/ExceptionInInitializerError.java
@@ -1,6 +1,6 @@
// ExceptionInInitializerError.java
-/* Copyright (C) 1998, 1999, 2000 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
This file is part of libgcj.
@@ -38,7 +38,7 @@ public class ExceptionInInitializerError extends LinkageError
public ExceptionInInitializerError (Throwable e)
{
- super ();
+ super (e.toString());
exception = e;
}
@@ -49,17 +49,35 @@ public class ExceptionInInitializerError extends LinkageError
public void printStackTrace ()
{
- exception.printStackTrace ();
+ if (exception != null)
+ {
+ System.err.print (this.getClass().getName() + ": ");
+ exception.printStackTrace ();
+ }
+ else
+ super.printStackTrace ();
}
public void printStackTrace (PrintStream ps)
{
- exception.printStackTrace (ps);
+ if (exception != null)
+ {
+ ps.print (this.getClass().getName() + ": ");
+ exception.printStackTrace (ps);
+ }
+ else
+ super.printStackTrace (ps);
}
public void printStackTrace (PrintWriter pw)
{
- exception.printStackTrace (pw);
+ if (exception != null)
+ {
+ pw.print (this.getClass().getName() + ": ");
+ exception.printStackTrace (pw);
+ }
+ else
+ super.printStackTrace (pw);
}
// The exception that caused this error.
diff --git a/libjava/java/lang/Integer.java b/libjava/java/lang/Integer.java
index 2cf7bb45349..88d0769a275 100644
--- a/libjava/java/lang/Integer.java
+++ b/libjava/java/lang/Integer.java
@@ -155,13 +155,15 @@ public final class Integer extends Number implements Comparable
public static Integer getInteger(String prop, Integer defobj)
{
try
- {
- return decode(System.getProperty(prop));
- }
+ {
+ String val = System.getProperty(prop);
+ if (val != null)
+ return decode(val);
+ }
catch (NumberFormatException ex)
- {
- return defobj;
- }
+ {
+ }
+ return defobj;
}
public int hashCode()
diff --git a/libjava/java/lang/Long.java b/libjava/java/lang/Long.java
index cb2cec2d904..2e812f9696d 100644
--- a/libjava/java/lang/Long.java
+++ b/libjava/java/lang/Long.java
@@ -156,13 +156,15 @@ public final class Long extends Number implements Comparable
public static Long getLong(String prop, Long defobj)
{
try
- {
- return decode(System.getProperty(prop));
- }
+ {
+ String val = System.getProperty(prop);
+ if (val != null)
+ return decode(val);
+ }
catch (NumberFormatException ex)
- {
- return defobj;
- }
+ {
+ }
+ return defobj;
}
public int hashCode()
diff --git a/libjava/java/lang/Runtime.java b/libjava/java/lang/Runtime.java
index e746c60b384..28befc26d19 100644
--- a/libjava/java/lang/Runtime.java
+++ b/libjava/java/lang/Runtime.java
@@ -1,6 +1,6 @@
// Runtime.java - Runtime class.
-/* Copyright (C) 1998, 1999, 2000 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
This file is part of libgcj.
@@ -63,6 +63,10 @@ public class Runtime
}
public native void exit (int status);
+
+ // Shutdown the runtime without a SecurityManager check. libgcj uses this
+ // exit function internally.
+ final native void _exit (int status);
public native long freeMemory ();
public native void gc ();
diff --git a/libjava/java/lang/String.java b/libjava/java/lang/String.java
index 22e11530f77..b985cf4186c 100644
--- a/libjava/java/lang/String.java
+++ b/libjava/java/lang/String.java
@@ -347,6 +347,5 @@ public final class String implements Serializable, Comparable
private native void init (byte[] chars, int hibyte, int offset, int count);
private native void init (byte[] chars, int offset, int count, String enc)
throws UnsupportedEncodingException;
- private static native void unintern (Object obj);
private static native void rehash ();
}
diff --git a/libjava/java/lang/System.java b/libjava/java/lang/System.java
index 162bc1f21eb..0f7bd7ba8b7 100644
--- a/libjava/java/lang/System.java
+++ b/libjava/java/lang/System.java
@@ -230,7 +230,7 @@ public final class System
public static void setSecurityManager (SecurityManager s)
{
if (secman != null)
- throw new SecurityException ();
+ secman.checkPermission(new RuntimePermission("setSecurityManager"));
secman = s;
}
diff --git a/libjava/java/lang/ThreadGroup.java b/libjava/java/lang/ThreadGroup.java
index cf1e7171ccb..bdf37f9ec9c 100644
--- a/libjava/java/lang/ThreadGroup.java
+++ b/libjava/java/lang/ThreadGroup.java
@@ -1,5 +1,5 @@
/* java.lang.ThreadGroup
- Copyright (C) 1998, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -204,16 +204,21 @@ public class ThreadGroup
* @return the number of active threads in this ThreadGroup and
* its descendants.
* @specnote it isn't clear what the definition of an "Active" thread is.
- * Current JDKs regard all threads as active until they are
- * finished, regardless of whether the thread has been started
- * or not. We implement this behaviour.
- * There is open JDC bug, <A HREF="http://developer.java.sun.com/developer/bugParade/bugs/4089701.html">
+ * Current JDKs regard a thread as active if has been
+ * started and not finished. We implement this behaviour.
+ * There is a JDC bug, <A HREF="http://developer.java.sun.com/developer/bugParade/bugs/4089701.html">
* 4089701</A>, regarding this issue.
*
*/
public synchronized int activeCount()
{
- int total = threads.size();
+ int total = 0;
+ for (int i = 0; i < threads.size(); ++i)
+ {
+ if (((Thread) threads.elementAt(i)).isAlive ())
+ ++total;
+ }
+
for (int i=0; i < groups.size(); i++)
{
ThreadGroup g = (ThreadGroup) groups.elementAt(i);
@@ -274,7 +279,11 @@ public class ThreadGroup
{
Enumeration e = threads.elements();
while (e.hasMoreElements() && next_index < list.length)
- list[next_index++] = (Thread) e.nextElement();
+ {
+ Thread t = (Thread) e.nextElement();
+ if (t.isAlive ())
+ list[next_index++] = t;
+ }
if (recurse && next_index != list.length)
{
e = groups.elements();
@@ -502,7 +511,19 @@ public class ThreadGroup
{
if (thread != null)
System.out.print("Exception in thread \"" + thread.getName() + "\" ");
- t.printStackTrace();
+ try
+ {
+ t.printStackTrace();
+ }
+ catch (Throwable x)
+ {
+ // This means that something is badly screwed up with the runtime,
+ // or perhaps someone is messing with the SecurityManager. In any
+ // case, try to deal with it gracefully.
+ System.out.println(t);
+ System.err.println("*** Got " + x.toString() +
+ " while trying to print stack trace");
+ }
had_uncaught_exception = true;
}
}
diff --git a/libjava/java/lang/Throwable.java b/libjava/java/lang/Throwable.java
index 4aa21399c5a..5c330fe315e 100644
--- a/libjava/java/lang/Throwable.java
+++ b/libjava/java/lang/Throwable.java
@@ -57,7 +57,7 @@ class CPlusPlusDemangler extends OutputStream
CPlusPlusDemangler (PrintWriter writer) throws IOException
{
p = writer;
- proc = Runtime.getRuntime ().exec ("c++filt");
+ proc = Runtime.getRuntime ().exec ("c++filt -s java");
procOut = proc.getOutputStream ();
procIn = proc.getInputStream ();
}
diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc
index 6678b7794cf..0786cacf517 100644
--- a/libjava/java/lang/natClass.cc
+++ b/libjava/java/lang/natClass.cc
@@ -72,7 +72,8 @@ static _Jv_Utf8Const *finit_leg_name = _Jv_makeUtf8Const ("$finit$", 7);
jclass
-java::lang::Class::forName (jstring className, java::lang::ClassLoader *loader)
+java::lang::Class::forName (jstring className, jboolean initialize,
+ java::lang::ClassLoader *loader)
{
if (! className)
JvThrow (new java::lang::NullPointerException);
@@ -90,10 +91,11 @@ java::lang::Class::forName (jstring className, java::lang::ClassLoader *loader)
? _Jv_FindClassFromSignature (name->data, loader)
: _Jv_FindClass (name, loader));
- if (klass)
+ if (klass == NULL)
+ throw new java::lang::ClassNotFoundException (className);
+
+ if (initialize)
_Jv_InitClass (klass);
- else
- JvThrow (new java::lang::ClassNotFoundException (className));
return klass;
}
@@ -102,7 +104,7 @@ jclass
java::lang::Class::forName (jstring className)
{
// FIXME: should use class loader from calling method.
- return forName (className, NULL);
+ return forName (className, true, NULL);
}
java::lang::reflect::Constructor *
@@ -290,8 +292,12 @@ java::lang::Class::getSignature (JArray<jclass> *param_types,
java::lang::StringBuffer *buf = new java::lang::StringBuffer ();
buf->append((jchar) '(');
jclass *v = elements (param_types);
- for (int i = 0; i < param_types->length; ++i)
- v[i]->getSignature(buf);
+ // A NULL param_types means "no parameters".
+ if (param_types != NULL)
+ {
+ for (int i = 0; i < param_types->length; ++i)
+ v[i]->getSignature(buf);
+ }
buf->append((jchar) ')');
if (is_constructor)
buf->append((jchar) 'V');
@@ -627,7 +633,7 @@ java::lang::Class::isAssignableFrom (jclass klass)
jboolean
java::lang::Class::isInstance (jobject obj)
{
- if (__builtin_expect (! obj || isPrimitive (), false))
+ if (! obj)
return false;
_Jv_InitClass (this);
return _Jv_IsAssignableFrom (this, JV_CLASS (obj));
@@ -903,11 +909,8 @@ _Jv_LookupInterfaceMethodIdx (jclass klass, jclass iface, int method_idx)
jboolean
_Jv_IsAssignableFrom (jclass target, jclass source)
{
- if (source == target
- || (target == &ObjectClass && !source->isPrimitive())
- || (source->ancestors != NULL
- && source->ancestors[source->depth - target->depth] == target))
- return true;
+ if (source == target)
+ return true;
// If target is array, so must source be.
if (target->isArray ())
@@ -932,15 +935,31 @@ _Jv_IsAssignableFrom (jclass target, jclass source)
if (__builtin_expect ((if_idt == NULL), false))
return false; // No class implementing TARGET has been loaded.
jshort cl_iindex = cl_idt->cls.iindex;
- if (cl_iindex <= if_idt->iface.ioffsets[0])
+ if (cl_iindex < if_idt->iface.ioffsets[0])
{
jshort offset = if_idt->iface.ioffsets[cl_iindex];
- if (offset < cl_idt->cls.itable_length
+ if (offset != -1 && offset < cl_idt->cls.itable_length
&& cl_idt->cls.itable[offset] == target)
return true;
}
+ return false;
}
+
+ // Primitive TYPE classes are only assignable to themselves.
+ if (__builtin_expect (target->isPrimitive(), false))
+ return false;
+ if (target == &ObjectClass)
+ {
+ if (source->isPrimitive())
+ return false;
+ return true;
+ }
+ else if (source->ancestors != NULL
+ && source->depth >= target->depth
+ && source->ancestors[source->depth - target->depth] == target)
+ return true;
+
return false;
}
@@ -1310,7 +1329,7 @@ _Jv_FindIIndex (jclass *ifaces, jshort *offsets, jshort num)
{
if (j >= num)
goto found;
- if (i > ifaces[j]->idt->iface.ioffsets[0])
+ if (i >= ifaces[j]->idt->iface.ioffsets[0])
continue;
int ioffset = ifaces[j]->idt->iface.ioffsets[i];
/* We can potentially share this position with another class. */
diff --git a/libjava/java/lang/natClassLoader.cc b/libjava/java/lang/natClassLoader.cc
index 979de3fc2d6..b3dfdff38f9 100644
--- a/libjava/java/lang/natClassLoader.cc
+++ b/libjava/java/lang/natClassLoader.cc
@@ -48,15 +48,6 @@ details. */
/////////// java.lang.ClassLoader native methods ////////////
-java::lang::ClassLoader *
-java::lang::ClassLoader::getSystemClassLoader (void)
-{
- JvSynchronize sync (&ClassLoaderClass);
- if (! system)
- system = gnu::gcj::runtime::VMClassLoader::getVMClassLoader ();
- return system;
-}
-
java::lang::Class *
java::lang::ClassLoader::defineClass0 (jstring name,
jbyteArray data,
@@ -79,7 +70,9 @@ java::lang::ClassLoader::defineClass0 (jstring name,
{
_Jv_Utf8Const * name2 = _Jv_makeUtf8Const (name);
- _Jv_VerifyClassName (name2);
+ if (! _Jv_VerifyClassName (name2))
+ JvThrow (new java::lang::ClassFormatError
+ (JvNewStringLatin1 ("erroneous class name")));
klass->name = name2;
}
@@ -176,11 +169,10 @@ java::lang::ClassLoader::markClassErrorState0 (java::lang::Class *klass)
klass->notifyAll ();
}
-
-/** this is the only native method in VMClassLoader, so
- we define it here. */
+// This is the findClass() implementation for the System classloader. It is
+// the only native method in VMClassLoader, so we define it here.
jclass
-gnu::gcj::runtime::VMClassLoader::findSystemClass (jstring name)
+gnu::gcj::runtime::VMClassLoader::findClass (jstring name)
{
_Jv_Utf8Const *name_u = _Jv_makeUtf8Const (name);
jclass klass = _Jv_FindClassInCache (name_u, 0);
@@ -209,6 +201,12 @@ gnu::gcj::runtime::VMClassLoader::findSystemClass (jstring name)
klass = _Jv_FindClassInCache (name_u, 0);
}
}
+
+ // Now try loading using the interpreter.
+ if (! klass)
+ {
+ klass = java::net::URLClassLoader::findClass (name);
+ }
return klass;
}
@@ -400,7 +398,8 @@ _Jv_UnregisterClass (jclass the_class)
void
_Jv_RegisterInitiatingLoader (jclass klass, java::lang::ClassLoader *loader)
{
- _Jv_LoaderInfo *info = new _Jv_LoaderInfo; // non-gc alloc!
+ // non-gc alloc!
+ _Jv_LoaderInfo *info = (_Jv_LoaderInfo *) _Jv_Malloc (sizeof(_Jv_LoaderInfo));
jint hash = HASH_UTF(klass->name);
_Jv_MonitorEnter (&ClassClass);
@@ -409,7 +408,6 @@ _Jv_RegisterInitiatingLoader (jclass klass, java::lang::ClassLoader *loader)
info->next = initiated_classes[hash];
initiated_classes[hash] = info;
_Jv_MonitorExit (&ClassClass);
-
}
// This function is called many times during startup, before main() is
diff --git a/libjava/java/lang/natDouble.cc b/libjava/java/lang/natDouble.cc
index bc60ddaec28..af2d70ad6f3 100644
--- a/libjava/java/lang/natDouble.cc
+++ b/libjava/java/lang/natDouble.cc
@@ -10,15 +10,12 @@ details. */
#include <config.h>
-#if HAVE_ALLOCA_H
-#include <alloca.h>
-#endif
-
#include <stdlib.h>
#include <gcj/cni.h>
#include <java/lang/String.h>
#include <java/lang/Double.h>
+#include <java/lang/Character.h>
#include <java/lang/NumberFormatException.h>
#include <jvm.h>
@@ -164,23 +161,28 @@ jdouble
java::lang::Double::parseDouble(jstring str)
{
int length = str->length();
- // Note that UTF can expand 3x.
-
-#ifdef HAVE_ALLOCA
- char *data = (char *) alloca (3 * length + 1);
-#else
-#error --- need an alternate implementation here ---
-#endif
-
- data[_Jv_GetStringUTFRegion (str, 0, length, data)] = 0;
-
- struct _Jv_reent reent;
- memset (&reent, 0, sizeof reent);
-
- double val = _strtod_r (&reent, data, NULL);
-
- if (reent._errno)
- _Jv_Throw (new NumberFormatException);
-
- return val;
+ while (length > 0
+ && Character::isWhitespace(str->charAt(length - 1)))
+ length--;
+ jsize start = 0;
+ while (length > 0
+ && Character::isWhitespace(str->charAt(start)))
+ start++, length--;
+
+ if (length > 0)
+ {
+ // Note that UTF can expand 3x.
+ char *data = (char *) __builtin_alloca (3 * length + 1);
+ jsize blength = _Jv_GetStringUTFRegion (str, start, length, data);
+ data[blength] = 0;
+
+ struct _Jv_reent reent;
+ memset (&reent, 0, sizeof reent);
+
+ char *endptr;
+ double val = _strtod_r (&reent, data, &endptr);
+ if (endptr == data + blength)
+ return val;
+ }
+ _Jv_Throw (new NumberFormatException);
}
diff --git a/libjava/java/lang/natRuntime.cc b/libjava/java/lang/natRuntime.cc
index 5ff7d2edacf..3f1a0b335fc 100644
--- a/libjava/java/lang/natRuntime.cc
+++ b/libjava/java/lang/natRuntime.cc
@@ -1,6 +1,6 @@
// natRuntime.cc - Implementation of native side of Runtime class.
-/* Copyright (C) 1998, 1999, 2000 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
This file is part of libgcj.
@@ -78,7 +78,12 @@ void
java::lang::Runtime::exit (jint status)
{
checkExit (status);
+ _exit (status);
+}
+void
+java::lang::Runtime::_exit (jint status)
+{
// Make status right for Unix. This is perhaps strange.
if (status < 0 || status > 255)
status = 255;
diff --git a/libjava/java/lang/natString.cc b/libjava/java/lang/natString.cc
index bb903fbde6f..255d4cf11c7 100644
--- a/libjava/java/lang/natString.cc
+++ b/libjava/java/lang/natString.cc
@@ -1,6 +1,6 @@
// natString.cc - Implementation of java.lang.String native methods.
-/* Copyright (C) 1998, 1999, 2000 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
This file is part of libgcj.
@@ -29,6 +29,7 @@ details. */
#include <gnu/gcj/convert/BytesToUnicode.h>
#include <jvm.h>
+static void unintern (jobject);
static jstring* strhash = NULL;
static int strhash_count = 0; /* Number of slots used in strhash. */
static int strhash_size = 0; /* Number of slots available in strhash.
@@ -45,6 +46,10 @@ static int strhash_size = 0; /* Number of slots available in strhash.
#define DELETED_STRING ((jstring)(~0))
#define SET_STRING_IS_INTERNED(STR) /* nothing */
+#define UNMASK_PTR(Ptr) (((unsigned long) (Ptr)) & ~0x01)
+#define MASK_PTR(Ptr) (((unsigned long) (Ptr)) | 0x01)
+#define PTR_MASKED(Ptr) (((unsigned long) (Ptr)) & 0x01)
+
/* Find a slot where the string with elements DATA, length LEN,
and hash HASH should go in the strhash table of interned strings. */
jstring*
@@ -57,11 +62,12 @@ _Jv_StringFindSlot (jchar* data, jint len, jint hash)
int index = start_index;
/* step must be non-zero, and relatively prime with strhash_size. */
- int step = 8 * hash + 7;
+ jint step = (hash ^ (hash >> 16)) | 1;
for (;;)
{
jstring* ptr = &strhash[index];
- if (*ptr == NULL)
+ jstring value = (jstring) UNMASK_PTR (*ptr);
+ if (value == NULL)
{
if (deleted_index >= 0)
return (&strhash[deleted_index]);
@@ -70,8 +76,8 @@ _Jv_StringFindSlot (jchar* data, jint len, jint hash)
}
else if (*ptr == DELETED_STRING)
deleted_index = index;
- else if ((*ptr)->length() == len
- && memcmp(JvGetStringChars(*ptr), data, 2*len) == 0)
+ else if (value->length() == len
+ && memcmp(JvGetStringChars(value), data, 2*len) == 0)
return (ptr);
index = (index + step) & (strhash_size - 1);
JvAssert (index != start_index);
@@ -115,16 +121,18 @@ java::lang::String::rehash()
if (strhash == NULL)
{
strhash_size = 1024;
- strhash = (jstring *) _Jv_AllocBytes (strhash_size * sizeof (jstring));
+ strhash = (jstring *) _Jv_AllocBytesChecked (strhash_size
+ * sizeof (jstring));
memset (strhash, 0, strhash_size * sizeof (jstring));
}
else
{
int i = strhash_size;
jstring* ptr = strhash + i;
- strhash_size *= 2;
- strhash = (jstring *) _Jv_AllocBytes (strhash_size * sizeof (jstring));
- memset (strhash, 0, strhash_size * sizeof (jstring));
+ int nsize = strhash_size * 2;
+ jstring *next = (jstring *) _Jv_AllocBytesChecked (nsize
+ * sizeof (jstring));
+ memset (next, 0, nsize * sizeof (jstring));
while (--i >= 0)
{
@@ -134,19 +142,23 @@ java::lang::String::rehash()
/* This is faster equivalent of
* *__JvGetInternSlot(*ptr) = *ptr; */
- jint hash = (*ptr)->hashCode();
- jint index = hash & (strhash_size - 1);
- jint step = 8 * hash + 7;
+ jstring val = (jstring) UNMASK_PTR (*ptr);
+ jint hash = val->hashCode();
+ jint index = hash & (nsize - 1);
+ jint step = (hash ^ (hash >> 16)) | 1;
for (;;)
{
- if (strhash[index] == NULL)
+ if (next[index] == NULL)
{
- strhash[index] = *ptr;
+ next[index] = *ptr;
break;
}
- index = (index + step) & (strhash_size - 1);
+ index = (index + step) & (nsize - 1);
}
}
+
+ strhash_size = nsize;
+ strhash = next;
}
}
@@ -154,30 +166,61 @@ jstring
java::lang::String::intern()
{
JvSynchronize sync (&StringClass);
- if (4 * strhash_count >= 3 * strhash_size)
+ if (3 * strhash_count >= 2 * strhash_size)
rehash();
jstring* ptr = _Jv_StringGetSlot(this);
if (*ptr != NULL && *ptr != DELETED_STRING)
- return *ptr;
- SET_STRING_IS_INTERNED(this);
+ {
+ // See description in unintern() to understand this.
+ *ptr = (jstring) MASK_PTR (*ptr);
+ return (jstring) UNMASK_PTR (*ptr);
+ }
+ jstring str = this->data == this ? this
+ : _Jv_NewString(JvGetStringChars(this), this->length());
+ SET_STRING_IS_INTERNED(str);
strhash_count++;
- *ptr = this;
+ *ptr = str;
// When string is GC'd, clear the slot in the hash table.
- // _Jv_RegisterFinalizer ((void *) this, unintern);
- return this;
+ _Jv_RegisterFinalizer ((void *) str, unintern);
+ return str;
}
/* Called by String fake finalizer. */
-void
-java::lang::String::unintern (jobject obj)
+static void
+unintern (jobject obj)
{
JvSynchronize sync (&StringClass);
jstring str = reinterpret_cast<jstring> (obj);
jstring* ptr = _Jv_StringGetSlot(str);
if (*ptr == NULL || *ptr == DELETED_STRING)
return;
- *ptr = DELETED_STRING;
- strhash_count--;
+
+ // We assume the lowest bit of the pointer is free for our nefarious
+ // manipulations. What we do is set it to `0' (implicitly) when
+ // interning the String. If we subsequently re-intern the same
+ // String, then we set the bit. When finalizing, if the bit is set
+ // then we clear it and re-register the finalizer. We know this is
+ // a safe approach because both the intern() and unintern() acquire
+ // the class lock; this bit can't be manipulated when the lock is
+ // not held. So if we are finalizing and the bit is clear then we
+ // know all references are gone and we can clear the entry in the
+ // hash table. The naive approach of simply clearing the pointer
+ // here fails in the case where a request to intern a new string
+ // with the same contents is made between the time the intern()d
+ // string is found to be unreachable and when the finalizer is
+ // actually run. In this case we could clear a pointer to a valid
+ // string, and future intern() calls for that particular value would
+ // spuriously fail.
+ if (PTR_MASKED (*ptr))
+ {
+ *ptr = (jstring) UNMASK_PTR (*ptr);
+ _Jv_RegisterFinalizer ((void *) obj, unintern);
+ }
+ else
+ {
+ *ptr = DELETED_STRING;
+ strhash_count--;
+ }
}
jstring
@@ -222,17 +265,21 @@ _Jv_NewStringUtf8Const (Utf8Const* str)
chrs = JvGetStringChars(jstr);
}
+ jint hash = 0;
while (data < limit)
- *chrs++ = UTF8_GET(data, limit);
+ {
+ jchar ch = UTF8_GET(data, limit);
+ hash = (31 * hash) + ch;
+ *chrs++ = ch;
+ }
chrs -= length;
JvSynchronize sync (&StringClass);
- if (4 * strhash_count >= 3 * strhash_size)
+ if (3 * strhash_count >= 2 * strhash_size)
java::lang::String::rehash();
- int hash = str->hash;
jstring* ptr = _Jv_StringFindSlot (chrs, length, hash);
if (*ptr != NULL && *ptr != DELETED_STRING)
- return *ptr;
+ return (jstring) UNMASK_PTR (*ptr);
strhash_count++;
if (jstr == NULL)
{
@@ -242,6 +289,8 @@ _Jv_NewStringUtf8Const (Utf8Const* str)
}
*ptr = jstr;
SET_STRING_IS_INTERNED(jstr);
+ // When string is GC'd, clear the slot in the hash table.
+ _Jv_RegisterFinalizer ((void *) jstr, unintern);
return jstr;
}
diff --git a/libjava/java/lang/natSystem.cc b/libjava/java/lang/natSystem.cc
index 330be72220f..57e135c7db5 100644
--- a/libjava/java/lang/natSystem.cc
+++ b/libjava/java/lang/natSystem.cc
@@ -90,7 +90,7 @@ java::lang::System::arraycopy (jobject src, jint src_offset,
jint count)
{
if (! src || ! dst)
- _Jv_Throw (new NullPointerException);
+ throw new NullPointerException;
jclass src_c = src->getClass();
jclass dst_c = dst->getClass();
@@ -100,14 +100,14 @@ java::lang::System::arraycopy (jobject src, jint src_offset,
if (! src_c->isArray() || ! dst_c->isArray()
|| src_comp->isPrimitive() != dst_comp->isPrimitive()
|| (src_comp->isPrimitive() && src_comp != dst_comp))
- _Jv_Throw (new ArrayStoreException);
+ throw new ArrayStoreException;
__JArray *src_a = (__JArray *) src;
__JArray *dst_a = (__JArray *) dst;
if (src_offset < 0 || dst_offset < 0 || count < 0
|| src_offset + count > src_a->length
|| dst_offset + count > dst_a->length)
- _Jv_Throw (new ArrayIndexOutOfBoundsException);
+ throw new ArrayIndexOutOfBoundsException;
// Do-nothing cases.
if ((src == dst && src_offset == dst_offset)
@@ -149,7 +149,7 @@ java::lang::System::arraycopy (jobject src, jint src_offset,
{
if (*src_elts
&& ! dst_comp->isAssignableFrom((*src_elts)->getClass()))
- _Jv_Throw (new ArrayStoreException);
+ throw new ArrayStoreException;
*dst_elts++ = *src_elts++;
}
}
@@ -249,9 +249,11 @@ java::lang::System::getSystemTimeZone (void)
mktime(tim = localtime(&current_time));
#ifdef STRUCT_TM_HAS_GMTOFF
- tzoffset = -(tim->tm_gmtoff); // tm_gmtoff is secs EAST of UTC.
+ // tm_gmtoff is secs EAST of UTC.
+ tzoffset = -(tim->tm_gmtoff) + tim->tm_isdst * 3600L;
#elif HAVE_TIMEZONE
- tzoffset = timezone; // timezone is secs WEST of UTC.
+ // timezone is secs WEST of UTC.
+ tzoffset = timezone;
#else
// FIXME: there must be another global if neither tm_gmtoff nor timezone
// is available, esp. if tzname is valid.
diff --git a/libjava/java/lang/natThrowable.cc b/libjava/java/lang/natThrowable.cc
index dab3ba6387a..e2821c5ddfb 100644
--- a/libjava/java/lang/natThrowable.cc
+++ b/libjava/java/lang/natThrowable.cc
@@ -39,10 +39,6 @@ details. */
#include <name-finder.h>
-#ifdef __ia64__
-extern "C" int __ia64_backtrace (void **array, int size);
-#endif
-
/* FIXME: size of the stack trace is limited to 128 elements. It's
undoubtedly sensible to limit the stack trace, but 128 is rather
arbitrary. It may be better to configure this. */
@@ -52,20 +48,16 @@ java::lang::Throwable::fillInStackTrace (void)
{
if (! trace_enabled)
return this;
-#if defined (HAVE_BACKTRACE) || defined (__ia64__)
+#if defined (HAVE_BACKTRACE)
void *p[128];
// We subtract 1 from the number of elements because we don't want
// to include the call to fillInStackTrace in the trace.
-#if defined (__ia64__)
- int n = __ia64_backtrace (p, 128) - 1;
-#else
int n = backtrace (p, 128) - 1;
-#endif
if (n > 0)
{
- // ??? Might this cause a problem if the byte array isn't aligned?
+ // We copy the array below to deal with alignment issues.
stackTrace = JvNewByteArray (n * sizeof p[0]);
memcpy (elements (stackTrace), p+1, (n * sizeof p[0]));
}
@@ -83,8 +75,9 @@ java::lang::Throwable::printRawStackTrace (java::io::PrintWriter *wr)
if (!stackTrace)
return;
- void **p = (void **)elements (stackTrace);
- int depth = stackTrace->length / sizeof p[0];
+ int depth = stackTrace->length / sizeof (void *);
+ void *p[depth];
+ memcpy (p, elements (stackTrace), sizeof p);
_Jv_name_finder finder (_Jv_ThisExecutable ());
diff --git a/libjava/java/lang/reflect/Constructor.java b/libjava/java/lang/reflect/Constructor.java
index 77c437e24fa..2d527c3ba75 100644
--- a/libjava/java/lang/reflect/Constructor.java
+++ b/libjava/java/lang/reflect/Constructor.java
@@ -1,6 +1,6 @@
// Constructor.java - Represents a constructor for a class.
-/* Copyright (C) 1998, 1999, 2000 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
This file is part of libgcj.
@@ -38,6 +38,8 @@ public final class Constructor extends AccessibleObject implements Member
public Class[] getExceptionTypes ()
{
+ if (exception_types == null)
+ getType();
return (Class[]) exception_types.clone();
}
diff --git a/libjava/java/lang/reflect/Method.java b/libjava/java/lang/reflect/Method.java
index 119a56f2141..e616670e587 100644
--- a/libjava/java/lang/reflect/Method.java
+++ b/libjava/java/lang/reflect/Method.java
@@ -1,6 +1,6 @@
// Method.java - Represent method of class or interface.
-/* Copyright (C) 1998, 1999, 2000 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
This file is part of libgcj.
@@ -39,6 +39,8 @@ public final class Method extends AccessibleObject implements Member
public Class[] getExceptionTypes ()
{
+ if (exception_types == null)
+ getType();
return (Class[]) exception_types.clone();
}
diff --git a/libjava/java/lang/reflect/natConstructor.cc b/libjava/java/lang/reflect/natConstructor.cc
index a8da794bdb8..2209ad9fa64 100644
--- a/libjava/java/lang/reflect/natConstructor.cc
+++ b/libjava/java/lang/reflect/natConstructor.cc
@@ -34,6 +34,10 @@ java::lang::reflect::Constructor::getType ()
declaringClass,
&parameter_types,
NULL);
+
+ // FIXME: for now we have no way to get exception information.
+ exception_types =
+ (JArray<jclass> *) JvNewObjectArray (0, &java::lang::Class::class$, NULL);
}
jobject
diff --git a/libjava/java/lang/reflect/natField.cc b/libjava/java/lang/reflect/natField.cc
index 57421d690b4..0aedc4ea363 100644
--- a/libjava/java/lang/reflect/natField.cc
+++ b/libjava/java/lang/reflect/natField.cc
@@ -1,6 +1,6 @@
// natField.cc - Implementation of java.lang.reflect.Field native methods.
-/* Copyright (C) 1998, 1999, 2000 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
This file is part of libgcj.
@@ -44,17 +44,8 @@ jclass
java::lang::reflect::Field::getType ()
{
jfieldID fld = _Jv_FromReflectedField (this);
- if (! fld->isResolved())
- {
- JvSynchronize sync (declaringClass);
- if (! fld->isResolved())
- {
- fld->type
- = _Jv_FindClassFromSignature(((Utf8Const*) (fld->type))->data,
- declaringClass->getClassLoader());
- fld->flags &= ~_Jv_FIELD_UNRESOLVED_FLAG;
- }
- }
+ JvSynchronize sync (declaringClass);
+ _Jv_ResolveField (fld, declaringClass->getClassLoader ());
return fld->type;
}