OSDN Git Service

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