* src/vm/vm.c (vm_create): make agentlib/agentpath work
[cacao.git] / src / cacao / cacao.c
1 /* src/cacao/cacao.c - contains main() of cacao
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Reinhard Grafl
28
29    Changes: Andi Krall
30             Mark Probst
31             Philipp Tomsich
32             Christian Thalinger
33
34    $Id: cacao.c 4892 2006-05-06 18:29:55Z motse $
35
36 */
37
38
39 #include "config.h"
40
41 #include <assert.h>
42 #include <stdlib.h>
43 #include <string.h>
44
45 #include "vm/types.h"
46
47 #include "native/jni.h"
48 #include "native/include/java_lang_String.h"
49
50 #if defined(ENABLE_JVMTI)
51 #include "native/jvmti/jvmti.h"
52 #include "native/jvmti/cacaodbg.h"
53
54 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
55 #include <pthread.h>
56 #endif
57 #endif
58
59 #include "toolbox/logging.h"
60 #include "vm/classcache.h"
61 #include "vm/exceptions.h"
62 #include "vm/global.h"
63 #include "vm/loader.h"
64 #include "vm/options.h"
65 #include "vm/statistics.h"
66 #include "vm/stringlocal.h"
67 #include "vm/suck.h"
68 #include "vm/vm.h"
69 #include "vm/jit/asmpart.h"
70 #include "vm/jit/jit.h"
71
72 #ifdef TYPEINFO_DEBUG_TEST
73 #include "vm/jit/verify/typeinfo.h"
74 #endif
75
76 #ifdef TYPECHECK_STATISTICS
77 void typecheck_print_statistics(FILE *file);
78 #endif
79
80 /* getmainclassfromjar *********************************************************
81
82    Gets the name of the main class form a JAR's manifest file.
83
84 *******************************************************************************/
85
86 static char *getmainclassnamefromjar(char *mainstring)
87 {
88         classinfo         *c;
89         java_objectheader *o;
90         methodinfo        *m;
91         java_lang_String  *s;
92
93         c = load_class_from_sysloader(utf_new_char("java/util/jar/JarFile"));
94
95         if (!c)
96                 throw_main_exception_exit();
97         
98         /* create JarFile object */
99
100         o = builtin_new(c);
101
102         if (!o)
103                 throw_main_exception_exit();
104
105
106         m = class_resolveclassmethod(c,
107                                                                  utf_init, 
108                                                                  utf_java_lang_String__void,
109                                                                  class_java_lang_Object,
110                                                                  true);
111
112         if (!m)
113                 throw_main_exception_exit();
114
115         s = javastring_new_from_ascii(mainstring);
116
117         (void) vm_call_method(m, o, s);
118
119         if (*exceptionptr)
120                 throw_main_exception_exit();
121
122         /* get manifest object */
123
124         m = class_resolveclassmethod(c,
125                                                                  utf_new_char("getManifest"), 
126                                                                  utf_new_char("()Ljava/util/jar/Manifest;"),
127                                                                  class_java_lang_Object,
128                                                                  true);
129
130         if (!m)
131                 throw_main_exception_exit();
132
133         o = vm_call_method(m, o);
134
135         if (o == NULL) {
136                 fprintf(stderr, "Could not get manifest from %s (invalid or corrupt jarfile?)\n", mainstring);
137                 vm_exit(1);
138         }
139
140
141         /* get Main Attributes */
142
143         m = class_resolveclassmethod(o->vftbl->class,
144                                                                  utf_new_char("getMainAttributes"), 
145                                                                  utf_new_char("()Ljava/util/jar/Attributes;"),
146                                                                  class_java_lang_Object,
147                                                                  true);
148
149         if (!m)
150                 throw_main_exception_exit();
151
152         o = vm_call_method(m, o);
153
154         if (o == NULL) {
155                 fprintf(stderr, "Could not get main attributes from %s (invalid or corrupt jarfile?)\n", mainstring);
156                 vm_exit(1);
157         }
158
159
160         /* get property Main-Class */
161
162         m = class_resolveclassmethod(o->vftbl->class,
163                                                                  utf_new_char("getValue"), 
164                                                                  utf_new_char("(Ljava/lang/String;)Ljava/lang/String;"),
165                                                                  class_java_lang_Object,
166                                                                  true);
167
168         if (!m)
169                 throw_main_exception_exit();
170
171         s = javastring_new_from_ascii("Main-Class");
172
173         o = vm_call_method(m, o, s);
174
175         if (!o)
176                 throw_main_exception_exit();
177
178         return javastring_tochar(o);
179 }
180
181 void exit_handler(void);
182
183
184 /* main ************************************************************************
185
186    The main program.
187    
188 *******************************************************************************/
189
190 int main(int argc, char **argv)
191 {
192 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
193         void *dummy;
194 #endif
195         s4 i;
196         
197         /* local variables ********************************************************/
198
199         JavaVMInitArgs *vm_args;
200         JavaVM         *jvm;                /* denotes a Java VM                  */
201
202 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
203         stackbottom = &dummy;
204 #endif
205
206         if (atexit(vm_exit_handler))
207                 throw_cacao_exception_exit(string_java_lang_InternalError,
208                                                                    "Unable to register exit_handler");
209
210
211         /**************************** Program start *****************************/
212
213         if (opt_verbose)
214                 log_text("CACAO started -------------------------------------------------------");
215
216         /* prepare the options */
217
218         vm_args = options_prepare(argc, argv);
219         
220         /* load and initialize a Java VM, return a JNI interface pointer in env */
221
222         JNI_CreateJavaVM(&jvm, (void **) &_Jv_env, vm_args);
223
224 #if defined(ENABLE_JVMTI)
225         pthread_mutex_init(&dbgcomlock,NULL);
226         set_jvmti_phase(JVMTI_PHASE_START);
227 #endif
228
229         /* do we have a main class? */
230
231         if (mainstring == NULL)
232                 usage();
233
234
235         /* start worker routines **************************************************/
236
237         if (opt_run == true) {
238                 utf              *mainutf;
239                 classinfo        *mainclass;
240                 methodinfo       *m;
241                 java_objectarray *oa; 
242                 s4                oalength;
243                 java_lang_String *s;
244                 s4                status;
245
246                 /* set return value to OK */
247
248                 status = 0;
249
250                 if (opt_jar == true) {
251                         /* open jar file with java.util.jar.JarFile */
252                         mainstring = getmainclassnamefromjar(mainstring);
253                 }
254
255                 /* load the main class */
256
257                 mainutf = utf_new_char(mainstring);
258
259                 if (!(mainclass = load_class_from_sysloader(mainutf)))
260                         throw_main_exception_exit();
261
262                 /* error loading class, clear exceptionptr for new exception */
263
264                 if (*exceptionptr || !mainclass) {
265 /*                      *exceptionptr = NULL; */
266
267 /*                      *exceptionptr = */
268 /*                              new_exception_message(string_java_lang_NoClassDefFoundError, */
269 /*                                                                        mainstring); */
270                         throw_main_exception_exit();
271                 }
272
273                 if (!link_class(mainclass))
274                         throw_main_exception_exit();
275                         
276                 /* find the `main' method of the main class */
277
278                 m = class_resolveclassmethod(mainclass,
279                                                                          utf_new_char("main"), 
280                                                                          utf_new_char("([Ljava/lang/String;)V"),
281                                                                          class_java_lang_Object,
282                                                                          false);
283
284                 if (*exceptionptr) {
285                         throw_main_exception_exit();
286                 }
287
288                 /* there is no main method or it isn't static */
289
290                 if (!m || !(m->flags & ACC_STATIC)) {
291                         *exceptionptr = NULL;
292
293                         *exceptionptr =
294                                 new_exception_message(string_java_lang_NoSuchMethodError,
295                                                                           "main");
296                         throw_main_exception_exit();
297                 }
298
299                 /* build argument array */
300
301                 oalength = vm_args->nOptions - opt_index;
302
303                 oa = builtin_anewarray(oalength, class_java_lang_String);
304
305                 for (i = 0; i < oalength; i++) {
306                         s = javastring_new(utf_new_char(vm_args->options[opt_index + i].optionString));
307                         oa->data[i] = (java_objectheader *) s;
308                 }
309
310 #ifdef TYPEINFO_DEBUG_TEST
311                 /* test the typeinfo system */
312                 typeinfo_test();
313 #endif
314                 /*class_showmethods(currentThread->group->header.vftbl->class); */
315
316 #if defined(ENABLE_JVMTI)
317                 /* start the jdwp listening */
318                 if (jdwp) {
319                         log_text("cacao vm - init VMjdwp");
320                         if (!VMjdwpInit()) exit(1);
321                         setup_jdwp_thread(transport);
322                         if (!suspend) {
323                                 fprintf(stderr,"suspend false -> continue debuggee\n");
324                         } else {
325                                 fprintf(stderr,"suspend true -> do no continue debuggee(todo)\n");
326                                 /* XXX todo*/
327                         }
328                 }
329
330                 set_jvmti_phase(JVMTI_PHASE_LIVE);
331
332                 log_text("debuggee: herewe go");
333 #endif
334
335                 (void) vm_call_method(m, NULL, oa);
336
337                 /* exception occurred? */
338
339                 if (*exceptionptr) {
340                         throw_main_exception();
341                         status = 1;
342                 }
343
344                 /* unload the JavaVM */
345
346                 vm_destroy(jvm);
347
348                 /* and exit */
349
350                 vm_exit(status);
351         }
352
353
354         /* If requested, compile all methods. *************************************/
355
356 #if !defined(NDEBUG)
357         if (compileall) {
358                 classinfo *c;
359                 methodinfo *m;
360                 u4 slot;
361                 s4 i;
362                 classcache_name_entry *nmen;
363                 classcache_class_entry *clsen;
364
365                 /* create all classes found in the bootclasspath */
366                 /* XXX currently only works with zip/jar's */
367
368                 loader_load_all_classes();
369
370                 /* link all classes */
371
372                 for (slot = 0; slot < hashtable_classcache.size; slot++) {
373                         nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot];
374
375                         for (; nmen; nmen = nmen->hashlink) {
376                                 /* iterate over all class entries */
377
378                                 for (clsen = nmen->classes; clsen; clsen = clsen->next) {
379                                         c = clsen->classobj;
380
381                                         if (!c)
382                                                 continue;
383
384                                         if (!(c->state & CLASS_LINKED)) {
385                                                 if (!link_class(c)) {
386                                                         fprintf(stderr, "Error linking: ");
387                                                         utf_fprint_printable_ascii_classname(stderr, c->name);
388                                                         fprintf(stderr, "\n");
389
390                                                         /* print out exception and cause */
391
392                                                         exceptions_print_exception(*exceptionptr);
393
394                                                         /* goto next class */
395
396                                                         continue;
397                                                 }
398                                         }
399
400                                         /* compile all class methods */
401
402                                         for (i = 0; i < c->methodscount; i++) {
403                                                 m = &(c->methods[i]);
404
405                                                 if (m->jcode) {
406                                                         if (!jit_compile(m)) {
407                                                                 fprintf(stderr, "Error compiling: ");
408                                                                 utf_fprint_printable_ascii_classname(stderr, c->name);
409                                                                 fprintf(stderr, ".");
410                                                                 utf_fprint_printable_ascii(stderr, m->name);
411                                                                 utf_fprint_printable_ascii(stderr, m->descriptor);
412                                                                 fprintf(stderr, "\n");
413
414                                                                 /* print out exception and cause */
415
416                                                                 exceptions_print_exception(*exceptionptr);
417                                                         }
418                                                 }
419                                         }
420                                 }
421                         }
422                 }
423         }
424 #endif /* !defined(NDEBUG) */
425
426
427         /* If requested, compile a specific method. *******************************/
428
429 #if !defined(NDEBUG)
430         if (opt_method != NULL) {
431                 methodinfo *m;
432
433                 /* create, load and link the main class */
434
435                 if (!(mainclass = load_class_bootstrap(utf_new_char(mainstring))))
436                         throw_main_exception_exit();
437
438                 if (!link_class(mainclass))
439                         throw_main_exception_exit();
440
441                 if (opt_signature != NULL) {
442                         m = class_resolveclassmethod(mainclass,
443                                                                                  utf_new_char(opt_method),
444                                                                                  utf_new_char(opt_signature),
445                                                                                  mainclass,
446                                                                                  false);
447                 } else {
448                         m = class_resolveclassmethod(mainclass,
449                                                                                  utf_new_char(opt_method),
450                                                                                  NULL,
451                                                                                  mainclass,
452                                                                                  false);
453                 }
454
455                 if (!m) {
456                         char message[MAXLOGTEXT];
457                         sprintf(message, "%s%s", opt_method,
458                                         opt_signature ? opt_signature : "");
459
460                         *exceptionptr =
461                                 new_exception_message(string_java_lang_NoSuchMethodException,
462                                                                           message);
463                                                                                  
464                         throw_main_exception_exit();
465                 }
466                 
467                 jit_compile(m);
468         }
469
470         vm_shutdown(0);
471 #endif /* !defined(NDEBUG) */
472
473         /* keep compiler happy */
474
475         return 0;
476 }
477
478
479 /*
480  * These are local overrides for various environment variables in Emacs.
481  * Please do not remove this and leave it at the end of the file, where
482  * Emacs will automagically detect them.
483  * ---------------------------------------------------------------------
484  * Local variables:
485  * mode: c
486  * indent-tabs-mode: t
487  * c-basic-offset: 4
488  * tab-width: 4
489  * End:
490  */