标签: java-native-interface

JNI - 在Java和Native代码之间传递大量数据

我想要实现以下目标:

1)我在java端有一个表示图像的字节数组.

2)我需要让我的本机代码访问它.

3)本机代码使用GraphicsMagick解码此图像,并通过调用resize创建一堆缩略图.它还计算图像的感知散列,该散列是矢量或unint8_t数组.

4)一旦我将这些数据返回给Java端,不同的线程就会读取它.缩略图将通过HTTP上传到某些外部存储服务.

我的问题是:

1)将字节从Java传递到我的本机代码的最有效方法是什么?我可以将其作为字节数组访问.我认为将其作为字节缓冲区(包装此字节数组)与字节数组传递在此处没有任何特别的优势.

2)将这些缩略图和感知哈希返回给java代码的最佳方法是什么?我想到了几个选择:

(i)我可以在Java中分配一个字节缓冲区,然后将其传递给我的本机方法.然后,本机方法可以写入并在完成后设置一个限制并返回写入的字节数或一些表示成功的布尔值.然后,我可以对字节缓冲区进行切片和切块,以提取不同的缩略图和感知哈希,并将其传递给将上传缩略图的不同线程.这种方法的问题是我不知道要分配的大小.所需的大小将取决于我提前生成的缩略图的大小和缩略图的数量(我事先知道).

(ii)一旦我知道所需的大小,我也可以在本机代码中分配字节缓冲区.我可以根据自定义打包协议将我的blob记忆到正确的区域并返回此字节缓冲区.(i)和(ii)都很复杂,因为自定义打包协议必须指示每个缩略图的长度和感知散列.

(iii)定义一个具有缩略图字段的Java类:字节缓冲区数组和感知散列字节:字节数组.当我知道所需的确切大小时,我可以在本机代码中分配字节缓冲区.然后,我可以将GraphicsMagick blob中的字节memcpy到每个字节缓冲区的直接地址.我假设还有一些方法来设置写在字节缓冲区上的字节数,以便java代码知道字节缓冲区有多大.设置字节缓冲区后,我可以填写我的Java对象并返回它.与(i)和(ii)相比,我在这里创建了更多的字节缓冲区以及Java对象,但我避免了自定义协议的复杂性.(i),(ii)和(iii)背后的基本原理 - 鉴于我对这些缩略图的唯一做法是上传它们,我希望通过NIO上传它们时保存带字节缓冲区(vs字节数组)的额外副本.

(iv)定义一个Java类,它具有缩略图的字节数组(而不是字节缓冲区)和感知散列的字节数组.我在我的本机代码中创建这些Java数组,并使用SetByteArrayRegion从我的GraphicsMagick blob复制字节.与以前的方法相比,缺点是,当上传它时,将这个字节数组从堆复制到某个直接缓冲区时,现在Java中还会有另一个副本.不确定我是否会在复杂性方面保存任何东西,而不是(iii).

任何建议都会很棒.

编辑:@main提出了一个有趣的解决方案.我正在编辑我的问题以跟进该选项.如果我想像@main建议的那样在DirectBuffer中包装本机内存,我怎么知道何时可以安全地释放本机内存?

java java-native-interface graphicsmagick

27
推荐指数
1
解决办法
1万
查看次数

如何捕获JNI/Java异常

我的应用程序中有一个JNI层.在某些情况下,Java会抛出异常.如何在JNI层中获取Java异常?我的代码如下所示.

if((*(pConnDA->penv))->ExceptionCheck(pConnDA->penv))
{
    (*(pConnDA->penv))->ExceptionDescribe(pConnDA->penv); 
    (*(pConnDA->penv))->ExceptionClear(pConnDA->penv);
}
Run Code Online (Sandbox Code Playgroud)

这个代码块是否只捕获JNI异常?将在控制台(stderr)中记录异常描述的位置?如何将其插入缓冲区,以便将其传递给记录器模块?

java-native-interface

26
推荐指数
2
解决办法
4万
查看次数

如何在eclipse中删除Android项目的本机支持,因为eclipse在jni中显示错误?

我不小心点击了"Android工具"中的"添加原生支持"...这搞砸了我项目的所有jni文件.我该如何撤消?如何从我的Android项目中删除本机支持?

eclipse java-native-interface android android-ndk

26
推荐指数
2
解决办法
2万
查看次数

如何使用NDK定位多个架构?

背景

我最近开始使用NDK开发一些代码,我想到了使用NDK开发时可能出现的可移植性问题.

问题

由于NDK使用本机代码,因此需要根据CPU架构进行编译.这是一个问题,因为无论设备具有什么CPU,用户都需要运行应用程序.

到目前为止我找到了可能的解决方案

我注意到我可以修改文件"jni/Application.mk"并使用:

APP_ABI:= armeabi armeabi-v7a x86

但是,我不知道从这一步开始我应该做些什么.该应用程序是否包含每个CPU架构的所有已编译代码,并在运行时自动选择正确的代码?

另外,如果有另一个未知的CPU架构怎么办?

如果我尝试在Google TV上运行该应用会发生什么,根据我记得的内容根本不支持NDK?

我发现的另一个解决方案是多apk支持.但是,我不确定我理解它.这一切是否意味着您每次使用不同的配置创建相同的APK?ADT没有专门的自动化工具来帮助解决这个问题吗?

java-native-interface android cpu-architecture android-ndk

26
推荐指数
2
解决办法
2万
查看次数

什么可以导致Java本机函数(在C中)在进入时出现段错误?

该项目

我正在使用Java Native Interface为内部网络和网络测试工具的C库编写Java命令行界面.C代码(我没有写)是复杂的低级别,通常在位级别操作内存,并且只使用原始套接字.应用程序是C端的多线程(后台运行的pthread)以及Java端(ScheduledThreadPoolExecutors运行调用本机代码的线程).也就是说,C库应该基本稳定.事实证明,Java和JNI接口代码会导致问题.

问题

应用程序在进入本机C函数时崩溃并出现分段错误.这仅在程序处于特定状态时才会发生(即,成功运行特定本机函数会导致下一次调用另一个特定本机函数进行段错误).此外,当应用程序崩溃时,应用程序崩溃时会出现类似的段错误quit发出命令,但同样,只有在成功运行相同的特定本机函数之后才会.

我是一个没有经验的C开发人员和经验丰富的Java开发人员 - 我习惯崩溃,给我一个特定的原因和一个特定的行号.在这种情况下,我所有的工作就是hs_err_pid*.log输出和核心转储.在这个问题的最后,我已经包含了我所能做的.

我的工作到目前为止

  1. 当然,我想找到发生崩溃的特定代码行.我System.out.println()在Java端的本机调用之前放置了一个权限,并且printf()作为本机函数的第一行,程序崩溃fflush(stdout)后必须直接使用.该System.out呼叫跑和printf呼吁没有.这告诉我,在进入函数时发生了段错误 - 这是我以前从未见过的.
  2. 我将参数三重检查到函数,以确保它们不会起作用.但是,我只传递一个参数(类型jint).另外两个(JNIEnv *env, jobject j_object)是JNI构造,并且不受我的控制.
  3. 我注释掉了函数中的每一行,最后只留下了一行return 0;.段错仍然发生.这让我相信问题不在这个功能中.
  4. 我以不同的顺序运行命令(有效地运行本机函数不同的命令).只有在崩溃函数调用之前运行一个特定的本机函数时才会发生段错误.此特定功能在运行时似乎表现正常.
  5. 我打印了env指针的值和&j_object接近另一个函数末尾的值,以确保我没有以某种方式破坏它们.我不知道我是否损坏了它们,但是在退出函数时它们都具有非零值.
  6. 编辑1:通常,相同的函数在许多线程中运行(通常不是并发的,但它应该是线程安全的).我从主线程运行该函数,而没有任何其他线程处于活动状态,以确保Java端的多线程不会导致问题.它不是,我得到了相同的段错误.

所有这一切都困扰着我.如果我注释掉整个函数,除了返回语句之外,为什么它仍然是段错误?如果问题出现在这个其他功能中,为什么不在那里失败?如果第一个函数弄乱内存并且第二个函数非法访问损坏的内存是一个问题,为什么不在非法访问的行上失败,而不是进入函数?

如果您看到一篇互联网文章,其中某人解释了与我类似的问题,请对其进行评论.有很多段错误的文章,似乎都没有包含这个特定的问题.对于SO问题同样如此.问题也可能是我没有足够的经验来应用这个问题的抽象解决方案.

我的问题

什么可以导致Java本机函数(在C中)在这样输入时出现段错误?我可以找到哪些具体的东西来帮我压扁这个bug?我怎样才能在将来编写代码来帮助我避免这个问题呢?

有用的信息

为了记录,我实际上无法发布代码.如果您认为代码的描述会有所帮助,请注释,我将对其进行编辑.

错误信息

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00002aaaaaf6d9c3, pid=2185, tid=1086892352
#
# JRE version: 6.0_21-b06 …
Run Code Online (Sandbox Code Playgroud)

c java java-native-interface segmentation-fault

26
推荐指数
1
解决办法
5421
查看次数

何时在Android NDK中使用JNIEXPORT和JNICALL?

我正在尝试编写自己的jni源代码.看一些ndk示例,我发现他们经常使用那些宏JNIEXPORT和JNICALL,这些宏的名字跟java包一样

JNIEXPORT void JNICALL Java_com_example_plasma_PlasmaView_renderPlasma(JNIEnv * env, jobject obj, jobject bitmap, jlong time_ms)

我用Google搜索,但我无法理解何时以及如何使用这些宏

c++ macros java-native-interface android android-ndk

26
推荐指数
3
解决办法
2万
查看次数

如何从android中的本机代码中查找内存泄漏

只是想知道是否有人知道如何从Android中找出本机代码中的内存泄漏.谷歌搜索提供了很多解决方案,但没有一个是完整的.如果有人知道怎么做,请告诉我.

java-native-interface android memory-leaks memory-management android-ndk

25
推荐指数
1
解决办法
2万
查看次数

如何使用JNI在C中获取原始Android相机缓冲区?

我一直在搜索谷歌和StackOverflow,但无法找到它.也许我错过了一些明显的东西.谢谢!

(这是因为预览回调的Java实现[甚至使用缓冲区]效率太低.)

c java java-native-interface camera android

25
推荐指数
2
解决办法
1万
查看次数

传递,返回并转换为JNI上的向量列表

我需要从Java传递

List< List<MyPoint> > points;
Run Code Online (Sandbox Code Playgroud)

从jni到C++并转换为

std::vector< std::vector<MyPoint> >
Run Code Online (Sandbox Code Playgroud)

处理此向量并返回

List< List<MyPoint> >
Run Code Online (Sandbox Code Playgroud)
  1. 如何正确传递和返回列表清单?
  2. 如何转换对象向量向量中的对象列表列表并向后转换?

c++ java java-native-interface list stdvector

25
推荐指数
2
解决办法
1万
查看次数

从OS获取事件

我在Windows上工作,但我被困在Mac上.我有佳能SDK,并JNA在它上面构建了一个包装器.它适用于Windows,需要一些Mac帮助.在sdk中,有一个函数可以注册回调函数.基本上当相机发生事件时,它会调用回调函数.

在Windows上,注册后,我需要用来User32获取事件并通过以下方式调度事件:

private static final User32 lib = User32.INSTANCE;
boolean hasMessage = lib.PeekMessage( msg, null, 0, 0, 1 ); // peek and remove
if( hasMessage ){
    lib.TranslateMessage( msg ); 
    lib.DispatchMessage( msg ); //message gets dispatched and hence the callback function is called
}
Run Code Online (Sandbox Code Playgroud)

在api中,我在Mac中找不到类似的类.我怎么去这个?

PS:unix 的JNA api很广泛,我无法弄清楚要寻找什么.该参考可能有助于

java macos java-native-interface jna

25
推荐指数
1
解决办法
987
查看次数