我试图了解JNI Application的奇怪行为。我正在从本机JNI dll例程(sayHello)启动线程,而该例程在启动时依次尝试附加到JVM线程以获取环境变量。但是,它暗示除非主线程退出,否则无法这样做。怎么来的?在下面的示例中(忽略线程内存泄漏),仅在主线程中的Thread.sleep(5000)之后,线程例程foo才能成功附加到JVM。这是为什么?
输出:
Hello World!!!
Hello World from C++!
Hello FROM FOO
Good Bye World!!!
%%% JNIEnv attached : 00000206FF8E7B40
JAVA代码
package com.home;
public class Main {
static {
System.loadLibrary("JNITest"); // Load native library hello.dll (Windows) or libhello.so (Unixes)
// at runtime
// This library contains a native method called sayHello()
}
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
System.out.println("Hello World!!!");
new Main().sayHello();
Thread.sleep(5000);
System.out.println("Good Bye World!!!");
}
// Declare an instance native method sayHello() which receives no parameter and returns void
private native void sayHello();
}
JNI DLL
// JNITest.cpp : Defines the exported functions for the DLL application.
//
#include "com_home_Main.h"
#include "stdafx.h"
#include <iostream>
#include <thread>
static JavaVM *g_jVM = NULL;
using namespace std;
void foo()
{
JNIEnv *jEnv = NULL;
cout << "Hello FROM FOO" << endl;
g_jVM->AttachCurrentThreadAsDaemon((void **)(&jEnv), NULL);
if (jEnv == NULL)
{
std::cout << "\n !!! Failed to attach current thread with JVM !!! \n";
}
else
{
std::cout << "\n %%%\t JNIEnv attached : " << (void *)jEnv;
g_jVM->DetachCurrentThread();
}
}
extern "C"
// Implementation of the native method sayHello()
JNIEXPORT void JNICALL Java_com_home_Main_sayHello(JNIEnv *env, jobject thisObj) {
cout << "Hello World from C++!" << endl;
env->GetJavaVM(&g_jVM);
std::thread *first = new std::thread(foo);
return;
}