java调用dll多线程,C ++多线程Java JNI方法调用

I have a simple class in Java:

public class MyClass

{

public static void dummyTest()

{

}

}

And in C++ I do the following JNI Call:

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);

}

If a single program calls the static method c_call_function() it is ok.

But if a multithread program calls the c_call_function(), it gives me the following message, when passes the line env->CallStaticIntMethod(clazz, mid_dummyTest);:

Access violation at 0x000000006FC77154 read to 0x0000000000000000

If the program is multithread, it uses the same JNIEnv variable.

But I also tried to load the same JNIEnv via AttachCurrentThread method and it gives me the same problem.

What is the restriction when calling the method bellow by multiple threads as long as I don't create any local references or even delete or modify anything?

env->CallStaticIntMethod(clazz, mid_dummyTest);

解决方案

I a able to run similar code (look below) where I have multiple threads accessing the same JVM (macOS). I am using pthread.

Few things that are important

attaching thread to JVM ("The JNI interface pointer (JNIEnv) is valid only in the current thread. Should another thread need to access the Java VM, it must first call AttachCurrentThread() to attach itself to the VM and obtain a JNI interface pointer.")

joining threads

i guess it's a good idea to use mutex as well to prevent multiple threads being attached

main.c

#include

#include

#include

#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

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

Once you run the code, you get following result:

./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

Java多线程可以调用DLL(Dynamic-Link Library)来进行一些特定操作。 首先,在Java调用DLL需要使用到Java Native Interface(JNI)技术。JNIJava提供的一种机制,用于在Java程序中调用本地的C/C++代码。通过JNI,我们可以在Java程序中加载和调用DLL中的函数。 在多线程调用DLL的过程如下: 1. 首先,在Java中编写一个JNI的接口类,用于定义与DLL中函数的映射关系。这个接口类需要使用Java的native关键字来声明与DLL中函数对应的本地方法。 2. 在DLL中实现与接口类中声明的本地方法对应的C/C++函数。这些函数可以通过DLL导出符号的方式供Java程序调用。 3. 在Java程序中加载DLL调用其中的函数。 使用多线程调用DLL时,需要注意以下几点: 1. 线程安全性:在多线程环境下调用DLL时,需要确保DLL中的函数是线程安全的,即能够正确处理多个线程间的共享数据。 2. 同步控制:如果DLL中的函数需要访问共享资源,需要在Java程序中使用同步控制机制,如synchronized关键字或Lock对象来确保线程之间的互斥访问。 3. 线程间通信:如果多个线程需要相互通信,可以通过共享内存或消息传递的方式实现。在DLL中可以使用线程同步的机制来实现线程间的互斥、等待和通知操作。 总之,Java多线程可以通过JNI技术调用DLL来完成一些底层的特定操作。在进行多线程调用DLL时,需要保证线程安全性,确保合适的同步控制和线程间通信方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值