그래서 저는 C++에서 java 메소드를 호출하지 않으려 고 노력했습니다.JNI - C++에서 Java 메소드 호출
JNI 에러 (앱 버그) : 액세스 부실 로컬 기준 0x5cb00019 0xdeadd00d에서 VM 중단 치명적인 신호 (11) (SIGSEGV) (크기 2의 테이블의 인덱스 6) (이는 I가받는 에러입니다 코드 = 1)
다음
내가 코드 (자바 쪽) 할 것입니다 :
public class Wrapper extends Activity{
private native void initJNIBridge();
static final String TAG = "Wrapper";
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
initJNIBridge(); // Calls C++ function.
}
public void upgradeAdFree() {
Log.d(TAG, "Wrapper::upgradeAdFree()");
}
그리고 여기를 C++ 쪽 :
typedef struct JniMethodInfo_
{
JNIEnv * env;
jclass classID;
jmethodID methodID;
} JniMethodInfo;
extern "C"
{
static jobject javaObj;
// get env and cache it
static JNIEnv* getJNIEnv(void)
{
JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
if (NULL == jvm) {
LOGD("Failed to get JNIEnv. JniHelper::getJavaVM() is NULL");
return NULL;
}
JNIEnv *env = NULL;
// get jni environment
jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
switch (ret) {
case JNI_OK :
// Success!
return env;
case JNI_EDETACHED :
// Thread not attached
// TODO : If calling AttachCurrentThread() on a native thread
// must call DetachCurrentThread() in future.
// see: http://developer.android.com/guide/practices/design/jni.html
if (jvm->AttachCurrentThread(&env, NULL) < 0)
{
LOGD("Failed to get the environment using AttachCurrentThread()");
return NULL;
} else {
// Success : Attached and obtained JNIEnv!
return env;
}
case JNI_EVERSION :
// Cannot recover from this error
LOGD("JNI interface version 1.4 not supported");
default :
LOGD("Failed to get the environment using GetEnv()");
return NULL;
}
}
// get class and make it a global reference, release it at endJni().
static jclass getClassID(JNIEnv *pEnv)
{
jclass ret = pEnv->FindClass(CLASS_NAME);
if (! ret)
{
LOGD("Failed to find class of %s", CLASS_NAME);
}
return ret;
}
static bool getMethodInfo(JniMethodInfo &methodinfo, const char *methodName, const char *paramCode)
{
jmethodID methodID = 0;
JNIEnv *pEnv = 0;
bool bRet = false;
do
{
pEnv = getJNIEnv();
if (! pEnv)
{
break;
}
jclass classID = getClassID(pEnv);
methodID = pEnv->GetMethodID(classID, methodName, paramCode);
if (! methodID)
{
LOGD("Failed to find method id of %s", methodName);
break;
}
methodinfo.classID = classID;
methodinfo.env = pEnv;
methodinfo.methodID = methodID;
bRet = true;
} while (0);
return bRet;
}
JNIEXPORT void JNICALL Java_org_test_games_Wrapper_initJNIBridge(JNIEnv *, jobject jobj){
LOGD("Java_org_test_games_Wrapper_initJNIBridge()");
javaObj = jobj;
return;
}
void upgradeAdFreeJNI()
{
LOGD("upgradeAdFreeJNI");
JniMethodInfo methodInfo;
if (! getMethodInfo(methodInfo, "upgradeAdFree", "()V"))
{
LOGD("Cannot find method!");
return;
}
methodInfo.env->CallVoidMethod(javaObj, methodInfo.methodID);
}
}
나는 이것을 며칠 동안 그리고이 문제를 디버깅하기위한 세계에서 가장 쉬운 작업이 아니기 때문에 여기에있는 모든 의견을 크게 기뻐할 것입니다.
감사
감사 mkaes 님의 http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/functions.html#global_local
변경을 참조하십시오! 그것은 트릭을했다. – kub