void initialiseString() { FieldBlock *count = NULL, *value, *offset; string_class = findSystemClass0(SYMBOL(java_lang_String)); registerStaticClassRef(&string_class); if(string_class != NULL) { count = findField(string_class, SYMBOL(count), SYMBOL(I)); value = findField(string_class, SYMBOL(value), SYMBOL(array_C)); offset = findField(string_class, SYMBOL(offset), SYMBOL(I)); } /* findField doesn't throw an exception... */ if((count == NULL) || (value == NULL) || (offset == NULL)) { jam_fprintf(stderr, "Error initialising VM (initialiseString)\n"); exitVM(1); } count_offset = count->offset; value_offset = value->offset; offset_offset = offset->offset; /* Init hash table and create lock */ initHashTable(hash_table, HASHTABSZE, TRUE); }
char *nativeJVMPath() { Dl_info info; char *path; if(dladdr(nativeJVMPath, &info) == 0) { printf("Error: dladdr failed. Aborting VM\n"); exitVM(1); } path = sysMalloc(strlen(info.dli_fname) + 1); strcpy(path, info.dli_fname); return path; }
long long getPhysicalMemory() { /* Long longs are used here because with PAE, a 32-bit machine can have more than 4GB of physical memory */ // On Mac OS X, sysctl with selectors CTL_HW, HW_PHYSMEM returns only a // 4-byte value, even if passed an 8-byte buffer, and limits the returned // value to 2GB when the actual RAM size is > 2GB. The Gestalt selector // gestaltPhysicalRAMSizeInMegabytes is available starting with OS 10.3.0. long mem_size; if (Gestalt(gestaltPhysicalRAMSizeInMegabytes, &mem_size)) { perror("Error: Couldn't determine physical RAM size. Aborting VM\n"); exitVM(1); } return ((long long)(1024 * 1024)) * mem_size; }
void classlibCacheClassLoaderFields(Class *loader_class) { FieldBlock *classes_fb = findField(loader_class, SYMBOL(classes), SYMBOL(sig_java_util_vector)); FieldBlock *parent_fb = findField(loader_class, SYMBOL(parent), SYMBOL(sig_java_lang_ClassLoader)); if(classes_fb == NULL || parent_fb == NULL) { jam_fprintf(stderr, "Expected \"classes\" and/or \"parent\" field " "missing in java.lang.ClassLoader\n"); exitVM(1); } hideFieldFromGC(classes_fb); ldr_classes_offset = classes_fb->u.offset; ldr_parent_offset = parent_fb->u.offset; }
void initialiseException() { FieldBlock *bcktrce; int i; ste_class = findSystemClass0(SYMBOL(java_lang_StackTraceElement)); ste_array_class = findArrayClass(SYMBOL(array_java_lang_StackTraceElement)); vmthrow_class = findSystemClass0(SYMBOL(java_lang_VMThrowable)); throw_class = findSystemClass0(SYMBOL(java_lang_Throwable)); bcktrce = findField(vmthrow_class, SYMBOL(backtrace), SYMBOL(sig_java_lang_Object)); vmthrow_init_mb = findMethod(ste_class, SYMBOL(object_init), SYMBOL(_java_lang_String_I_java_lang_String_java_lang_String_Z__V)); if((bcktrce == NULL) || (vmthrow_init_mb == NULL)) { jam_fprintf(stderr, "Error initialising VM (initialiseException)\n"); exitVM(1); } CLASS_CB(vmthrow_class)->flags |= VMTHROWABLE; backtrace_offset = bcktrce->offset; registerStaticClassRef(&ste_class); registerStaticClassRef(&ste_array_class); registerStaticClassRef(&vmthrow_class); registerStaticClassRef(&throw_class); /* Load and register the exceptions used within the VM. These are preloaded to speed up access. The VM will abort if any can't be loaded */ for(i = 0; i < MAX_EXCEPTION_ENUM; i++) { exceptions[i] = findSystemClass0(symbol_values[exception_symbols[i]]); registerStaticClassRef(&exceptions[i]); } inited = TRUE; }
void dumpThreadsLoop(Thread *self) { //return; // do nothing for now //assert(false); char buffer[256]; Thread *thread; sigset_t mask; int sig; sigemptyset(&mask); sigaddset(&mask, SIGQUIT); sigaddset(&mask, SIGINT); disableSuspend0(self, &self); for(;;) { sigwait(&mask, &sig); /* If it was an interrupt (e.g. Ctrl-C) terminate the VM */ if(sig == SIGINT) exitVM(0); /* It must be a SIGQUIT. Do a thread dump */ suspendAllThreads(self); jam_printf("\n------ JamVM version %s Full Thread Dump -------\n", VERSION); for(thread = &main_thread; thread != NULL; thread = thread->next) { //uintptr_t *thr_data = INST_DATA(thread->ee->thread); uintptr_t *thr_data = INST_DATA(thread->thread); int priority = thr_data[priority_offset]; int daemon = thr_data[daemon_offset]; assert(false); //Frame *last = thread->ee->last_frame; Frame* last = threadSelf()->get_current_spmt_thread()->get_current_mode()->frame; /* Get thread name; we don't use String2Cstr(), as this mallocs memory and may deadlock with a thread suspended in malloc/realloc/free */ String2Buff((Object*)thr_data[name_offset], buffer, sizeof(buffer)); jam_printf("\n\"%s\"%s %p priority: %d tid: %p id: %d state: %s (%d)\n", buffer, daemon ? " (daemon)" : "", thread, priority, thread->tid, thread->id, getThreadStateString(thread), thread->state); while(last->prev != NULL) { for(; last->mb != NULL; last = last->prev) { MethodBlock *mb = last->mb; ClassBlock *cb = CLASS_CB(mb->classobj); /* Convert slashes in class name to dots. Similar to above, we don't use slash2dots(), as this mallocs memory */ slash2dots2buff(cb->name, buffer, sizeof(buffer)); jam_printf("\tat %s.%s(", buffer, mb->name); if(mb->is_native()) jam_printf("Native method"); else if(cb->source_file_name == NULL) jam_printf("Unknown source"); else { int line = mapPC2LineNo(mb, last->last_pc); jam_printf("%s", cb->source_file_name); if(line != -1) jam_printf(":%d", line); } jam_printf(")\n"); } last = last->prev; } } resumeAllThreads(self); } }
void initialiseThreadStage2(InitArgs *args) { Object *java_thread; Class *thrdGrp_class; MethodBlock *run, *remove_thread; FieldBlock *group, *priority, *root, *threadId; FieldBlock *vmThread = NULL, *thread = NULL; FieldBlock *vmData, *daemon, *name; /* Load thread class and register reference for compaction threading */ thread_class = findSystemClass0(SYMBOL(java_lang_Thread)); registerStaticClassRef(&thread_class); if(thread_class != NULL) { vmThread = findField(thread_class, SYMBOL(vmThread), SYMBOL(sig_java_lang_VMThread)); daemon = findField(thread_class, SYMBOL(daemon), SYMBOL(Z)); name = findField(thread_class, SYMBOL(name), SYMBOL(sig_java_lang_String)); group = findField(thread_class, SYMBOL(group), SYMBOL(sig_java_lang_ThreadGroup)); priority = findField(thread_class, SYMBOL(priority), SYMBOL(I)); threadId = findField(thread_class, SYMBOL(threadId), SYMBOL(J)); init_mb = findMethod(thread_class, SYMBOL(object_init), SYMBOL(_java_lang_VMThread_java_lang_String_I_Z__V)); run = findMethod(thread_class, SYMBOL(run), SYMBOL(___V)); vmthread_class = findSystemClass0(SYMBOL(java_lang_VMThread)); CLASS_CB(vmthread_class)->flags |= VMTHREAD; /* Register class reference for compaction threading */ registerStaticClassRef(&vmthread_class); if(vmthread_class != NULL) { thread = findField(vmthread_class, SYMBOL(thread), SYMBOL(sig_java_lang_Thread)); vmData = findField(vmthread_class, SYMBOL(vmData), SYMBOL(I)); } } /* findField and findMethod do not throw an exception... */ if((init_mb == NULL) || (vmData == NULL) || (run == NULL) || (daemon == NULL) || (name == NULL) || (group == NULL) || (priority == NULL) || (vmThread == NULL) || (thread == NULL) || (threadId == NULL)) goto error; vmthread_offset = vmThread->offset; thread_offset = thread->offset; vmData_offset = vmData->offset; daemon_offset = daemon->offset; group_offset = group->offset; priority_offset = priority->offset; threadId_offset = threadId->offset; name_offset = name->offset; run_mtbl_idx = run->method_table_index; /* Initialise the Java-level thread objects for the main thread */ java_thread = initJavaThread(&main_thread, FALSE, "main"); /* Main thread is now sufficiently setup to be able to run the thread group initialiser. This is essential to create the root thread group */ thrdGrp_class = findSystemClass(SYMBOL(java_lang_ThreadGroup)); root = findField(thrdGrp_class, SYMBOL(root), SYMBOL(sig_java_lang_ThreadGroup)); addThread_mb = findMethod(thrdGrp_class, SYMBOL(addThread), SYMBOL(_java_lang_Thread_args__void)); remove_thread = findMethod(thrdGrp_class, SYMBOL(removeThread), SYMBOL(_java_lang_Thread_args__void)); /* findField and findMethod do not throw an exception... */ if((root == NULL) || (addThread_mb == NULL) || (remove_thread == NULL)) goto error; rmveThrd_mtbl_idx = remove_thread->method_table_index; /* Add the main thread to the root thread group */ INST_DATA(java_thread)[group_offset] = root->static_value; { DummyFrame dummy; executeMethod(&dummy, ((Object*)root->static_value), addThread_mb, java_thread); } // dyn INST_DATA(java_thread)[vmthread_offset] = 0; /* Setup signal handling. This will be inherited by all threads created within Java */ initialiseSignals(); /* Create the signal handler thread. It is responsible for catching and handling SIGQUIT (thread dump) and SIGINT (user-termination of the VM, e.g. via Ctrl-C). Note it must be a valid Java-level thread as it needs to run the shutdown hooks in the event of user-termination */ createVMThread("Signal Handler", dumpThreadsLoop); return; error: jam_fprintf(stderr, "Error initialising VM (initialiseMainThread)\nCheck " "the README for compatible versions of GNU Classpath\n"); printException(); exitVM(1); }
int main(int argc, char *argv[]) { Class *array_class, *main_class; Object *system_loader, *array; MethodBlock *mb; InitArgs args; int class_arg; char *cpntr; int status; int i; setDefaultInitArgs(&args); class_arg = parseCommandLine(argc, argv, &args); args.main_stack_base = &array_class; initVM(&args); if((system_loader = getSystemClassLoader()) == NULL) { printf("Cannot create system class loader\n"); printException(); exitVM(1); } mainThreadSetContextClassLoader(system_loader); for(cpntr = argv[class_arg]; *cpntr; cpntr++) if(*cpntr == '.') *cpntr = '/'; if((main_class = findClassFromClassLoader(argv[class_arg], system_loader)) != NULL) initClass(main_class); if(exceptionOccurred()) { printException(); exitVM(1); } mb = lookupMethod(main_class, SYMBOL(main), SYMBOL(_array_java_lang_String__V)); if(!mb || !(mb->access_flags & ACC_STATIC)) { printf("Static method \"main\" not found in %s\n", argv[class_arg]); exitVM(1); } /* Create the String array holding the command line args */ i = class_arg + 1; if((array_class = findArrayClass(SYMBOL(array_java_lang_String))) && (array = allocArray(array_class, argc - i, sizeof(Object*)))) { Object **args = (Object**)ARRAY_DATA(array) - i; for(; i < argc; i++) if(!(args[i] = Cstr2String(argv[i]))) break; /* Call the main method */ if(i == argc) executeStaticMethod(main_class, mb, array); } /* ExceptionOccurred returns the exception or NULL, which is OK for normal conditionals, but not here... */ if((status = exceptionOccurred() ? 1 : 0)) printException(); /* Wait for all but daemon threads to die */ mainThreadWaitToExitVM(); exitVM(status); }