Как использовать JNI для изменения полей класса Java
Я использую нативную функцию ac для изменения целочисленных полей класса Java. В основном я хочу увидеть, как вызов по ссылке может быть реализован с использованием JNI. Но я получаю сообщение об ошибке "Не найдена реализация для родного". Кто-нибудь может помочь мне решить эту проблему. Я новичок в Android и Java. Ниже приведены коды, которые я написал. Если кто-то может изменить это, чтобы удовлетворить то, что я хочу, я определенно буду признателен ему за помощь.
Java-код:
class myclass {
int a = 1;
int b = 2;
public native void callTochangeJNI();
static {
System.loadLibrary("sum_jni");
}
}
public class sum extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sum);
myclass myobject = new myclass();
System.out.println("calling the jni native method");
myobject.callTochangeJNI();
System.out.println("returned from jni native method one");
myobject.callTochangeJNI();
System.out.format(" a = %d%n....", myobject.a);
System.out.format("b = %d%n...", myobject.b);
}
}
c родной метод:
void Java_com_kpit_myfirstndkapp_sum_callTochangeJNI(JNIEnv* env, jobject obj )
{
jfieldID fid;
jmethodID mid;
jclass myclass;
printf(" Inside the JNI native method \n");
jclass localRefCls = (*env)->FindClass(env, "java/lang/String");
myclass = (*env)->NewGlobalRef(env, localRefCls);
fid = (*env)->GetFieldID(env,myclass," a ","I");
(*env)->SetIntField(env, obj ,fid,3);
fid = (*env)->GetFieldID(env,myclass," b ","I");
(*env)->SetIntField(env, obj ,fid,4);
}
ниже журнал, который я получаю:
07-25 09:33:07.723: D/dalvikvm(573): Trying to load lib /data/da/com.kpit.myfirstndkapp /lib/libsum_jni.so 0x4129d7b8
07-25 09:33:07.723: D/dalvikvm(573): Added shared lib /data/data/com.kpit.myfirstndkapp/lib/libsum_jni.so 0x4129d7b8
07-25 09:33:07.723: D/dalvikvm(573): No JNI_OnLoad found in /data/data/com.kpit.myfirstndkapp/lib/libsum_jni.so 0x4129d7b8, skipping init
07-25 09:33:07.723: I/System.out(573): calling the jni native method
07-25 09:33:07.723: W/dalvikvm(573): No implementation found for native Lcom/kpit/myfirstndkapp/myclass;.callTochangeJNI ()V
07-25 09:33:07.733: I/dalvikvm(573): Wrote stack traces to '/data/anr/traces.txt'
07-25 09:33:07.804: D/AndroidRuntime(573): Shutting down VM
07-25 09:33:07.804: W/dalvikvm(573): threadid=1: thread exiting with uncaught exception (group=0x409c01f8)
07-25 09:33:07.854: E/AndroidRuntime(573): FATAL EXCEPTION: main
07-25 09:33:07.854: E/AndroidRuntime(573): java.lang.UnsatisfiedLinkError: callTochangeJNI
07-25 09:33:07.854: E/AndroidRuntime(573): at com.kpit.myfirstndkapp.myclass.callTochangeJNI(Native Method)
07-25 09:33:07.854: E/AndroidRuntime(573): at com.kpit.myfirstndkapp.sum.onCreate(sum.java:27)
07-25 09:33:07.854: E/AndroidRuntime(573): at android.app.Activity.performCreate(Activity.java:4465)
07-25 09:33:07.854: E/AndroidRuntime(573): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
07-25 09:33:07.854: E/AndroidRuntime(573): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
07-25 09:33:07.854: E/AndroidRuntime(573): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
07-25 09:33:07.854: E/AndroidRuntime(573): at android.app.ActivityThread.access$600(ActivityThread.java:123)
07-25 09:33:07.854: E/AndroidRuntime(573): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
07-25 09:33:07.854: E/AndroidRuntime(573): at android.os.Handler.dispatchMessage(Handler.java:99)
07-25 09:33:07.854: E/AndroidRuntime(573): at android.os.Looper.loop(Looper.java:137)
07-25 09:33:07.854: E/AndroidRuntime(573): at android.app.ActivityThread.main(ActivityThread.java:4424)
07-25 09:33:07.854: E/AndroidRuntime(573): at java.lang.reflect.Method.invokeNative(Native Method)
07-25 09:33:07.854: E/AndroidRuntime(573): at java.lang.reflect.Method.invoke(Method.java:511)
07-25 09:33:07.854: E/AndroidRuntime(573): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
07-25 09:33:07.854: E/AndroidRuntime(573): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
07-25 09:33:07.854: E/AndroidRuntime(573): at dalvik.system.NativeStart.main(Native Method)
07-25 09:33:08.234: I/dalvikvm(573): threadid=3: reacting to signal 3
07-25 09:33:08.264: I/dalvikvm(573): Wrote stack traces to '/data/anr/traces.txt'
07-25 09:33:08.554: I/dalvikvm(573): threadid=3: reacting to signal 3
07-25 09:33:08.623: I/dalvikvm(573): Wrote stack traces to '/data/anr/traces.txt'
07-25 09:38:07.994: I/Process(573): Sending signal. PID: 573 SIG: 9
пожалуйста, помогите мне
2 ответа
Неверно имя и подпись вашего метода C, имя должно быть Java_PackageName_ClassName_CfunctionName
Если вы звоните из класса с именем MyClass
и его имя пакета com.kpit.myfirstndkapp
тогда ваш метод должен быть объявлен как
JNIEXPORT void JNICALL Java_com_kpit_myfirstndkapp_MyClass_callToChangeJNI(...)
Наконец, после некоторой отладки я получил точный код, который изменяет значения a и b на новые значения. Вот правильный код:
Java code:
package com.kpit.myfirstndkapp;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
class myclass {
int a = 1;
int b = 2;
public native void callTochangeJNI();
static {
System.loadLibrary("sum_jni");
}
}
public class sum extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sum);
myclass myobject = new myclass();
System.out.println("calling the jni native method");
myobject.callTochangeJNI();
System.out.println("returned from jni native method one");
System.out.format(" a = %d%n....", myobject.a);
System.out.format("b = %d%n...", myobject.b);
}}
C native library code:
#include <stdio.h>
#include <stdlib.h>
#include <jni.h>
void Java_com_kpit_myfirstndkapp_myclass_callTochangeJNI(JNIEnv* env,
jobject obj)
{
jfieldID fid;
jmethodID mid;
jclass myclass;
printf(" Inside the JNI native method \n");
jclass cls = (*env)->GetObjectClass(env, obj);
fid = (*env)->GetFieldID(env,cls,"a","I");
(*env)->SetIntField(env, obj ,fid,3);
fid = (*env)->GetFieldID(env,cls,"b","I");
(*env)->SetIntField(env, obj ,fid,4);
}
This works and i get the below log on the screen:
07-26 06:42:30.838: I/System.out(551): calling the jni native method
07-26 06:42:30.859: I/System.out(551): returned from jni native method one
07-26 06:42:30.859: I/System.out(551): a = 3
07-26 06:42:30.868: I/System.out(551): ....b = 4
07-26 06:42:31.179: I/Process(93): Sending signal. PID: 551 SIG: 3
07-26 06:42:31.179: I/dalvikvm(551): threadid=3: reacting to signal 3
07-26 06:42:31.269: I/dalvikvm(551): Wrote stack traces to '/data/anr/traces.txt'
07-26 06:42:31.348: D/gralloc_goldfish(551): Emulator without GPU emulation detected.
07-26 06:42:31.498: I/ActivityManager(93): Displayed com.kpit.myfirstndkapp/.sum:
+ 2s524ms (всего +1m25s486ms) 07-26 06:42:31.558: I/ActivityManager(93): отображается com.android.launcher/com.android.launcher2.Launcher: +1m25s544ms
Я очень благодарен stackru.com за предоставление такой платформы помощи для таких учеников, как я