ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] # 1. 前言 在C中可以通过反射的方式来调用Java的代码,同样还是借助前面配置的JNI环境。这里首先配置要需要供C语言调用的Java类和方法: ~~~ public class JavaMethod { public int add(int a, int b){ System.out.println("调用了JavaMethod类中的类方法。"); return a + b; } public static void showInfo(){ System.out.println("调用了JavaMethod类中的静态方法。"); } } ~~~ # 2. 得到方法签名 可以使用javap命令来查看每个方法的签名,比如可以任意打开一个cmd窗口,执行: ``` javap -s java.lang.String ``` 来查看String类中每个方法的签名。类似的,我们可以先编译一下这个项目,然后在build->intermediates->javac->debug->classes->com.xxx的字节码文件下: ![](https://img.kancloud.cn/c6/f0/c6f01b0c72ca774cbd62a6038421583f_1062x157.png) 然后,拷贝这个地址,比如我这里为: ``` D:\openSourceLearnProject\Android\CustomView\myapplication\build\intermediates\javac\debug\classes\com\weizu\jnitest\JNITest.class ``` 然后执行: ``` javap -s D:\openSourceLearnProject\Android\CustomView\myapplication\build\intermediates\javac\debug\classes\com\weizu\jnitest\JNITest.class ``` 即可得到方法签名: ![](https://img.kancloud.cn/2f/d3/2fd3042c3dfbe0bc11d050e9f7408493_424x186.png) 当然,我这里所需要的不是这个类,我所需要的是上面的JavaMethod 类,这里再次执行一下对应的javap命令,可以得到: ![](https://img.kancloud.cn/0f/cc/0fccfcea2ecda3721f4d1708b0da1e0e_460x233.png) # 3. C语言中反射Java非静态方法 对应的在上一个案例中的native-lib.cpp中将之前的: ~~~ // native-lib.cpp #include "com_weizu_jnitest_JNITest.h" extern "C" jstring Java_com_weizu_jnitest_JNITest_helloJni( JNIEnv* env, jobject /* this */) { std::string hello = "Hello from C++"; return env->NewStringUTF(hello.c_str()); } ~~~ 修改为: ~~~ #include "com_weizu_jnitest_JNITest.h" #include <android/log.h> #define LOG_TAG "System.out" #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) // 在这个方法中进行C调java的反射 extern "C" jstring Java_com_weizu_jnitest_JNITest_helloJni( JNIEnv* env, jobject /* this */) { std::string hello = "Hello from C++"; // 1. 字节码 jclass jclazz = (*env).FindClass("com/weizu/jnitest/JavaMethod"); // 2. 方法add jmethodID jmethodId = (*env).GetMethodID(jclazz, "add", "(II)I"); // 3. 实例化类 jobject jobjectInstance = (*env).AllocObject(jclazz); // 4. 调用方法 jint result = (*env).CallIntMethod(jobjectInstance, jmethodId, 24, 26); LOGE("在C语言中计算结果为:%d\n", result); return env->NewStringUTF(hello.c_str()); } ~~~ 因为在MainActivity中调用了这个方法,且打印结果在日志中: ~~~ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) Log.e("TAG", "onCreate: ${JNITest().helloJni()}" ) } } ~~~ 直接运行程序,查看一下日志信息,就可以知道是否成功: ![](https://img.kancloud.cn/2c/b0/2cb0d57bdcb83fa790a326f542a8488f_1188x248.png) # 4. C语言中反射Java静态方法 我们在写Java中的反射的时候已经比较熟悉了,这里将上面的方法做一个简单的修改: ~~~ // 在这个方法中进行C调java的反射 extern "C" jstring Java_com_weizu_jnitest_JNITest_helloJni( JNIEnv* env, jobject /* this */) { std::string hello = "Hello from C++"; // 1. 字节码 jclass jclazz = (*env).FindClass("com/weizu/jnitest/JavaMethod"); // 2. 方法add jmethodID jmethodId = (*env).GetStaticMethodID(jclazz, "showInfo", "()V"); // 静态方法不需要实例化类 // jobject jobjectInstance = (*env).AllocObject(jclazz); // 3. 调用方法 (*env).CallStaticVoidMethod(jclazz, jmethodId); LOGE("在C语言中调用了Java的静态方法。\n"); return env->NewStringUTF(hello.c_str()); } ~~~ ![](https://img.kancloud.cn/82/76/827635982e734996361e2b32f60a6d70_990x241.png)