Exemple #1
0
/**
 * Returns the list of all Java threads.
 *
 * @param[out] threads resulting threads list
 * @param[out] count_ptr number of threads in the resulting list
 */
IDATA VMCALL jthread_get_all_threads(jthread ** threads, jint * count_ptr)
{
    assert(threads);
    assert(count_ptr);

    hythread_group_t java_thread_group = get_java_thread_group();
    assert(java_thread_group);
    hythread_iterator_t iterator = hythread_iterator_create(java_thread_group);
    IDATA count = hythread_iterator_size(iterator);

    IDATA java_thread_count = 0;
    for (IDATA i = 0; i < count; i++) {
        hythread_t native_thread = hythread_iterator_next(&iterator);
        vm_thread_t vm_thread = jthread_get_vm_thread(native_thread);
        if (vm_thread && vm_thread->java_thread) {
            java_thread_count++;
        }
    }

    jthread *java_threads = (jthread*)malloc(sizeof(jthread) * java_thread_count);
    if (!java_threads) {
        hythread_iterator_release(&iterator);
        return TM_ERROR_OUT_OF_MEMORY;
    }

    hythread_iterator_reset(&iterator);
    java_thread_count = 0;
    for (IDATA i = 0; i < count; i++) {
        hythread_t native_thread = hythread_iterator_next(&iterator);
        vm_thread_t vm_thread = jthread_get_vm_thread(native_thread);
        if (vm_thread && vm_thread->java_thread) {
            hythread_suspend_disable();
            ObjectHandle thr = oh_allocate_local_handle();
            assert(thr);
            thr->object = vm_thread->java_thread->object;
            assert(thr->object);
            hythread_suspend_enable();
            java_threads[java_thread_count++] = thr;
        }
    }
    *threads = java_threads;
    *count_ptr = (jint)java_thread_count;
    IDATA status = hythread_iterator_release(&iterator);

    return status;
} // jthread_get_all_threads
Exemple #2
0
void ti_enumerate_roots(TIEnv *ti_env, hythread_iterator_t iterator)
{
    TRACE2("ti.trace", "enumerating roots");

    // FIXME: weird function table manipulations
    void (*save_gc_add_root_set_entry)
        (Managed_Object_Handle *ref, Boolean pinned);
    void (*save_gc_add_weak_root_set_entry)
        (Managed_Object_Handle *ref1, Boolean pinned, Boolean short_weak);
    void (*save_gc_add_root_set_entry_interior_pointer)
        (void **slot, int offset, Boolean pinned);
    void (*save_gc_add_compressed_root_set_entry)
        (U_32 *ref, Boolean pinned);

    // save away old values
    save_gc_add_root_set_entry =
        gc_add_root_set_entry;
    save_gc_add_weak_root_set_entry =
        gc_add_weak_root_set_entry;
    save_gc_add_root_set_entry_interior_pointer =
        gc_add_root_set_entry_interior_pointer;
    save_gc_add_compressed_root_set_entry =
        gc_add_compressed_root_set_entry;

    // hijack ti enumeration functions
    gc_add_root_set_entry =
        ti_add_root_set_entry;
    gc_add_weak_root_set_entry =
        ti_add_weak_root_set_entry;
    gc_add_root_set_entry_interior_pointer =
        ti_add_root_set_entry_interior_pointer;
    gc_add_compressed_root_set_entry =
        ti_add_compressed_root_set_entry;

    // Run through list of active threads and enumerate each one of them.
    hythread_t tm_thread = hythread_iterator_next(&iterator);
    while (tm_thread && !ti_env->iteration_state->abort) {
        vm_thread_t thread = jthread_get_vm_thread(tm_thread);
        if (thread)
            ti_enumerate_thread(ti_env, thread);
        tm_thread = hythread_iterator_next(&iterator);
    }

    // finally, process all the global refs
    ti_enumerate_globals(ti_env);

    // restore original enumeration functions
    gc_add_root_set_entry =
        save_gc_add_root_set_entry;
    gc_add_weak_root_set_entry =
        save_gc_add_weak_root_set_entry;
    gc_add_root_set_entry_interior_pointer =
        save_gc_add_root_set_entry_interior_pointer;
    gc_add_compressed_root_set_entry =
        save_gc_add_compressed_root_set_entry;

    TRACE2("ti.trace", "completed root enumeration");
}
Exemple #3
0
/**
 * Returns the <code>thread</code>'s state according
 * to JVMTI specification. See <a href=http://java.sun.com/j2se/1.5.0/docs/guide/jvmti/jvmti.html#GetThreadState> 
 * JVMTI Specification </a> for more details.
 *
 * @param[in] java_thread thread those state is to be queried
 * @param[out] state resulting thread state
 * 
 */
IDATA VMCALL jthread_get_jvmti_state(jthread java_thread, jint * state)
{
    assert(state);
    assert(java_thread);

    hythread_t native_thread = jthread_get_native_thread(java_thread);
    vm_thread_t vm_thread = jthread_get_vm_thread(native_thread);
    *state = 0;
    if (!native_thread) {
        // Not started yet
        return TM_ERROR_NONE;
    }

    if (hythread_is_alive(native_thread)) {
        *state |= JVMTI_THREAD_STATE_ALIVE;
    }
    if (hythread_is_runnable(native_thread)) {
        *state |= JVMTI_THREAD_STATE_RUNNABLE;
    }
    if (hythread_is_blocked_on_monitor_enter(native_thread)) {
        *state |= JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
    }
    if (hythread_is_waiting(native_thread)) {
        *state |= JVMTI_THREAD_STATE_WAITING;
    }
    if (hythread_is_waiting_indefinitely(native_thread)) {
        *state |= JVMTI_THREAD_STATE_WAITING_INDEFINITELY;
    }
    if (hythread_is_waiting_with_timeout(native_thread)) {
        *state |= JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT;
    }
    if (hythread_is_sleeping(native_thread)) {
        *state |= JVMTI_THREAD_STATE_SLEEPING;
    }
    if (hythread_is_in_monitor_wait(native_thread)) {
        *state |= JVMTI_THREAD_STATE_IN_OBJECT_WAIT;
    }
    if (hythread_is_parked(native_thread)) {
        *state |= JVMTI_THREAD_STATE_PARKED;
    }
    if (hythread_interrupted(native_thread)) {
        *state |= JVMTI_THREAD_STATE_INTERRUPTED;
    }
    if (hythread_is_in_native(native_thread)) {
        *state |= JVMTI_THREAD_STATE_IN_NATIVE;
    }
    if (hythread_is_terminated(native_thread)) {
        *state |= JVMTI_THREAD_STATE_TERMINATED;
    }
    if (vm_thread && vm_thread->suspend_flag) {
        *state |= JVMTI_THREAD_STATE_SUSPENDED;
    }

    return TM_ERROR_NONE;
} // jthread_get_jvmti_state
Exemple #4
0
static bool ncai_thread_is_alive(hythread_t hythread)
{
    if (!hythread)
        return false;

    vm_thread_t vm_thread = jthread_get_vm_thread(hythread);

    if (!vm_thread || !vm_thread->java_thread)
        return false;

    return hythread_is_alive(hythread);
}
Exemple #5
0
ncaiError JNICALL
ncaiGetThreadInfo(ncaiEnv *env, ncaiThread thread, ncaiThreadInfo *info_ptr)
{
    TRACE2("ncai.thread", "ncaiGetThreadsInfo called");
    SuspendEnabledChecker sec;

    if (env == NULL)
        return NCAI_ERROR_INVALID_ENVIRONMENT;

    if (info_ptr == NULL)
        return NCAI_ERROR_NULL_POINTER;

    if (thread == NULL)
        return NCAI_ERROR_INVALID_THREAD;

    hythread_t hythread = reinterpret_cast<hythread_t>(thread);

    if (!ncai_thread_is_alive(hythread))
        return NCAI_ERROR_THREAD_NOT_ALIVE;

    jthread java_thread = jthread_get_java_thread(hythread);

    if (java_thread != NULL)
    {
        JNIEnv* jni_env = jthread_get_vm_thread(hythread)->jni_env;
        jclass cl = GetObjectClass(jni_env, java_thread);
        jmethodID id = jni_env->GetMethodID(cl, "getName","()Ljava/lang/String;");
        jstring  name = jni_env->CallObjectMethod(java_thread, id);
        info_ptr->name = (char *)jni_env->GetStringUTFChars(name, NULL);

        info_ptr->kind = NCAI_THREAD_JAVA;
        return NCAI_ERROR_NONE;
    }

    info_ptr->kind = NCAI_THREAD_VM_INTERNAL;

    const char* name_int = "native_0x";
    size_t name_len = strlen(name_int) + 4 + 1;
    info_ptr->name = (char*)ncai_alloc(name_len);
    assert(info_ptr->name);
    sprintf(info_ptr->name, "%s%04X", name_int, hythread_get_id(hythread));

    return NCAI_ERROR_NONE;
}
Exemple #6
0
/**
 * Returns the number of all Java threads.
 *
 * @param[out] count_ptr number of threads.
 */
IDATA VMCALL jthread_get_thread_count(jint * count_ptr)
{
    assert(count_ptr);
    hythread_group_t java_thread_group = get_java_thread_group();
    assert(java_thread_group);
    hythread_iterator_t iterator = hythread_iterator_create(java_thread_group);
    IDATA count = hythread_iterator_size(iterator);

    IDATA java_thread_count = 0;
    for (IDATA i = 0; i < count; i++) {
        hythread_t native_thread = hythread_iterator_next(&iterator);
        vm_thread_t vm_thread = jthread_get_vm_thread(native_thread);
        if (vm_thread) {
            java_thread_count++;
        }
    }
    *count_ptr = (jint)java_thread_count;
    IDATA status = hythread_iterator_release(&iterator);

    return status;
} // jthread_get_thread_count
Exemple #7
0
ncaiError JNICALL
ncaiTerminateThread(ncaiEnv *env, ncaiThread thread)
{
    TRACE2("ncai.thread", "TerminateThread called");
    SuspendEnabledChecker sec;

    if (env == NULL)
        return NCAI_ERROR_INVALID_ENVIRONMENT;

    if (thread == NULL)
        return NCAI_ERROR_INVALID_THREAD;

    hythread_t hythread = reinterpret_cast<hythread_t>(thread);

    hythread_t self = hythread_self();

    if (hythread == self)
        return NCAI_ERROR_INVALID_THREAD;

    assert(thread);

    // grab hythread global lock
    hythread_global_lock();

    if (!ncai_thread_is_alive(hythread))
    {
        hythread_global_unlock();
        return NCAI_ERROR_THREAD_NOT_ALIVE;
    }

    IDATA UNUSED status = jthread_vm_detach(jthread_get_vm_thread(hythread));
    assert(status == TM_ERROR_NONE);

    hythread_cancel(hythread);

    // release hythread global lock
    hythread_global_unlock();

    return NCAI_ERROR_NONE;
}
Exemple #8
0
/**
 * Returns the owner of the lock associated with the given monitor.
 *
 * If the given monitor is not owned by any thread, NULL is returned.
 *
 * @param[in] monitor monitor those owner needs to be determined
 * @param[out] lock_owner thread which owns the monitor
 */
IDATA VMCALL jthread_get_lock_owner(jobject monitor, jthread * lock_owner)
{
    assert(monitor);
    assert(lock_owner);

    *lock_owner = NULL;
    IDATA status = TM_ERROR_NONE;

    hythread_suspend_disable();
    hythread_thin_monitor_t *lockword = vm_object_get_lockword_addr(monitor);
    hythread_t native_thread = hythread_thin_monitor_get_owner(lockword);
    if (native_thread) {
        vm_thread_t vm_thread = jthread_get_vm_thread(native_thread);
        if (vm_thread) {
            *lock_owner = vm_thread->java_thread;
        } else {
            status = TM_ERROR_ILLEGAL_STATE;
        }
    }
    hythread_suspend_enable();

    return status;
} // jthread_get_lock_owner
Exemple #9
0
/**
 * Detaches current thread from VM.
 */
jint vm_detach(jobject java_thread)
{
    assert(hythread_is_suspend_enabled());

    hythread_t native_thread = jthread_get_native_thread(java_thread);
    assert(native_thread);
    vm_thread_t p_vm_thread = jthread_get_vm_thread(native_thread);
    assert(p_vm_thread);

    // Send Thread End event
    if(jvmti_should_report_event(JVMTI_EVENT_THREAD_END)) {
        jvmti_send_thread_start_end_event(p_vm_thread, 0);
    }

    // change java_status for native thread
    native_thread->java_status = TM_STATUS_ALLOCATED;

    if (native_thread == hythread_self()) {
        // Notify GC about thread detaching.
        // FIXME - GC notify detach thread works for current thread only
        gc_thread_kill(&p_vm_thread->_gc_private_information);
    }

    if (ti_is_enabled())
    {
        apr_status_t UNREF status;
        status = port_vmem_free(
            p_vm_thread->jvmti_thread.jvmti_jit_breakpoints_handling_buffer,
            TM_JVMTI_MAX_BUFFER_SIZE);
        assert(status == APR_SUCCESS);
    }

    // Destroy current VM_thread pool and zero VM_thread structure
    jthread_deallocate_vm_thread_pool(p_vm_thread);

    return JNI_OK;
}
Exemple #10
0
vm_thread_t jthread_get_vm_thread_ptr_safe(jobject thread_obj)
{
    hythread_t native = jthread_get_native_thread(thread_obj);
    return jthread_get_vm_thread(native);
}
Exemple #11
0
/*
 * Set Step Mode for given thread
 * If thread is NULL, set mode for all known threads
 */
ncaiError JNICALL
ncaiSetStepMode(ncaiEnv* env,
                ncaiThread thread,
                ncaiStepMode mode)
{
    TRACE2("ncai.event", "SetStepMode called," <<
        "thread = " << thread << " mode = " << mode);
    SuspendEnabledChecker sec;

    if (mode < NCAI_STEP_OFF || mode > NCAI_STEP_OUT)
        return NCAI_ERROR_ILLEGAL_ARGUMENT;

    GlobalNCAI* ncai = VM_Global_State::loader_env->NCAI;
    hythread_t hythread = reinterpret_cast<hythread_t>(thread);
    VMBreakPoints* vm_brpt = ((NCAIEnv*)env)->ti_env->vm->vm_env->TI->vm_brpt;
    vm_thread_t vm_thread = jthread_get_vm_thread(hythread);

    assert(vm_thread);
    if (vm_thread == NULL)
        return NCAI_ERROR_INTERNAL;

    jvmti_thread_t jvmti_thread = &vm_thread->jvmti_thread;

    LMAutoUnlock lock(vm_brpt->get_lock());

    if (thread)
    {
        ncai_check_alloc_ss_data(jvmti_thread);
        jvmti_thread->ncai_ss->use_local_mode = true;
        jvmti_thread->ncai_ss->step_mode = mode;
        jvmti_thread->ncai_ss->flag_out = false;
        return NCAI_ERROR_NONE;
    }

    ncaiThread* threads;
    jint thread_count;

    ncaiError err = ncaiGetAllThreads((ncaiEnv*)env, &thread_count, &threads);

    if (err != NCAI_ERROR_NONE)
        return err;

    assert(thread_count > 0);

    for (jint i = 0; i < thread_count; i++)
    {
        hythread = (hythread_t)threads[i];
        vm_thread = jthread_get_vm_thread(hythread);

        if (!vm_thread)
            continue;

        ncai_check_alloc_ss_data(&vm_thread->jvmti_thread);
        vm_thread->jvmti_thread.ncai_ss->use_local_mode = false;
        vm_thread->jvmti_thread.ncai_ss->flag_out = false;
    }

    ncai->step_mode = mode;

    return NCAI_ERROR_NONE;
}