JavaNative 使用Boost多线程库的问题
Java类文件package com.fangzhaoguo.primefinder;public class NativeConcurrentPrimeFinder {
static {
System.loadLibrary("libJavaNative_ConcurrentPrimeFinder");
}
public NativeConcurrentPrimeFinder() {
}
public native boolean isPrime(final long number);
public native int countPrime(final long number);
public native int countPrime(final long lower, final long upper);
public native int countPrimeInRange(final long lower, final long upper);
}
javah后的C头文件,并且经过我的修改,加入了自定义的变量/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
#include <boost/thread.hpp>
#include <stdio.h>
#include <math.h>
/* Header for class com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder */
jint total = 0;
#ifndef _Included_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder
#define _Included_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder
* Method: isPrime
* Signature: (J)Z
*/
JNIEXPORT jboolean JNICALL Java_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder_isPrime(
JNIEnv *, jobject, jlong);
/*
* Class: com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder
* Method: countPrime
* Signature: (J)I
*/
JNIEXPORT jint JNICALL Java_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder_countPrime__J(
JNIEnv *, jobject, jlong);
/*
* Class: com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder
* Method: countPrime
* Signature: (JJ)I
*/
JNIEXPORT jint JNICALL Java_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder_countPrime__JJ(
JNIEnv *, jobject, jlong, jlong);
/*
* Class: com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder
* Method: countPrimeInRange
* Signature: (JJ)V
*/
JNIEXPORT void JNICALL Java_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder_countPrimeInRange(
JNIEnv *, jobject, jlong, jlong);
#ifdef __cplusplus
}
#endif
#endif
Mingw编译的C++文件 ,使用了Boost库,并且在链接时使用了system和thread两个动态链接库,编译正常/*
* com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder.c
*
*Created on: 2013年7月18日
* Author: root
*/
#include "com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder.h"
JNIEXPORT jboolean JNICALL Java_com_fangzhaoguo_primefinder_NativePrimeFinder_isPrime(
JNIEnv *env, jobject obj, jlong number) {
jlong i = 0;
if (1 >= number) {
return 0;
}
for (i = 2; i <= sqrt(number); i++) {
if (0 == number % i) {
return 0;
}
}
return 1;
}
JNIEXPORT void JNICALL Java_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder_countPrimeInRange(
JNIEnv *env, jobject obj, jlong lower, jlong upper) {
jlong i = 0;
for (i = lower; i < upper; i++) {
if (Java_com_fangzhaoguo_primefinder_NativePrimeFinder_isPrime(env, obj,
i)) {
total++;
}
}
}
JNIEXPORT jint JNICALL Java_com_fangzhaoguo_primefinder_NativePrimeFinder_countPrime__J(
JNIEnv *env, jobject obj, jlong number) {
using namespace boost;
jlong start = 0, end = 0;
jlong range = number / 4;
jint i = 0;
for (i = 0; i < 4; i++) {
start = 0 + range * i;
if (i < 3) {
end = start + range;
} else {
end = number;
}
thread mythread(
Java_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder_countPrimeInRange,
env, obj, start, end);
}
return total;
}
JNIEXPORT jint JNICALL Java_com_fangzhaoguo_primefinder_NativePrimeFinder_countPrime__JJ(
JNIEnv *env, jobject obj, jlong lower, jlong upper) {
jlong i = 0;
for (i = lower; i < upper; i++) {
if (Java_com_fangzhaoguo_primefinder_NativePrimeFinder_isPrime(env, obj,
i)) {
total++;
}
}
return total;
}
但是现在的问题是在java中运行时报错,不管使用C写还是加载boost类的C++写,都报相同的错误。有不使用C/C++多线程的例子,可以正常使用
以下是报错内容Exception in thread "main" java.lang.UnsatisfiedLinkError: com.fangzhaoguo.primefinder.NativeConcurrentPrimeFinder.countPrime(J)I
at com.fangzhaoguo.primefinder.NativeConcurrentPrimeFinder.countPrime(Native Method)
at com.fangzhaoguo.primefinder.Main.timeAndCompute(Main.java:58)
at com.fangzhaoguo.primefinder.Main.main(Main.java:6)
System.loadLibrary("libJavaNative_ConcurrentPrimeFinder");你Android里的模块名是"libJavaNative_ConcurrentPrimeFinder"?JNICALL Java_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder_countPrime__J
Java_com_fangzhaoguo_primefinder_NativePrimeFinder_countPrime__JJ为啥你J前面是两个"_",应该只有一个"_"才对.你javah生成后仔细对比下看看 rover12421 发表于 2013-07-20 02:43 static/image/common/back.gif
你Android里的模块名是"libJavaNative_ConcurrentPrimeFinder"?为啥你J前面是两个"_",应该只有一个"_"才对. ...
我用javah生成就这样,使两个下划线(刚刚又试了一下)。
我还有一个疑惑,我在JavaNative的C函数调用一个函数,是必须按照javah生成的格式写,还是按照普通的C函数写 回复 3# 方兆国
有两种方式,一种是你现在的这种,必须使用javah生成的函数名.还有一种是在jni_onload里注册.这样的函数名就可以随意
比如:package com.kill;
public class Check {
static {
/**
* 加载动态库
*/
System.loadLibrary("kill");
}
private static native int kill();
}第一种:JNIEXPORT jint JNICALL Java_com_rover12421_iamemulated_IAmEmulatedActivity_test
(JNIEnv * env, jclass clazz)
{
return 0;
}
第二种:
# define NELEM(x) ((int) (sizeof(x) / sizeof((x))))
JNIEXPORT jint JNICALL test(JNIEnv * env, jclass clazz);
static JNINativeMethod methods[] = {
{"kill", "()I", (void*)test},
};
static const char *classPathName = "com/kill/Check";
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
jclass clazz;
//获取JNI环境对象
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
return JNI_ERR;
}
//注册本地方法Load 目标类
clazz = (*env)->FindClass(env,classPathName);
if (clazz == NULL) {
return JNI_ERR;
}
//注册本地native方法
if((*env)->RegisterNatives(env, clazz, methods, NELEM(methods)) < 0) {
return JNI_ERR;
}
/* success -- return valid version number */
return JNI_VERSION_1_4;
}
JNIEXPORT jint JNICALL test(JNIEnv * env, jclass clazz)
{
return 0;
}其实第二种注册方式,运行效率会更高 看你代码应该是没错的,你检查下修改的代码是否编译进so了
打开so查找Java_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder_countPrime__J这个字符串,如果有的话,应该是没问题的才是 rover12421 发表于 2013-07-20 20:26 static/image/common/back.gif
看你代码应该是没错的,你检查下修改的代码是否编译进so了
打开so查找Java_com_fangzhaoguo_primefinder_Na ...0000000068481550 T Java_com_fangzhaoguo_primefinder_NativePrimeFinder_countPrime
_J
00000000684816e0 T Java_com_fangzhaoguo_primefinder_NativePrimeFinder_countPrime
_JJ
0000000068481470 T Java_com_fangzhaoguo_primefinder_NativePrimeFinder_isPrime在动态链接库中是一个下划线
这是C版本的,用了C++ Boost的里面的函数名完全变了
回复 6# 方兆国
应该是找到原因了,应该是"_"的问题,我测试下看看 测试发现,只要是有同名的方法,方法名和参数之间就是用两个"_"分割的,编译的链接库里也是两个"_"的
还有个问题没问你System.loadLibrary("libJavaNative_ConcurrentPrimeFinder");windows下加载的是libJavaNative_ConcurrentPrimeFinder.dll文件,linux下加载的是liblibJavaNative_ConcurrentPrimeFinder.so文件.不知道你是啥平台.对应的文件对不对
如果这个没问题,你就应该检查下,为啥源代码是两个"_",而你编译之后的动态链接库却只有一个"_"
rover12421 发表于 2013-07-21 01:51 static/image/common/back.gif
测试发现,只要是有同名的方法,方法名和参数之间就是用两个"_"分割的,编译的链接库里也是两个"_"的
还有个 ...
我是Windows下的mingw。之前有过成功的例子,不过当时没有用到c多线程,现在带多线程的都是这个问题 回复 9# 方兆国
你先检查下那个"_"问题,为啥不一致,实在不行,不用重名方法试试.如果只是多线程引起的话,是不是编译还需要加多线程支持参数
页:
[1]
2