aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/lang
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/java/lang')
-rw-r--r--libjava/java/lang/Class.h10
-rw-r--r--libjava/java/lang/ClassLoader.java18
-rw-r--r--libjava/java/lang/StringBuffer.java39
-rw-r--r--libjava/java/lang/System.java45
-rw-r--r--libjava/java/lang/Win32Process.java52
-rw-r--r--libjava/java/lang/natClass.cc41
-rw-r--r--libjava/java/lang/natClassLoader.cc75
-rw-r--r--libjava/java/lang/natObject.cc5
-rw-r--r--libjava/java/lang/natRuntime.cc50
-rw-r--r--libjava/java/lang/natSystem.cc5
-rw-r--r--libjava/java/lang/natWin32Process.cc295
-rw-r--r--libjava/java/lang/reflect/Modifier.java13
-rw-r--r--libjava/java/lang/reflect/natMethod.cc47
13 files changed, 537 insertions, 158 deletions
diff --git a/libjava/java/lang/Class.h b/libjava/java/lang/Class.h
index 4ccf3886431..0012fc24365 100644
--- a/libjava/java/lang/Class.h
+++ b/libjava/java/lang/Class.h
@@ -1,6 +1,6 @@
// Class.h - Header file for java.lang.Class. -*- c++ -*-
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation
This file is part of libgcj.
@@ -182,9 +182,9 @@ public:
JArray<java::lang::reflect::Method *> *getMethods (void);
inline jint getModifiers (void)
- {
- return accflags;
- }
+ {
+ return accflags & java::lang::reflect::Modifier::ALL_FLAGS;
+ }
jstring getName (void);
@@ -348,6 +348,7 @@ private:
_Jv_Utf8Const *method_signature);
friend void _Jv_PrepareClass (jclass);
+ friend void _Jv_PrepareMissingMethods (jclass base, jclass iface_class);
friend class _Jv_ClassReader;
friend class _Jv_InterpClass;
@@ -360,6 +361,7 @@ private:
friend class _Jv_BytecodeVerifier;
friend class gnu::gcj::runtime::StackTrace;
+ friend class java::io::VMObjectStreamClass;
// Chain for class pool.
jclass next;
diff --git a/libjava/java/lang/ClassLoader.java b/libjava/java/lang/ClassLoader.java
index 033b2cc4a6e..5d564dce747 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, 2001, 2002 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation
This file is part of libgcj.
@@ -468,17 +468,18 @@ public abstract class ClassLoader
{
throw x; // rethrow
}
- catch (java.lang.VirtualMachineError x)
+ catch (VirtualMachineError x)
{
throw x; // rethrow
}
- catch (java.lang.Throwable x)
+ catch (Throwable x)
{
// This should never happen, or we are beyond spec.
- throw new InternalError ("Unexpected exception "
- + "while defining class "
- + name + ": "
- + x.toString ());
+ InternalError r = new InternalError ("Unexpected exception "
+ + "while defining class "
+ + name);
+ r.initCause(x);
+ throw r;
}
}
@@ -732,8 +733,7 @@ public abstract class ClassLoader
/**
* If a class named <code>name</code> was previously loaded using
* this <code>ClassLoader</code>, then it is returned. Otherwise
- * it returns <code>null</code>. (Unlike the JDK this is native,
- * since we implement the class table internally.)
+ * it returns <code>null</code>.
* @param name class to find.
* @return the class loaded, or null.
*/
diff --git a/libjava/java/lang/StringBuffer.java b/libjava/java/lang/StringBuffer.java
index bfaaaf92f23..922d6bb6d24 100644
--- a/libjava/java/lang/StringBuffer.java
+++ b/libjava/java/lang/StringBuffer.java
@@ -308,26 +308,27 @@ public final class StringBuffer implements Serializable, CharSequence
}
}
- /** Get the specified array of characters.
- * The characters will be copied into the array you pass in.
- * @param srcOffset the index to start copying from in the
- * <code>StringBuffer</code>.
- * @param srcEnd the number of characters to copy.
- * @param dst the array to copy into.
- * @param dstOffset the index to start copying into <code>dst</code>.
- * @exception NullPointerException if dst is null.
- * @exception IndexOutOfBoundsException if any source or target
- * indices are out of range.
- * @see java.lang.System#arraycopy(java.lang.Object,int,java.lang.Object,int,int)
- */
- public synchronized void getChars (int srcOffset, int srcEnd,
- char[] dst, int dstOffset)
- {
- if (srcOffset < 0 || srcOffset > srcEnd)
- throw new StringIndexOutOfBoundsException (srcOffset);
+ /**
+ * Get the specified array of characters. <code>srcOffset - srcEnd</code>
+ * characters will be copied into the array you pass in.
+ *
+ * @param srcOffset the index to start copying from (inclusive)
+ * @param srcEnd the index to stop copying from (exclusive)
+ * @param dst the array to copy into
+ * @param dstOffset the index to start copying into
+ * @throws NullPointerException if dst is null
+ * @throws IndexOutOfBoundsException if any source or target indices are
+ * out of range (while unspecified, source problems cause a
+ * StringIndexOutOfBoundsException, and dest problems cause an
+ * ArrayIndexOutOfBoundsException)
+ * @see System#arraycopy(Object, int, Object, int, int)
+ */
+ public synchronized void getChars(int srcOffset, int srcEnd,
+ char[] dst, int dstOffset)
+ {
int todo = srcEnd - srcOffset;
- if (srcEnd > count || dstOffset + todo > count)
- throw new StringIndexOutOfBoundsException (srcEnd);
+ if (srcOffset < 0 || srcEnd > count || todo < 0)
+ throw new StringIndexOutOfBoundsException();
System.arraycopy(value, srcOffset, dst, dstOffset, todo);
}
diff --git a/libjava/java/lang/System.java b/libjava/java/lang/System.java
index edc818fb181..2e7c031b16c 100644
--- a/libjava/java/lang/System.java
+++ b/libjava/java/lang/System.java
@@ -1,5 +1,5 @@
/* System.java -- useful methods to interface with the system
- Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -73,22 +73,41 @@ public final class System
loadLibrary("javalang");
Properties defaultProperties = Runtime.defaultProperties;
- defaultProperties.put("gnu.cpu.endian",
- isWordsBigEndian() ? "big" : "little");
+ // Set base URL if not already set.
+ if (defaultProperties.get("gnu.classpath.home.url") == null)
+ defaultProperties.put("gnu.classpath.home.url",
+ "file://"
+ + defaultProperties.get("gnu.classpath.home")
+ + "/lib");
+
+ // Set short name if not already set.
+ if (defaultProperties.get("gnu.classpath.vm.shortname") == null)
+ {
+ String value = defaultProperties.getProperty("java.vm.name");
+ int index = value.lastIndexOf(' ');
+ if (index != -1)
+ value = value.substring(index + 1);
+ defaultProperties.put("gnu.classpath.vm.shortname", value);
+ }
+
+ defaultProperties.put("gnu.cpu.endian",
+ isWordsBigEndian() ? "big" : "little");
// XXX FIXME - Temp hack for old systems that set the wrong property
if (defaultProperties.get("java.io.tmpdir") == null)
defaultProperties.put("java.io.tmpdir",
defaultProperties.get("java.tmpdir"));
}
-
+
/**
* Stores the current system properties. This can be modified by
* {@link #setProperties(Properties)}, but will never be null, because
* setProperties(null) sucks in the default properties.
*/
+ // Note that we use clone here and not new. Some programs assume
+ // that the system properties do not have a parent.
private static Properties properties
- = new Properties(Runtime.defaultProperties);
+ = (Properties) Runtime.defaultProperties.clone();
/**
* The standard InputStream. This is assigned at startup and starts its
@@ -101,7 +120,7 @@ public final class System
* however.
*/
public static final InputStream in
- = new BufferedInputStream (new FileInputStream(FileDescriptor.in));
+ = new BufferedInputStream(new FileInputStream(FileDescriptor.in));
/**
* The standard output PrintStream. This is assigned at startup and
* starts its life perfectly valid. Although it is marked final, you can
@@ -113,7 +132,7 @@ public final class System
* you, however.
*/
public static final PrintStream out
- = new PrintStream(new BufferedOutputStream (new FileOutputStream(FileDescriptor.out)), true);
+ = new PrintStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.out)), true);
/**
* The standard output PrintStream. This is assigned at startup and
* starts its life perfectly valid. Although it is marked final, you can
@@ -125,7 +144,7 @@ public final class System
* you, however.
*/
public static final PrintStream err
- = new PrintStream(new BufferedOutputStream (new FileOutputStream(FileDescriptor.err)), true);
+ = new PrintStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.err)), true);
/**
* This class is uninstantiable.
@@ -312,6 +331,10 @@ public final class System
* In addition, gnu defines several other properties, where ? stands for
* each character in '0' through '9':
* <dl>
+ * <dl> gnu.classpath.vm.shortname <dd> Succinct version of the VM name;
+ * used for finding property files in file system
+ * <dl> gnu.classpath.home.url <dd> Base URL; used for finding
+ * property files in file system
* <dt> gnu.cpu.endian <dd>big or little
* <dt> gnu.java.io.encoding_scheme_alias.ISO-8859-? <dd>8859_?
* <dt> gnu.java.io.encoding_scheme_alias.iso-8859-? <dd>8859_?
@@ -348,7 +371,11 @@ public final class System
if (sm != null)
sm.checkPropertiesAccess();
if (properties == null)
- properties = new Properties(Runtime.defaultProperties);
+ {
+ // Note that we use clone here and not new. Some programs
+ // assume that the system properties do not have a parent.
+ properties = (Properties) Runtime.defaultProperties.clone();
+ }
System.properties = properties;
}
diff --git a/libjava/java/lang/Win32Process.java b/libjava/java/lang/Win32Process.java
index 72911d2961b..b1c7e027379 100644
--- a/libjava/java/lang/Win32Process.java
+++ b/libjava/java/lang/Win32Process.java
@@ -1,6 +1,6 @@
// Win32Process.java - Subclass of Process for Win32 systems.
-/* Copyright (C) 2002 Free Software Foundation
+/* Copyright (C) 2002, 2003 Free Software Foundation
This file is part of libgcj.
@@ -22,51 +22,63 @@ import java.io.IOException;
// This is entirely internal to our implementation.
-// NOTE: when this is implemented, we'll need to add
-// HANDLE_FLAG_INHERIT in FileDescriptor and other places, to make
-// sure that file descriptors aren't inherited by the child process.
-// See _Jv_platform_close_on_exec.
-
// This file is copied to `ConcreteProcess.java' before compilation.
// Hence the class name apparently does not match the file name.
final class ConcreteProcess extends Process
{
- public void destroy ()
- {
- throw new Error("not implemented");
- }
-
+ public native void destroy ();
+
+ public native boolean hasExited ();
+
public int exitValue ()
{
- throw new Error("not implemented");
+ if (! hasExited ())
+ throw new IllegalThreadStateException ("Process has not exited");
+
+ return exitCode;
}
public InputStream getErrorStream ()
{
- throw new Error("not implemented");
+ return errorStream;
}
public InputStream getInputStream ()
{
- throw new Error("not implemented");
+ return inputStream;
}
public OutputStream getOutputStream ()
{
- throw new Error("not implemented");
+ return outputStream;
}
- public int waitFor () throws InterruptedException
- {
- throw new Error("not implemented");
- }
+ public native int waitFor () throws InterruptedException;
+
+ public native void startProcess (String[] progarray,
+ String[] envp,
+ File dir)
+ throws IOException;
+
+ public native void cleanup ();
public ConcreteProcess (String[] progarray,
String[] envp,
File dir)
throws IOException
{
- throw new IOException("not implemented");
+ startProcess (progarray, envp, dir);
}
+ // The standard streams (stdin, stdout and stderr, respectively)
+ // of the child as seen by the parent process.
+ private OutputStream outputStream;
+ private InputStream inputStream;
+ private InputStream errorStream;
+
+ // Handle to the child process - cast to HANDLE before use.
+ private int procHandle;
+
+ // Exit code of the child if it has exited.
+ private int exitCode;
}
diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc
index bafac789b0d..768ced611ac 100644
--- a/libjava/java/lang/natClass.cc
+++ b/libjava/java/lang/natClass.cc
@@ -343,7 +343,9 @@ java::lang::Class::_getDeclaredMethod (jstring name,
while (--i >= 0)
{
if (_Jv_equalUtf8Consts (methods[i].name, utf_name)
- && _Jv_equaln (methods[i].signature, partial_sig, p_len))
+ && _Jv_equaln (methods[i].signature, partial_sig, p_len)
+ && (methods[i].accflags
+ & java::lang::reflect::Modifier::INVISIBLE) == 0)
{
// Found it.
using namespace java::lang::reflect;
@@ -368,7 +370,9 @@ java::lang::Class::getDeclaredMethods (void)
if (method->name == NULL
|| _Jv_equalUtf8Consts (method->name, clinit_name)
|| _Jv_equalUtf8Consts (method->name, init_name)
- || _Jv_equalUtf8Consts (method->name, finit_name))
+ || _Jv_equalUtf8Consts (method->name, finit_name)
+ || (methods[i].accflags
+ & java::lang::reflect::Modifier::INVISIBLE) != 0)
continue;
numMethods++;
}
@@ -382,7 +386,9 @@ java::lang::Class::getDeclaredMethods (void)
if (method->name == NULL
|| _Jv_equalUtf8Consts (method->name, clinit_name)
|| _Jv_equalUtf8Consts (method->name, init_name)
- || _Jv_equalUtf8Consts (method->name, finit_name))
+ || _Jv_equalUtf8Consts (method->name, finit_name)
+ || (methods[i].accflags
+ & java::lang::reflect::Modifier::INVISIBLE) != 0)
continue;
java::lang::reflect::Method* rmethod
= new java::lang::reflect::Method ();
@@ -514,7 +520,9 @@ java::lang::Class::_getMethod (jstring name, JArray<jclass> *param_types)
{
// FIXME: access checks.
if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
- && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len))
+ && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len)
+ && (klass->methods[i].accflags
+ & java::lang::reflect::Modifier::INVISIBLE) == 0)
{
// Found it.
using namespace java::lang::reflect;
@@ -565,7 +573,9 @@ java::lang::Class::_getMethods (JArray<java::lang::reflect::Method *> *result,
if (method->name == NULL
|| _Jv_equalUtf8Consts (method->name, clinit_name)
|| _Jv_equalUtf8Consts (method->name, init_name)
- || _Jv_equalUtf8Consts (method->name, finit_name))
+ || _Jv_equalUtf8Consts (method->name, finit_name)
+ || (method->accflags
+ & java::lang::reflect::Modifier::INVISIBLE) != 0)
continue;
// Only want public methods.
if (! java::lang::reflect::Modifier::isPublic (method->accflags))
@@ -1564,6 +1574,13 @@ isVirtualMethod (_Jv_Method *meth)
&& meth->name->data[0] != '<');
}
+// This is put in empty vtable slots.
+static void
+_Jv_abstractMethodError (void)
+{
+ throw new java::lang::AbstractMethodError();
+}
+
// Prepare virtual method declarations in KLASS, and any superclasses as
// required, by determining their vtable index, setting method->index, and
// finally setting the class's vtable_method_count. Must be called with the
@@ -1594,13 +1611,16 @@ _Jv_LayoutVTableMethods (jclass klass)
continue;
if (superclass != NULL)
- super_meth = _Jv_LookupDeclaredMethod (superclass, meth->name,
- meth->signature);
+ {
+ super_meth = _Jv_LookupDeclaredMethod (superclass, meth->name,
+ meth->signature);
+ }
if (super_meth)
meth->index = super_meth->index;
- else if (! (meth->accflags & java::lang::reflect::Modifier::FINAL))
- meth->index = index++;
+ else if (! (meth->accflags & java::lang::reflect::Modifier::FINAL)
+ && ! (klass->accflags & java::lang::reflect::Modifier::FINAL))
+ meth->index = index++;
}
klass->vtable_method_count = index;
@@ -1626,8 +1646,7 @@ _Jv_SetVTableEntries (jclass klass, _Jv_VTable *vtable, jboolean *flags)
continue;
if ((meth->accflags & Modifier::ABSTRACT))
{
- // FIXME: we should set abstract slots to a function that
- // throws AbstractMethodError. How can we do that on IA-64?
+ vtable->set_method(meth->index, (void *) &_Jv_abstractMethodError);
flags[meth->index] = false;
}
else
diff --git a/libjava/java/lang/natClassLoader.cc b/libjava/java/lang/natClassLoader.cc
index aeee08a6265..96a81812219 100644
--- a/libjava/java/lang/natClassLoader.cc
+++ b/libjava/java/lang/natClassLoader.cc
@@ -56,17 +56,18 @@ java::lang::ClassLoader::defineClass0 (jstring name,
sizeof (_Jv_InterpClass));
_Jv_InitNewClassFields (klass);
- // synchronize on the class, so that it is not
- // attempted initialized until we're done loading.
- _Jv_MonitorEnter (klass);
+ // Synchronize on the class, so that it is not attempted initialized
+ // until we're done loading.
+ JvSynchronize sync (klass);
- // record which is the defining loader
- klass->loader = this;
+ // Record the defining loader. For the system class loader, we
+ // record NULL.
+ if (this != java::lang::ClassLoader::getSystemClassLoader())
+ klass->loader = this;
- // register that we are the initiating loader...
if (name != 0)
{
- _Jv_Utf8Const * name2 = _Jv_makeUtf8Const (name);
+ _Jv_Utf8Const *name2 = _Jv_makeUtf8Const (name);
if (! _Jv_VerifyClassName (name2))
throw new java::lang::ClassFormatError
@@ -86,16 +87,8 @@ java::lang::ClassLoader::defineClass0 (jstring name,
_Jv_UnregisterClass (klass);
- _Jv_MonitorExit (klass);
-
- // FIXME: Here we may want to test that EX does
- // indeed represent a valid exception. That is,
- // anything but ClassNotFoundException,
- // or some kind of Error.
-
- // FIXME: Rewrite this as a cleanup instead of
- // as a catch handler.
-
+ // If EX is not a ClassNotFoundException, that's ok, because we
+ // account for the possibility in defineClass().
throw ex;
}
@@ -104,10 +97,6 @@ java::lang::ClassLoader::defineClass0 (jstring name,
// if everything proceeded sucessfully, we're loaded.
JvAssert (klass->state == JV_STATE_LOADED);
- // if an exception is generated, this is initially missed.
- // however, we come back here in handleException0 below...
- _Jv_MonitorExit (klass);
-
return klass;
#else // INTERPRETER
@@ -293,10 +282,11 @@ _Jv_PrepareCompiledClass (jclass klass)
// Hash function for Utf8Consts.
#define HASH_UTF(Utf) (((Utf)->hash) % HASH_LEN)
-struct _Jv_LoaderInfo {
- _Jv_LoaderInfo *next;
- java::lang::Class *klass;
- java::lang::ClassLoader *loader;
+struct _Jv_LoaderInfo
+{
+ _Jv_LoaderInfo *next;
+ java::lang::Class *klass;
+ java::lang::ClassLoader *loader;
};
static _Jv_LoaderInfo *initiated_classes[HASH_LEN];
@@ -309,9 +299,12 @@ static jclass loaded_classes[HASH_LEN];
jclass
_Jv_FindClassInCache (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
{
- _Jv_MonitorEnter (&java::lang::Class::class$);
+ JvSynchronize sync (&java::lang::Class::class$);
jint hash = HASH_UTF (name);
+ if (loader && loader == java::lang::ClassLoader::getSystemClassLoader())
+ loader = NULL;
+
// first, if LOADER is a defining loader, then it is also initiating
jclass klass;
for (klass = loaded_classes[hash]; klass; klass = klass->next)
@@ -337,15 +330,13 @@ _Jv_FindClassInCache (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
}
}
- _Jv_MonitorExit (&java::lang::Class::class$);
-
return klass;
}
void
_Jv_UnregisterClass (jclass the_class)
{
- _Jv_MonitorEnter (&java::lang::Class::class$);
+ JvSynchronize sync (&java::lang::Class::class$);
jint hash = HASH_UTF(the_class->name);
jclass *klass = &(loaded_classes[hash]);
@@ -363,29 +354,32 @@ _Jv_UnregisterClass (jclass the_class)
{
while (*info && (*info)->klass == the_class)
{
+ _Jv_LoaderInfo *old = *info;
*info = (*info)->next;
+ _Jv_Free (old);
}
if (*info == NULL)
break;
}
-
- _Jv_MonitorExit (&java::lang::Class::class$);
}
void
_Jv_RegisterInitiatingLoader (jclass klass, java::lang::ClassLoader *loader)
{
- // non-gc alloc!
- _Jv_LoaderInfo *info = (_Jv_LoaderInfo *) _Jv_Malloc (sizeof(_Jv_LoaderInfo));
+ if (loader && loader == java::lang::ClassLoader::getSystemClassLoader())
+ loader = NULL;
+
+ // This information can't be visible to the GC.
+ _Jv_LoaderInfo *info
+ = (_Jv_LoaderInfo *) _Jv_Malloc (sizeof(_Jv_LoaderInfo));
jint hash = HASH_UTF(klass->name);
- _Jv_MonitorEnter (&java::lang::Class::class$);
+ JvSynchronize sync (&java::lang::Class::class$);
info->loader = loader;
info->klass = klass;
info->next = initiated_classes[hash];
initiated_classes[hash] = info;
- _Jv_MonitorExit (&java::lang::Class::class$);
}
// This function is called many times during startup, before main() is
@@ -471,6 +465,9 @@ _Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
{
jstring sname = _Jv_NewStringUTF (name->data);
+ java::lang::ClassLoader *sys
+ = java::lang::ClassLoader::getSystemClassLoader ();
+
if (loader)
{
// Load using a user-defined loader, jvmspec 5.3.2
@@ -479,14 +476,14 @@ _Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
// If "loader" delegated the loadClass operation to another
// loader, explicitly register that it is also an initiating
// loader of the given class.
- if (klass && (klass->getClassLoader () != loader))
+ java::lang::ClassLoader *delegate = (loader == sys
+ ? NULL
+ : loader);
+ if (klass && klass->getClassLoaderInternal () != delegate)
_Jv_RegisterInitiatingLoader (klass, loader);
}
else
{
- java::lang::ClassLoader *sys
- = java::lang::ClassLoader::getSystemClassLoader ();
-
// Load using the bootstrap loader jvmspec 5.3.1.
klass = sys->loadClass (sname, false);
diff --git a/libjava/java/lang/natObject.cc b/libjava/java/lang/natObject.cc
index 4c2fd6cab03..33f3e8de27f 100644
--- a/libjava/java/lang/natObject.cc
+++ b/libjava/java/lang/natObject.cc
@@ -1,6 +1,6 @@
// natObject.cc - Implementation of the Object class.
-/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation
This file is part of libgcj.
@@ -9,6 +9,7 @@ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#include <config.h>
+#include <platform.h>
#include <string.h>
@@ -532,7 +533,7 @@ spin(unsigned n)
unsigned duration = MIN_SLEEP_USECS << (n - yield_limit);
if (n >= 15 + yield_limit || duration > MAX_SLEEP_USECS)
duration = MAX_SLEEP_USECS;
- java::lang::Thread::sleep(0, duration);
+ _Jv_platform_usleep(duration);
}
}
diff --git a/libjava/java/lang/natRuntime.cc b/libjava/java/lang/natRuntime.cc
index f5177b0aa35..e46c37e049c 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, 2001, 2002 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation
This file is part of libgcj.
@@ -9,6 +9,7 @@ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#include <config.h>
+#include <platform.h>
#include <stdlib.h>
@@ -29,11 +30,10 @@ details. */
#include <java/lang/ConcreteProcess.h>
#include <java/lang/ClassLoader.h>
#include <gnu/gcj/runtime/StackTrace.h>
+#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <jni.h>
-#include "platform.h"
-
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
@@ -128,6 +128,10 @@ _Jv_SetDLLSearchPath (const char *)
+extern int _Jv_argc;
+extern const char **_Jv_argv;
+ // our process' command line arguments
+
void
java::lang::Runtime::exitInternal (jint status)
{
@@ -181,19 +185,26 @@ java::lang::Runtime::_load (jstring path, jboolean do_search)
ClassLoader *sys = ClassLoader::getSystemClassLoader();
ClassLoader *look = NULL;
gnu::gcj::runtime::StackTrace *t = new gnu::gcj::runtime::StackTrace(10);
- for (int i = 0; i < 10; ++i)
- {
- jclass klass = t->classAt(i);
- if (klass != NULL)
+ try
+ {
+ for (int i = 0; i < 10; ++i)
{
- ClassLoader *loader = klass->getClassLoaderInternal();
- if (loader != NULL && loader != sys)
+ jclass klass = t->classAt(i);
+ if (klass != NULL)
{
- look = loader;
- break;
+ ClassLoader *loader = klass->getClassLoaderInternal();
+ if (loader != NULL && loader != sys)
+ {
+ look = loader;
+ break;
+ }
}
}
}
+ catch (::java::lang::ArrayIndexOutOfBoundsException *e)
+ {
+ }
+
if (look != NULL)
{
// Don't include solib prefix in string passed to
@@ -233,6 +244,19 @@ java::lang::Runtime::_load (jstring path, jboolean do_search)
add_library (h);
void *onload = lt_dlsym (h, "JNI_OnLoad");
+
+#ifdef WIN32
+ // On Win32, JNI_OnLoad is an "stdcall" function taking two pointers
+ // (8 bytes) as arguments. It could also have been exported as
+ // "JNI_OnLoad@8" (MinGW) or "_JNI_OnLoad@8" (MSVC).
+ if (onload == NULL)
+ {
+ onload = lt_dlsym (h, "JNI_OnLoad@8");
+ if (onload == NULL)
+ onload = lt_dlsym (h, "_JNI_OnLoad@8");
+ }
+#endif /* WIN32 */
+
if (onload != NULL)
{
JavaVM *vm = _Jv_GetJavaVM ();
@@ -241,7 +265,7 @@ java::lang::Runtime::_load (jstring path, jboolean do_search)
// FIXME: what?
return;
}
- jint vers = ((jint (*) (JavaVM *, void *)) onload) (vm, NULL);
+ jint vers = ((jint (JNICALL *) (JavaVM *, void *)) onload) (vm, NULL);
if (vers != JNI_VERSION_1_1 && vers != JNI_VERSION_1_2
&& vers != JNI_VERSION_1_4)
{
@@ -587,7 +611,7 @@ java::lang::Runtime::insertSystemProperties (java::util::Properties *newprops)
}
// The name used to invoke this process (argv[0] in C).
- SET ("gnu.gcj.progname", _Jv_ThisExecutable());
+ SET ("gnu.gcj.progname", _Jv_argv[0]);
// Allow platform specific settings and overrides.
_Jv_platform_initProperties (newprops);
diff --git a/libjava/java/lang/natSystem.cc b/libjava/java/lang/natSystem.cc
index ffa3f1a5053..e2d42324386 100644
--- a/libjava/java/lang/natSystem.cc
+++ b/libjava/java/lang/natSystem.cc
@@ -1,6 +1,6 @@
// natSystem.cc - Native code implementing System class.
-/* Copyright (C) 1998, 1999, 2000, 2001 , 2002 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation
This file is part of libgcj.
@@ -9,6 +9,7 @@ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#include <config.h>
+#include <platform.h>
#include <stdio.h>
#include <string.h>
@@ -24,8 +25,6 @@ details. */
#include <java/io/PrintStream.h>
#include <java/io/InputStream.h>
-#include "platform.h"
-
void
diff --git a/libjava/java/lang/natWin32Process.cc b/libjava/java/lang/natWin32Process.cc
index e69de29bb2d..ff7ddb5f50a 100644
--- a/libjava/java/lang/natWin32Process.cc
+++ b/libjava/java/lang/natWin32Process.cc
@@ -0,0 +1,295 @@
+// natWin32Process.cc - Native side of Win32 process code.
+
+/* Copyright (C) 2003 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+// Conflicts with the definition in "java/lang/reflect/Modifier.h"
+#undef STRICT
+
+#include <gcj/cni.h>
+#include <jvm.h>
+
+#include <java/lang/ConcreteProcess.h>
+#include <java/lang/IllegalThreadStateException.h>
+#include <java/lang/InterruptedException.h>
+#include <java/lang/NullPointerException.h>
+#include <java/lang/Thread.h>
+#include <java/io/File.h>
+#include <java/io/FileDescriptor.h>
+#include <java/io/FileInputStream.h>
+#include <java/io/FileOutputStream.h>
+#include <java/io/IOException.h>
+#include <java/lang/OutOfMemoryError.h>
+
+void
+java::lang::ConcreteProcess::cleanup (void)
+{
+ if (inputStream != NULL)
+ {
+ inputStream->close ();
+ inputStream = NULL;
+ }
+
+ if (outputStream != NULL)
+ {
+ outputStream->close ();
+ outputStream = NULL;
+ }
+
+ if (errorStream != NULL)
+ {
+ errorStream->close ();
+ errorStream = NULL;
+ }
+}
+
+void
+java::lang::ConcreteProcess::destroy (void)
+{
+ if (! hasExited ())
+ {
+ // Kill it forcibly and assign an (arbitrary) exit code of 0.
+ TerminateProcess ((HANDLE) procHandle, 0);
+ exitCode = 0;
+
+ cleanup ();
+ }
+}
+
+jboolean
+java::lang::ConcreteProcess::hasExited (void)
+{
+ DWORD exitStatus;
+
+ if (GetExitCodeProcess ((HANDLE) procHandle, &exitStatus) != 0)
+ {
+ // NOTE: STILL_ACTIVE is defined as "259" by Win32 - if the
+ // child actually exits with this return code, we have a
+ // problem here. See MSDN documentation on GetExitCodeProcess( ).
+
+ if (exitStatus == STILL_ACTIVE)
+ return false;
+ else
+ {
+ cleanup ();
+ exitCode = exitStatus;
+ return true;
+ }
+ }
+ else
+ return true;
+}
+
+jint
+java::lang::ConcreteProcess::waitFor (void)
+{
+ if (! hasExited ())
+ {
+ DWORD exitStatus = 0UL;
+
+ // FIXME: The wait should be interruptible.
+ WaitForSingleObject ((HANDLE) procHandle, INFINITE);
+
+ GetExitCodeProcess ((HANDLE) procHandle, &exitStatus);
+ exitCode = exitStatus;
+
+ cleanup ();
+ }
+
+ return exitCode;
+}
+
+static char *
+new_string (jstring string)
+{
+ jsize s = _Jv_GetStringUTFLength (string);
+ char *buf = (char *) _Jv_Malloc (s + 1);
+ _Jv_GetStringUTFRegion (string, 0, s, buf);
+ buf[s] = '\0';
+ return buf;
+}
+
+void
+java::lang::ConcreteProcess::startProcess (jstringArray progarray,
+ jstringArray envp,
+ java::io::File *dir)
+{
+ using namespace java::io;
+
+ procHandle = (jint) INVALID_HANDLE_VALUE;
+
+ // Reconstruct the command line.
+ jstring *elts = elements (progarray);
+
+ int cmdLineLen = 0;
+
+ for (int i = 0; i < progarray->length; ++i)
+ cmdLineLen += (_Jv_GetStringUTFLength (elts[i]) + 3);
+
+ char *cmdLine = (char *) _Jv_Malloc (cmdLineLen + 1);
+ char *cmdLineCurPos = cmdLine;
+
+ for (int i = 0; i < progarray->length; ++i)
+ {
+ if (i > 0)
+ *cmdLineCurPos++ = ' ';
+ *cmdLineCurPos++ = '\"';
+ jsize s = _Jv_GetStringUTFLength (elts[i]);
+ _Jv_GetStringUTFRegion (elts[i], 0, s, cmdLineCurPos);
+ cmdLineCurPos += s;
+ *cmdLineCurPos++ = '\"';
+ }
+ *cmdLineCurPos = '\0';
+
+ // Get the environment, if any.
+ char *env = NULL;
+ if (envp)
+ {
+ elts = elements (envp);
+
+ int envLen = 0;
+ for (int i = 0; i < envp->length; ++i)
+ envLen += (_Jv_GetStringUTFLength (elts[i]) + 1);
+
+ env = (char *) _Jv_Malloc (envLen + 1);
+
+ int j = 0;
+ for (int i = 0; i < envp->length; ++i)
+ {
+ jsize s = _Jv_GetStringUTFLength (elts[i]);
+ _Jv_GetStringUTFRegion (elts[i], 0, s, (env + j));
+
+ j += s;
+ *(env + j) = '\0';
+ j++;
+ }
+ *(env + j) = '\0';
+ }
+
+ // Get the working directory path, if specified.
+ char *wdir = NULL;
+ if (dir != NULL)
+ wdir = new_string (dir->getPath ());
+
+ errorStream = NULL;
+ inputStream = NULL;
+ outputStream = NULL;
+
+ java::lang::Throwable *exc = NULL;
+
+ try
+ {
+ // We create anonymous pipes to communicate with the child
+ // on each of standard streams.
+
+ HANDLE cldStdInRd, cldStdInWr;
+ HANDLE cldStdOutRd, cldStdOutWr;
+ HANDLE cldStdErrRd, cldStdErrWr;
+
+ SECURITY_ATTRIBUTES sAttrs;
+
+ // Explicitly allow the handles to the pipes to be inherited.
+ sAttrs.nLength = sizeof (SECURITY_ATTRIBUTES);
+ sAttrs.bInheritHandle = 1;
+ sAttrs.lpSecurityDescriptor = NULL;
+
+
+ char tmpBuff[64];
+ if (CreatePipe (&cldStdInRd, &cldStdInWr, &sAttrs, 0) == 0)
+ {
+ sprintf (tmpBuff,
+ "Error creating stdin pipe (Win32 Error Code: %lu)",
+ GetLastError ());
+ throw new IOException (JvNewStringLatin1 (tmpBuff));
+ }
+
+ if (CreatePipe (&cldStdOutRd, &cldStdOutWr, &sAttrs, 0) == 0)
+ {
+ sprintf (tmpBuff,
+ "Error creating stdout pipe (Win32 Error Code: %lu)",
+ GetLastError ());
+ throw new IOException (JvNewStringLatin1 (tmpBuff));
+ }
+
+ if (CreatePipe (&cldStdErrRd, &cldStdErrWr, &sAttrs, 0) == 0)
+ {
+ sprintf (tmpBuff,
+ "Error creating stderr pipe (Win32 Error Code: %lu)",
+ GetLastError ());
+ throw new IOException (JvNewStringLatin1 (tmpBuff));
+ }
+
+ outputStream = new FileOutputStream
+ (new FileDescriptor ((jint) cldStdInWr));
+ inputStream = new FileInputStream
+ (new FileDescriptor ((jint) cldStdOutRd));
+ errorStream = new FileInputStream
+ (new FileDescriptor ((jint) cldStdErrRd));
+
+ // Now create the child process.
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si;
+
+ ZeroMemory (&pi, sizeof (PROCESS_INFORMATION));
+
+ ZeroMemory (&si, sizeof (STARTUPINFO));
+ si.cb = sizeof (STARTUPINFO);
+
+ // Explicitly specify the handles to the standard streams.
+ si.dwFlags |= STARTF_USESTDHANDLES;
+
+ si.hStdInput = cldStdInRd;
+ si.hStdOutput = cldStdOutWr;
+ si.hStdError = cldStdErrWr;
+
+ if (CreateProcess (NULL,
+ cmdLine,
+ NULL,
+ NULL,
+ 1,
+ 0,
+ env,
+ wdir,
+ &si,
+ &pi) == 0)
+ {
+ sprintf (tmpBuff,
+ "Error creating child process (Win32 Error Code: %lu)",
+ GetLastError ());
+ throw new IOException (JvNewStringLatin1 (tmpBuff));
+ }
+
+ procHandle = (jint ) pi.hProcess;
+
+ // Close the wrong ends (for the parent) of the pipes.
+ CloseHandle (cldStdInRd);
+ CloseHandle (cldStdOutWr);
+ CloseHandle (cldStdErrWr);
+
+ _Jv_Free (cmdLine);
+ if (env != NULL)
+ _Jv_Free (env);
+ if (wdir != NULL)
+ _Jv_Free (wdir);
+ }
+ catch (java::lang::Throwable *thrown)
+ {
+ cleanup ();
+ exc = thrown;
+ }
+
+ if (exc != NULL)
+ throw exc;
+}
diff --git a/libjava/java/lang/reflect/Modifier.java b/libjava/java/lang/reflect/Modifier.java
index 75d0c9b47f5..8171a88feb5 100644
--- a/libjava/java/lang/reflect/Modifier.java
+++ b/libjava/java/lang/reflect/Modifier.java
@@ -1,5 +1,5 @@
/* java.lang.reflect.Modifier
- Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -158,6 +158,17 @@ public class Modifier
static final int ALL_FLAGS = 0xfff;
/**
+ * GCJ-LOCAL: This access flag is set on methods we declare
+ * internally but which must not be visible to reflection.
+ */
+ static final int INVISIBLE = 0x1000;
+
+ /**
+ * GCJ-LOCAL: This access flag is set on interpreted classes.
+ */
+ static final int INTERPRETED = 0x1000;
+
+ /**
* Check whether the given modifier is abstract.
* @param mod the modifier.
* @return <code>true</code> if abstract, <code>false</code> otherwise.
diff --git a/libjava/java/lang/reflect/natMethod.cc b/libjava/java/lang/reflect/natMethod.cc
index 9b697d25024..c0f7077cc40 100644
--- a/libjava/java/lang/reflect/natMethod.cc
+++ b/libjava/java/lang/reflect/natMethod.cc
@@ -358,46 +358,30 @@ _Jv_CallAnyMethodA (jobject obj,
obj = JvAllocObject (return_type);
}
- int i = 0;
- int size = 0;
- if (needs_this)
- {
- // The `NULL' type is `Object'.
- argtypes[i++] = get_ffi_type (NULL);
- size += sizeof (jobject);
- }
-
- for (int arg = 0; i < param_count; ++i, ++arg)
- {
- argtypes[i] = get_ffi_type (paramelts[arg]);
- if (paramelts[arg]->isPrimitive())
- size += paramelts[arg]->size();
- else
- size += sizeof (jobject);
- }
-
+ const int size_per_arg = sizeof(jvalue);
ffi_cif cif;
- if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, param_count,
- rtype, argtypes) != FFI_OK)
- {
- // FIXME: throw some kind of VirtualMachineError here.
- }
- char *p = (char *) __builtin_alloca (size);
- void **values = (void **) __builtin_alloca (param_count * sizeof (void *));
+ char *p = (char *) __builtin_alloca (param_count * size_per_arg);
+ // Overallocate to get correct alignment.
+ void **values = (void **)
+ __builtin_alloca (param_count * sizeof (void *));
- i = 0;
+ int i = 0;
if (needs_this)
{
+ // The `NULL' type is `Object'.
+ argtypes[i] = get_ffi_type (NULL);
values[i] = p;
memcpy (p, &obj, sizeof (jobject));
- p += sizeof (jobject);
+ p += size_per_arg;
++i;
}
for (int arg = 0; i < param_count; ++i, ++arg)
{
int tsize;
+
+ argtypes[i] = get_ffi_type (paramelts[arg]);
if (paramelts[arg]->isPrimitive())
tsize = paramelts[arg]->size();
else
@@ -406,9 +390,16 @@ _Jv_CallAnyMethodA (jobject obj,
// Copy appropriate bits from the jvalue into the ffi array.
// FIXME: we could do this copying all in one loop, above, by
// over-allocating a bit.
+ // How do we do this without breaking big-endian platforms?
values[i] = p;
memcpy (p, &args[arg], tsize);
- p += tsize;
+ p += size_per_arg;
+ }
+
+ if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, param_count,
+ rtype, argtypes) != FFI_OK)
+ {
+ // FIXME: throw some kind of VirtualMachineError here.
}
using namespace java::lang;