OSDN Git Service

2011-07-12 Andrew Haley <aph@redhat.com>
[pf3gnuchains/gcc-fork.git] / libjava / java / lang / natRuntime.cc
1 // natRuntime.cc - Implementation of native side of Runtime class.
2
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007  Free Software Foundation
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 #include <config.h>
12 #include <platform.h>
13
14 #include <stdlib.h>
15
16 #include <gcj/cni.h>
17 #include <jvm.h>
18 #include <java-props.h>
19 #include <java-stack.h>
20 #include <java/lang/Long.h>
21 #include <java/lang/Runtime.h>
22 #include <java/lang/UnknownError.h>
23 #include <java/lang/UnsatisfiedLinkError.h>
24 #include <gnu/gcj/runtime/FinalizerThread.h>
25 #include <java/io/File.h>
26 #include <java/util/TimeZone.h>
27 #include <java/lang/StringBuffer.h>
28 #include <java/lang/Process.h>
29 #include <java/lang/ClassLoader.h>
30
31 // It is convenient and safe to simply include all of these.
32 #include <java/lang/Win32Process.h>
33 #include <java/lang/EcosProcess.h>
34 #include <java/lang/PosixProcess.h>
35
36 #include <jni.h>
37
38 #ifdef HAVE_PWD_H
39 #include <pwd.h>
40 #endif
41 #include <errno.h>
42
43 #ifdef HAVE_LOCALE_H
44 #include <locale.h>
45 #endif
46
47 #ifdef HAVE_LANGINFO_H
48 #include <langinfo.h>
49 #endif
50
51 \f
52
53 #ifdef USE_LTDL
54 #include <ltdl.h>
55
56 /* FIXME: we don't always need this.  The next libtool will let us use
57    AC_LTDL_PREOPEN to see if we do.  */
58 extern const lt_dlsymlist lt_preloaded_symbols[1] = { { 0, 0 } };
59
60 struct lookup_data
61 {
62   const char *symname;
63   void *result;
64 };
65
66 static int
67 find_symbol (lt_dlhandle handle, lt_ptr data)
68 {
69   lookup_data *ld = (lookup_data *) data;
70   ld->result = lt_dlsym (handle, ld->symname);
71   return ld->result != NULL;
72 }
73
74 void *
75 _Jv_FindSymbolInExecutable (const char *symname)
76 {
77   lookup_data data;
78   data.symname = symname;
79   data.result = NULL;
80   lt_dlforeach (find_symbol, (lt_ptr) &data);
81   return data.result;
82 }
83
84 #else
85
86 void *
87 _Jv_FindSymbolInExecutable (const char *)
88 {
89   return NULL;
90 }
91
92 #endif /* USE_LTDL */
93
94 \f
95
96 void
97 java::lang::Runtime::runFinalizationForExit ()
98 {
99   if (finalizeOnExit)
100     _Jv_RunAllFinalizers ();
101 }
102
103 void
104 java::lang::Runtime::exitInternal (jint status)
105 {
106   // Make status right for Unix.  This is perhaps strange.
107   if (status < 0 || status > 255)
108     status = 255;
109
110   ::exit (status);
111 }
112
113 jlong
114 java::lang::Runtime::freeMemory (void)
115 {
116   return _Jv_GCFreeMemory ();
117 }
118
119 void
120 java::lang::Runtime::gc (void)
121 {
122   _Jv_RunGC ();
123 }
124
125 #ifdef USE_LTDL
126 // List of names for JNI_OnLoad.
127 static const char *onload_names[] = _Jv_platform_onload_names;
128 #endif
129
130 void
131 java::lang::Runtime::_load (jstring path, jboolean do_search)
132 {
133   JvSynchronize sync (this);
134   using namespace java::lang;
135 #ifdef USE_LTDL
136   jint len = _Jv_GetStringUTFLength (path);
137   char buf[len + 1 + strlen (_Jv_platform_solib_prefix)
138            + strlen (_Jv_platform_solib_suffix)];
139   int offset = 0;
140   if (do_search)
141     {
142       strcpy (buf, _Jv_platform_solib_prefix);
143       offset = strlen (_Jv_platform_solib_prefix);
144     }
145   jsize total = JvGetStringUTFRegion (path, 0, path->length(), &buf[offset]);
146   buf[offset + total] = '\0';
147
148   char *lib_name = buf;
149
150   if (do_search)
151     {
152       ClassLoader *look = _Jv_StackTrace::GetFirstNonSystemClassLoader ();
153
154       if (look != NULL)
155         {
156           // Don't include solib prefix in string passed to
157           // findLibrary.
158           jstring name = look->findLibrary(JvNewStringUTF(&buf[offset]));
159           if (name != NULL)
160             {
161               len = _Jv_GetStringUTFLength (name);
162               lib_name = (char *) _Jv_AllocBytes(len + 1);
163               total = JvGetStringUTFRegion (name, 0,
164                                             name->length(), lib_name);
165               lib_name[total] = '\0';
166               // Don't append suffixes any more; we have the full file
167               // name.
168               do_search = false;
169             }
170         }
171     }
172
173   lt_dlhandle h;
174   // FIXME: make sure path is absolute.
175   {
176     // Synchronize on java.lang.Class. This is to protect the class chain from
177     // concurrent modification by class registration calls which may be run
178     // during the dlopen().
179     JvSynchronize sync (&java::lang::Class::class$);
180     h = do_search ? lt_dlopenext (lib_name) : lt_dlopen (lib_name);
181   }
182   if (h == NULL)
183     {
184       const char *msg = lt_dlerror ();
185       jstring str = JvNewStringLatin1 (lib_name);
186       str = str->concat (JvNewStringLatin1 (": "));
187       str = str->concat (JvNewStringLatin1 (msg));
188       throw new UnsatisfiedLinkError (str);
189     }
190
191   // Search for JNI_OnLoad function.
192   void *onload = NULL;
193   const char **name = onload_names;
194   while (*name != NULL)
195     {
196       onload = lt_dlsym (h, *name);
197       if (onload != NULL)
198         break;
199       ++name;
200     }
201
202   if (onload != NULL)
203     {
204       JavaVM *vm = _Jv_GetJavaVM ();
205       if (vm == NULL)
206         {
207           // FIXME: what?
208           return;
209         }
210
211       // Push a new frame so that JNI_OnLoad will get the right class
212       // loader if it calls FindClass.
213       ::java::lang::ClassLoader *loader
214           = _Jv_StackTrace::GetFirstNonSystemClassLoader();
215       JNIEnv *env = _Jv_GetJNIEnvNewFrameWithLoader (loader);
216       jint vers = ((jint (JNICALL *) (JavaVM *, void *)) onload) (vm, NULL);
217       _Jv_JNI_PopSystemFrame (env);
218       if (vers != JNI_VERSION_1_1 && vers != JNI_VERSION_1_2
219           && vers != JNI_VERSION_1_4)
220         {
221           // FIXME: unload the library.
222           throw new UnsatisfiedLinkError (JvNewStringLatin1 ("unrecognized version from JNI_OnLoad"));
223         }
224     }
225 #else
226   throw new UnknownError
227     (JvNewStringLatin1 (do_search
228                         ? "Runtime.loadLibrary not implemented"
229                         : "Runtime.load not implemented"));
230 #endif /* USE_LTDL */
231 }
232
233 jboolean
234 java::lang::Runtime::loadLibraryInternal (jstring lib)
235 {
236   JvSynchronize sync (this);
237   using namespace java::lang;
238 #ifdef USE_LTDL
239   jint len = _Jv_GetStringUTFLength (lib);
240   char buf[len + 1];
241   jsize total = JvGetStringUTFRegion (lib, 0, lib->length(), buf);
242   buf[total] = '\0';
243   // FIXME: make sure path is absolute.
244   lt_dlhandle h = lt_dlopenext (buf);
245   return h != NULL;
246 #else
247   return false;
248 #endif /* USE_LTDL */
249 }
250
251 void
252 java::lang::Runtime::init (void)
253 {
254 #ifdef USE_LTDL
255   lt_dlinit ();
256   // Set module load path.
257   lt_dlsetsearchpath (_Jv_Module_Load_Path);
258   // Make sure self is opened.
259   lt_dlopen (NULL);
260 #endif
261 }
262
263 void
264 java::lang::Runtime::runFinalization (void)
265 {
266   gnu::gcj::runtime::FinalizerThread::finalizerReady ();
267 }
268
269 jlong
270 java::lang::Runtime::totalMemory (void)
271 {
272   return _Jv_GCTotalMemory ();
273 }
274
275 jlong
276 java::lang::Runtime::maxMemory (void)
277 {
278   // We don't have a maximum.  FIXME: we might if we ask the GC for
279   // one.
280   return Long::MAX_VALUE;
281 }
282
283 void
284 java::lang::Runtime::traceInstructions (jboolean)
285 {
286   // Do nothing.
287 }
288
289 void
290 java::lang::Runtime::traceMethodCalls (jboolean)
291 {
292   // Do nothing.
293 }
294
295 java::lang::Process *
296 java::lang::Runtime::execInternal (jstringArray cmd,
297                                    jstringArray env,
298                                    java::io::File *dir)
299 {
300   return new _Jv_platform_process (cmd, env, dir, false);
301 }
302
303 jint
304 java::lang::Runtime::availableProcessors (void)
305 {
306   // FIXME: find the real value.
307   return 1;
308 }
309
310 jstring
311 java::lang::Runtime::nativeGetLibname (jstring pathname, jstring libname)
312 {
313   java::lang::StringBuffer *sb = new java::lang::StringBuffer ();
314   sb->append(pathname);
315   if (pathname->length() > 0)
316     sb->append (_Jv_platform_file_separator);
317
318   sb->append (JvNewStringLatin1 (_Jv_platform_solib_prefix));
319   sb->append(libname);
320   sb->append (JvNewStringLatin1 (_Jv_platform_solib_suffix));
321
322   return sb->toString();
323 }