/* src/cacao/cacao.c - contains main() of cacao
- Copyright (C) 1996-2005, 2006 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
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
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 4559 2006-03-05 23:24:50Z twisti $
-
*/
#include "config.h"
#include <assert.h>
+
+#if defined(ENABLE_JRE_LAYOUT)
+# include <errno.h>
+# include <libgen.h>
+# include <unistd.h>
+#endif
+
#include <stdlib.h>
#include <string.h>
#include "vm/types.h"
-#include "mm/boehm.h"
-#include "mm/memory.h"
#include "native/jni.h"
-#include "native/include/java_lang_String.h"
+#include "native/native.h"
#if defined(ENABLE_JVMTI)
-#include "native/jvmti/jvmti.h"
-#include "native/jvmti/dbg.h"
-#include <sys/types.h>
-#include <signal.h>
-#include <sys/wait.h>
+# 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
+#include "vmcore/system.h"
+#include "vm/vm.hpp"
-#ifdef TYPECHECK_STATISTICS
-void typecheck_print_statistics(FILE *file);
-#endif
-/* setup_debugger_process *****************************************************
+/* Defines. *******************************************************************/
- Helper function to start JDWP threads
-
-*******************************************************************************/
-#if defined(ENABLE_JVMTI)
-
-static void setup_debugger_process(char* transport) {
- java_objectheader *o;
- methodinfo *m;
- java_lang_String *s;
-
- /* new gnu.classpath.jdwp.Jdwp() */
- mainclass =
- load_class_from_sysloader(utf_new_char("gnu.classpath.jdwp.Jdwp"));
- if (!mainclass)
- throw_main_exception_exit();
-
- o = builtin_new(mainclass);
-
- if (!o)
- throw_main_exception_exit();
-
- m = class_resolveclassmethod(mainclass,
- utf_init,
- utf_java_lang_String__void,
- class_java_lang_Object,
- true);
- if (!m)
- throw_main_exception_exit();
+#define LIBJVM_NAME NATIVE_LIBRARY_PREFIX"jvm"NATIVE_LIBRARY_SUFFIX
- (void) vm_call_method(m, o);
- /* configure(transport,NULL) */
- m = class_resolveclassmethod(
- mainclass, utf_new_char("configure"),
- utf_new_char("(Ljava/lang/String;Ljava/lang/Thread;)V"),
- class_java_lang_Object,
- false);
-
-
- s = javastring_new_char(transport);
-
- (void) vm_call_method(m, o, s);
-
- if (!m)
- throw_main_exception_exit();
-
- /* _doInitialization */
- m = class_resolveclassmethod(mainclass,
- utf_new_char("_doInitialization"),
- utf_new_char("()V"),
- mainclass,
- false);
-
- if (!m)
- throw_main_exception_exit();
-
- (void) vm_call_method(m, o);
-}
-#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;
+/* forward declarations *******************************************************/
- 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_char(mainstring);
-
- (void) vm_call_method(m, o, s);
-
- if (*exceptionptr)
- throw_main_exception_exit();
-
- /* 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_char("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 ************************************************************************
int main(int argc, char **argv)
{
- void *dummy;
- s4 i;
-
- /* local variables ********************************************************/
-
- JavaVMInitArgs *vm_args;
- JavaVM *jvm; /* denotes a Java VM */
-
-#if defined(ENABLE_JVMTI)
- bool dbg = false;
- char *transport;
- int waitval;
-#endif
+#if defined(ENABLE_LIBJVM)
+ char* path;
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
- stackbottom = &dummy;
+# if defined(ENABLE_JRE_LAYOUT)
+ int len;
+# endif
#endif
-
- if (atexit(vm_exit_handler))
- throw_cacao_exception_exit(string_java_lang_InternalError,
- "Unable to register exit_handler");
+#if defined(ENABLE_LIBJVM)
+ /* Variables for JNI_CreateJavaVM dlopen call. */
+ void* libjvm_handle;
+ void* libjvm_VM_create;
+ void* libjvm_vm_run;
+ const char* lterror;
- /**************************** Program start *****************************/
+ bool (*VM_create)(JavaVM **, void **, void *);
+ void (*vm_run)(JavaVM *, JavaVMInitArgs *);
+#endif
- 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)
- set_jvmti_phase(JVMTI_PHASE_START);
-#endif
-
- /* do we have a main class? */
-
- if (mainstring == NULL)
- usage();
+#if defined(ENABLE_LIBJVM)
+# if defined(ENABLE_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);
+ len = strlen(path) + strlen("/../lib/"LIBJVM_NAME) + strlen("0");
- /* load the main class */
+ if (len > 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_NAME);
+# else
+ path = CACAO_LIBDIR"/"LIBJVM_NAME;
+# endif
- /* error loading class, clear exceptionptr for new exception */
+ /* First try to open where dlopen searches, e.g. LD_LIBRARY_PATH.
+ If not found, try the absolute path. */
- if (*exceptionptr || !mainclass) {
-/* *exceptionptr = NULL; */
+ libjvm_handle = system_dlopen(LIBJVM_NAME, RTLD_NOW);
-/* *exceptionptr = */
-/* new_exception_message(string_java_lang_NoClassDefFoundError, */
-/* mainstring); */
- throw_main_exception_exit();
- }
+ if (libjvm_handle == NULL) {
+ /* save the error message */
- if (!link_class(mainclass))
- throw_main_exception_exit();
-
- /* find the `main' method of the main class */
+ lterror = strdup(system_dlerror());
- m = class_resolveclassmethod(mainclass,
- utf_new_char("main"),
- utf_new_char("([Ljava/lang/String;)V"),
- class_java_lang_Object,
- false);
+ libjvm_handle = system_dlopen(path, RTLD_NOW);
- if (*exceptionptr) {
- throw_main_exception_exit();
- }
+ if (libjvm_handle == NULL) {
+ /* print the first error message too */
- /* there is no main method or it isn't static */
+ fprintf(stderr, "main: system_dlopen failed: %s\n", lterror);
- if (!m || !(m->flags & ACC_STATIC)) {
- *exceptionptr = NULL;
+ /* and now the current one */
- *exceptionptr =
- new_exception_message(string_java_lang_NoSuchMethodError,
- "main");
- throw_main_exception_exit();
+ fprintf(stderr, "main: system_dlopen failed: %s\n",
+ system_dlerror());
+ abort();
}
- /* build argument array */
+ /* free the error string */
- oalength = vm_args->nOptions - opt_index;
+ free((void *) lterror);
+ }
- oa = builtin_anewarray(oalength, class_java_lang_String);
+ libjvm_VM_create = system_dlsym(libjvm_handle, "VM_create");
- 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_create == NULL) {
+ fprintf(stderr, "main: lt_dlsym failed: %s\n", system_dlerror());
+ abort();
+ }
-#ifdef TYPEINFO_DEBUG_TEST
- /* test the typeinfo system */
- typeinfo_test();
-#endif
- /*class_showmethods(currentThread->group->header.vftbl->class); */
-
-#if defined(ENABLE_JVMTI) && defined(NATIVE_THREADS)
- if(dbg) {
- debuggee = fork();
- if (debuggee == (-1)) {
- log_text("fork error");
- exit(1);
- } else {
- if (debuggee == 0) {
- /* child: allow helper process to trace us */
- if (TRACEME != 0) exit(0);
-
- /* give parent/helper debugger process control */
- kill(0, SIGTRAP); /* do we need this at this stage ? */
-
- /* continue with normal startup */
-
- } else {
-
- /* parent/helper debugger process */
- wait(&waitval);
-
- remotedbgjvmtienv = new_jvmtienv();
- /* set eventcallbacks */
- if (JVMTI_ERROR_NONE ==
- remotedbgjvmtienv->
- SetEventCallbacks(remotedbgjvmtienv,
- &jvmti_jdwp_EventCallbacks,
- sizeof(jvmti_jdwp_EventCallbacks))){
- log_text("unable to setup event callbacks");
- vm_exit(1);
- }
-
- /* setup listening process (JDWP) */
- setup_debugger_process(transport);
-
- /* start to be debugged program */
- CONT(debuggee);
-
- /* exit debugger process - todo: cleanup */
- joinAllThreads();
- cacao_exit(0);
- }
- }
- }
- else
- debuggee= -1;
-
+ VM_create =
+ (bool (*)(JavaVM **, void **, void *)) (ptrint) libjvm_VM_create;
#endif
- /* here we go... */
- (void) vm_call_method(m, NULL, oa);
+ /* create the Java VM */
- /* exception occurred? */
+ (void) VM_create(&vm, (void *) &env, vm_args);
- if (*exceptionptr) {
- throw_main_exception();
- status = 1;
- }
-
- /* unload the JavaVM */
-
- vm_destroy(jvm);
+#if defined(ENABLE_JVMTI)
+# error This should be a JVMTI function.
+ Mutex_init(&dbgcomlock);
+ if (jvmti) jvmti_set_phase(JVMTI_PHASE_START);
+#endif
- /* and exit */
+#if defined(ENABLE_LIBJVM)
+ libjvm_vm_run = system_dlsym(libjvm_handle, "vm_run");
- vm_exit(status);
+ if (libjvm_vm_run == NULL) {
+ fprintf(stderr, "main: system_dlsym failed: %s\n", system_dlerror());
+ abort();
}
- /************* If requested, compile all methods ********************/
-
- 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_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_classname(stderr, c->name);
- fprintf(stderr, ".");
- utf_fprint(stderr, m->name);
- utf_fprint(stderr, m->descriptor);
- fprintf(stderr, "\n");
-
- /* print out exception and cause */
+ vm_run = (void (*)(JavaVM *, JavaVMInitArgs *)) (ptrint) libjvm_vm_run;
+#endif
- exceptions_print_exception(*exceptionptr);
- }
- }
- }
- }
- }
- }
- }
+ /* run the VM */
+ vm_run(vm, vm_args);
- /******** If requested, compile a specific method ***************/
+ /* keep compiler happy */
- 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);
+ 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;
}