首页 > 代码库 > Class doesn't implement Cloneable之怪象

Class doesn't implement Cloneable之怪象

1. 报错:

  1. 11-20 14:06:10.89: W/dalvikvm(10190): threadid=15: thread exiting with uncaught exception (group=0x4001d400)   
  2. 11-20 14:06:10.360: E/AndroidRuntime(10190): FATAL EXCEPTION: GLThread 10  
  3. 11-20 14:06:10: E/AndroidRuntime(10190): java.lang.CloneNotSupportedException: Class doesn‘t implement Cloneable   
  4. 11-20 14:06:10.360: E/AndroidRuntime(10190):    at java.lang.Object.clone(Object.java:79)   
  5. 11-20 14:06:10.360: E/AndroidRuntime(10190):    at com.jnitest.nativetest(Native Method)

2. 现场说明:

   在进行android项目开发时, 想用java代码调用jni的test函数,, 而且再通过c的callCallBack函数, 回调到java的onCallback函数., 发生以上错误.

 

3. 代码:(这里仅仅列出重要的,关键的代码.)

 java代码:

public class NativeClass {

private static String TAG= "NativeClass";

static {
        System.loadLibrary("test-jni");
    }

public static int onCallBack(int event, int type,String str) {  //回调回来的回调函数
  Log.i(TAG, "onCallBack======= " + event);
  Log.i(TAG, "onCallBack======= " + type);

Log.i(TAG, "onCallBack======= " + str);

return event;

}

public static native int test();  //native函数

 

c代码:

jobject my_obj;
JNIEnv* my_env;


extern "C" int callCallBack(int event, int type, const char *str) ;

extern "C"
{

//用于调用java的callback
int  callCallBack(int event, int type, const char *str)
{
    int err = 1000;
 jclass objClass = (my_env)->FindClass("com/jnitest/native/NativeClass");
 if(!objClass) {
  return -1;
 }
 //获取并调用java层的onCallBack函数
 jmethodID methodId = (my_env)->GetStaticMethodID(objClass, "onCallBack", "(IILjava/lang/String;)I");
 if (methodId == 0) {
  LOGDV("here can not find method %s\n", "onCallBack");
 } else {
  jstring data = http://www.mamicode.com/(update_env)->NewStringUTF(str));
  
  err = (my_env)->CallStaticIntMethod(objClass, methodId, event, type, data);
  if(data)  my_env->DeleteLocalRef(data);
 }

 my_env->DeleteLocalRef(objClass);
 
 
 return err;

}

//jni native函数.
JNIEXPORT jstring JNICALL
Java_com_jnitest_native_test( JNIEnv* env, jobject thiz,jstring testStr )
{
    my_env = env; //必须保存,用于在回调的时候获取回调函数所在的class.
 my_obj = thiz;  //在本程序中,没实用到这个变量.
    const char *test_char = (env)->GetStringUTFChars(testStr, NULL);
 
 //调用callCallBack
 int i = callCallBack(0,1,test_char);

    return (env)->NewStringUTF(test_char);

}
}

 

測试代码:

maintest.java:

 

void testFunc() {

String s = NativeClass.test("ssss");

    Log.i("jniTest", " testFunc  s = " + s);

}

 

測试结果:

onCallBack=======0

onCallBack=======1

onCallBack=======ssss

 testFunc  s =ssss

 

4. 分析与 解决:

分析,:

依据错误提示:

1).  有clone相关错误;

2)   就发生在NativeClass的test函数中.

3). 那么, 是哪个类没有进行clone?

或者, 根本就不是clone的原因?

 4). NativeClass中,没有数据成员, 理论上讲,就不须要进行克隆.所以,应该不是NativeClass克隆的原因.

5). 在jni的test函数中,有对于my_obj的赋值,会不会是这个变量的赋值导致的呢?

解决:  因为my_obj没实用到(本来赋值后想用的), 并且可能会引起错误,所以,将这个变量的声明和赋值语句都去掉,

 

再測试,程序正常执行.

 

5. 总结:

1)  由java调用c时,一定要注意參数的正确传递.

2)  本例展示了怎样用java调用c,再由c调用到java的过程.

3) 本例来源于android程序开发.

 

 

Class doesn't implement Cloneable之怪象