native functions, getClassContext, currentClassLoader implementation (with stack...
[cacao.git] / src / native / vm / VMRuntime.c
1 /* nat/Runtime.c - java/lang/Runtime
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
31    $Id: VMRuntime.c 930 2004-03-02 21:18:23Z jowenn $
32
33 */
34
35
36 #include <string.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <sys/utsname.h>
40 #include "jni.h"
41 #include "builtin.h"
42 #include "loader.h"
43 #include "native.h"
44 #include "tables.h"
45 #include "asmpart.h"
46 #include "mm/boehm.h"
47 #include "toolbox/loging.h"
48 #include "toolbox/memory.h"
49 #include "java_io_File.h"
50 #include "java_lang_String.h"
51 #include "java_lang_Process.h"
52 #include "java_util_Properties.h"    /* needed for java_lang_Runtime.h */
53 #include "java_lang_Runtime.h"
54
55
56 #define JOWENN_DEBUG
57
58
59 #define MAXPROPS 100
60 static int activeprops = 19;  
61    
62 static char *proplist[MAXPROPS][2] = {
63         { "java.class.path", NULL },
64         { "java.home", NULL },
65         { "user.home", NULL },  
66         { "user.name", NULL },
67         { "user.dir",  NULL },
68                                 
69         { "os.arch", NULL },
70         { "os.name", NULL },
71         { "os.version", NULL },
72                                          
73         { "java.class.version", "45.3" },
74         { "java.version", PACKAGE":"VERSION },
75         { "java.vendor", "CACAO Team" },
76         { "java.vendor.url", "http://www.complang.tuwien.ac.at/java/cacao/" },
77         { "java.vm.name", "CACAO"}, 
78         { "java.tmpdir", "/tmp/"},
79         { "java.io.tmpdir", "/tmp/"},
80
81         { "path.separator", ":" },
82         { "file.separator", "/" },
83         { "line.separator", "\n" },
84         { "java.protocol.handler.pkgs", "gnu.java.net.protocol"}
85 };
86
87 void attach_property(char *name, char *value)
88 {
89         if (activeprops >= MAXPROPS) panic("Too many properties defined");
90         proplist[activeprops][0] = name;
91         proplist[activeprops][1] = value;
92         activeprops++;
93 }
94 /*
95  * Class:     java_lang_Runtime
96  * Method:    execInternal
97  * Signature: ([Ljava/lang/String;[Ljava/lang/String;Ljava/io/File;)Ljava/lang/Process;
98  */
99 JNIEXPORT java_lang_Process* JNICALL Java_java_lang_Runtime_execInternal(JNIEnv *env, java_lang_Runtime *this, java_objectarray *cmd, java_objectarray *shellenv, java_io_File *workingdir)
100 {
101         log_text("Java_java_lang_Runtime_execInternal called");
102
103         return NULL;
104 }
105
106
107 /*
108  * Class:     java/lang/Runtime
109  * Method:    exitInternal
110  * Signature: (I)V
111  */
112 JNIEXPORT void JNICALL Java_java_lang_Runtime_exitInternal(JNIEnv *env, java_lang_Runtime *this, s4 par1)
113 {
114         cacao_shutdown(par1);
115 }
116
117
118 /*
119  * Class:     java/lang/Runtime
120  * Method:    freeMemory
121  * Signature: ()J
122  */
123 JNIEXPORT s8 JNICALL Java_java_lang_Runtime_freeMemory(JNIEnv *env, java_lang_Runtime *this)
124 {
125         log_text ("java_lang_Runtime_freeMemory called");
126
127         return builtin_i2l(0);
128 }
129
130
131 /*
132  * Class:     java/lang/Runtime
133  * Method:    gc
134  * Signature: ()V
135  */
136 JNIEXPORT void JNICALL Java_java_lang_Runtime_gc(JNIEnv *env, java_lang_Runtime *this)
137 {
138         gc_call();
139 }
140
141
142 /*
143  * Class:     java/lang/Runtime
144  * Method:    runFinalization
145  * Signature: ()V
146  */
147 JNIEXPORT void JNICALL Java_java_lang_Runtime_runFinalization(JNIEnv *env, java_lang_Runtime *this)
148 {
149         /* empty */
150 }
151
152
153 /*
154  * Class:     java/lang/Runtime
155  * Method:    runFinalizersOnExit
156  * Signature: (Z)V
157  */
158 JNIEXPORT void JNICALL Java_java_lang_Runtime_runFinalizersOnExitInternal(JNIEnv *env, jclass clazz, s4 par1)
159 {
160         log_text("Java_java_lang_Runtime_runFinalizersOnExit0 called");
161 }
162
163
164 /*
165  * Class:     java/lang/Runtime
166  * Method:    totalMemory
167  * Signature: ()J
168  */
169 JNIEXPORT s8 JNICALL Java_java_lang_Runtime_totalMemory(JNIEnv *env, java_lang_Runtime *this)
170 {
171         log_text ("java_lang_Runtime_totalMemory called");
172
173         return builtin_i2l(0);
174 }
175
176
177 /*
178  * Class:     java/lang/Runtime
179  * Method:    traceInstructions
180  * Signature: (Z)V
181  */
182 JNIEXPORT void JNICALL Java_java_lang_Runtime_traceInstructions(JNIEnv *env, java_lang_Runtime *this, s4 par1)
183 {
184         log_text("Java_java_lang_Runtime_traceInstructions called");
185 }
186
187
188 /*
189  * Class:     java/lang/Runtime
190  * Method:    traceMethodCalls
191  * Signature: (Z)V
192  */
193 JNIEXPORT void JNICALL Java_java_lang_Runtime_traceMethodCalls(JNIEnv *env, java_lang_Runtime *this, s4 par1)
194 {
195         log_text("Java_java_lang_Runtime_traceMethodCalls called");
196 }
197
198 #define CPULINELEN 100
199
200 #if defined(__ALPHA__)
201 s4 getCPUCount() {
202         FILE *cpuinfo;
203         char line[CPULINELEN];
204         cpuinfo=fopen("/proc/cpuinfo","r");
205         if (!cpuinfo) {
206                 if (verbose) log_text("/proc/cpuinfo not accessible, assuming 1 available processor");
207                 return 1; /* we have at least one cpu ;) */
208         }
209         while (fgets(line,CPULINELEN,cpuinfo)!=EOF) {
210                 if (strncmp("cpus detected",line,13)==0) {
211                         s4 cpucnt=0;
212                         char *p;
213                         char *ep;
214                         fclose(cpuinfo);
215                         for (p=&line[strlen(line)-2];(*p>='0') && (*p<='9');p--);
216                         cpucnt=strtol(p,&ep,10);
217                         if (p==ep) return 1;
218                         
219                         if (verbose) log_text("returning value retrieved by parsing cpus detected line");
220                         return cpucnt;
221                 }
222         }
223         fclose (cpuinfo);
224         if (verbose) log_text("/proc/cpuinfo did not contain a cpus detected line, assuming 1 available processor");
225         return 1; /* we have at least one cpu ;) */
226 }
227 #endif
228
229 #if (defined(__I386__) || defined(__X86_64__))
230 s4 getCPUCount() {
231         FILE *cpuinfo;
232         char line[CPULINELEN];
233         int cnt=0;
234         cpuinfo=fopen("/proc/cpuinfo","r");
235         if (!cpuinfo) {
236                 if (verbose) log_text("/proc/cpuinfo not accessible, assuming 1 available processor");
237                 return 1; /* we have at least one cpu ;) */
238         }
239
240         while (fgets(line,CPULINELEN,cpuinfo)!=EOF) {
241                 if (strncmp("processor",line,9)==0) {
242                         cnt++;
243                 }
244         }
245
246         fclose(cpuinfo);
247
248         if (cnt==0) {
249                 if (verbose) log_text("/proc/cpuinfo did not contain processor, assuming 1 available processor");
250                 return 1; /* we have at least one cpu ;) */
251         }
252
253         return cnt;
254 }
255 #endif
256
257 /*
258  * Class:     java_lang_Runtime
259  * Method:    availableProcessors
260  * Signature: ()I
261  */
262 JNIEXPORT s4 JNICALL Java_java_lang_Runtime_availableProcessors(JNIEnv *env, java_lang_Runtime *this)
263 {
264 /*      log_text("Java_java_lang_Runtime_availableProcessors called, returning hardcoded 1"); */
265 /* the classpath documentations says, that the number of available cpu's for the vm could vary. No idea how to really determine 
266 that. Let's try to find out the total number of cpus in the system for now (jowenn) */
267
268 /* If this gets more complex, it should be considered moving this into the jit/ subdirectory (jowenn)*/
269 #if  (!defined(__LINUX__))
270         return 1;
271 #else
272 #if defined(__ALPHA__)
273         return getCPUCount();
274 #else
275 #if (defined(__I386__) || defined(__X86_64__))
276         return getCPUCount();
277 #else
278         return 1;
279 #endif
280 #endif
281 #endif
282 }
283
284
285 /*
286  * Class:     java_lang_Runtime
287  * Method:    nativeLoad
288  * Signature: (Ljava/lang/String;)I
289  */
290 JNIEXPORT s4 JNICALL Java_java_lang_Runtime_nativeLoad(JNIEnv *env, java_lang_Runtime *this, java_lang_String *par1)
291 {
292 #ifdef JOWENN_DEBUG     
293         char *buffer;
294         int buffer_len;
295         utf *data;
296         
297         data = javastring_toutf(par1, 0);
298         
299         if (!data) {
300                 log_text("nativeLoad: Error: empty string");
301                 return 1;
302         }
303         
304         buffer_len = utf_strlen(data) + 40;
305
306                 
307         buffer = MNEW(char, buffer_len);
308
309         strcpy(buffer, "Java_java_lang_Runtime_nativeLoad:");
310         utf_sprint(buffer + strlen((char *) data), data);
311         log_text(buffer);       
312
313         MFREE(buffer, char, buffer_len);
314 #endif
315         log_text("Java_java_lang_Runtime_nativeLoad");
316
317         return 1;
318 }
319
320
321 /*
322  * Class:     java_lang_Runtime
323  * Method:    nativeGetLibname
324  * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
325  */
326 JNIEXPORT java_lang_String* JNICALL Java_java_lang_Runtime_nativeGetLibname(JNIEnv *env, jclass clazz, java_lang_String *par1, java_lang_String *par2)
327 {
328 #ifdef JOWENN_DEBUG     
329         char *buffer;
330         int buffer_len;
331         utf *data;
332         
333         data = javastring_toutf(par2, 0);
334         
335         if (!data) {
336                 log_text("nativeGetLibName: Error: empty string");
337                 return 0;;
338         }
339         
340         buffer_len = utf_strlen(data) + 40;
341         
342         buffer = MNEW(char, buffer_len);
343
344         strcpy(buffer, "Java_java_lang_Runtime_nativeGetLibname:");
345         utf_sprint(buffer + strlen((char *) data), data);
346         log_text(buffer);       
347
348         MFREE(buffer, char, buffer_len);
349 #endif
350         log_text("Java_java_lang_Runtime_nativeGetLibname");
351
352         return 0;
353 }
354
355
356 /*
357  * Class:     java_lang_Runtime
358  * Method:    insertSystemProperties
359  * Signature: (Ljava/util/Properties;)V
360  */
361 JNIEXPORT void JNICALL Java_java_lang_Runtime_insertSystemProperties(JNIEnv *env, jclass clazz, java_util_Properties *p)
362 {
363
364 #define BUFFERSIZE 200
365         u4 i;
366         methodinfo *m;
367         char buffer[BUFFERSIZE];
368         struct utsname utsnamebuf;
369
370         proplist[0][1] = classpath;
371         proplist[1][1] = getenv("JAVA_HOME");
372         proplist[2][1] = getenv("HOME");
373         proplist[3][1] = getenv("USER");
374         proplist[4][1] = getcwd(buffer, BUFFERSIZE);
375
376         /* get properties from system */
377         uname(&utsnamebuf);
378         proplist[5][1] = utsnamebuf.machine;
379         proplist[6][1] = utsnamebuf.sysname;
380         proplist[7][1] = utsnamebuf.release;
381
382         if (!p)
383                 panic("Java_java_lang_Runtime_insertSystemProperties called with NULL-Argument");
384
385         /* search for method to add properties */
386         m = class_resolvemethod(p->header.vftbl->class,
387                                                         utf_new_char("put"),
388                                                         utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")
389                                                         );
390
391         if (!m)
392                 panic("Can not find method 'put' for class Properties");
393
394         /* add the properties */
395         for (i = 0; i < activeprops; i++) {
396
397                 if (proplist[i][1] == NULL) proplist[i][1] = "";
398
399                 asm_calljavafunction(m,
400                                                          p,
401                                                          javastring_new_char(proplist[i][0]),
402                                                          javastring_new_char(proplist[i][1]),
403                                                          NULL
404                                                          );
405         }
406
407         return;
408 }
409
410
411 /*
412  * Class:     java_lang_Runtime
413  * Method:    maxMemory
414  * Signature: ()J
415  */
416 JNIEXPORT s8 JNICALL Java_java_lang_Runtime_maxMemory(JNIEnv *env, java_lang_Runtime *this)
417 {
418         log_text("Java_java_lang_Runtime_maxMemory");
419
420         return 0;
421 }
422
423
424 /*
425  * These are local overrides for various environment variables in Emacs.
426  * Please do not remove this and leave it at the end of the file, where
427  * Emacs will automagically detect them.
428  * ---------------------------------------------------------------------
429  * Local variables:
430  * mode: c
431  * indent-tabs-mode: t
432  * c-basic-offset: 4
433  * tab-width: 4
434  * End:
435  */