diff options
Diffstat (limited to 'libjava/java/lang')
-rw-r--r-- | libjava/java/lang/Class.h | 10 | ||||
-rw-r--r-- | libjava/java/lang/ClassLoader.java | 18 | ||||
-rw-r--r-- | libjava/java/lang/StringBuffer.java | 39 | ||||
-rw-r--r-- | libjava/java/lang/System.java | 45 | ||||
-rw-r--r-- | libjava/java/lang/Win32Process.java | 52 | ||||
-rw-r--r-- | libjava/java/lang/natClass.cc | 41 | ||||
-rw-r--r-- | libjava/java/lang/natClassLoader.cc | 75 | ||||
-rw-r--r-- | libjava/java/lang/natObject.cc | 5 | ||||
-rw-r--r-- | libjava/java/lang/natRuntime.cc | 50 | ||||
-rw-r--r-- | libjava/java/lang/natSystem.cc | 5 | ||||
-rw-r--r-- | libjava/java/lang/natWin32Process.cc | 295 | ||||
-rw-r--r-- | libjava/java/lang/reflect/Modifier.java | 13 | ||||
-rw-r--r-- | libjava/java/lang/reflect/natMethod.cc | 47 |
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; |