5cf652e482b9c9329bca6e1c2696a7647710f209
[cacao.git] / src / native / vm / VMRuntime.c
1 /* native/vm/VMRuntime.c - java/lang/VMRuntime
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
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 1621 2004-11-30 13:06:55Z 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         char *buffer;
307         int buffer_len;
308         utf *data;
309
310 #ifdef JOWENN_DEBUG
311         log_text("Java_java_lang_VMRuntime_nativeLoad");
312 #endif
313
314         data = javastring_toutf(par1, 0);
315         
316         if (!data) {
317                 log_text("nativeLoad: Error: empty string");
318                 return 1;
319         }
320         
321 #if JOWENN_DEBUG        
322         buffer_len = utf_strlen(data) + 40;
323
324         buffer = MNEW(char, buffer_len);
325         strcpy(buffer, "Java_java_lang_VMRuntime_nativeLoad:");
326         utf_sprint(buffer + strlen((char *) data), data);
327         log_text(buffer);       
328         
329   
330         MFREE(buffer, char, buffer_len);
331 #endif
332
333 #ifndef STATIC_CLASSPATH
334         /*here it could be interesting to store the references in a list eg for nicely cleaning up or for certain platforms*/
335         if (dlopen(data->text,RTLD_NOW | RTLD_GLOBAL)) {
336                 log_text("LIBLOADED");
337                 retVal=1;
338         }
339 #else
340         retVal=1;
341 #endif
342
343         return retVal;
344 }
345
346
347 /*
348  * Class:     java/lang/VMRuntime
349  * Method:    nativeGetLibname
350  * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
351  */
352 JNIEXPORT java_lang_String* JNICALL Java_java_lang_VMRuntime_nativeGetLibname(JNIEnv *env, jclass clazz, java_lang_String *pathname, java_lang_String *libname)
353 {
354         char *buffer;
355         int buffer_len;
356         utf *u;
357         java_lang_String *s;
358
359         if (!libname) {
360                 *exceptionptr = new_nullpointerexception();
361                 return NULL;
362         }
363
364         u = javastring_toutf(libname, 0);
365         
366         if (!u) {
367                 log_text("nativeGetLibName: Error: empty string");
368                 return 0;;
369         }
370         
371         buffer_len = utf_strlen(u) + 6 /*lib .so */ +1 /*0*/;
372         buffer = MNEW(char, buffer_len);
373
374         sprintf(buffer, "lib");
375         utf_sprint(buffer + 3, u);
376         strcat(buffer, ".so");
377
378 #ifdef JOWENN_DEBUG
379         log_text("nativeGetLibName:");
380         log_text(buffer);
381 #endif
382         
383         s = javastring_new_char(buffer);        
384
385         MFREE(buffer, char, buffer_len);
386
387         return s;
388 }
389
390
391 /*
392  * Class:     java_lang_VMRuntime
393  * Method:    insertSystemProperties
394  * Signature: (Ljava/util/Properties;)V
395  */
396 JNIEXPORT void JNICALL Java_java_lang_VMRuntime_insertSystemProperties(JNIEnv *env, jclass clazz, java_util_Properties *p)
397 {
398
399 #define BUFFERSIZE 200
400         methodinfo *m;
401         char cwd[BUFFERSIZE];
402         char *java_home;
403         char *user;
404         char *home;
405         struct utsname utsnamebuf;
406
407         if (!p) {
408                 *exceptionptr = new_exception(string_java_lang_NullPointerException);
409                 return;
410         }
411
412         /* get properties from system */
413
414         (void) getcwd(cwd, BUFFERSIZE);
415         java_home = getenv("JAVA_HOME");
416         user = getenv("USER");
417         home = getenv("HOME");
418         uname(&utsnamebuf);
419
420         /* search for method to add properties */
421
422         m = class_resolveclassmethod(p->header.vftbl->class,
423                                                                  utf_new_char("put"),
424                                                                  utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
425                                                                  clazz,
426                                                                  true);
427
428         if (!m)
429                 return;
430
431         insert_property(m, p, "java.version", VERSION);
432         insert_property(m, p, "java.vendor", "CACAO Team");
433         insert_property(m, p, "java.vendor.url", "http://www.complang.tuwien.ac.at/java/cacao/");
434         insert_property(m, p, "java.home", java_home ? java_home : "null");
435         insert_property(m, p, "java.vm.specification.version", "1.0");
436         insert_property(m, p, "java.vm.specification.vendor", "Sun Microsystems Inc.");
437         insert_property(m, p, "java.vm.specification.name", "Java Virtual Machine Specification");
438         insert_property(m, p, "java.vm.version", VERSION);
439         insert_property(m, p, "java.vm.vendor", "CACAO Team");
440         insert_property(m, p, "java.vm.name", "CACAO");
441         insert_property(m, p, "java.specification.version", "1.4");
442         insert_property(m, p, "java.specification.vendor", "Sun Microsystems Inc.");
443         insert_property(m, p, "java.specification.name", "Java Platform API Specification");
444         insert_property(m, p, "java.class.version", "48.0");
445         insert_property(m, p, "java.class.path", classpath);
446 #if defined(STATIC_CLASSPATH)
447         insert_property(m, p, "java.library.path" , ".");
448 #else
449         insert_property(m, p, "java.library.path" , getenv("LD_LIBRARY_PATH"));
450 #endif
451         insert_property(m, p, "java.io.tmpdir", "/tmp");
452         insert_property(m, p, "java.compiler", "cacao.jit");
453         insert_property(m, p, "java.ext.dirs", "");
454         insert_property(m, p, "os.name", utsnamebuf.sysname);
455         insert_property(m, p, "os.arch", utsnamebuf.machine);
456         insert_property(m, p, "os.version", utsnamebuf.release);
457         insert_property(m, p, "file.separator", "/");
458         /* insert_property(m, p, "file.encoding", "null"); -- this must be set properly */
459         insert_property(m, p, "path.separator", ":");
460         insert_property(m, p, "line.separator", "\n");
461         insert_property(m, p, "user.name", user ? user : "null");
462         insert_property(m, p, "user.home", home ? home : "null");
463         insert_property(m, p, "user.dir", cwd ? cwd : "null");
464
465 #if 0
466         /* how do we get them? */
467         { "user.language", "en" },
468         { "user.region", "US" },
469         { "user.country", "US" },
470         { "user.timezone", "Europe/Vienna" },
471
472         /* XXX do we need this one? */
473         { "java.protocol.handler.pkgs", "gnu.java.net.protocol"}
474 #endif
475         insert_property(m,p,"java.protocol.handler.pkgs","gnu.java.net.protocol");
476
477         /* insert properties defined on commandline */
478
479         while (properties) {
480                 property *tp;
481
482                 insert_property(m, p, properties->key, properties->value);
483
484                 tp = properties;
485                 properties = properties->next;
486                 FREE(tp, property);
487         }
488
489         return;
490 }
491
492
493 /*
494  * Class:     java_lang_VMRuntime
495  * Method:    maxMemory
496  * Signature: ()J
497  */
498 JNIEXPORT s8 JNICALL Java_java_lang_VMRuntime_maxMemory(JNIEnv *env, jclass clazz)
499 {
500         return gc_get_max_heap_size();
501 }
502
503
504 /*
505  * These are local overrides for various environment variables in Emacs.
506  * Please do not remove this and leave it at the end of the file, where
507  * Emacs will automagically detect them.
508  * ---------------------------------------------------------------------
509  * Local variables:
510  * mode: c
511  * indent-tabs-mode: t
512  * c-basic-offset: 4
513  * tab-width: 4
514  * End:
515  */