* Removed all Id tags.
[cacao.git] / src / cacao / cacao.c
index 388d9e8660380b729b1d808601aa925f3e40c65e..ac005387bfbc27aad3c8abd55b6ee0ed5f59559f 100644 (file)
@@ -1,6 +1,6 @@
 /* src/cacao/cacao.c - contains main() of cacao
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Reinhard Grafl
-
-   Changes: Andi Krall
-            Mark Probst
-            Philipp Tomsich
-            Christian Thalinger
-
-   $Id: cacao.c 4879 2006-05-05 17:34:49Z edwin $
-
 */
 
 
 #include "config.h"
 
 #include <assert.h>
+
+#if defined(ENABLE_LIBJVM)
+# include <ltdl.h>
+#endif
+
+#if defined(WITH_JRE_LAYOUT)
+# include <errno.h>
+# include <libgen.h>
+# include <unistd.h>
+#endif
+
 #include <stdlib.h>
 #include <string.h>
 
 #include "vm/types.h"
 
 #include "native/jni.h"
-#include "native/include/java_lang_String.h"
 
 #if defined(ENABLE_JVMTI)
-#include "native/jvmti/jvmti.h"
-#include "native/jvmti/cacaodbg.h"
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-#include <pthread.h>
-#endif
+# include "native/jvmti/jvmti.h"
+# include "native/jvmti/cacaodbg.h"
 #endif
 
-#include "toolbox/logging.h"
-#include "vm/classcache.h"
-#include "vm/exceptions.h"
-#include "vm/global.h"
-#include "vm/loader.h"
-#include "vm/options.h"
-#include "vm/statistics.h"
-#include "vm/stringlocal.h"
-#include "vm/suck.h"
 #include "vm/vm.h"
-#include "vm/jit/asmpart.h"
-#include "vm/jit/jit.h"
-
-#ifdef TYPEINFO_DEBUG_TEST
-#include "vm/jit/verify/typeinfo.h"
-#endif
-
-#ifdef TYPECHECK_STATISTICS
-void typecheck_print_statistics(FILE *file);
-#endif
-
-/* getmainclassfromjar *********************************************************
-
-   Gets the name of the main class form a JAR's manifest file.
-
-*******************************************************************************/
-
-static char *getmainclassnamefromjar(char *mainstring)
-{
-       classinfo         *c;
-       java_objectheader *o;
-       methodinfo        *m;
-       java_lang_String  *s;
-
-       c = load_class_from_sysloader(utf_new_char("java/util/jar/JarFile"));
-
-       if (!c)
-               throw_main_exception_exit();
-       
-       /* create JarFile object */
-
-       o = builtin_new(c);
-
-       if (!o)
-               throw_main_exception_exit();
-
-
-       m = class_resolveclassmethod(c,
-                                                                utf_init, 
-                                                                utf_java_lang_String__void,
-                                                                class_java_lang_Object,
-                                                                true);
-
-       if (!m)
-               throw_main_exception_exit();
-
-       s = javastring_new_from_ascii(mainstring);
 
-       (void) vm_call_method(m, o, s);
 
-       if (*exceptionptr)
-               throw_main_exception_exit();
+/* forward declarations *******************************************************/
 
-       /* get manifest object */
-
-       m = class_resolveclassmethod(c,
-                                                                utf_new_char("getManifest"), 
-                                                                utf_new_char("()Ljava/util/jar/Manifest;"),
-                                                                class_java_lang_Object,
-                                                                true);
-
-       if (!m)
-               throw_main_exception_exit();
-
-       o = vm_call_method(m, o);
-
-       if (o == NULL) {
-               fprintf(stderr, "Could not get manifest from %s (invalid or corrupt jarfile?)\n", mainstring);
-               vm_exit(1);
-       }
-
-
-       /* get Main Attributes */
-
-       m = class_resolveclassmethod(o->vftbl->class,
-                                                                utf_new_char("getMainAttributes"), 
-                                                                utf_new_char("()Ljava/util/jar/Attributes;"),
-                                                                class_java_lang_Object,
-                                                                true);
-
-       if (!m)
-               throw_main_exception_exit();
-
-       o = vm_call_method(m, o);
-
-       if (o == NULL) {
-               fprintf(stderr, "Could not get main attributes from %s (invalid or corrupt jarfile?)\n", mainstring);
-               vm_exit(1);
-       }
-
-
-       /* get property Main-Class */
-
-       m = class_resolveclassmethod(o->vftbl->class,
-                                                                utf_new_char("getValue"), 
-                                                                utf_new_char("(Ljava/lang/String;)Ljava/lang/String;"),
-                                                                class_java_lang_Object,
-                                                                true);
-
-       if (!m)
-               throw_main_exception_exit();
-
-       s = javastring_new_from_ascii("Main-Class");
-
-       o = vm_call_method(m, o, s);
-
-       if (!o)
-               throw_main_exception_exit();
-
-       return javastring_tochar(o);
-}
-
-void exit_handler(void);
+static JavaVMInitArgs *cacao_options_prepare(int argc, char **argv);
 
 
 /* main ************************************************************************
@@ -188,286 +67,146 @@ void exit_handler(void);
 
 int main(int argc, char **argv)
 {
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       void *dummy;
+#if defined(ENABLE_LIBJVM) && !defined(WITH_STATIC_CLASSPATH)
+       char           *path;
 #endif
-       s4 i;
-       
-       /* local variables ********************************************************/
 
-       JavaVMInitArgs *vm_args;
-       JavaVM         *jvm;                /* denotes a Java VM                  */
+#if defined(ENABLE_LIBJVM)     
+       /* Variables for JNI_CreateJavaVM dlopen call. */
+       lt_dlhandle     libjvm_handle;
+       lt_ptr          libjvm_vm_createjvm;
+       lt_ptr          libjvm_vm_run;
+       const char     *lterror;
 
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       stackbottom = &dummy;
+       bool (*vm_createjvm)(JavaVM **, void **, void *);
+       void (*vm_run)(JavaVM *, JavaVMInitArgs *);
 #endif
-       
-       if (atexit(vm_exit_handler))
-               throw_cacao_exception_exit(string_java_lang_InternalError,
-                                                                  "Unable to register exit_handler");
-
 
-       /**************************** Program start *****************************/
-
-       if (opt_verbose)
-               log_text("CACAO started -------------------------------------------------------");
+       JavaVM         *vm;                 /* denotes a Java VM                  */
+       JNIEnv         *env;
+       JavaVMInitArgs *vm_args;
 
        /* prepare the options */
 
-       vm_args = options_prepare(argc, argv);
+       vm_args = cacao_options_prepare(argc, argv);
        
        /* load and initialize a Java VM, return a JNI interface pointer in env */
 
-       JNI_CreateJavaVM(&jvm, (void **) &_Jv_env, vm_args);
-
-#if defined(ENABLE_JVMTI)
-       if (dbgprocess && jvmti && jdwp) /* is this the parent/debugger process ? */
-               set_jvmti_phase(JVMTI_PHASE_START);
-#endif
+#if defined(ENABLE_LIBJVM) && !defined(WITH_STATIC_CLASSPATH)
+# if defined(WITH_JRE_LAYOUT)
+       /* SUN also uses a buffer of 4096-bytes (strace is your friend). */
 
-       /* do we have a main class? */
-
-       if (mainstring == NULL)
-               usage();
+       path = malloc(sizeof(char) * 4096);
 
+       if (readlink("/proc/self/exe", path, 4095) == -1) {
+               fprintf(stderr, "main: readlink failed: %s\n", strerror(errno));
+               abort();
+       }
 
-       /* start worker routines **************************************************/
+       /* get the path of the current executable */
 
-       if (opt_run == true) {
-               utf              *mainutf;
-               classinfo        *mainclass;
-               methodinfo       *m;
-               java_objectarray *oa; 
-               s4                oalength;
-               java_lang_String *s;
-               s4                status;
+       path = dirname(path);
 
-               /* set return value to OK */
+       if ((strlen(path) + strlen("/../lib/libjvm") + strlen("0")) > 4096) {
+               fprintf(stderr, "main: libjvm name to long for buffer\n");
+               abort();
+       }
 
-               status = 0;
+       /* concatinate the library name */
 
-               if (opt_jar == true) {
-                       /* open jar file with java.util.jar.JarFile */
-                       mainstring = getmainclassnamefromjar(mainstring);
-               }
+       strcat(path, "/../lib/libjvm");
+# else
+       path = CACAO_LIBDIR"/libjvm";
+# endif
 
-               /* load the main class */
+       if (lt_dlinit()) {
+               fprintf(stderr, "main: lt_dlinit failed: %s\n", lt_dlerror());
+               abort();
+       }
 
-               mainutf = utf_new_char(mainstring);
+       /* First try to open where dlopen searches, e.g. LD_LIBRARY_PATH.
+          If not found, try the absolute path. */
 
-               if (!(mainclass = load_class_from_sysloader(mainutf)))
-                       throw_main_exception_exit();
+       if (!(libjvm_handle = lt_dlopenext("libjvm"))) {
+               /* save the error message */
 
-               /* error loading class, clear exceptionptr for new exception */
+               lterror = strdup(lt_dlerror());
 
-               if (*exceptionptr || !mainclass) {
-/*                     *exceptionptr = NULL; */
+               if (!(libjvm_handle = lt_dlopenext(path))) {
+                       /* print the first error message too */
 
-/*                     *exceptionptr = */
-/*                             new_exception_message(string_java_lang_NoClassDefFoundError, */
-/*                                                                       mainstring); */
-                       throw_main_exception_exit();
-               }
+                       fprintf(stderr, "main: lt_dlopenext failed: %s\n", lterror);
 
-               if (!link_class(mainclass))
-                       throw_main_exception_exit();
-                       
-               /* find the `main' method of the main class */
+                       /* and now the current one */
 
-               m = class_resolveclassmethod(mainclass,
-                                                                        utf_new_char("main"), 
-                                                                        utf_new_char("([Ljava/lang/String;)V"),
-                                                                        class_java_lang_Object,
-                                                                        false);
-
-               if (*exceptionptr) {
-                       throw_main_exception_exit();
+                       fprintf(stderr, "main: lt_dlopenext failed: %s\n", lt_dlerror());
+                       abort();
                }
 
-               /* there is no main method or it isn't static */
-
-               if (!m || !(m->flags & ACC_STATIC)) {
-                       *exceptionptr = NULL;
+               /* free the error string */
 
-                       *exceptionptr =
-                               new_exception_message(string_java_lang_NoSuchMethodError,
-                                                                         "main");
-                       throw_main_exception_exit();
-               }
+               free((void *) lterror);
+       }
 
-               /* build argument array */
+       if (!(libjvm_vm_createjvm = lt_dlsym(libjvm_handle, "vm_createjvm"))) {
+               fprintf(stderr, "main: lt_dlsym failed: %s\n", lt_dlerror());
+               abort();
+       }
 
-               oalength = vm_args->nOptions - opt_index;
+       vm_createjvm =
+               (bool (*)(JavaVM **, void **, void *)) (ptrint) libjvm_vm_createjvm;
+#endif
 
-               oa = builtin_anewarray(oalength, class_java_lang_String);
+       /* create the Java VM */
 
-               for (i = 0; i < oalength; i++) {
-                       s = javastring_new(utf_new_char(vm_args->options[opt_index + i].optionString));
-                       oa->data[i] = (java_objectheader *) s;
-               }
-
-#ifdef TYPEINFO_DEBUG_TEST
-               /* test the typeinfo system */
-               typeinfo_test();
-#endif
-               /*class_showmethods(currentThread->group->header.vftbl->class); */
+       (void) vm_createjvm(&vm, (void *) &env, vm_args);
 
 #if defined(ENABLE_JVMTI)
-               /* if this is the parent process than start the jdwp listening */
-               if (jvmti || jdwp) {
-                       fprintf(stderr, "jdwp/debugger set herewego brkpt %p\n",&&herewego);
-                       setsysbrkpt(HEREWEGOBRK,&&herewego);
-                       if (dbgprocess && jdwp) cacaodbglisten(transport);
-               }
-
-               if (!dbgprocess) {
-                       fprintf(stderr,"debuggee: herewe go\n");
-                       fflush(stderr);
-               }
-               /* here we go... */
-       herewego:
+       pthread_mutex_init(&dbgcomlock,NULL);
+       if (jvmti) jvmti_set_phase(JVMTI_PHASE_START);
 #endif
-               (void) vm_call_method(m, NULL, oa);
-
-               /* exception occurred? */
-
-               if (*exceptionptr) {
-                       throw_main_exception();
-                       status = 1;
-               }
-
-               /* unload the JavaVM */
-
-               vm_destroy(jvm);
-
-               /* and exit */
 
-               vm_exit(status);
+#if !defined(WITH_STATIC_CLASSPATH) && defined(ENABLE_LIBJVM)
+       if (!(libjvm_vm_run = lt_dlsym(libjvm_handle, "vm_run"))) {
+               fprintf(stderr, "lt_dlsym failed: %s\n", lt_dlerror());
+               abort();
        }
 
+       vm_run = (void (*)(JavaVM *, JavaVMInitArgs *)) (ptrint) libjvm_vm_run;
+#endif
 
-       /* If requested, compile all methods. *************************************/
-
-#if !defined(NDEBUG)
-       if (compileall) {
-               classinfo *c;
-               methodinfo *m;
-               u4 slot;
-               s4 i;
-               classcache_name_entry *nmen;
-               classcache_class_entry *clsen;
-
-               /* create all classes found in the bootclasspath */
-               /* XXX currently only works with zip/jar's */
-
-               loader_load_all_classes();
-
-               /* link all classes */
-
-               for (slot = 0; slot < hashtable_classcache.size; slot++) {
-                       nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot];
-
-                       for (; nmen; nmen = nmen->hashlink) {
-                               /* iterate over all class entries */
-
-                               for (clsen = nmen->classes; clsen; clsen = clsen->next) {
-                                       c = clsen->classobj;
-
-                                       if (!c)
-                                               continue;
-
-                                       if (!(c->state & CLASS_LINKED)) {
-                                               if (!link_class(c)) {
-                                                       fprintf(stderr, "Error linking: ");
-                                                       utf_fprint_printable_ascii_classname(stderr, c->name);
-                                                       fprintf(stderr, "\n");
-
-                                                       /* print out exception and cause */
-
-                                                       exceptions_print_exception(*exceptionptr);
-
-                                                       /* goto next class */
-
-                                                       continue;
-                                               }
-                                       }
-
-                                       /* compile all class methods */
-
-                                       for (i = 0; i < c->methodscount; i++) {
-                                               m = &(c->methods[i]);
-
-                                               if (m->jcode) {
-                                                       if (!jit_compile(m)) {
-                                                               fprintf(stderr, "Error compiling: ");
-                                                               utf_fprint_printable_ascii_classname(stderr, c->name);
-                                                               fprintf(stderr, ".");
-                                                               utf_fprint_printable_ascii(stderr, m->name);
-                                                               utf_fprint_printable_ascii(stderr, m->descriptor);
-                                                               fprintf(stderr, "\n");
-
-                                                               /* print out exception and cause */
-
-                                                               exceptions_print_exception(*exceptionptr);
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-#endif /* !defined(NDEBUG) */
+       /* run the VM */
 
+       vm_run(vm, vm_args);
 
-       /* If requested, compile a specific method. *******************************/
+       /* keep compiler happy */
 
-#if !defined(NDEBUG)
-       if (opt_method != NULL) {
-               methodinfo *m;
+       return 0;
+}
 
-               /* create, load and link the main class */
 
-               if (!(mainclass = load_class_bootstrap(utf_new_char(mainstring))))
-                       throw_main_exception_exit();
+/* cacao_options_prepare *******************************************************
 
-               if (!link_class(mainclass))
-                       throw_main_exception_exit();
+   Prepare the JavaVMInitArgs.
 
-               if (opt_signature != NULL) {
-                       m = class_resolveclassmethod(mainclass,
-                                                                                utf_new_char(opt_method),
-                                                                                utf_new_char(opt_signature),
-                                                                                mainclass,
-                                                                                false);
-               } else {
-                       m = class_resolveclassmethod(mainclass,
-                                                                                utf_new_char(opt_method),
-                                                                                NULL,
-                                                                                mainclass,
-                                                                                false);
-               }
+*******************************************************************************/
 
-               if (!m) {
-                       char message[MAXLOGTEXT];
-                       sprintf(message, "%s%s", opt_method,
-                                       opt_signature ? opt_signature : "");
+static JavaVMInitArgs *cacao_options_prepare(int argc, char **argv)
+{
+       JavaVMInitArgs *vm_args;
+       s4              i;
 
-                       *exceptionptr =
-                               new_exception_message(string_java_lang_NoSuchMethodException,
-                                                                         message);
-                                                                                
-                       throw_main_exception_exit();
-               }
-               
-               jit_compile(m);
-       }
+       vm_args = malloc(sizeof(JavaVMInitArgs));
 
-       vm_shutdown(0);
-#endif /* !defined(NDEBUG) */
+       vm_args->version            = JNI_VERSION_1_2;
+       vm_args->nOptions           = argc - 1;
+       vm_args->options            = malloc(sizeof(JavaVMOption) * argc);
+       vm_args->ignoreUnrecognized = JNI_FALSE;
 
-       /* keep compiler happy */
+       for (i = 1; i < argc; i++)
+               vm_args->options[i - 1].optionString = argv[i];
 
-       return 0;
+       return vm_args;
 }