diff options
author | Per Bothner <per@bothner.com> | 2001-05-21 23:47:48 -0700 |
---|---|---|
committer | Per Bothner <bothner@gcc.gnu.org> | 2001-05-21 23:47:48 -0700 |
commit | c93d7fae7b9825449c023d42eb40641c0ad80be2 (patch) | |
tree | ecfc0fb5d915f5f6596ef061114d1b6b7ec5270a /libjava/prims.cc | |
parent | b4fbaca7cb5c6ff5fb5e24e554d510257cb488eb (diff) | |
download | gcc-c93d7fae7b9825449c023d42eb40641c0ad80be2.zip gcc-c93d7fae7b9825449c023d42eb40641c0ad80be2.tar.gz gcc-c93d7fae7b9825449c023d42eb40641c0ad80be2.tar.bz2 |
Implement invocation interface; don't create new thread for main.
From-SVN: r42428
Diffstat (limited to 'libjava/prims.cc')
-rw-r--r-- | libjava/prims.cc | 240 |
1 files changed, 174 insertions, 66 deletions
diff --git a/libjava/prims.cc b/libjava/prims.cc index 0fa42a4..6bcf646 100644 --- a/libjava/prims.cc +++ b/libjava/prims.cc @@ -36,6 +36,7 @@ details. */ #ifdef ENABLE_JVMPI #include <jvmpi.h> +#include <java/lang/ThreadGroup.h> #endif #ifndef DISABLE_GETENV_PROPERTIES @@ -62,6 +63,7 @@ details. */ #include <java/lang/System.h> #include <java/lang/reflect/Modifier.h> #include <java/io/PrintStream.h> +#include <java/lang/UnsatisfiedLinkError.h> #ifdef USE_LTDL #include <ltdl.h> @@ -74,8 +76,10 @@ static java::lang::OutOfMemoryError *no_memory; // Largest representable size_t. #define SIZE_T_MAX ((size_t) (~ (size_t) 0)) +static const char *no_properties[] = { NULL }; + // Properties set at compile time. -const char **_Jv_Compiler_Properties; +const char **_Jv_Compiler_Properties = no_properties; // The JAR file to add to the beginning of java.class.path. const char *_Jv_Jar_Class_Path; @@ -92,6 +96,8 @@ static char * _Jv_execName; const char **_Jv_argv; int _Jv_argc; +typedef void main_func (jobject); + #ifdef ENABLE_JVMPI // Pointer to JVMPI notification functions. void (*_Jv_JVMPI_Notify_OBJECT_ALLOC) (JVMPI_Event *event); @@ -640,51 +646,15 @@ win32_exception_handler (LPEXCEPTION_POINTERS e) #endif -static void -main_init () +/* This will be non-NULL if the user has preloaded a JNI library, or + linked one into the executable. */ +extern "C" { - // Turn stack trace generation off while creating exception objects. - _Jv_InitClass (&java::lang::Throwable::class$); - java::lang::Throwable::trace_enabled = 0; - - INIT_SEGV; -#ifdef HANDLE_FPE - INIT_FPE; -#else - arithexception = new java::lang::ArithmeticException - (JvNewStringLatin1 ("/ by zero")); -#endif - - no_memory = new java::lang::OutOfMemoryError; - - java::lang::Throwable::trace_enabled = 1; - -#ifdef USE_LTDL - LTDL_SET_PRELOADED_SYMBOLS (); -#endif - -#ifdef USE_WINSOCK - // Initialise winsock for networking - WSADATA data; - if (WSAStartup (MAKEWORD (1, 1), &data)) - MessageBox (NULL, "Error initialising winsock library.", "Error", MB_OK | MB_ICONEXCLAMATION); -#endif /* USE_WINSOCK */ - -#ifdef USE_WIN32_SIGNALLING - // Install exception handler - SetUnhandledExceptionFilter (win32_exception_handler); -#else - // We only want this on POSIX systems. - struct sigaction act; - act.sa_handler = SIG_IGN; - sigemptyset (&act.sa_mask); - act.sa_flags = 0; - sigaction (SIGPIPE, &act, NULL); -#endif /* USE_WIN32_SIGNALLING */ - - _Jv_JNI_Init (); +#pragma weak JNI_OnLoad + extern jint JNI_OnLoad (JavaVM *, void *) __attribute__((weak)); } + #ifndef DISABLE_GETENV_PROPERTIES static char * @@ -828,15 +798,162 @@ process_gcj_properties () } #endif // DISABLE_GETENV_PROPERTIES -void -JvRunMain (jclass klass, int argc, const char **argv) +jint +_Jv_CreateJavaVM (void* /*vm_args*/) { PROCESS_GCJ_PROPERTIES; + // Turn stack trace generation off while creating exception objects. + _Jv_InitClass (&java::lang::Throwable::class$); + java::lang::Throwable::trace_enabled = 0; + + INIT_SEGV; +#ifdef HANDLE_FPE + INIT_FPE; +#else + arithexception = new java::lang::ArithmeticException + (JvNewStringLatin1 ("/ by zero")); +#endif + + no_memory = new java::lang::OutOfMemoryError; + + java::lang::Throwable::trace_enabled = 1; + +#ifdef USE_LTDL + LTDL_SET_PRELOADED_SYMBOLS (); +#endif + +#ifdef USE_WINSOCK + // Initialise winsock for networking + WSADATA data; + if (WSAStartup (MAKEWORD (1, 1), &data)) + MessageBox (NULL, "Error initialising winsock library.", "Error", MB_OK | MB_ICONEXCLAMATION); +#endif /* USE_WINSOCK */ + +#ifdef USE_WIN32_SIGNALLING + // Install exception handler + SetUnhandledExceptionFilter (win32_exception_handler); +#else + // We only want this on POSIX systems. + struct sigaction act; + act.sa_handler = SIG_IGN; + sigemptyset (&act.sa_mask); + act.sa_flags = 0; + sigaction (SIGPIPE, &act, NULL); +#endif /* USE_WIN32_SIGNALLING */ + + _Jv_JNI_Init (); + + /* Some systems let you preload shared libraries before running a + program. Under Linux, this is done by setting the LD_PRELOAD + environment variable. We take advatage of this here to allow for + dynamically loading a JNI library into a fully linked executable. */ + + if (JNI_OnLoad != NULL) + { + JavaVM *vm = _Jv_GetJavaVM (); + if (vm == NULL) + { + // FIXME: what? + return -1; + } + jint vers = JNI_OnLoad (vm, NULL); + if (vers != JNI_VERSION_1_1 && vers != JNI_VERSION_1_2) + { + // FIXME: unload the library. + _Jv_Throw (new java::lang::UnsatisfiedLinkError (JvNewStringLatin1 ("unrecognized version from preloaded JNI_OnLoad"))); + } + } + return 0; +} + +static void +runFirst (::java::lang::Class *klass, ::java::lang::Object *args) +{ + Utf8Const* main_signature = _Jv_makeUtf8Const ("([Ljava.lang.String;)V", 22); + Utf8Const* main_name = _Jv_makeUtf8Const ("main", 4); + + _Jv_Method *meth = _Jv_GetMethodLocal (klass, main_name, main_signature); + + // Some checks from Java Spec section 12.1.4. + const char *msg = NULL; + if (meth == NULL) + msg = "no suitable method `main' in class"; + else if (! java::lang::reflect::Modifier::isStatic(meth->accflags)) + msg = "`main' must be static"; + else if (! java::lang::reflect::Modifier::isPublic(meth->accflags)) + msg = "`main' must be public"; + if (msg != NULL) + { + fprintf (stderr, "%s\n", msg); + ::exit(1); + } + +#ifdef WITH_JVMPI + if (_Jv_JVMPI_Notify_THREAD_START) + { + JVMPI_Event event; + + jstring thread_name = getName (); + jstring group_name = NULL, parent_name = NULL; + java::lang::ThreadGroup *group = getThreadGroup (); + + if (group) + { + group_name = group->getName (); + group = group->getParent (); + + if (group) + parent_name = group->getName (); + } + + int thread_len = thread_name ? JvGetStringUTFLength (thread_name) : 0; + int group_len = group_name ? JvGetStringUTFLength (group_name) : 0; + int parent_len = parent_name ? JvGetStringUTFLength (parent_name) : 0; + + char thread_chars[thread_len + 1]; + char group_chars[group_len + 1]; + char parent_chars[parent_len + 1]; + + if (thread_name) + JvGetStringUTFRegion (thread_name, 0, + thread_name->length(), thread_chars); + if (group_name) + JvGetStringUTFRegion (group_name, 0, + group_name->length(), group_chars); + if (parent_name) + JvGetStringUTFRegion (parent_name, 0, + parent_name->length(), parent_chars); + + thread_chars[thread_len] = '\0'; + group_chars[group_len] = '\0'; + parent_chars[parent_len] = '\0'; + + event.event_type = JVMPI_EVENT_THREAD_START; + event.env_id = NULL; + event.u.thread_start.thread_name = thread_chars; + event.u.thread_start.group_name = group_chars; + event.u.thread_start.parent_name = parent_chars; + event.u.thread_start.thread_id = (jobjectID) this; + event.u.thread_start.thread_env_id = _Jv_GetCurrentJNIEnv (); + + _Jv_DisableGC (); + (*_Jv_JVMPI_Notify_THREAD_START) (&event); + _Jv_EnableGC (); + } +#endif + + main_func *real_main = (main_func *) meth->ncode; + (*real_main) (args); +} + +void +JvRunMain (jclass klass, int argc, const char **argv) +{ _Jv_argv = argv; _Jv_argc = argc; - main_init (); + _Jv_CreateJavaVM (NULL); #ifdef HAVE_PROC_SELF_EXE char exec_name[20]; sprintf (exec_name, "/proc/%d/exe", getpid ()); @@ -845,10 +962,9 @@ JvRunMain (jclass klass, int argc, const char **argv) _Jv_ThisExecutable (argv[0]); #endif + main_thread = _Jv_AttachCurrentThread (JvNewStringLatin1 ("main"), NULL); arg_vec = JvConvertArgv (argc - 1, argv + 1); - main_thread = new gnu::gcj::runtime::FirstThread (klass, arg_vec); - - main_thread->start(); + runFirst (klass, arg_vec); _Jv_ThreadWait (); int status = (int) java::lang::ThreadGroup::had_uncaught_exception; @@ -860,9 +976,8 @@ void _Jv_RunMain (const char *name, int argc, const char **argv, bool is_jar) { jstring class_name; - PROCESS_GCJ_PROPERTIES; - main_init (); + _Jv_CreateJavaVM (NULL); #ifdef HAVE_PROC_SELF_EXE char exec_name[20]; @@ -870,23 +985,17 @@ _Jv_RunMain (const char *name, int argc, const char **argv, bool is_jar) _Jv_ThisExecutable (exec_name); #endif + main_thread = _Jv_AttachCurrentThread (JvNewStringLatin1 ("main"), NULL); + if (is_jar) { // name specifies a jar file. We must now extract the - // Main-Class attribute from the jar's manifest file. This is - // done by gnu.gcj.runtime.FirstThread.main. + // Main-Class attribute from the jar's manifest file. + // This is done by gnu.gcj.runtime.FirstThread.getMain. _Jv_Jar_Class_Path = strdup (name); - arg_vec = JvConvertArgv (1, &_Jv_Jar_Class_Path); - - main_thread = - new gnu::gcj::runtime::FirstThread (&gnu::gcj::runtime::FirstThread::class$, - arg_vec); - main_thread->start(); - _Jv_ThreadWait (); - - // FirstThread.main extracts the main class name and stores it - // here. - class_name = gnu::gcj::runtime::FirstThread::jarMainClassName; + jstring jar_name = JvNewStringLatin1 (name); + // FirstThread.getMain extracts the main class name. + class_name = gnu::gcj::runtime::FirstThread::getMain (jar_name); // We need a new ClassLoader because the classpath must be the // jar file only. The easiest way to do this is to lose our @@ -900,8 +1009,7 @@ _Jv_RunMain (const char *name, int argc, const char **argv, bool is_jar) if (class_name) { - main_thread = new gnu::gcj::runtime::FirstThread (class_name, arg_vec); - main_thread->start(); + runFirst(java::lang::Class::forName (class_name), arg_vec); _Jv_ThreadWait (); } |