C ++多线程Java JNI方法调用

 2023-01-20    350  

问题描述

我在Java中有一个简单的课程:

public class MyClass 
{
    public static void dummyTest() 
    {
    }
}

和在C ++中我进行以下JNI调用:

C ++多线程Java JNI方法调用

void c_call_function() 
{
    JNIEnv *env ...// the JNIEnv initialization in JNI...
    jclass clazz ...// the class initialization in JNI...

    jmethodID mid_dummyTest = env->GetStaticMethodID(clazz, "dummyTest", "()V");
env->CallStaticIntMethod(clazz, mid_dummyTest);}

如果单个程序调用静态方法C_CALL_FUNCTICT(),则可以.

但是,如果多线程程序调用c_call_function(),它会给我以下消息,当通过行env-> call-> callstaticintmethod(clazz,mid_dummyTest);:

>

违反访问违规,请访问0x000000006fc77154读取到0x000000000000000000

如果程序是多线程,则使用相同的JNIENV变量.
但是我也尝试通过artachcurrentthread方法加载相同的jnienv,这给了我同样的问题.

只要我不创建任何局部引用,甚至删除或修改任何东西,呼叫该方法在多个线程中调用该方法时的限制是什么?

env->CallStaticIntMethod(clazz, mid_dummyTest);

推荐答案

i能够运行相似的代码(以下)我有多个线程访问相同的JVM(MACOS).我正在使用pthread.

很重要的几件事

  • 将线程连接到JVM(” JNI接口指针(JNIENV)仅在当前线程中有效.如果另一个线程需要访问Java VM,则必须首先调用attachCurrentThreadThread()以将自己附加到VM上并获得JNI接口指针.”)
  • 连接线程
  • 我猜想也是一个好主意

main.c

#include <stdio.h>
#include <jni.h>
#include <pthread.h>

#define NUM_THREADS 6

pthread_mutex_t mutexjvm;
pthread_t threads[NUM_THREADS];

struct JVM {
  JNIEnv *env;
  JavaVM *jvm;
};

void invoke_class(JNIEnv* env);

void *jvmThreads(void* myJvm) {

  struct JVM *myJvmPtr = (struct JVM*) myJvm;
  JavaVM *jvmPtr = myJvmPtr -> jvm;
  JNIEnv *env = myJvmPtr -> env;

  pthread_mutex_lock (&mutexjvm);
  printf("I will call JVM\n");
  (*jvmPtr)->AttachCurrentThread(jvmPtr, (void**) &(env), NULL);
  invoke_class( env );
  (*jvmPtr)->DetachCurrentThread(jvmPtr);
  pthread_mutex_unlock (&mutexjvm);
  pthread_exit(NULL);
}

JNIEnv* create_vm(struct JVM *jvm)
{
    JNIEnv* env;
    JavaVMInitArgs vm_args;
    JavaVMOption options;
    options.optionString = "-Djava.class.path=./";

    vm_args.options = &options;
    vm_args.ignoreUnrecognized = 0;
    vm_args.version = JNI_VERSION_1_6;
    vm_args.nOptions = 1;

    int status = JNI_CreateJavaVM(&jvm->jvm, (void**)&env, &vm_args);
    if (status < 0 || !env)
        printf("Error\n");
    return env;
}

void invoke_class(JNIEnv* env)
{
    jclass Main_class;
    jmethodID fun_id;
    Main_class= (*env)->FindClass(env, "Main");
    fun_id = (*env)->GetStaticMethodID(env, Main_class, "fun", "()I");
    (*env)->CallStaticIntMethod(env, Main_class, fun_id);
}

int main(int argc, char **argv)
{
    struct JVM myJvm;
    myJvm.env = create_vm(&myJvm);

    if(myJvm.env == NULL)
        return 1;

    pthread_mutex_init(&mutexjvm, NULL);
    for(int i=0; i<NUM_THREADS; i++){
        pthread_create(&threads[i], NULL, jvmThreads, (void*) &myJvm);
        pthread_join(threads[i], 0);
    }
    (*myJvm.jvm)->DestroyJavaVM(myJvm.jvm);
}

main.java

public class Main {
    public static void main(String[] args){
        System.out.println("Hello, world");
    }
    public static int fun() {
        System.out.println("From JVM");
        return 0;
    }
}

makefile

all: Main.class main

Main.class: Main.java
    javac Main.java

main.o: main.c
    llvm-gcc -c main.c \
    -I${JAVA_HOME}/include \
    -I${JAVA_HOME}/include/darwin/ \

main: main.o
    ld -o main -L${JAVA_HOME}/jre/lib/server/ \
        -ljvm \
    -rpath ${JAVA_HOME}/jre/lib/server \
    -L/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk \
    -demangle -dynamic -arch x86_64 \
    -macosx_version_min 10.12.0 \
    -lSystem \
    -rpath ${JAVA_HOME}/jre/lib/server/ \
    main.o

clean:
    rm -f Main.class main main.o

运行代码后,您将获得以下结果:

./main
I will call JVM
From JVM
I will call JVM
From JVM
I will call JVM
From JVM
I will call JVM
From JVM
I will call JVM
From JVM
I will call JVM
From JVM

其他推荐答案

env 应分别为每个线程获得.当且仅当线程是*不是由JVM启动的 时,您应该使用 tactercurrentthread().对于发出 entachCurrentThread()的每个线程,您必须调用 distachcurrentthread().

.

clazz 应分别为每个线程获得,或者您可以保存对从 findclass().

mid_dummyTest 可以保存在全局变量中:此ID独立于线程, env 和 clazz .

以上所述是小编给大家介绍的C ++多线程Java JNI方法调用,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!

原文链接:https://77isp.com/post/26120.html

=========================================

https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。