2014-09-29 140 views
1

我得到的C++结构在头文件,JNI findClass的返回NULL

struct StatusLine 
{ 
    static jclass Class; // Lorg/apache/http/StatusLine; 
    static jmethodID GetStatusCode; //()I 
}; 

struct ByteArrayOutputStream 
{ 
    static jclass Class; // Ljava/io/ByteArrayOutputStream; 
    static jmethodID Constructor; //()V 
    static jmethodID Close; //()V 
    static jmethodID ToByteArray; //()[B 
}; 

struct HttpEntity 
{ 
    static jclass Class; // Lorg/apache/http/HttpEntity; 
    static jmethodID WriteTo; // (Ljava/io/OutputStream;)V 
    static jmethodID GetContent; //()Ljava/io/InputStream; 
}; 

和CPP文件是

#define JAVA_STATUS_LINE_CLASS    "org/apache/http/StatusLine" 
#define JAVA_HTTP_ENTITY_CLASS    "org/apache/http/HttpEntity" 
#define JAVA_BYTE_ARRAY_OUTPUT_STREAM_CLASS "java/io/ByteArrayOutputStream" 

jclass StatusLine::Class = 0; 
jmethodID StatusLine::GetStatusCode = 0; 

jclass ByteArrayOutputStream::Class = 0; 
jmethodID ByteArrayOutputStream::Constructor = 0; 
jmethodID ByteArrayOutputStream::Close = 0; 
jmethodID ByteArrayOutputStream::ToByteArray = 0; 

jclass HttpEntity::Class = 0; 
jmethodID HttpEntity::WriteTo = 0; 
jmethodID HttpEntity::GetContent = 0; 

void initializeJniPointers() 
{ 
     StatusLine::Class = GetJniEnv()->FindClass(JAVA_STATUS_LINE_CLASS); 
     StatusLine::GetStatusCode = GetJniEnv()->GetMethodID(StatusLine::Class, "getStatusCode", "()I"); 


     ByteArrayOutputStream::Class = GetJniEnv()->FindClass(JAVA_BYTE_ARRAY_OUTPUT_STREAM_CLASS); 
     ByteArrayOutputStream::Constructor = GetJniEnv()->GetMethodID(ByteArrayOutputStream::Class, "<init>", "()V"); 
     ByteArrayOutputStream::Close = GetJniEnv()->GetMethodID(ByteArrayOutputStream::Class, "close", "()V"); 
     ByteArrayOutputStream::ToByteArray = GetJniEnv()->GetMethodID(ByteArrayOutputStream::Class, "toByteArray", "()[B"); 

     HttpEntity::Class = GetJniEnv()->FindClass(JAVA_HTTP_ENTITY_CLASS); 
     HttpEntity::WriteTo = GetJniEnv()->GetMethodID(HttpEntity::Class, "writeTo", "(Ljava/io/OutputStream;)V"); 
     HttpEntity::GetContent = GetJniEnv()->GetMethodID(HttpEntity::Class, "getContent", "()Ljava/io/InputStream;"); 
} 

功能initializeJniPointers()压碎上线状态行:: GetStatusCode = GetJniEnv() - >的GetMethodID();因为StatusLine :: Class是NULL。 但是!我注意到: 如果我写这个项目 状态行升一些Java文件=新StatuLine(){ ... }

功能上ByteArrayOutputStream击碎::构造,因为ByteArrayOutputStream ::类为null ,如果我在java中创建一个ByteArrayOutputStream对象,函数将进一步到下一个对象,等等......我注意到:如果我只声明ByteArrayOutputStream的变量,findClass将返回NULL。

有人能解释我该怎么做吗?顺便说一下,我使用Android 2.3.5设备三星GT-S5363,我尝试了其他android(老人)和设备的顶点,它工作正常。

回答

6

基本上,如果您询问FindClass的线程不是主线程,并且您的线程系统不会构建java类ID的映射,则可能会发生此问题。

检查一下,可能你必须首先在主线程中(当JNI加载或其他地方)询问FindClass,然后你将有能力在任何线程中做到这一点。

http://discuss.cocos2d-x.org/t/jni-findclass-cannot-find-a-class-if-its-called-by-a-new-pthread/1873/4

也尝试了这一点,这个工作对我来说: https://svn.apache.org/repos/asf/mesos/branches/0.10.x/src/java/jni/convert.cpp

溶液(来自上面的链接所)被发现在JNI_OnLoad您的应用程序的Java类加载器,并要求他找到类然后从任何线程。否则,在调用env-> FindClass之后,JNI可以回退到只加载像String这样的系统类的系统类加载器。

+0

我想是的,因为我加载类manualy后,指针返回正常。但是,只有Android 2.x版本才会出现此问题。在Android 4.x版本上,该错误没有发生。 – theroom101 2015-01-15 13:09:50

+0

对我来说,这个问题只发生在Android> 5.0 – DisableR 2015-01-15 13:16:05

+0

虽然没有在<4.0.4上测试过这个解决方案。 – DisableR 2015-01-15 17:33:18

0

另一种为我工作的技术是在本地方法调用之前(例如在AsyncTask doInBackground()中)实例化所需类Java对象的对象。