GNU header update.
[cacao.git] / src / native / vm / VMRuntime.c
1 /* native/vm/VMRuntime.c - java/lang/VMRuntime
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Roman Obermaiser
28
29    Changes: Joseph Wenninger
30             Christian Thalinger
31
32    $Id: VMRuntime.c 1735 2004-12-07 14:33:27Z twisti $
33
34 */
35
36
37 #include <string.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include <sys/utsname.h>
41
42 #if !defined(STATIC_CLASSPATH)
43 #include <dlfcn.h>
44 #endif
45
46 #include "config.h"
47 #include "cacao/cacao.h"
48 #include "mm/boehm.h"
49 #include "mm/memory.h"
50 #include "native/jni.h"
51 #include "native/native.h"
52 #include "native/include/java_io_File.h"
53 #include "native/include/java_lang_String.h"
54 #include "native/include/java_lang_Process.h"
55 #include "native/include/java_util_Properties.h"     /* java_lang_VMRuntime.h */
56 #include "native/include/java_lang_VMRuntime.h"
57 #include "toolbox/logging.h"
58 #include "vm/builtin.h"
59 #include "vm/exceptions.h"
60 #include "vm/loader.h"
61 #include "vm/tables.h"
62 #include "vm/jit/asmpart.h"
63
64
65 /* this should work on BSD */
66 /*
67 #if defined(__DARWIN__)
68 #include <sys/sysctl.h>
69 #endif
70 */
71
72 #undef JOWENN_DEBUG
73
74 /* should we run all finalizers on exit? */
75 static bool finalizeOnExit = false;
76
77 /* temporary property structure */
78
79 typedef struct property property;
80
81 struct property {
82         char     *key;
83         char     *value;
84         property *next;
85 };
86
87 static property *properties = NULL;
88
89
90 /* create_property *************************************************************
91
92    Create a property entry for a command line property definition.
93
94 *******************************************************************************/
95
96 void create_property(char *key, char *value)
97 {
98         property *p;
99
100         p = NEW(property);
101         p->key = key;
102         p->value = value;
103         p->next = properties;
104         properties = p;
105 }
106
107
108 /* insert_property *************************************************************
109
110    Used for inserting a property into the system's properties table. Method m
111    (usually put) and the properties table must be given.
112
113 *******************************************************************************/
114
115 static void insert_property(methodinfo *m, java_util_Properties *p, char *key,
116                                                         char *value)
117 {
118         asm_calljavafunction(m,
119                                                  p,
120                                                  javastring_new_char(key),
121                                                  javastring_new_char(value),
122                                                  NULL);
123 }
124
125
126 /*
127  * Class:     java_lang_VMRuntime
128  * Method:    execInternal
129  * Signature: ([Ljava/lang/String;[Ljava/lang/String;Ljava/io/File;)Ljava/lang/Process;
130  */
131 JNIEXPORT java_lang_Process* JNICALL Java_java_lang_VMRuntime_execInternal(JNIEnv *env, jclass clazz, java_objectarray *cmd, java_objectarray *shellenv, java_io_File *workingdir)
132 {
133         log_text("Java_java_lang_Runtime_execInternal called");
134
135         return NULL;
136 }
137
138
139 /*
140  * Class:     java/lang/VMRuntime
141  * Method:    exitInternal
142  * Signature: (I)V
143  */
144 JNIEXPORT void JNICALL Java_java_lang_VMRuntime_exit(JNIEnv *env, jclass clazz, s4 par1)
145 {
146         if (finalizeOnExit)
147                 gc_finalize_all();
148
149         cacao_shutdown(par1);
150 }
151
152
153 /*
154  * Class:     java/lang/Runtime
155  * Method:    freeMemory
156  * Signature: ()J
157  */
158 JNIEXPORT s8 JNICALL Java_java_lang_VMRuntime_freeMemory(JNIEnv *env, jclass clazz)
159 {
160         return gc_get_free_bytes();
161 }
162
163
164 /*
165  * Class:     java/lang/Runtime
166  * Method:    gc
167  * Signature: ()V
168  */
169 JNIEXPORT void JNICALL Java_java_lang_VMRuntime_gc(JNIEnv *env, jclass clazz)
170 {
171         gc_call();
172 }
173
174
175 /*
176  * Class:     java/lang/Runtime
177  * Method:    runFinalization
178  * Signature: ()V
179  */
180 JNIEXPORT void JNICALL Java_java_lang_VMRuntime_runFinalization(JNIEnv *env, jclass clazz)
181 {
182         gc_invoke_finalizers();
183 }
184
185
186 /*
187  * Class:     java/lang/Runtime
188  * Method:    runFinalizersOnExit
189  * Signature: (Z)V
190  */
191 JNIEXPORT void JNICALL Java_java_lang_VMRuntime_runFinalizersOnExit(JNIEnv *env, jclass clazz, s4 value)
192 {
193 #ifdef __GNUC__
194 #warning threading
195 #endif
196         finalizeOnExit = value;
197 }
198
199
200 /*
201  * Class:     java/lang/Runtime
202  * Method:    runFinalizationsForExit
203  * Signature: ()V
204  */
205 JNIEXPORT void JNICALL Java_java_lang_VMRuntime_runFinalizationForExit(JNIEnv *env, jclass clazz)
206 {
207 /*      if (finalizeOnExit) { */
208 /*              gc_call(); */
209         /* gc_finalize_all(); */
210 /*      } */
211 /*      log_text("Java_java_lang_VMRuntime_runFinalizationForExit called"); */
212         /*gc_finalize_all();*/
213         /*gc_invoke_finalizers();*/
214         /*gc_call();*/
215 }
216
217
218 /*
219  * Class:     java/lang/Runtime
220  * Method:    totalMemory
221  * Signature: ()J
222  */
223 JNIEXPORT s8 JNICALL Java_java_lang_VMRuntime_totalMemory(JNIEnv *env, jclass clazz)
224 {
225         return gc_get_heap_size();
226 }
227
228
229 /*
230  * Class:     java/lang/Runtime
231  * Method:    traceInstructions
232  * Signature: (Z)V
233  */
234 JNIEXPORT void JNICALL Java_java_lang_VMRuntime_traceInstructions(JNIEnv *env, jclass clazz, s4 par1)
235 {
236         /* not supported */
237 }
238
239
240 /*
241  * Class:     java/lang/Runtime
242  * Method:    traceMethodCalls
243  * Signature: (Z)V
244  */
245 JNIEXPORT void JNICALL Java_java_lang_VMRuntime_traceMethodCalls(JNIEnv *env, jclass clazz, s4 par1)
246 {
247         /* not supported */
248 }
249
250
251 /*
252  * Class:     java_lang_Runtime
253  * Method:    availableProcessors
254  * Signature: ()I
255  */
256 JNIEXPORT s4 JNICALL Java_java_lang_VMRuntime_availableProcessors(JNIEnv *env, jclass clazz)
257 {
258 #if defined(_SC_NPROC_ONLN)
259         return (s4) sysconf(_SC_NPROC_ONLN);
260
261 #elif defined(_SC_NPROCESSORS_ONLN)
262         return (s4) sysconf(_SC_NPROCESSORS_ONLN);
263
264 #elif defined(__DARWIN__)
265         /* this should work in BSD */
266         /*
267         int ncpu, mib[2], rc;
268         size_t len;
269
270         mib[0] = CTL_HW;
271         mib[1] = HW_NCPU;
272         len = sizeof(ncpu);
273         rc = sysctl(mib, 2, &ncpu, &len, NULL, 0);
274
275         return (s4) ncpu;
276         */
277
278         host_basic_info_data_t hinfo;
279         mach_msg_type_number_t hinfo_count = HOST_BASIC_INFO_COUNT;
280         kern_return_t rc;
281
282         rc = host_info(mach_host_self(), HOST_BASIC_INFO,
283                                    (host_info_t) &hinfo, &hinfo_count);
284  
285         if (rc != KERN_SUCCESS) {
286                 return -1;
287         }
288
289     return (s4) hinfo.avail_cpus;
290
291 #else
292         return 1;
293 #endif
294 }
295
296
297 /*
298  * Class:     java_lang_Runtime
299  * Method:    nativeLoad
300  * Signature: (Ljava/lang/String;)I
301  */
302 JNIEXPORT s4 JNICALL Java_java_lang_VMRuntime_nativeLoad(JNIEnv *env, jclass clazz, java_lang_String *par1)
303 {
304         int retVal=0;
305
306 #ifdef JOWENN_DEBUG
307         char *buffer;
308         int buffer_len;
309 #endif
310         utf *data;
311
312 #ifdef JOWENN_DEBUG
313         log_text("Java_java_lang_VMRuntime_nativeLoad");
314 #endif
315
316         data = javastring_toutf(par1, 0);
317         
318         if (!data) {
319                 log_text("nativeLoad: Error: empty string");
320                 return 1;
321         }
322         
323 #if JOWENN_DEBUG        
324         buffer_len = utf_strlen(data) + 40;
325
326         buffer = MNEW(char, buffer_len);
327         strcpy(buffer, "Java_java_lang_VMRuntime_nativeLoad:");
328         utf_sprint(buffer + strlen((char *) data), data);
329         log_text(buffer);       
330         
331   
332         MFREE(buffer, char, buffer_len);
333 #endif
334
335 #ifndef STATIC_CLASSPATH
336         /*here it could be interesting to store the references in a list eg for nicely cleaning up or for certain platforms*/
337         if (dlopen(data->text,RTLD_NOW | RTLD_GLOBAL)) {
338                 /*log_text("LIBLOADED");*/
339                 retVal=1;
340         }
341 #else
342         retVal=1;
343 #endif
344
345         return retVal;
346 }
347
348
349 /*
350  * Class:     java/lang/VMRuntime
351  * Method:    nativeGetLibname
352  * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
353  */
354 JNIEXPORT java_lang_String* JNICALL Java_java_lang_VMRuntime_nativeGetLibname(JNIEnv *env, jclass clazz, java_lang_String *pathname, java_lang_String *libname)
355 {
356         char *buffer;
357         int buffer_len;
358         utf *u;
359         java_lang_String *s;
360
361         if (!libname) {
362                 *exceptionptr = new_nullpointerexception();
363                 return NULL;
364         }
365
366         u = javastring_toutf(libname, 0);
367         
368         if (!u) {
369                 log_text("nativeGetLibName: Error: empty string");
370                 return 0;;
371         }
372         
373         buffer_len = utf_strlen(u) + 6 /*lib .so */ +1 /*0*/;
374         buffer = MNEW(char, buffer_len);
375
376         sprintf(buffer, "lib");
377         utf_sprint(buffer + 3, u);
378         strcat(buffer, ".so");
379
380 #ifdef JOWENN_DEBUG
381         log_text("nativeGetLibName:");
382         log_text(buffer);
383 #endif
384         
385         s = javastring_new_char(buffer);        
386
387         MFREE(buffer, char, buffer_len);
388
389         return s;
390 }
391
392
393 /*
394  * Class:     java_lang_VMRuntime
395  * Method:    insertSystemProperties
396  * Signature: (Ljava/util/Properties;)V
397  */
398 JNIEXPORT void JNICALL Java_java_lang_VMRuntime_insertSystemProperties(JNIEnv *env, jclass clazz, java_util_Properties *p)
399 {
400
401 #define BUFFERSIZE 200
402         methodinfo *m;
403         char cwd[BUFFERSIZE];
404         char *java_home;
405         char *user;
406         char *home;
407         struct utsname utsnamebuf;
408 #if !defined(STATIC_CLASSPATH)
409         char *libpath;
410         s4    libpathlen;
411 #endif
412
413         if (!p) {
414                 *exceptionptr = new_nullpointerexception();
415                 return;
416         }
417
418         /* get properties from system */
419
420         (void) getcwd(cwd, BUFFERSIZE);
421         java_home = getenv("JAVA_HOME");
422         user = getenv("USER");
423         home = getenv("HOME");
424         uname(&utsnamebuf);
425
426         /* search for method to add properties */
427
428         m = class_resolveclassmethod(p->header.vftbl->class,
429                                                                  utf_new_char("put"),
430                                                                  utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
431                                                                  clazz,
432                                                                  true);
433
434         if (!m)
435                 return;
436
437         insert_property(m, p, "java.version", VERSION);
438         insert_property(m, p, "java.vendor", "CACAO Team");
439         insert_property(m, p, "java.vendor.url", "http://www.complang.tuwien.ac.at/java/cacao/");
440         insert_property(m, p, "java.home", java_home ? java_home : "null");
441         insert_property(m, p, "java.vm.specification.version", "1.0");
442         insert_property(m, p, "java.vm.specification.vendor", "Sun Microsystems Inc.");
443         insert_property(m, p, "java.vm.specification.name", "Java Virtual Machine Specification");
444         insert_property(m, p, "java.vm.version", VERSION);
445         insert_property(m, p, "java.vm.vendor", "CACAO Team");
446         insert_property(m, p, "java.vm.name", "CACAO");
447         insert_property(m, p, "java.specification.version", "1.4");
448         insert_property(m, p, "java.specification.vendor", "Sun Microsystems Inc.");
449         insert_property(m, p, "java.specification.name", "Java Platform API Specification");
450         insert_property(m, p, "java.class.version", "48.0");
451         insert_property(m, p, "java.class.path", classpath);
452
453 #if defined(STATIC_CLASSPATH)
454         insert_property(m, p, "java.library.path" , ".");
455 #else
456         libpathlen = strlen(INSTALL_PREFIX) + strlen(CACAO_LIBRARY_PATH) + 1;
457
458         if (getenv("CACAO_LIB_OVERRIDE"))
459                 libpathlen += strlen(getenv("CACAO_LIB_OVERRIDE")) + 1;
460
461         if (getenv("LD_LIBRARY_PATH"))
462                 libpathlen += strlen(getenv("LD_LIBRARY_PATH")) + 1;
463
464         libpath = MNEW(char, libpathlen);
465
466         if (getenv("CACAO_LIB_OVERRIDE")) {
467                 strcat(libpath, getenv("CACAO_LIB_OVERRIDE"));
468                 strcat(libpath, ":");
469         }
470
471         strcat(libpath, INSTALL_PREFIX);
472         strcat(libpath, CACAO_LIBRARY_PATH);
473
474         if (getenv("LD_LIBRARY_PATH")) {
475                 strcat(libpath, ":");
476                 strcat(libpath, getenv("LD_LIBRARY_PATH"));
477         }
478         insert_property(m, p, "java.library.path", libpath);
479
480         MFREE(libpath, char, libpathlen);
481 #endif
482
483         insert_property(m, p, "java.io.tmpdir", "/tmp");
484         insert_property(m, p, "java.compiler", "cacao.jit");
485         insert_property(m, p, "java.ext.dirs", "");
486         insert_property(m, p, "os.name", utsnamebuf.sysname);
487         insert_property(m, p, "os.arch", utsnamebuf.machine);
488         insert_property(m, p, "os.version", utsnamebuf.release);
489         insert_property(m, p, "file.separator", "/");
490         /* insert_property(m, p, "file.encoding", "null"); -- this must be set properly */
491         insert_property(m, p, "path.separator", ":");
492         insert_property(m, p, "line.separator", "\n");
493         insert_property(m, p, "user.name", user ? user : "null");
494         insert_property(m, p, "user.home", home ? home : "null");
495         insert_property(m, p, "user.dir", cwd ? cwd : "null");
496
497 #if 0
498         /* how do we get them? */
499         { "user.language", "en" },
500         { "user.region", "US" },
501         { "user.country", "US" },
502         { "user.timezone", "Europe/Vienna" },
503
504         /* XXX do we need this one? */
505         { "java.protocol.handler.pkgs", "gnu.java.net.protocol"}
506 #endif
507         insert_property(m, p, "java.protocol.handler.pkgs", "gnu.java.net.protocol");
508
509         /* insert properties defined on commandline */
510
511         while (properties) {
512                 property *tp;
513
514                 insert_property(m, p, properties->key, properties->value);
515
516                 tp = properties;
517                 properties = properties->next;
518                 FREE(tp, property);
519         }
520
521         return;
522 }
523
524
525 /*
526  * Class:     java_lang_VMRuntime
527  * Method:    maxMemory
528  * Signature: ()J
529  */
530 JNIEXPORT s8 JNICALL Java_java_lang_VMRuntime_maxMemory(JNIEnv *env, jclass clazz)
531 {
532         return gc_get_max_heap_size();
533 }
534
535
536 /*
537  * These are local overrides for various environment variables in Emacs.
538  * Please do not remove this and leave it at the end of the file, where
539  * Emacs will automagically detect them.
540  * ---------------------------------------------------------------------
541  * Local variables:
542  * mode: c
543  * indent-tabs-mode: t
544  * c-basic-offset: 4
545  * tab-width: 4
546  * End:
547  */