void *threadStart(void *arg) { Thread *thread = (Thread *)arg; //Object *jThread = thread->ee->thread; Object *jThread = thread->thread; /* Parent thread created thread with suspension disabled. This is inherited so we need to enable */ enableSuspend(thread); /* Complete initialisation of the thread structure, create the thread stack and add the thread to the thread list */ initThread(thread, INST_DATA(jThread)[daemon_offset], &thread); /* Add thread to thread ID map hash table. */ addThreadToHash(thread); /* Execute the thread's run method */ DummyFrame dummy; executeMethod(&dummy, jThread, CLASS_CB(jThread->classobj)->method_table[run_mtbl_idx]); /* Run has completed. Detach the thread from the VM and exit */ detachThread(thread); TRACE("Thread 0x%x id: %d exited\n", thread, thread->id); return NULL; }
/*Create a new String *invoked by:OPC_LDC */ O createJstring(char *s) { if (java_lang_String == NULL) java_lang_String = loadClass("java/lang/String"); ClassBlock_t *cb = CLASS_CB(java_lang_String); if (!inited) initString(); O char_obj, string_obj; FieldBlock_t *fb; int length, offset; length = strlen(s); char_obj = char2Char(s); short *data = (short *) char_obj->data; unsigned char *ss = (unsigned char *) s; convertUtf8(ss, data); string_obj = allocObject(java_lang_String); string_obj->type = OBJECT_STRING; OBJECT_DATA(string_obj, value_offset - 1, O) = char_obj; OBJECT_DATA(string_obj, count_offset - 1, int) = length; //*(((Object**)string_obj->data)+offset-1) = char_obj; string_obj->cb = cb; string_obj->el_size = sizeof(int); return string_obj; }
Object *classlibThreadPreInit(Class *thread_class, Class *thrdGrp_class) { MethodBlock *system_init_mb, *main_init_mb; FieldBlock *thread_status_fb, *eetop_fb; Object *system, *main, *main_name; init_mb_with_name = findMethod(thread_class, SYMBOL(object_init), SYMBOL(_java_lang_ThreadGroup_java_lang_String__V)); init_mb_no_name = findMethod(thread_class, SYMBOL(object_init), SYMBOL(_java_lang_ThreadGroup_java_lang_Runnable__V)); thread_status_fb = findField(thread_class, SYMBOL(threadStatus), SYMBOL(I)); eetop_fb = findField(thread_class, SYMBOL(eetop), SYMBOL(J)); system_init_mb = findMethod(thrdGrp_class, SYMBOL(object_init), SYMBOL(___V)); main_init_mb = findMethod(thrdGrp_class, SYMBOL(object_init), SYMBOL(_java_lang_ThreadGroup_java_lang_String__V)); if(init_mb_with_name == NULL || init_mb_no_name == NULL || system_init_mb == NULL || main_init_mb == NULL || thread_status_fb == NULL || eetop_fb == NULL) return NULL; CLASS_CB(thread_class)->flags |= JTHREAD; thread_status_offset = thread_status_fb->u.offset; eetop_offset = eetop_fb->u.offset; if((system = allocObject(thrdGrp_class)) == NULL) return NULL; executeMethod(system, system_init_mb); if(exceptionOccurred()) return NULL; if((main = allocObject(thrdGrp_class)) == NULL || (main_name = Cstr2String("main")) == NULL) return NULL; executeMethod(main, main_init_mb, system, main_name); if(exceptionOccurred()) return NULL; return main; }
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 detachThread(Thread *thread) { Object *group, *excep; //ExecEnv *ee = thread->ee; //Object *jThread = ee->thread; Object *jThread = thread->thread; Object *vmthread = (Object*)INST_DATA(jThread)[vmthread_offset]; /* Get the thread's group */ group = (Object *)INST_DATA(jThread)[group_offset]; /* If there's an uncaught exception, call uncaughtException on the thread's exception handler, or the thread's group if this is unset */ if((excep = exceptionOccurred())) { FieldBlock *fb = findField(thread_class, SYMBOL(exceptionHandler), SYMBOL(sig_java_lang_Thread_UncaughtExceptionHandler)); Object *thread_handler = fb == NULL ? NULL : (Object *)INST_DATA(jThread)[fb->offset]; Object *handler = thread_handler == NULL ? group : thread_handler; MethodBlock *uncaught_exp = lookupMethod(handler->classobj, SYMBOL(uncaughtException), SYMBOL(_java_lang_Thread_java_lang_Throwable__V)); if(uncaught_exp) { clearException(); DummyFrame dummy; executeMethod(&dummy, handler, uncaught_exp, jThread, excep); } else printException(); } /* remove thread from thread group */ DummyFrame dummy; executeMethod(&dummy, group, (CLASS_CB(group->classobj))->method_table[rmveThrd_mtbl_idx], jThread); /* set VMThread ref in Thread object to null - operations after this point will result in an IllegalThreadStateException */ INST_DATA(jThread)[vmthread_offset] = 0; /* Remove thread from the ID map hash table */ deleteThreadFromHash(thread); /* Disable suspend to protect lock operation */ disableSuspend(thread); /* Grab global lock, and update thread structures protected by it (thread list, thread ID and number of daemon threads) */ pthread_mutex_lock(&lock); /* remove from thread list... */ if((thread->prev->next = thread->next)) thread->next->prev = thread->prev; /* One less live thread */ threads_count--; /* Recycle the thread's thread ID */ freeThreadID(thread->id); /* Handle daemon thread status */ if(!INST_DATA(jThread)[daemon_offset]) non_daemon_thrds--; pthread_mutex_unlock(&lock); /* notify any threads waiting on VMThread object - these are joining this thread */ objectLock(vmthread); objectNotifyAll(vmthread); objectUnlock(vmthread); /* It is safe to free the thread's ExecEnv and stack now as these are only used within the thread. It is _not_ safe to free the native thread structure as another thread may be concurrently accessing it. However, they must have a reference to the VMThread -- therefore, it is safe to free during GC when the VMThread is determined to be no longer reachable. */ // sysFree(ee->stack); //sysFree(ee); /* If no more daemon threads notify the main thread (which may be waiting to exit VM). Note, this is not protected by lock, but main thread checks again */ if(non_daemon_thrds == 0) { /* No need to bother with disabling suspension * around lock, as we're no longer on thread list */ pthread_mutex_lock(&exit_lock); pthread_cond_signal(&exit_cv); pthread_mutex_unlock(&exit_lock); } TRACE("Thread 0x%x id: %d detached from VM\n", thread, thread->id); }
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); }
*/ #include "jam.h" #include "symbol.h" static Class *magic_accessor; int classlibInitialiseAccess() { magic_accessor = findSystemClass0(SYMBOL(sun_reflect_MagicAccessorImpl)); if(magic_accessor == NULL) return FALSE; registerStaticClassRef(&magic_accessor); return TRUE; } int classlibAccessCheck(Class *class, Class *referrer) { Class *host_class = CLASS_CB(referrer)->host_class; if(host_class != NULL) { while(CLASS_CB(host_class)->host_class != NULL) host_class = CLASS_CB(host_class)->host_class; if(host_class == class) return TRUE; } return isSubClassOf(magic_accessor, referrer); }
* or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "jam.h" char implements(Class *class, Class *test) { ClassBlock *test_cb = CLASS_CB(test); int i; for(i = 0; i < test_cb->interfaces_count; i++) if((class == test_cb->interfaces[i]) || implements(class, test_cb->interfaces[i])) return TRUE; if(test_cb->super) return implements(class, test_cb->super); return FALSE; } char isSubClassOf(Class *class, Class *test) { for(; test != NULL && test != class; test = CLASS_CB(test)->super);