android C++ 和 jni,根据JNIEnv的FindClass获取java类,包括多线程

  • Post author:
  • Post category:java


java代码

TestC.java

package com.example.testnativejava;

import android.util.Log;

public class TestC {

private final static String tag = “TestC”;

}

TestNativeJava.java

package com.example.testnativejava;

import android.util.Log;

public class TestNativeJava {

private final String tag = “TestNativeJava”;

public TestNativeJava() {


Log.d(tag, “new TestNativeJava”);

}

public void ShowLog() {


Log.d(tag, “show log entry”);

System.load(“libtest_c_java.so”);

SayHello();

Log.d(tag, “show log exit”);

}

// jni 接口

public native int SayHello();

}

下面是C++代码

c++ 代码

#include <cerrno>

#include <cstddef>

#include <stdio.h>

#include <stdarg.h>

#include <vector>

#include <dlfcn.h>

#include <android/log.h>

#include <thread>

#include <chrono>         // std::chrono::seconds

#include <jni.h>

#include “test_c_java.h”

#define LOGI(…) ((void)__android_log_print(ANDROID_LOG_INFO, “Test_c_java”, __VA_ARGS__))

static JavaVM *g_JavaVM;

static bool stop = false;

static JNIEnv* jniEnv;

static void Run() {


LOGI(“%s, entry”, __FUNCTION__);

g_JavaVM->AttachCurrentThread(&jniEnv, NULL);

const char *classStr = “android/net/Proxy”;

LOGI(“find class 1 str = %s, !!!!!”, classStr);

jclass p = jniEnv->FindClass(classStr);

LOGI(“find class 2 str = %s, !!!!!”, classStr);

if(p != NULL){


jniEnv->DeleteLocalRef(p);

LOGI(“find class testC is success”);

}

g_JavaVM->DetachCurrentThread();

stop = true;

LOGI(“%s, exit”, __FUNCTION__);

}

static void TestEnv1(JNIEnv *env) {


LOGI(“%s, entry”, __FUNCTION__);

const char *classStr = “android/net/Proxy”;

LOGI(“find class 1 str = %s, !!!!!”, classStr);

jclass p = env->FindClass(classStr);

LOGI(“find class 2 str = %s, !!!!!”, classStr);

if(p == NULL){


LOGI(“find class is error!!!!!”);

LOGI(“%s, exit”, __FUNCTION__);

return;

}

env->DeleteLocalRef(p);

LOGI(“%s, success exit”, __FUNCTION__);

}

static void TestEnv2(JNIEnv *env) {


LOGI(“%s, entry”, __FUNCTION__);

const char *classStr = “com/example/testnativejava/TestC”;

LOGI(“find class testC 1 str = %s, !!!!!”, classStr);

jclass TestC = env->FindClass(classStr);

LOGI(“find class testC 2 str = %s, !!!!!”, classStr);

if(TestC == NULL){


LOGI(“find class testC is error!!!!!”);

return;

}

env->DeleteLocalRef(TestC);

LOGI(“%s, success exit”, __FUNCTION__);

}

jint Java_com_example_testnativejava_TestNativeJava_SayHello(JNIEnv *env, jobject thiz) {


LOGI(“%s, entry”, __FUNCTION__);

TestEnv1(env);

TestEnv2(env);

std::thread t(Run);

while (1) {


if (stop)

break;

std::this_thread::sleep_for (std::chrono::seconds(1));

}

t.join();

LOGI(“%s, exit”, __FUNCTION__);

return 0;

}

jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {


LOGI(“%s, entry”, __FUNCTION__);

g_JavaVM = vm;

LOGI(“%s, exit”, __FUNCTION__);

return JNI_VERSION_1_4;

}

void JNI_OnUnload(JavaVM* vm, void* reserved) {


LOGI(“%s, exit”, __FUNCTION__);

}

JNI_OnLoad在apk加载时就会被调用,用于保存Java的虚拟机实例,JavaVM,在android下是不能自己创建的。

以上有3次使用FindClass去获取jclass,是在java层由jni接口SayHello 调用的

1.TestEnv1 测试android的java 类,具体可以查看类似我的sdk\sources\android-19\android\net\Proxy.java 去查找

2.TestEnv2 测试是自己的apk中java 类,我只从SayHello的入参 env中可以获取到;如果使用JavaVM->AttachCurrentThread(&env, NULL); 使用FindClass是获取不到的,应该是env的classpath不对,应该把AttachCurrentThread的第二个参数 NULL 替换掉,具体换成什么,请自己查看怎么创建JavaVM,当然这个是我的猜测,最好是使用android jni传下的入参。

3. 起线程在run中获取android 的java 类。

以上测试都是成功的。

总结困难:

1.如果获取JavaVM,android 居然不能自己创建,真TNND的CaoDan。

2.测试在线程中如何查找Java类,路径必须要精确到类名,否则是找不到的。

第一篇android的博客终于写完了,花了2天时间终于搞完了。

付出不一定有回报,但不付出一定不会有回报,嘎嘎嘎~



版权声明:本文为zjp114695092原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。