theroom101
theroom101

Reputation: 609

Jni FindClass returns NULL

I got c++ structs in header file,

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;
};  

and cpp file is

 #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;");
 }

function initializeJniPointers() crushes on line StatusLine::GetStatusCode = GetJniEnv()->GetMethodID(); because StatusLine::Class is NULL. But! I notice that: If I write this in some java file of the project StatusLine l = new StatuLine() { ... }

Function crushes on ByteArrayOutputStream::Constructor because ByteArrayOutputStream::Class is NULL, if I create an object of ByteArrayOutputStream in java, function will go further to the next object, etc... I notice that: If I just declare a variable of ByteArrayOutputStream, findClass will return NULL.

Could someone explain me what to do? BTW I use Android 2.3.5 device Samsung GT-S5363, I tried other vertions of android (elder) and devices and it works fine.

Upvotes: 2

Views: 8685

Answers (2)

Eugene Dudnyk
Eugene Dudnyk

Reputation: 6030

Basically this can occur if the thread where you ask FindClass is not the main thread and in your thread system does not build a map of java class IDs.

Check this out, probably you have to ask FindClass first in the main thread (when JNI loads or somewhere else), and then you will have ability to do that in any thread.

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

Also try this out, this worked for me: https://svn.apache.org/repos/asf/mesos/branches/0.10.x/src/java/jni/convert.cpp

The solution (taken from link above) is finding a Java class loader from your app in JNI_OnLoad and ask him to find class then from any thread. Otherwise, after calling env->FindClass JNI can fall back to the system class loader which loads only system classes like String.

Upvotes: 8

Boyko Perfanov
Boyko Perfanov

Reputation: 3047

Another technique that has worked for me is to instantiate an object of the needed class, Java-side, just before the native method call (e.g. in AsyncTask doInBackground()).

Upvotes: 0

Related Questions