免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3878 | 回复: 10

JavaNative 使用Boost多线程库的问题 [复制链接]

论坛徽章:
19
CU大牛徽章
日期:2013-03-13 15:32:35CU大牛徽章
日期:2013-09-18 15:15:15CU大牛徽章
日期:2013-05-20 10:46:44CU大牛徽章
日期:2013-05-20 10:46:38CU大牛徽章
日期:2013-05-20 10:46:31CU大牛徽章
日期:2013-05-20 10:46:25CU大牛徽章
日期:2013-05-20 10:46:18CU大牛徽章
日期:2013-04-17 11:19:51CU大牛徽章
日期:2013-04-17 11:19:42CU大牛徽章
日期:2013-04-17 11:19:37CU大牛徽章
日期:2013-04-17 11:19:32CU大牛徽章
日期:2013-04-17 11:19:28
发表于 2013-07-19 11:43 |显示全部楼层
Java类文件
  1. package com.fangzhaoguo.primefinder;

  2. public class NativeConcurrentPrimeFinder {

  3.         static {
  4.                 System.loadLibrary("libJavaNative_ConcurrentPrimeFinder");
  5.         }

  6.         public NativeConcurrentPrimeFinder() {
  7.         }

  8.         public native boolean isPrime(final long number);

  9.         public native int countPrime(final long number);

  10.         public native int countPrime(final long lower, final long upper);

  11.              public native int countPrimeInRange(final long lower, final long upper);
  12. }
复制代码
javah后的C头文件,并且经过我的修改,加入了自定义的变量
  1. /* DO NOT EDIT THIS FILE - it is machine generated */
  2. #include "jni.h"
  3. #include <boost/thread.hpp>
  4. #include <stdio.h>
  5. #include <math.h>
  6. /* Header for class com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder */
  7. jint total = 0;

  8. #ifndef _Included_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder
  9. #define _Included_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder
  10. #ifdef __cplusplus
  11. extern "C" {
  12. #endif
  13. /*
  14. * Class:     com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder
  15. * Method:    isPrime
  16. * Signature: (J)Z
  17. */
  18. JNIEXPORT jboolean JNICALL Java_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder_isPrime(
  19.                 JNIEnv *, jobject, jlong);

  20. /*
  21. * Class:     com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder
  22. * Method:    countPrime
  23. * Signature: (J)I
  24. */
  25. JNIEXPORT jint JNICALL Java_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder_countPrime__J(
  26.                 JNIEnv *, jobject, jlong);

  27. /*
  28. * Class:     com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder
  29. * Method:    countPrime
  30. * Signature: (JJ)I
  31. */
  32. JNIEXPORT jint JNICALL Java_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder_countPrime__JJ(
  33.                 JNIEnv *, jobject, jlong, jlong);

  34. /*
  35. * Class:     com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder
  36. * Method:    countPrimeInRange
  37. * Signature: (JJ)V
  38. */
  39. JNIEXPORT void JNICALL Java_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder_countPrimeInRange(
  40.                 JNIEnv *, jobject, jlong, jlong);

  41. #ifdef __cplusplus
  42. }
  43. #endif
  44. #endif
复制代码
Mingw编译的C++文件 ,使用了Boost库,并且在链接时使用了system和thread两个动态链接库,编译正常
  1. /*
  2. * com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder.c
  3. *
  4. *  Created on: 2013年7月18日
  5. *      Author: root
  6. */

  7. #include "com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder.h"

  8. JNIEXPORT jboolean JNICALL Java_com_fangzhaoguo_primefinder_NativePrimeFinder_isPrime(
  9.                 JNIEnv *env, jobject obj, jlong number) {
  10.         jlong i = 0;
  11.         if (1 >= number) {
  12.                 return 0;
  13.         }
  14.         for (i = 2; i <= sqrt(number); i++) {
  15.                 if (0 == number % i) {
  16.                         return 0;
  17.                 }
  18.         }
  19.         return 1;
  20. }

  21. JNIEXPORT void JNICALL Java_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder_countPrimeInRange(
  22.                 JNIEnv *env, jobject obj, jlong lower, jlong upper) {
  23.         jlong i = 0;
  24.         for (i = lower; i < upper; i++) {
  25.                 if (Java_com_fangzhaoguo_primefinder_NativePrimeFinder_isPrime(env, obj,
  26.                                 i)) {
  27.                         total++;
  28.                 }
  29.         }
  30. }

  31. JNIEXPORT jint JNICALL Java_com_fangzhaoguo_primefinder_NativePrimeFinder_countPrime__J(
  32.                 JNIEnv *env, jobject obj, jlong number) {
  33.         using namespace boost;
  34.         jlong start = 0, end = 0;
  35.         jlong range = number / 4;
  36.         jint i = 0;
  37.         for (i = 0; i < 4; i++) {
  38.                 start = 0 + range * i;
  39.                 if (i < 3) {
  40.                         end = start + range;
  41.                 } else {
  42.                         end = number;
  43.                 }
  44.                 thread mythread(
  45.                                 Java_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder_countPrimeInRange,
  46.                                 env, obj, start, end);
  47.         }
  48.         return total;
  49. }

  50. JNIEXPORT jint JNICALL Java_com_fangzhaoguo_primefinder_NativePrimeFinder_countPrime__JJ(
  51.                 JNIEnv *env, jobject obj, jlong lower, jlong upper) {
  52.         jlong i = 0;
  53.         for (i = lower; i < upper; i++) {
  54.                 if (Java_com_fangzhaoguo_primefinder_NativePrimeFinder_isPrime(env, obj,
  55.                                 i)) {
  56.                         total++;
  57.                 }
  58.         }
  59.         return total;
  60. }
复制代码
但是现在的问题是在java中运行时报错,不管使用C写还是加载boost类的C++写,都报相同的错误。有不使用C/C++多线程的例子,可以正常使用
以下是报错内容
  1. Exception in thread "main" java.lang.UnsatisfiedLinkError: com.fangzhaoguo.primefinder.NativeConcurrentPrimeFinder.countPrime(J)I
  2.         at com.fangzhaoguo.primefinder.NativeConcurrentPrimeFinder.countPrime(Native Method)
  3.         at com.fangzhaoguo.primefinder.Main.timeAndCompute(Main.java:58)
  4.         at com.fangzhaoguo.primefinder.Main.main(Main.java:6)
复制代码

论坛徽章:
39
白银圣斗士
日期:2015-11-24 10:40:40酉鸡
日期:2015-03-20 14:15:44寅虎
日期:2015-03-20 14:13:59午马
日期:2015-03-20 14:13:16白羊座
日期:2015-03-20 14:12:54金牛座
日期:2015-03-20 14:12:09双子座
日期:2015-03-20 14:11:57巨蟹座
日期:2015-03-20 14:11:44狮子座
日期:2015-03-20 14:11:29亥猪
日期:2015-03-20 14:16:24戌狗
日期:2015-03-20 14:16:40申猴
日期:2015-03-20 14:17:05
发表于 2013-07-20 02:43 |显示全部楼层
  1. System.loadLibrary("libJavaNative_ConcurrentPrimeFinder");
复制代码
你Android里的模块名是"libJavaNative_ConcurrentPrimeFinder"?
  1. JNICALL Java_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder_countPrime__J
  2. Java_com_fangzhaoguo_primefinder_NativePrimeFinder_countPrime__JJ
复制代码
为啥你J前面是两个"_",应该只有一个"_"才对.你javah生成后仔细对比下看看

论坛徽章:
19
CU大牛徽章
日期:2013-03-13 15:32:35CU大牛徽章
日期:2013-09-18 15:15:15CU大牛徽章
日期:2013-05-20 10:46:44CU大牛徽章
日期:2013-05-20 10:46:38CU大牛徽章
日期:2013-05-20 10:46:31CU大牛徽章
日期:2013-05-20 10:46:25CU大牛徽章
日期:2013-05-20 10:46:18CU大牛徽章
日期:2013-04-17 11:19:51CU大牛徽章
日期:2013-04-17 11:19:42CU大牛徽章
日期:2013-04-17 11:19:37CU大牛徽章
日期:2013-04-17 11:19:32CU大牛徽章
日期:2013-04-17 11:19:28
发表于 2013-07-20 18:04 |显示全部楼层
rover12421 发表于 2013-07-20 02:43
你Android里的模块名是"libJavaNative_ConcurrentPrimeFinder"?为啥你J前面是两个"_",应该只有一个"_"才对. ...


我用javah生成就这样,使两个下划线(刚刚又试了一下)。
我还有一个疑惑,我在JavaNative的C函数调用一个函数,是必须按照javah生成的格式写,还是按照普通的C函数写

论坛徽章:
39
白银圣斗士
日期:2015-11-24 10:40:40酉鸡
日期:2015-03-20 14:15:44寅虎
日期:2015-03-20 14:13:59午马
日期:2015-03-20 14:13:16白羊座
日期:2015-03-20 14:12:54金牛座
日期:2015-03-20 14:12:09双子座
日期:2015-03-20 14:11:57巨蟹座
日期:2015-03-20 14:11:44狮子座
日期:2015-03-20 14:11:29亥猪
日期:2015-03-20 14:16:24戌狗
日期:2015-03-20 14:16:40申猴
日期:2015-03-20 14:17:05
发表于 2013-07-20 20:16 |显示全部楼层
回复 3# 方兆国


    有两种方式,一种是你现在的这种,必须使用javah生成的函数名.还有一种是在jni_onload里注册.这样的函数名就可以随意
比如:
  1. package com.kill;

  2. public class Check {
  3.     static {
  4.         /**
  5.          * 加载动态库
  6.          */
  7.         System.loadLibrary("kill");
  8.     }
  9.         
  10.     private static native int kill();
  11. }
复制代码
第一种:
  1. JNIEXPORT jint JNICALL Java_com_rover12421_iamemulated_IAmEmulatedActivity_test
  2.   (JNIEnv * env, jclass clazz)
  3. {
  4.         return 0;
  5. }
复制代码
第二种:


  1. # define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))

  2. JNIEXPORT jint JNICALL test(JNIEnv * env, jclass clazz);

  3. static JNINativeMethod methods[] = {
  4.                 {"kill", "()I", (void*)test},
  5. };

  6. static const char *classPathName = "com/kill/Check";

  7. jint JNI_OnLoad(JavaVM* vm, void* reserved) {
  8.         JNIEnv* env = NULL;
  9.         jclass clazz;
  10.         //获取JNI环境对象
  11.         if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
  12.                 return JNI_ERR;
  13.         }


  14.         //注册本地方法Load 目标类
  15.         clazz = (*env)->FindClass(env,classPathName);
  16.         if (clazz == NULL) {
  17.                 return JNI_ERR;
  18.         }


  19.         //注册本地native方法
  20.         if((*env)->RegisterNatives(env, clazz, methods, NELEM(methods)) < 0) {
  21.                 return JNI_ERR;
  22.         }

  23.         /* success -- return valid version number */
  24.         return JNI_VERSION_1_4;
  25. }

  26. JNIEXPORT jint JNICALL test(JNIEnv * env, jclass clazz)
  27. {
  28.        return 0;
  29. }
复制代码
其实第二种注册方式,运行效率会更高

论坛徽章:
39
白银圣斗士
日期:2015-11-24 10:40:40酉鸡
日期:2015-03-20 14:15:44寅虎
日期:2015-03-20 14:13:59午马
日期:2015-03-20 14:13:16白羊座
日期:2015-03-20 14:12:54金牛座
日期:2015-03-20 14:12:09双子座
日期:2015-03-20 14:11:57巨蟹座
日期:2015-03-20 14:11:44狮子座
日期:2015-03-20 14:11:29亥猪
日期:2015-03-20 14:16:24戌狗
日期:2015-03-20 14:16:40申猴
日期:2015-03-20 14:17:05
发表于 2013-07-20 20:26 |显示全部楼层
看你代码应该是没错的,你检查下修改的代码是否编译进so了
打开so查找Java_com_fangzhaoguo_primefinder_NativeConcurrentPrimeFinder_countPrime__J这个字符串,如果有的话,应该是没问题的才是

论坛徽章:
19
CU大牛徽章
日期:2013-03-13 15:32:35CU大牛徽章
日期:2013-09-18 15:15:15CU大牛徽章
日期:2013-05-20 10:46:44CU大牛徽章
日期:2013-05-20 10:46:38CU大牛徽章
日期:2013-05-20 10:46:31CU大牛徽章
日期:2013-05-20 10:46:25CU大牛徽章
日期:2013-05-20 10:46:18CU大牛徽章
日期:2013-04-17 11:19:51CU大牛徽章
日期:2013-04-17 11:19:42CU大牛徽章
日期:2013-04-17 11:19:37CU大牛徽章
日期:2013-04-17 11:19:32CU大牛徽章
日期:2013-04-17 11:19:28
发表于 2013-07-20 23:00 |显示全部楼层
rover12421 发表于 2013-07-20 20:26
看你代码应该是没错的,你检查下修改的代码是否编译进so了
打开so查找Java_com_fangzhaoguo_primefinder_Na ...
  1. 0000000068481550 T Java_com_fangzhaoguo_primefinder_NativePrimeFinder_countPrime
  2. _J
  3. 00000000684816e0 T Java_com_fangzhaoguo_primefinder_NativePrimeFinder_countPrime
  4. _JJ
  5. 0000000068481470 T Java_com_fangzhaoguo_primefinder_NativePrimeFinder_isPrime
复制代码
在动态链接库中是一个下划线


这是C版本的,用了C++ Boost的里面的函数名完全变了

论坛徽章:
39
白银圣斗士
日期:2015-11-24 10:40:40酉鸡
日期:2015-03-20 14:15:44寅虎
日期:2015-03-20 14:13:59午马
日期:2015-03-20 14:13:16白羊座
日期:2015-03-20 14:12:54金牛座
日期:2015-03-20 14:12:09双子座
日期:2015-03-20 14:11:57巨蟹座
日期:2015-03-20 14:11:44狮子座
日期:2015-03-20 14:11:29亥猪
日期:2015-03-20 14:16:24戌狗
日期:2015-03-20 14:16:40申猴
日期:2015-03-20 14:17:05
发表于 2013-07-21 00:32 |显示全部楼层
回复 6# 方兆国


    应该是找到原因了,应该是"_"的问题,我测试下看看

论坛徽章:
39
白银圣斗士
日期:2015-11-24 10:40:40酉鸡
日期:2015-03-20 14:15:44寅虎
日期:2015-03-20 14:13:59午马
日期:2015-03-20 14:13:16白羊座
日期:2015-03-20 14:12:54金牛座
日期:2015-03-20 14:12:09双子座
日期:2015-03-20 14:11:57巨蟹座
日期:2015-03-20 14:11:44狮子座
日期:2015-03-20 14:11:29亥猪
日期:2015-03-20 14:16:24戌狗
日期:2015-03-20 14:16:40申猴
日期:2015-03-20 14:17:05
发表于 2013-07-21 01:51 |显示全部楼层
测试发现,只要是有同名的方法,方法名和参数之间就是用两个"_"分割的,编译的链接库里也是两个"_"的

还有个问题没问你
  1. System.loadLibrary("libJavaNative_ConcurrentPrimeFinder");
复制代码
windows下加载的是libJavaNative_ConcurrentPrimeFinder.dll文件,linux下加载的是liblibJavaNative_ConcurrentPrimeFinder.so文件.不知道你是啥平台.对应的文件对不对
如果这个没问题,你就应该检查下,为啥源代码是两个"_",而你编译之后的动态链接库却只有一个"_"

论坛徽章:
19
CU大牛徽章
日期:2013-03-13 15:32:35CU大牛徽章
日期:2013-09-18 15:15:15CU大牛徽章
日期:2013-05-20 10:46:44CU大牛徽章
日期:2013-05-20 10:46:38CU大牛徽章
日期:2013-05-20 10:46:31CU大牛徽章
日期:2013-05-20 10:46:25CU大牛徽章
日期:2013-05-20 10:46:18CU大牛徽章
日期:2013-04-17 11:19:51CU大牛徽章
日期:2013-04-17 11:19:42CU大牛徽章
日期:2013-04-17 11:19:37CU大牛徽章
日期:2013-04-17 11:19:32CU大牛徽章
日期:2013-04-17 11:19:28
发表于 2013-07-21 11:39 |显示全部楼层
rover12421 发表于 2013-07-21 01:51
测试发现,只要是有同名的方法,方法名和参数之间就是用两个"_"分割的,编译的链接库里也是两个"_"的

还有个 ...


我是Windows下的mingw。之前有过成功的例子,不过当时没有用到c多线程,现在带多线程的都是这个问题

论坛徽章:
39
白银圣斗士
日期:2015-11-24 10:40:40酉鸡
日期:2015-03-20 14:15:44寅虎
日期:2015-03-20 14:13:59午马
日期:2015-03-20 14:13:16白羊座
日期:2015-03-20 14:12:54金牛座
日期:2015-03-20 14:12:09双子座
日期:2015-03-20 14:11:57巨蟹座
日期:2015-03-20 14:11:44狮子座
日期:2015-03-20 14:11:29亥猪
日期:2015-03-20 14:16:24戌狗
日期:2015-03-20 14:16:40申猴
日期:2015-03-20 14:17:05
发表于 2013-07-21 11:44 |显示全部楼层
回复 9# 方兆国


    你先检查下那个"_"问题,为啥不一致,实在不行,不用重名方法试试.如果只是多线程引起的话,是不是编译还需要加多线程支持参数
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP