C代码需要调用Java代码缓冲区,但无法获取其JNIEnv
我有一个java缓冲区,需要对其进行一些c数据操作。 为此,我调用了一个本机函数“SimpleFunction”,它调用java代码来检索特定索引处的缓冲区值(buffer\u read\u byte)并保存修改后的值(buffer\u byte\u write) Java端:C代码需要调用Java代码缓冲区,但无法获取其JNIEnv,java,android,c,jvm-crash,jnienv,Java,Android,C,Jvm Crash,Jnienv,我有一个java缓冲区,需要对其进行一些c数据操作。 为此,我调用了一个本机函数“SimpleFunction”,它调用java代码来检索特定索引处的缓冲区值(buffer\u read\u byte)并保存修改后的值(buffer\u byte\u write) Java端: byte buffer = new byte[100]; public static byte getByte(int index) { return buffer[index]; } public sta
byte buffer = new byte[100];
public static byte getByte(int index) {
return buffer[index];
}
public static void writeByte(int in, int index) {
buffer[index] = (byte)(in);
}
private native void SimpleFunction(int size);
for(int i=0;i<100;i++)
setBufferModByteInt(0x55,i);
SimpleFunction(100);
#include <android/log.h>
#include <jni.h>
#include <string.h>
#include <stdio.h>
#include "algorithms/global.h"
#define LOG_TAG "NDK"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
static JavaVM* jvm;
void Java_com_App_SimpleFunction(JNIEnv * env, jobject this, jint size)
{
int address=0;
for(address=0;address<(int)(size);address++)
{
/*
some data manipulation on ""value""
*/
value=buffer_read_byte(env,this,address)&0xFF;
buffer_byte_write(env,this,address,value);
}
return;
}
uint8_t buffer_read_byte(JNIEnv * env, jobject this, jint pos)
{
uint8_t value=0;
const char * ss="2";
if ((*env)->ExceptionCheck(env)) {
return;
}
jclass cls = (*env)->FindClass(env,"com/App/Class");
if ((*env)->ExceptionCheck(env)) {
return 0;
}
jmethodID method = (*env)->GetStaticMethodID(env, cls, "getByte", "(I)B");
if ((*env)->ExceptionCheck(env)) {
return 0;
}
jbyte result = (*env)->CallStaticByteMethod(env, cls, method,pos);
if ((*env)->ExceptionCheck(env)) {
return 0;
}
value=(uint8_t) result&0xFF;
if(cls!=NULL)
{
(*env)->DeleteLocalRef(env,cls);
if ((*env)->ExceptionCheck(env)) {
return 0;
}
}
return value;
}
void buffer_byte_write(JNIEnv * env, jobject this, jint pos, jint data)
{
int value=data&0xFF;
jclass cls = (*env)->FindClass(env,"com/App/Class");
if ((*env)->ExceptionCheck(env)) {
return;
}
jmethodID method = (*env)->GetStaticMethodID(env, cls, "writeByte", "(II)V");
if ((*env)->ExceptionCheck(env)) {
return;
}
(*env)->CallStaticVoidMethod(env, cls, method,value,pos);
if ((*env)->ExceptionCheck(env)) {
return;
}
if(cls!=NULL)
{
(*env)->DeleteLocalRef(env,cls);
if ((*env)->ExceptionCheck(env)) {
return;
}
}
return;
}
byte buffer=新字节[100];
公共静态字节getByte(int索引){
返回缓冲区[索引];
}
公共静态void writeByte(int-in,int-index){
缓冲区[索引]=(字节)(in);
}
私有本机void SimpleFunction(int-size);
对于(int i=0;iFindClass(env,“com/App/Class”);
如果((*env)->例外检查(env)){
返回0;
}
jmethodID方法=(*env)->GetStaticMethodID(env,cls,“getByte”,“I)B”);
如果((*env)->例外检查(env)){
返回0;
}
jbyte result=(*env)->CallStaticByteMethod(env、cls、method、pos);
如果((*env)->例外检查(env)){
返回0;
}
值=(uint8_t)结果&0xFF;
如果(cls!=NULL)
{
(*env)->DeleteLocalRef(env,cls);
如果((*env)->例外检查(env)){
返回0;
}
}
返回值;
}
无效缓冲区字节写入(JNIEnv*env、jobject this、jint pos、jint数据)
{
int值=数据&0xFF;
jclass cls=(*env)->FindClass(env,“com/App/Class”);
如果((*env)->例外检查(env)){
返回;
}
jmethodID方法=(*env)->GetStaticMethodID(env,cls,“writeByte”,“II)V”);
如果((*env)->例外检查(env)){
返回;
}
(*env)->CallStaticVoidMethod(env、cls、method、value、pos);
如果((*env)->例外检查(env)){
返回;
}
如果(cls!=NULL)
{
(*env)->DeleteLocalRef(env,cls);
如果((*env)->例外检查(env)){
返回;
}
}
返回;
}
上面的代码有效
现在让我们假设数据操作是由许多内部函数实现的,这些函数在内核中使用c函数buffer\u read\u byte和buffer\u byte\u write。
如何避免在每个调用函数级别显式传递为输入(JNIEnv*env,jobject this)
我有很多预先存在的函数,它们最终需要使用buffer\u read\u byte和buffer\u byte\u write访问java缓冲区。
我如何避免在每个预先存在的父函数和子函数中必须声明输入(JNIEnv*env,jobject this),因为JNIEnv只在内核函数buffer\u read\u byte和buffer\u byte\u write中需要
我检查了全局JVM:
void Java_com_App_SimpleFunction(JNIEnv * env, jobject this, jint size)
{
(*env)->GetJavaVM(env, &jvm);
int address=0;
for(address=0;address<(int)(size);address++)
{
value=buffer_read_byte(address)&0xFF;
/*
some data manipulation on ""value""
*/
buffer_byte_write(address,value);
}
return;
}
uint8_t buffer_read_byte(jint pos)
{
JNIEnv * env;
jint rs=(*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_4);
JavaVMAttachArgs args;
args.version = JNI_VERSION_1_6; // choose your JNI version
args.name = NULL; // you might want to give the java thread a name
args.group = NULL; // you might want to assign the java thread to a ThreadGroup
jint rs=(*jvm)->AttachCurrentThread(jvm, (void**)&env, &args);
//...
return value;
}
uint8_t buffer_byte_write(jint pos, jint data)
{
JNIEnv * env;
jint rs=(*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_4);
JavaVMAttachArgs args;
args.version = JNI_VERSION_1_6; // choose your JNI version
args.name = NULL; // you might want to give the java thread a name
args.group = NULL; // you might want to assign the java thread to a ThreadGroup
jint rs=(*jvm)->AttachCurrentThread(jvm, (void**)&env, &args);
//...
return;
}
void Java\u com\u App\u SimpleFunction(JNIEnv*env,jobject this,jint size)
{
(*env)->GetJavaVM(env和jvm);
int地址=0;
对于(address=0;addressGetEnv(jvm,(void**)和env,JNI_版本1_4);
JavaVMAttachArgs args;
args.version=JNI\u version\u 1\u 6;//选择您的JNI版本
args.name=NULL;//您可能希望为java线程指定一个名称
args.group=NULL;//您可能希望将java线程分配给线程组
jint rs=(*jvm)->AttachCurrentThread(jvm,(void**)和env以及args);
//...
返回值;
}
uint8缓冲区字节写入(jint pos、jint数据)
{
JNIEnv*env;
jintrs=(*jvm)->GetEnv(jvm,(void**)和env,JNI_版本1_4);
JavaVMAttachArgs args;
args.version=JNI\u version\u 1\u 6;//选择您的JNI版本
args.name=NULL;//您可能希望为java线程指定一个名称
args.group=NULL;//您可能希望将java线程分配给线程组
jint rs=(*jvm)->AttachCurrentThread(jvm,(void**)和env以及args);
//...
返回;
}
但是调用SimpleFunction(100)没有执行(我没有对缓冲区进行数据修改),并且在尝试执行GetEnv或者AttachCurrentThread时,会使应用程序崩溃
对于无法获取JNIenv的C代码来说,调用JAVA代码的最佳方法是什么?也许您需要找出它崩溃的原因。看起来您使用的方法是正确的。您也可以查看下面问题中的答案 对于无法获取JNIenv的C代码来说,调用JAVA代码的最佳方法是什么?给它一种获取env的方法。如果由于某种奇怪的原因无法做到这一点,您需要编写一个可以访问它的代理函数,复制实际函数需要的数据,调用实际函数,然后根据需要复制回数据。