2014-09-29 72 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對象的對象。