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