| // natRuntime.cc - Implementation of native side of Runtime class. | |
| /* Copyright (C) 1998, 1999, 2000, 2001 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 <stdlib.h> | |
| #include <gcj/cni.h> | |
| #include <jvm.h> | |
| #include <java/lang/Runtime.h> | |
| #include <java/lang/UnknownError.h> | |
| #include <java/lang/UnsatisfiedLinkError.h> | |
| #include <gnu/gcj/runtime/FileDeleter.h> | |
| #include <gnu/gcj/runtime/FinalizerThread.h> | |
| #include <jni.h> | |
| #ifdef USE_LTDL | |
| #include <ltdl.h> | |
| /* FIXME: we don't always need this. The next libtool will let us use | |
| AC_LTDL_PREOPEN to see if we do. */ | |
| extern const lt_dlsymlist lt_preloaded_symbols[1] = { { 0, 0 } }; | |
| // We keep track of all the libraries loaded by this application. For | |
| // now we use them to look up symbols for JNI. `libraries_size' holds | |
| // the total size of the buffer. `libraries_count' is the number of | |
| // items which are in use. | |
| static int libraries_size; | |
| static int libraries_count; | |
| static lt_dlhandle *libraries; | |
| static void | |
| add_library (lt_dlhandle lib) | |
| { | |
| if (libraries_count == libraries_size) | |
| { | |
| int ns = libraries_size * 2; | |
| if (ns == 0) | |
| ns = 10; | |
| lt_dlhandle *n = (lt_dlhandle *) _Jv_Malloc (ns * sizeof (lt_dlhandle)); | |
| if (libraries) | |
| { | |
| memcpy (n, libraries, libraries_size * sizeof (lt_dlhandle)); | |
| _Jv_Free (libraries); | |
| } | |
| libraries = n; | |
| libraries_size = ns; | |
| for (int i = libraries_count; i < libraries_size; ++i) | |
| libraries[i] = NULL; | |
| } | |
| libraries[libraries_count++] = lib; | |
| } | |
| void * | |
| _Jv_FindSymbolInExecutable (const char *symname) | |
| { | |
| for (int i = 0; i < libraries_count; ++i) | |
| { | |
| void *r = lt_dlsym (libraries[i], symname); | |
| if (r) | |
| return r; | |
| } | |
| return NULL; | |
| } | |
| #else | |
| void * | |
| _Jv_FindSymbolInExecutable (const char *symname) | |
| { | |
| return NULL; | |
| } | |
| #endif /* USE_LTDL */ | |
| 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; | |
| if (finalize_on_exit) | |
| _Jv_RunAllFinalizers (); | |
| // Delete all files registered with File.deleteOnExit() | |
| gnu::gcj::runtime::FileDeleter::deleteOnExitNow (); | |
| ::exit (status); | |
| } | |
| jlong | |
| java::lang::Runtime::freeMemory (void) | |
| { | |
| return _Jv_GCFreeMemory (); | |
| } | |
| void | |
| java::lang::Runtime::gc (void) | |
| { | |
| _Jv_RunGC (); | |
| } | |
| void | |
| java::lang::Runtime::_load (jstring path, jboolean do_search) | |
| { | |
| JvSynchronize sync (this); | |
| checkLink (path); | |
| using namespace java::lang; | |
| #ifdef USE_LTDL | |
| jint len = _Jv_GetStringUTFLength (path); | |
| char buf[len + 1 + 3]; | |
| int offset = 0; | |
| #ifndef WIN32 | |
| // On Unix boxes, prefix library name with `lib', for loadLibrary. | |
| if (do_search) | |
| { | |
| strcpy (buf, "lib"); | |
| offset = 3; | |
| } | |
| #endif | |
| jsize total = JvGetStringUTFRegion (path, 0, path->length(), &buf[offset]); | |
| buf[offset + total] = '\0'; | |
| lt_dlhandle h; | |
| // FIXME: make sure path is absolute. | |
| { | |
| // Synchronize on java.lang.Class. This is to protect the class chain from | |
| // concurrent modification by class registration calls which may be run | |
| // during the dlopen(). | |
| JvSynchronize sync (&java::lang::Class::class$); | |
| h = do_search ? lt_dlopenext (buf) : lt_dlopen (buf); | |
| } | |
| if (h == NULL) | |
| { | |
| const char *msg = lt_dlerror (); | |
| jstring str = path->concat (JvNewStringLatin1 (": ")); | |
| str = str->concat (JvNewStringLatin1 (msg)); | |
| throw new UnsatisfiedLinkError (str); | |
| } | |
| add_library (h); | |
| void *onload = lt_dlsym (h, "JNI_OnLoad"); | |
| if (onload != NULL) | |
| { | |
| JavaVM *vm = _Jv_GetJavaVM (); | |
| if (vm == NULL) | |
| { | |
| // FIXME: what? | |
| return; | |
| } | |
| jint vers = ((jint (*) (JavaVM *, void *)) onload) (vm, NULL); | |
| if (vers != JNI_VERSION_1_1 && vers != JNI_VERSION_1_2) | |
| { | |
| // FIXME: unload the library. | |
| throw new UnsatisfiedLinkError (JvNewStringLatin1 ("unrecognized version from JNI_OnLoad")); | |
| } | |
| } | |
| #else | |
| throw new UnknownError | |
| (JvNewStringLatin1 (do_search | |
| ? "Runtime.loadLibrary not implemented" | |
| : "Runtime.load not implemented")); | |
| #endif /* USE_LTDL */ | |
| } | |
| jboolean | |
| java::lang::Runtime::loadLibraryInternal (jstring lib) | |
| { | |
| JvSynchronize sync (this); | |
| using namespace java::lang; | |
| #ifdef USE_LTDL | |
| jint len = _Jv_GetStringUTFLength (lib); | |
| char buf[len + 1]; | |
| jsize total = JvGetStringUTFRegion (lib, 0, lib->length(), buf); | |
| buf[total] = '\0'; | |
| // FIXME: make sure path is absolute. | |
| lt_dlhandle h = lt_dlopenext (buf); | |
| if (h != NULL) | |
| add_library (h); | |
| return h != NULL; | |
| #else | |
| return false; | |
| #endif /* USE_LTDL */ | |
| } | |
| void | |
| java::lang::Runtime::init (void) | |
| { | |
| finalize_on_exit = false; | |
| #ifdef USE_LTDL | |
| lt_dlinit (); | |
| lt_dlhandle self = lt_dlopen (NULL); | |
| if (self != NULL) | |
| add_library (self); | |
| #endif | |
| } | |
| void | |
| java::lang::Runtime::runFinalization (void) | |
| { | |
| gnu::gcj::runtime::FinalizerThread::finalizerReady (); | |
| } | |
| jlong | |
| java::lang::Runtime::totalMemory (void) | |
| { | |
| return _Jv_GCTotalMemory (); | |
| } | |
| void | |
| java::lang::Runtime::traceInstructions (jboolean) | |
| { | |
| // Do nothing. | |
| } | |
| void | |
| java::lang::Runtime::traceMethodCalls (jboolean) | |
| { | |
| // Do nothing. | |
| } |