2011-09-14 47 views
2

我正在执行橡皮擦数据竞争检测算法作为JVMTI代理程序。 当我尝试运行一些示例输入值来测试我的代码,JVM的崩溃,与转储类似如下(可以显示相同的错误其他堆栈跟踪以及):JVMTI代理程序崩溃

FATAL ERROR in native method: Using JNIEnv in the wrong thread at Proxy.monitor_enter_(Native Method) at Proxy.monitor_enter(Proxy.java:30) at ex1.LifeThreads.setNeighborThreadChange(LifeThreads.java:36) at ex1.LifeThreads.neighbor(LifeThreads.java:425) at ex1.LifeThreads.standardItr(LifeThreads.java:321) at ex1.LifeThreads.run(LifeThreads.java:462)

(这种验尸跟踪可以通过Sun JVM的-Xcheck:jni选项获得)

在代码中,我执行与各种JDK示例(heapViewer,heapTracker等通过某些代理java类所示的相同种类的工具与本地方法)。在每个monitorenter指令之后调用本地方法Proxy.monitor_enter_

这是monitor_enter_代码:

void native_monitor_exit(JNIEnv *jni, jclass klass, jthread thread_id, jobject obj) 
{ 
    scoped_lock(agent::instance()->jvmti(), agent::instance()->monitor_); 
     if(agent::instance()->death_active_) 
       return; 

    std::string name = agent::instance()->thread_name(thread_id); 
     thread_t* thread = get_thread(thread_id); 
     if(thread == 0) 
      return; 
     jobject global_ref = agent::instance()->jni()->NewGlobalRef(obj); 
     if(global_ref == 0) 
       fatal_error("Out of memory while trying to create new global ref."); 

    logger::instance()->level(1) << "MONITOR ENTER" 
       << "\n\t" << "jthread name= " << name 
       << "\n\t" << "thread_t= " << thread << " " << *thread 
       << "\n\t" << "monitor gl= " << global_ref 
       << std::endl; 

     thread->lock(lock(global_ref)); 
} 

,其中scoped_lock基本上是输入范围的锁JVMTI原始监视器/退出, thread_t只是一个struct包装一些std::vector,其中lock类的实例(当调用thread->lock(lock(global_ref))时,它本身仅包含jobject全局引用global_ref)被存储。

JVMTI env。被全局高速缓存在代理单例中,而JNI env是线程本地的,每次在它使用之前都会重新加载(这不是那么高效,但现在我不在乎),如下所示:

JNIEnv* jni() 
{ 
    jint res; 
    JNIEnv* env = 0; 
    res = jvm()->GetEnv((void**)&env, JNI_VERSION_1_2); 
    if(res == JNI_EDETACHED) 
    { 
     res = jvm()->AttachCurrentThread((void **)&env, 0); 
     if(res != JNI_OK || env == 0) 
      fatal_error("ERROR: Unable to create JNIEnv by attach, error=%d\n", res); 
    } 
     else if(res != JNI_OK || env == 0) 
     fatal_error("ERROR: Unable to create JNIEnv, error=%d\n", res); 
    } 
    return env; 
} 

回答

0

您应该使用传递给native_monitor_exit方法的jni参数,而不是在您的jni()方法中查找它,它是从Java调用方法时应该使用的jni环境。