* Removed all Id tags.
[cacao.git] / src / cacao / cacao.c
index 4c5fb2cc014ca32d64404b7de6cefe3f7195cac8..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 4892 2006-05-06 18:29:55Z motse $
-
 */
 
 
 #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 ************************************************************************
@@ -189,290 +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)
-       pthread_mutex_init(&dbgcomlock,NULL);
-       set_jvmti_phase(JVMTI_PHASE_START);
-#endif
-
-       /* do we have a main class? */
-
-       if (mainstring == NULL)
-               usage();
+#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). */
 
+       path = malloc(sizeof(char) * 4096);
 
-       /* start worker routines **************************************************/
-
-       if (opt_run == true) {
-               utf              *mainutf;
-               classinfo        *mainclass;
-               methodinfo       *m;
-               java_objectarray *oa; 
-               s4                oalength;
-               java_lang_String *s;
-               s4                status;
-
-               /* set return value to OK */
+       if (readlink("/proc/self/exe", path, 4095) == -1) {
+               fprintf(stderr, "main: readlink failed: %s\n", strerror(errno));
+               abort();
+       }
 
-               status = 0;
+       /* get the path of the current executable */
 
-               if (opt_jar == true) {
-                       /* open jar file with java.util.jar.JarFile */
-                       mainstring = getmainclassnamefromjar(mainstring);
-               }
+       path = dirname(path);
 
-               /* load the main class */
+       if ((strlen(path) + strlen("/../lib/libjvm") + strlen("0")) > 4096) {
+               fprintf(stderr, "main: libjvm name to long for buffer\n");
+               abort();
+       }
 
-               mainutf = utf_new_char(mainstring);
+       /* concatinate the library name */
 
-               if (!(mainclass = load_class_from_sysloader(mainutf)))
-                       throw_main_exception_exit();
+       strcat(path, "/../lib/libjvm");
+# else
+       path = CACAO_LIBDIR"/libjvm";
+# endif
 
-               /* error loading class, clear exceptionptr for new exception */
+       if (lt_dlinit()) {
+               fprintf(stderr, "main: lt_dlinit failed: %s\n", lt_dlerror());
+               abort();
+       }
 
-               if (*exceptionptr || !mainclass) {
-/*                     *exceptionptr = NULL; */
+       /* First try to open where dlopen searches, e.g. LD_LIBRARY_PATH.
+          If not found, try the absolute path. */
 
-/*                     *exceptionptr = */
-/*                             new_exception_message(string_java_lang_NoClassDefFoundError, */
-/*                                                                       mainstring); */
-                       throw_main_exception_exit();
-               }
+       if (!(libjvm_handle = lt_dlopenext("libjvm"))) {
+               /* save the error message */
 
-               if (!link_class(mainclass))
-                       throw_main_exception_exit();
-                       
-               /* find the `main' method of the main class */
+               lterror = strdup(lt_dlerror());
 
-               m = class_resolveclassmethod(mainclass,
-                                                                        utf_new_char("main"), 
-                                                                        utf_new_char("([Ljava/lang/String;)V"),
-                                                                        class_java_lang_Object,
-                                                                        false);
+               if (!(libjvm_handle = lt_dlopenext(path))) {
+                       /* print the first error message too */
 
-               if (*exceptionptr) {
-                       throw_main_exception_exit();
-               }
+                       fprintf(stderr, "main: lt_dlopenext failed: %s\n", lterror);
 
-               /* there is no main method or it isn't static */
+                       /* and now the current one */
 
-               if (!m || !(m->flags & ACC_STATIC)) {
-                       *exceptionptr = NULL;
-
-                       *exceptionptr =
-                               new_exception_message(string_java_lang_NoSuchMethodError,
-                                                                         "main");
-                       throw_main_exception_exit();
+                       fprintf(stderr, "main: lt_dlopenext failed: %s\n", lt_dlerror());
+                       abort();
                }
 
-               /* build argument array */
-
-               oalength = vm_args->nOptions - opt_index;
+               /* free the error string */
 
-               oa = builtin_anewarray(oalength, class_java_lang_String);
+               free((void *) lterror);
+       }
 
-               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;
-               }
+       if (!(libjvm_vm_createjvm = lt_dlsym(libjvm_handle, "vm_createjvm"))) {
+               fprintf(stderr, "main: lt_dlsym failed: %s\n", lt_dlerror());
+               abort();
+       }
 
-#ifdef TYPEINFO_DEBUG_TEST
-               /* test the typeinfo system */
-               typeinfo_test();
+       vm_createjvm =
+               (bool (*)(JavaVM **, void **, void *)) (ptrint) libjvm_vm_createjvm;
 #endif
-               /*class_showmethods(currentThread->group->header.vftbl->class); */
 
-#if defined(ENABLE_JVMTI)
-               /* start the jdwp listening */
-               if (jdwp) {
-                       log_text("cacao vm - init VMjdwp");
-                       if (!VMjdwpInit()) exit(1);
-                       setup_jdwp_thread(transport);
-                       if (!suspend) {
-                               fprintf(stderr,"suspend false -> continue debuggee\n");
-                       } else {
-                               fprintf(stderr,"suspend true -> do no continue debuggee(todo)\n");
-                               /* XXX todo*/
-                       }
-               }
+       /* create the Java VM */
 
-               set_jvmti_phase(JVMTI_PHASE_LIVE);
+       (void) vm_createjvm(&vm, (void *) &env, vm_args);
 
-               log_text("debuggee: herewe go");
+#if defined(ENABLE_JVMTI)
+       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;
 }