Android调用GetMethodID时崩溃

3

如果您从onclick事件调用ndk函数,应用程序为什么会崩溃:

Test.cpp

#include <jni.h>
#include <stdio.h>
#include <android/log.h>
#define  LOG_TAG    "Test"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

static JNIEnv *m_env = 0;
static jclass m_activityClass;

// Library init
extern "C" jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
    return JNI_VERSION_1_4;
}

extern "C" void Java_com_test_TestActivity_Init(JNIEnv *env, jobject obj)
{

    m_env = env;
    m_activityClass = env->GetObjectClass(obj);
}

extern "C" void Java_com_test_TestActivity_OnButton()
{
    jmethodID mId = m_env->GetMethodID(m_activityClass, "GetDeviceId", "()V");
    if (mId)
        LOGI("success");
}

TestActivity.java

package com.test;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class TestActivity extends Activity
{
static
{
    System.loadLibrary("Test");
}   

public native void Init();
public native void OnButton();

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    Init();

    Button button = (Button)findViewById(R.id.button1);
    button.setOnClickListener(_clickListener);
}

private OnClickListener _clickListener = new OnClickListener()
{
    public void onClick(View v)
    {
        OnButton();
    }
};

public void GetDeviceId()
{

}   
}

日志:

09-03 15:08:42.719: INFO/System.out(749): debugger has settled (1480)
09-03 15:08:43.129: DEBUG/dalvikvm(749): Trying to load lib /data/data/com.test/lib/libTest.so 0x44edee48
09-03 15:08:43.129: DEBUG/dalvikvm(749): Added shared lib /data/data/com.test/lib/libTest.so 0x44edee48
09-03 15:08:43.539: WARN/InputManagerService(59): Starting input on non-focused client com.android.internal.view.IInputMethodClient$Stub$Proxy@4504ae08 (uid=10031 pid=713)
09-03 15:08:43.689: INFO/ActivityManager(59): Displayed activity com.test/.TestActivity: 3971 ms (total 3971 ms)
09-03 15:08:48.879: DEBUG/dalvikvm(263): GC_EXPLICIT freed 50 objects / 2360 bytes in 118ms
09-03 15:08:50.189: WARN/dalvikvm(749): JNI WARNING: 0x44ee2c80 is not a valid JNI reference
09-03 15:08:50.189: WARN/dalvikvm(749):              in Lcom/test/TestActivity;.OnButton ()V (GetMethodID)
09-03 15:08:50.189: INFO/dalvikvm(749): "main" prio=5 tid=1 RUNNABLE
09-03 15:08:50.189: INFO/dalvikvm(749):   | group="main" sCount=0 dsCount=0 s=N obj=0x4001d8e0 self=0xccb0
09-03 15:08:50.199: INFO/dalvikvm(749):   | sysTid=749 nice=0 sched=0/0 cgrp=default handle=-1345026008
09-03 15:08:50.199: INFO/dalvikvm(749):   | schedstat=( 805400585 705858293 113 )
09-03 15:08:50.199: INFO/dalvikvm(749):   at com.test.TestActivity.OnButton(Native Method)
09-03 15:08:50.199: INFO/dalvikvm(749):   at com.test.TestActivity$1.onClick(TestActivity.java:36)
09-03 15:08:50.199: INFO/dalvikvm(749):   at android.view.View.performClick(View.java:2408)
09-03 15:08:50.199: INFO/dalvikvm(749):   at android.view.View$PerformClick.run(View.java:8816)
09-03 15:08:50.199: INFO/dalvikvm(749):   at android.os.Handler.handleCallback(Handler.java:587)
09-03 15:08:50.199: INFO/dalvikvm(749):   at android.os.Handler.dispatchMessage(Handler.java:92)
09-03 15:08:50.199: INFO/dalvikvm(749):   at android.os.Looper.loop(Looper.java:123)
09-03 15:08:50.199: INFO/dalvikvm(749):   at android.app.ActivityThread.main(ActivityThread.java:4627)
09-03 15:08:50.199: INFO/dalvikvm(749):   at java.lang.reflect.Method.invokeNative(Native Method)
09-03 15:08:50.199: INFO/dalvikvm(749):   at java.lang.reflect.Method.invoke(Method.java:521)
09-03 15:08:50.209: INFO/dalvikvm(749):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
09-03 15:08:50.209: INFO/dalvikvm(749):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
09-03 15:08:50.209: INFO/dalvikvm(749):   at dalvik.system.NativeStart.main(Native Method)
09-03 15:08:50.219: ERROR/dalvikvm(749): VM aborting
09-03 15:08:50.383: INFO/DEBUG(31): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
09-03 15:08:50.383: INFO/DEBUG(31): Build fingerprint: 'generic/sdk/generic/:2.2/FRF91/43546:eng/test-keys'
09-03 15:08:50.389: INFO/DEBUG(31): pid: 749, tid: 749  >>> com.test <<<
09-03 15:08:50.389: INFO/DEBUG(31): signal 11 (SIGSEGV), fault addr deadd00d
09-03 15:08:50.389: INFO/DEBUG(31):  r0 00000374  r1 0000000c  r2 0000000c  r3 deadd00d
09-03 15:08:50.389: INFO/DEBUG(31):  r4 00000026  r5 80887fc4  r6 8086d834  r7 0000aa50
09-03 15:08:50.389: INFO/DEBUG(31):  r8 bea64878  r9 4186bdd4  10 0000ce04  fp 4186bdd0
09-03 15:08:50.403: INFO/DEBUG(31):  ip 808881ec  sp bea647d8  lr afd154c5  pc 8083b162  cpsr 20000030
09-03 15:08:50.489: INFO/DEBUG(31):          #00  pc 0003b162  /system/lib/libdvm.so
09-03 15:08:50.489: INFO/DEBUG(31):          #01  pc 0002cff4  /system/lib/libdvm.so
09-03 15:08:50.489: INFO/DEBUG(31):          #02  pc 0002df74  /system/lib/libdvm.so
09-03 15:08:50.489: INFO/DEBUG(31):          #03  pc 0002dfa6  /system/lib/libdvm.so
09-03 15:08:50.499: INFO/DEBUG(31):          #04  pc 0003055c  /system/lib/libdvm.so
09-03 15:08:50.499: INFO/DEBUG(31):          #05  pc 00031d54  /system/lib/libdvm.so
09-03 15:08:50.499: INFO/DEBUG(31):          #06  pc 00000ce8  /data/data/com.test/lib/libTest.so
09-03 15:08:50.509: INFO/DEBUG(31):          #07  pc 00013974  /system/lib/libdvm.so
09-03 15:08:50.509: INFO/DEBUG(31):          #08  pc 0003ddf0  /system/lib/libdvm.so
09-03 15:08:50.509: INFO/DEBUG(31):          #09  pc 000371b6  /system/lib/libdvm.so
09-03 15:08:50.529: INFO/DEBUG(31):          #10  pc 000432ec  /system/lib/libdvm.so
09-03 15:08:50.529: INFO/DEBUG(31):          #11  pc 00024dcc  /system/lib/libdvm.so
09-03 15:08:50.529: INFO/DEBUG(31):          #12  pc 0001d7cc  /system/lib/libdvm.so
09-03 15:08:50.529: INFO/DEBUG(31):          #13  pc 0005408e  /system/lib/libdvm.so
09-03 15:08:50.539: INFO/DEBUG(31):          #14  pc 0005bde2  /system/lib/libdvm.so
09-03 15:08:50.539: INFO/DEBUG(31):          #15  pc 00018714  /system/lib/libdvm.so
09-03 15:08:50.550: INFO/DEBUG(31):          #16  pc 0001e8c4  /system/lib/libdvm.so
09-03 15:08:50.550: INFO/DEBUG(31):          #17  pc 0001d790  /system/lib/libdvm.so
09-03 15:08:50.559: INFO/DEBUG(31):          #18  pc 00053eec  /system/lib/libdvm.so
09-03 15:08:50.559: INFO/DEBUG(31):          #19  pc 0004072c  /system/lib/libdvm.so
09-03 15:08:50.559: INFO/DEBUG(31):          #20  pc 00034454  /system/lib/libdvm.so
09-03 15:08:50.569: INFO/DEBUG(31):          #21  pc 0002c930  /system/lib/libandroid_runtime.so
09-03 15:08:50.579: INFO/DEBUG(31):          #22  pc 0002d85c  /system/lib/libandroid_runtime.so
09-03 15:08:50.579: INFO/DEBUG(31):          #23  pc 00008c86  /system/bin/app_process
09-03 15:08:50.579: INFO/DEBUG(31):          #24  pc 0000d362  /system/lib/libc.so
09-03 15:08:50.579: INFO/DEBUG(31): code around pc:
09-03 15:08:50.589: INFO/DEBUG(31): 8083b140 1861447c 200618a2 e878f7d8 f7d82000 
09-03 15:08:50.589: INFO/DEBUG(31): 8083b150 4808e9e4 6bdb5823 d0002b00 4b064798 
09-03 15:08:50.589: INFO/DEBUG(31): 8083b160 701c2426 ea5cf7d8 0004ce80 fffe4ae0 
09-03 15:08:50.589: INFO/DEBUG(31): 8083b170 fffe801c 00000374 deadd00d b510b40e 
09-03 15:08:50.589: INFO/DEBUG(31): 8083b180 4c0a4b09 447bb083 aa05591b 6b5bca02 
09-03 15:08:50.589: INFO/DEBUG(31): code around lr:
09-03 15:08:50.589: INFO/DEBUG(31): afd154a4 b0834a0d 589c447b 26009001 686768a5 
09-03 15:08:50.589: INFO/DEBUG(31): afd154b4 220ce008 2b005eab 1c28d003 47889901 
09-03 15:08:50.599: INFO/DEBUG(31): afd154c4 35544306 d5f43f01 2c006824 b003d1ee 
09-03 15:08:50.599: INFO/DEBUG(31): afd154d4 bdf01c30 0002ae7c 000000d4 1c0fb5f0 
09-03 15:08:50.599: INFO/DEBUG(31): afd154e4 43551c3d a904b087 1c16ac01 604d9004 
09-03 15:08:50.599: INFO/DEBUG(31): stack:
09-03 15:08:50.599: INFO/DEBUG(31):     bea64798  00000015  
09-03 15:08:50.599: INFO/DEBUG(31):     bea6479c  afd1453b  /system/lib/libc.so
09-03 15:08:50.609: INFO/DEBUG(31):     bea647a0  afd405a0  /system/lib/libc.so
09-03 15:08:50.609: INFO/DEBUG(31):     bea647a4  afd4054c  /system/lib/libc.so
09-03 15:08:50.609: INFO/DEBUG(31):     bea647a8  00000000  
09-03 15:08:50.609: INFO/DEBUG(31):     bea647ac  afd154c5  /system/lib/libc.so
09-03 15:08:50.609: INFO/DEBUG(31):     bea647b0  0000ccb0  [heap]
09-03 15:08:50.609: INFO/DEBUG(31):     bea647b4  afd1450d  /system/lib/libc.so
09-03 15:08:50.609: INFO/DEBUG(31):     bea647b8  0000aa50  [heap]
09-03 15:08:50.609: INFO/DEBUG(31):     bea647bc  80887fc4  /system/lib/libdvm.so
09-03 15:08:50.609: INFO/DEBUG(31):     bea647c0  80887fc4  /system/lib/libdvm.so
09-03 15:08:50.609: INFO/DEBUG(31):     bea647c4  8086d834  /system/lib/libdvm.so
09-03 15:08:50.609: INFO/DEBUG(31):     bea647c8  0000aa50  [heap]
09-03 15:08:50.609: INFO/DEBUG(31):     bea647cc  afd1456b  /system/lib/libc.so
09-03 15:08:50.609: INFO/DEBUG(31):     bea647d0  df002777  
09-03 15:08:50.619: INFO/DEBUG(31):     bea647d4  e3a070ad  
09-03 15:08:50.619: INFO/DEBUG(31): #00 bea647d8  44ee2c80  /dev/ashmem/mspace/dalvik-heap/2 (deleted)
09-03 15:08:50.619: INFO/DEBUG(31):     bea647dc  8082cff9  /system/lib/libdvm.so
09-03 15:08:50.619: INFO/DEBUG(31): #01 bea647e0  44ee2c80  /dev/ashmem/mspace/dalvik-heap/2 (deleted)
09-03 15:08:50.629: INFO/DEBUG(31):     bea647e4  8082df79  /system/lib/libdvm.so
09-03 15:08:51.209: DEBUG/Zygote(33): Process 749 terminated by signal (11)
09-03 15:08:51.221: INFO/WindowManager(59): WIN DEATH: Window{44ff35b8 com.test/com.test.TestActivity paused=false}
09-03 15:08:51.221: INFO/ActivityManager(59): Process com.test (pid 749) has died.
09-03 15:08:51.269: INFO/UsageStats(59): Unexpected resume of com.android.term while already resumed in com.test
09-03 15:08:51.280: INFO/BootReceiver(59): Copying /data/tombstones/tombstone_00 to DropBox (SYSTEM_TOMBSTONE)
09-03 15:08:51.499: DEBUG/dalvikvm(59): GC_FOR_MALLOC freed 2633 objects / 346848 bytes in 192ms
09-03 15:08:51.499: WARN/InputManagerService(59): Got RemoteException sending setActive(false) notification to pid 749 uid 10037
09-03 15:08:56.990: DEBUG/dalvikvm(220): GC_EXPLICIT freed 152 objects / 10888 bytes in 142ms
2个回答

2
问题在于您的本地方法声明了无效的签名,然后您尝试缓存本地引用。 方法签名规则很难记住,通常我们使用javah工具生成它。
Javah使用简单。创建项目后,您可以使用bin文件夹中构建的.class文件:
qrtt1:jni apple$ cd /Users/apple/Documents/workspace/TestAndroid
qrtt1:TestAndroid apple$ ls AndroidManifest.xml assets             
bin                 default.properties  gen                 res       
src qrtt1:TestAndroid apple$ cd bin

添加 "-jni" 选项以生成C头文件:
qrtt1:bin apple$ javah -jni com.test.TestActivity
qrtt1:bin apple$ ls -alh
total 72
drwxr-xr-x   8 apple  staff   272B  9  5 09:34 .
drwxr-xr-x  11 apple  staff   374B  9  5 09:28 ..
-rw-r--r--   1 apple  staff    14K  9  5 09:33 TestAndroid.apk
drwxr-xr-x   3 apple  staff   102B  9  5 09:28 aaa
-rw-r--r--   1 apple  staff   2.9K  9  5 09:33 classes.dex
drwxr-xr-x   3 apple  staff   102B  9  5 09:28 com
-rw-r--r--   1 apple  staff   597B  9  5 09:34 com_test_TestActivity.h
-rw-r--r--   1 apple  staff    10K  9  5 09:33 resources.ap_

最终,你得到了正确的方法签名:
qrtt1:bin apple$ cat com_test_TestActivity.h 
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_test_TestActivity */

#ifndef _Included_com_test_TestActivity
#define _Included_com_test_TestActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_test_TestActivity
 * Method:    Init
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_test_TestActivity_Init
  (JNIEnv *, jobject);

/*
 * Class:     com_test_TestActivity
 * Method:    OnButton
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_test_TestActivity_OnButton
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

如果您想更多地了解jni,有一本好书:Java Native Interface: Programmer's Guide and Specification http://java.sun.com/docs/books/jni/
请参见:
- Local and Global References http://java.sun.com/docs/books/jni/html/refs.html#27423 - The Invocation Interface http://java.sun.com/docs/books/jni/html/invoke.html#11202 - Traps and Pitfalls http://java.sun.com/docs/books/jni/html/pitfalls.html#25706

0

OnButton 应该长成这样:

extern "C" void Java_com_test_TestActivity_OnButton(JNIEnv *env, jobject obj) 

每个可由Java调用的本地方法都应该有这两个参数。崩溃是因为找不到一个名为OnButton()的本地方法,其签名与此类似。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接