【问题标题】:JVMTI agent crashesJVMTI 代理崩溃
【发布时间】:2011-09-14 17:57:41
【问题描述】:

我正在将橡皮擦数据竞争检测算法作为 JVMTI 代理来实现。 当我尝试运行一些示例输入来测试我的代码时,JVM 崩溃,转储如下(也可能显示相同错误的其他堆栈跟踪):

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 Raw Monitor 进入/退出的范围锁, thread_t 只是一个包装了一些 std::vector 的结构,其中在调用 thread-&gt;lock( lock(global_ref)) 时存储了类 lock 的实例(它本身仅包装了 jobject 全局引用 global_ref)。

JVMTI 环境。在代理单例中全局缓存,而线程本地的 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;
}

【问题讨论】:

    标签: java jvm agent jvmti


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-30
      • 2021-07-27
      • 2015-09-24
      • 2019-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-01
      相关资源
      最近更新 更多