mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			324 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			324 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
| // natRuntime.cc - Implementation of native side of Runtime class.
 | ||
| 
 | ||
| /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007  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 <platform.h>
 | ||
| 
 | ||
| #include <stdlib.h>
 | ||
| 
 | ||
| #include <gcj/cni.h>
 | ||
| #include <jvm.h>
 | ||
| #include <java-props.h>
 | ||
| #include <java-stack.h>
 | ||
| #include <java/lang/Long.h>
 | ||
| #include <java/lang/Runtime.h>
 | ||
| #include <java/lang/UnknownError.h>
 | ||
| #include <java/lang/UnsatisfiedLinkError.h>
 | ||
| #include <gnu/gcj/runtime/FinalizerThread.h>
 | ||
| #include <java/io/File.h>
 | ||
| #include <java/util/TimeZone.h>
 | ||
| #include <java/lang/StringBuffer.h>
 | ||
| #include <java/lang/Process.h>
 | ||
| #include <java/lang/ClassLoader.h>
 | ||
| 
 | ||
| // It is convenient and safe to simply include all of these.
 | ||
| #include <java/lang/Win32Process.h>
 | ||
| #include <java/lang/EcosProcess.h>
 | ||
| #include <java/lang/PosixProcess.h>
 | ||
| 
 | ||
| #include <jni.h>
 | ||
| 
 | ||
| #ifdef HAVE_PWD_H
 | ||
| #include <pwd.h>
 | ||
| #endif
 | ||
| #include <errno.h>
 | ||
| 
 | ||
| #ifdef HAVE_LOCALE_H
 | ||
| #include <locale.h>
 | ||
| #endif
 | ||
| 
 | ||
| #ifdef HAVE_LANGINFO_H
 | ||
| #include <langinfo.h>
 | ||
| #endif
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| #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 } };
 | ||
| 
 | ||
| struct lookup_data
 | ||
| {
 | ||
|   const char *symname;
 | ||
|   void *result;
 | ||
| };
 | ||
| 
 | ||
| static int
 | ||
| find_symbol (lt_dlhandle handle, lt_ptr data)
 | ||
| {
 | ||
|   lookup_data *ld = (lookup_data *) data;
 | ||
|   ld->result = lt_dlsym (handle, ld->symname);
 | ||
|   return ld->result != NULL;
 | ||
| }
 | ||
| 
 | ||
| void *
 | ||
| _Jv_FindSymbolInExecutable (const char *symname)
 | ||
| {
 | ||
|   lookup_data data;
 | ||
|   data.symname = symname;
 | ||
|   data.result = NULL;
 | ||
|   lt_dlforeach (find_symbol, (lt_ptr) &data);
 | ||
|   return data.result;
 | ||
| }
 | ||
| 
 | ||
| #else
 | ||
| 
 | ||
| void *
 | ||
| _Jv_FindSymbolInExecutable (const char *)
 | ||
| {
 | ||
|   return NULL;
 | ||
| }
 | ||
| 
 | ||
| #endif /* USE_LTDL */
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| void
 | ||
| java::lang::Runtime::runFinalizationForExit ()
 | ||
| {
 | ||
|   if (finalizeOnExit)
 | ||
|     _Jv_RunAllFinalizers ();
 | ||
| }
 | ||
| 
 | ||
| void
 | ||
| java::lang::Runtime::exitInternal (jint status)
 | ||
| {
 | ||
|   // Make status right for Unix.  This is perhaps strange.
 | ||
|   if (status < 0 || status > 255)
 | ||
|     status = 255;
 | ||
| 
 | ||
|   ::exit (status);
 | ||
| }
 | ||
| 
 | ||
| jlong
 | ||
| java::lang::Runtime::freeMemory (void)
 | ||
| {
 | ||
|   return _Jv_GCFreeMemory ();
 | ||
| }
 | ||
| 
 | ||
| void
 | ||
| java::lang::Runtime::gc (void)
 | ||
| {
 | ||
|   _Jv_RunGC ();
 | ||
| }
 | ||
| 
 | ||
| #ifdef USE_LTDL
 | ||
| // List of names for JNI_OnLoad.
 | ||
| static const char *onload_names[] = _Jv_platform_onload_names;
 | ||
| #endif
 | ||
| 
 | ||
| void
 | ||
| java::lang::Runtime::_load (jstring path, jboolean do_search)
 | ||
| {
 | ||
|   JvSynchronize sync (this);
 | ||
|   using namespace java::lang;
 | ||
| #ifdef USE_LTDL
 | ||
|   jint len = _Jv_GetStringUTFLength (path);
 | ||
|   char buf[len + 1 + strlen (_Jv_platform_solib_prefix)
 | ||
| 	   + strlen (_Jv_platform_solib_suffix)];
 | ||
|   int offset = 0;
 | ||
|   if (do_search)
 | ||
|     {
 | ||
|       strcpy (buf, _Jv_platform_solib_prefix);
 | ||
|       offset = strlen (_Jv_platform_solib_prefix);
 | ||
|     }
 | ||
|   jsize total = JvGetStringUTFRegion (path, 0, path->length(), &buf[offset]);
 | ||
|   buf[offset + total] = '\0';
 | ||
| 
 | ||
|   char *lib_name = buf;
 | ||
| 
 | ||
|   if (do_search)
 | ||
|     {
 | ||
|       ClassLoader *look = _Jv_StackTrace::GetFirstNonSystemClassLoader ();
 | ||
| 
 | ||
|       if (look != NULL)
 | ||
| 	{
 | ||
| 	  // Don't include solib prefix in string passed to
 | ||
| 	  // findLibrary.
 | ||
| 	  jstring name = look->findLibrary(JvNewStringUTF(&buf[offset]));
 | ||
| 	  if (name != NULL)
 | ||
| 	    {
 | ||
| 	      len = _Jv_GetStringUTFLength (name);
 | ||
| 	      lib_name = (char *) _Jv_AllocBytes(len + 1);
 | ||
| 	      total = JvGetStringUTFRegion (name, 0,
 | ||
| 					    name->length(), lib_name);
 | ||
| 	      lib_name[total] = '\0';
 | ||
| 	      // Don't append suffixes any more; we have the full file
 | ||
| 	      // name.
 | ||
| 	      do_search = false;
 | ||
| 	    }
 | ||
| 	}
 | ||
|     }
 | ||
| 
 | ||
|   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 (lib_name) : lt_dlopen (lib_name);
 | ||
|   }
 | ||
|   if (h == NULL)
 | ||
|     {
 | ||
|       const char *msg = lt_dlerror ();
 | ||
|       jstring str = JvNewStringLatin1 (lib_name);
 | ||
|       str = str->concat (JvNewStringLatin1 (": "));
 | ||
|       str = str->concat (JvNewStringLatin1 (msg));
 | ||
|       throw new UnsatisfiedLinkError (str);
 | ||
|     }
 | ||
| 
 | ||
|   // Search for JNI_OnLoad function.
 | ||
|   void *onload = NULL;
 | ||
|   const char **name = onload_names;
 | ||
|   while (*name != NULL)
 | ||
|     {
 | ||
|       onload = lt_dlsym (h, *name);
 | ||
|       if (onload != NULL)
 | ||
| 	break;
 | ||
|       ++name;
 | ||
|     }
 | ||
| 
 | ||
|   if (onload != NULL)
 | ||
|     {
 | ||
|       JavaVM *vm = _Jv_GetJavaVM ();
 | ||
|       if (vm == NULL)
 | ||
| 	{
 | ||
| 	  // FIXME: what?
 | ||
| 	  return;
 | ||
| 	}
 | ||
| 
 | ||
|       // Push a new frame so that JNI_OnLoad will get the right class
 | ||
|       // loader if it calls FindClass.
 | ||
|       ::java::lang::ClassLoader *loader
 | ||
| 	  = _Jv_StackTrace::GetFirstNonSystemClassLoader();
 | ||
|       JNIEnv *env = _Jv_GetJNIEnvNewFrameWithLoader (loader);
 | ||
|       jint vers = ((jint (JNICALL *) (JavaVM *, void *)) onload) (vm, NULL);
 | ||
|       _Jv_JNI_PopSystemFrame (env);
 | ||
|       if (vers != JNI_VERSION_1_1 && vers != JNI_VERSION_1_2
 | ||
| 	  && vers != JNI_VERSION_1_4)
 | ||
| 	{
 | ||
| 	  // 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);
 | ||
|   return h != NULL;
 | ||
| #else
 | ||
|   return false;
 | ||
| #endif /* USE_LTDL */
 | ||
| }
 | ||
| 
 | ||
| void
 | ||
| java::lang::Runtime::init (void)
 | ||
| {
 | ||
| #ifdef USE_LTDL
 | ||
|   lt_dlinit ();
 | ||
|   // Set module load path.
 | ||
|   lt_dlsetsearchpath (_Jv_Module_Load_Path);
 | ||
|   // Make sure self is opened.
 | ||
|   lt_dlopen (NULL);
 | ||
| #endif
 | ||
| }
 | ||
| 
 | ||
| void
 | ||
| java::lang::Runtime::runFinalization (void)
 | ||
| {
 | ||
|   gnu::gcj::runtime::FinalizerThread::finalizerReady ();
 | ||
| }
 | ||
| 
 | ||
| jlong
 | ||
| java::lang::Runtime::totalMemory (void)
 | ||
| {
 | ||
|   return _Jv_GCTotalMemory ();
 | ||
| }
 | ||
| 
 | ||
| jlong
 | ||
| java::lang::Runtime::maxMemory (void)
 | ||
| {
 | ||
|   // We don't have a maximum.  FIXME: we might if we ask the GC for
 | ||
|   // one.
 | ||
|   return Long::MAX_VALUE;
 | ||
| }
 | ||
| 
 | ||
| void
 | ||
| java::lang::Runtime::traceInstructions (jboolean)
 | ||
| {
 | ||
|   // Do nothing.
 | ||
| }
 | ||
| 
 | ||
| void
 | ||
| java::lang::Runtime::traceMethodCalls (jboolean)
 | ||
| {
 | ||
|   // Do nothing.
 | ||
| }
 | ||
| 
 | ||
| java::lang::Process *
 | ||
| java::lang::Runtime::execInternal (jstringArray cmd,
 | ||
| 				   jstringArray env,
 | ||
| 				   java::io::File *dir)
 | ||
| {
 | ||
|   return new _Jv_platform_process (cmd, env, dir, false);
 | ||
| }
 | ||
| 
 | ||
| jint
 | ||
| java::lang::Runtime::availableProcessors (void)
 | ||
| {
 | ||
|   // FIXME: find the real value.
 | ||
|   return 1;
 | ||
| }
 | ||
| 
 | ||
| jstring
 | ||
| java::lang::Runtime::nativeGetLibname (jstring pathname, jstring libname)
 | ||
| {
 | ||
|   java::lang::StringBuffer *sb = new java::lang::StringBuffer ();
 | ||
|   sb->append(pathname);
 | ||
|   if (pathname->length() > 0)
 | ||
|     sb->append (_Jv_platform_file_separator);
 | ||
| 
 | ||
|   sb->append (JvNewStringLatin1 (_Jv_platform_solib_prefix));
 | ||
|   sb->append(libname);
 | ||
|   sb->append (JvNewStringLatin1 (_Jv_platform_solib_suffix));
 | ||
| 
 | ||
|   return sb->toString();
 | ||
| }
 |