extern jboolean __attribute__ ((visibility ("hidden"))) dalvik_setup(
		JNIEnv* env, int apilevel) {
	void* dvm_hand = dlopen("libdvm.so", RTLD_NOW);
	if (dvm_hand) {
		dvmDecodeIndirectRef_fnPtr = dvm_dlsym(dvm_hand,
				apilevel > 10 ?
						"_Z20dvmDecodeIndirectRefP6ThreadP8_jobject" :
						"dvmDecodeIndirectRef");
		if (!dvmDecodeIndirectRef_fnPtr) {
			return JNI_FALSE;
		}
		dvmThreadSelf_fnPtr = dvm_dlsym(dvm_hand,
				apilevel > 10 ? "_Z13dvmThreadSelfv" : "dvmThreadSelf");
		if (!dvmThreadSelf_fnPtr) {
			return JNI_FALSE;
		}
		jclass clazz = env->FindClass("java/lang/reflect/Method");
		jClassMethod = env->GetMethodID(clazz, "getDeclaringClass",
						"()Ljava/lang/Class;");

		return JNI_TRUE;
	} else {
		return JNI_FALSE;
	}
}
extern jboolean __attribute__ ((visibility ("hidden"))) dalvik_setup(
		JNIEnv* env, int apilevel) {
	jni_env = env;
	void* dvm_hand = dlopen("libdvm.so", RTLD_NOW);
	if (dvm_hand) {
		dvmComputeMethodArgsSize_fnPtr = dvm_dlsym(dvm_hand,
				apilevel > 10 ?
						"_Z24dvmComputeMethodArgsSizePK6Method" :
						"dvmComputeMethodArgsSize");
		if (!dvmComputeMethodArgsSize_fnPtr) {
			throwNPE(env, "dvmComputeMethodArgsSize_fnPtr");
			return JNI_FALSE;
		}
		dvmCallMethod_fnPtr = dvm_dlsym(dvm_hand,
				apilevel > 10 ?
						"_Z13dvmCallMethodP6ThreadPK6MethodP6ObjectP6JValuez" :
						"dvmCallMethod");
		if (!dvmCallMethod_fnPtr) {
			throwNPE(env, "dvmCallMethod_fnPtr");
			return JNI_FALSE;
		}
		dexProtoGetParameterCount_fnPtr = dvm_dlsym(dvm_hand,
				apilevel > 10 ?
						"_Z25dexProtoGetParameterCountPK8DexProto" :
						"dexProtoGetParameterCount");
		if (!dexProtoGetParameterCount_fnPtr) {
			throwNPE(env, "dexProtoGetParameterCount_fnPtr");
			return JNI_FALSE;
		}

		dvmAllocArrayByClass_fnPtr = dvm_dlsym(dvm_hand,
				"dvmAllocArrayByClass");
		if (!dvmAllocArrayByClass_fnPtr) {
			throwNPE(env, "dvmAllocArrayByClass_fnPtr");
			return JNI_FALSE;
		}
		dvmBoxPrimitive_fnPtr = dvm_dlsym(dvm_hand,
				apilevel > 10 ?
						"_Z15dvmBoxPrimitive6JValueP11ClassObject" :
						"dvmWrapPrimitive");
		if (!dvmBoxPrimitive_fnPtr) {
			throwNPE(env, "dvmBoxPrimitive_fnPtr");
			return JNI_FALSE;
		}
		dvmFindPrimitiveClass_fnPtr = dvm_dlsym(dvm_hand,
				apilevel > 10 ?
						"_Z21dvmFindPrimitiveClassc" : "dvmFindPrimitiveClass");
		if (!dvmFindPrimitiveClass_fnPtr) {
			throwNPE(env, "dvmFindPrimitiveClass_fnPtr");
			return JNI_FALSE;
		}
		dvmReleaseTrackedAlloc_fnPtr = dvm_dlsym(dvm_hand,
				"dvmReleaseTrackedAlloc");
		if (!dvmReleaseTrackedAlloc_fnPtr) {
			throwNPE(env, "dvmReleaseTrackedAlloc_fnPtr");
			return JNI_FALSE;
		}
		dvmCheckException_fnPtr = dvm_dlsym(dvm_hand,
				apilevel > 10 ?
						"_Z17dvmCheckExceptionP6Thread" : "dvmCheckException");
		if (!dvmCheckException_fnPtr) {
			throwNPE(env, "dvmCheckException_fnPtr");
			return JNI_FALSE;
		}

		dvmGetException_fnPtr = dvm_dlsym(dvm_hand,
				apilevel > 10 ?
						"_Z15dvmGetExceptionP6Thread" : "dvmGetException");
		if (!dvmGetException_fnPtr) {
			throwNPE(env, "dvmGetException_fnPtr");
			return JNI_FALSE;
		}
		dvmFindArrayClass_fnPtr = dvm_dlsym(dvm_hand,
				apilevel > 10 ?
						"_Z17dvmFindArrayClassPKcP6Object" :
						"dvmFindArrayClass");
		if (!dvmFindArrayClass_fnPtr) {
			throwNPE(env, "dvmFindArrayClass_fnPtr");
			return JNI_FALSE;
		}
		dvmCreateReflectMethodObject_fnPtr = dvm_dlsym(dvm_hand,
				apilevel > 10 ?
						"_Z28dvmCreateReflectMethodObjectPK6Method" :
						"dvmCreateReflectMethodObject");
		if (!dvmCreateReflectMethodObject_fnPtr) {
			throwNPE(env, "dvmCreateReflectMethodObject_fnPtr");
			return JNI_FALSE;
		}

		dvmGetBoxedReturnType_fnPtr = dvm_dlsym(dvm_hand,
				apilevel > 10 ?
						"_Z21dvmGetBoxedReturnTypePK6Method" :
						"dvmGetBoxedReturnType");
		if (!dvmGetBoxedReturnType_fnPtr) {
			throwNPE(env, "dvmGetBoxedReturnType_fnPtr");
			return JNI_FALSE;
		}
		dvmUnboxPrimitive_fnPtr = dvm_dlsym(dvm_hand,
				apilevel > 10 ?
						"_Z17dvmUnboxPrimitiveP6ObjectP11ClassObjectP6JValue" :
						"dvmUnwrapPrimitive");
		if (!dvmUnboxPrimitive_fnPtr) {
			throwNPE(env, "dvmUnboxPrimitive_fnPtr");
			return JNI_FALSE;
		}
		dvmDecodeIndirectRef_fnPtr = dvm_dlsym(dvm_hand,
				apilevel > 10 ?
						"_Z20dvmDecodeIndirectRefP6ThreadP8_jobject" :
						"dvmDecodeIndirectRef");
		if (!dvmDecodeIndirectRef_fnPtr) {
			throwNPE(env, "dvmDecodeIndirectRef_fnPtr");
			return JNI_FALSE;
		}
		dvmThreadSelf_fnPtr = dvm_dlsym(dvm_hand,
				apilevel > 10 ? "_Z13dvmThreadSelfv" : "dvmThreadSelf");
		if (!dvmThreadSelf_fnPtr) {
			throwNPE(env, "dvmThreadSelf_fnPtr");
			return JNI_FALSE;
		}

		classJavaLangObjectArray = dvmFindArrayClass_fnPtr(
				"[Ljava/lang/Object;", NULL);
		jclass clazz = env->FindClass("java/lang/reflect/Method");
		jInvokeMethod = env->GetMethodID(clazz, "invoke",
				"(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
		jClassMethod = env->GetMethodID(clazz, "getDeclaringClass",
				"()Ljava/lang/Class;");
		NPEClazz = env->FindClass("java/lang/NullPointerException");
		CastEClazz = env->FindClass("java/lang/ClassCastException");
		return JNI_TRUE;
	} else {
		return JNI_FALSE;
	}
}