目前,我正在尝试创建一个使用CUDA功能的Java应用程序.CUDA和Java之间的连接工作正常,但我有另一个问题,想问一下,如果我的想法是正确的.
当我从Java调用本机函数时,我将一些数据传递给它,函数计算一些东西并返回结果.是否有可能让第一个函数返回一个引用(指针)到这个结果,我可以传递给JNI并调用另一个用结果进行进一步计算的函数?
我的想法是通过将数据保留在GPU内存中并只是传递对它的引用来减少从GPU复制数据所带来的开销,以便其他函数可以使用它.
经过一段时间的尝试,我想,这应该是不可能的,因为指针在应用程序结束后被删除(在这种情况下,当C函数终止时).它是否正确?或者我只是在C中看到解决方案?
编辑:嗯,稍微扩展问题(或使其更清楚):当函数结束时,JNI本机函数分配的内存是否已释放?或者我可以访问它,直到JNI应用程序结束或我手动释放它?
感谢您的输入 :)
我正在寻找一种使用Eclipse在Android NDK应用程序中轻松调试C代码的方法.我已经阅读了使用gdb或类似方法调试应用程序的方法,但我想要的是一种以某种方式将消息推送到Eclipse的方法.
我正在寻找一种简单的解决方案,就像在C中使用打印功能并在DDMS日志或类似的东西中看到它一样简单.有没有人有这方面的经验?
我有一些C函数,我通过JNI调用它接受一个结构的指针,以及一些其他函数,它们将分配/释放一个指向同一类型结构的指针,这样它就更容易处理我的包装器.令人惊讶的是,JNI文档对如何处理C结构几乎没有说明.
我的C头文件看起来像这样:
typedef struct _MyStruct {
float member;
} MyStruct;
MyStruct* createNewMyStruct();
void processData(int *data, int numObjects, MyStruct *arguments);
Run Code Online (Sandbox Code Playgroud)
相应的JNI C包装文件包含:
JNIEXPORT jobject JNICALL
Java_com_myorg_MyJavaClass_createNewMyStruct(JNIEnv *env, jobject this) {
return createNewMyStruct();
}
JNIEXPORT void JNICALL
Java_com_myorg_MyJavaClass_processData(JNIEnv *env, jobject this, jintArray data,
jint numObjects, jobject arguments) {
int *actualData = (*env)->GetIntArrayElements(env, data, NULL);
processData(actualData, numObjects, arguments);
(*env)->ReleaseIntArrayElements(env, data, actualData, NULL);
}
Run Code Online (Sandbox Code Playgroud)
...最后,相应的Java类:
public class MyJavaClass {
static { System.loadLibrary("MyJniLibrary"); }
private native MyStruct createNewMyStruct();
private native void processData(int[] data, int numObjects, …Run Code Online (Sandbox Code Playgroud) 在Ubuntu 12.04中,我安装了sun/oracle的jdk7.何时locate jni.h,它会打印多个位置
/usr/lib/jvm/java-6-openjdk-amd64/include/jni.h
/usr/lib/jvm/jdk1.7.0_07/include/jni.h
...
Run Code Online (Sandbox Code Playgroud)
在JDK生成的头文件中,有include <jni.h>,并且目前它抱怨
fatal error: jni.h: No such file or directory.
Run Code Online (Sandbox Code Playgroud)
在我看来Makefile,没有关于位置的规范jni.h.我问是否有可能配置某些系统参数以使jni.h(例如/usr/lib/jvm/jdk1.7.0_07/include/jni.h)在编译时知道路径.
我出于性能原因使用Android NDK主要在C中创建应用程序,但似乎fopen等文件操作在Android中无法正常运行.每当我尝试使用这些功能时,应用程序崩溃.
如何使用Android NDK创建/写入文件?
我正在使用JNI并且有一个jbyte类型的数组,其中jbyte表示为有符号字符,即-128到127.jbytes表示图像像素.对于图像处理,我们通常希望像素分量的范围为0到255.因此我想将jbyte值转换为0到255的范围(即与unsigned char相同的范围),对值进行一些计算然后存储结果再次作为jbyte.
如何安全地进行这些转换?
我设法让这段代码工作,其中一个像素值增加30但是被限制为255,但我不明白它是安全的还是可移植的:
#define CLAMP255(v) (v > 255 ? 255 : (v < 0 ? 0 : v))
jbyte pixel = ...
pixel = CLAMP_255((unsigned char)pixel + 30);
Run Code Online (Sandbox Code Playgroud)
我很想知道如何在C和C++中做到这一点.
我想要一种在JNI代码中抛出异常的一致而简单的方法; 处理链式异常的东西(隐式地来自env-> ExceptionOccurred方法,或显式地通过参数,无论哪种方式都是好的)并且每次我想要这样做时都会让我查找构造函数.所有上述内容最好都是C语言,尽管我可以根据需要从C++中翻译它.
SO上有没有人可以分享这样的东西?
简介:在本机创建的线程上从本机代码调用Java时,我看到Java线程泄漏.
(2014年2月11日更新:我们将此作为对Oracle的支持请求提出.现在Oracle 已经在Java 7更新45上证实了它.它只影响64位Linux(可能还有Mac)平台:32位Linux不受影响) .
(2014年4月29日更新:Oracle已解决此问题,并将在Java 7更新80中发布).
我有一个由Java层和本机库组成的应用程序.Java层通过JNI调用本机库:这会导致新的本机线程开始运行,后者将调用回Java.由于新的本机线程未附加到JVM,因此需要在执行回调之前将其附加,然后再分离.通常的方法是使用AttachCurrentThread/DetachCurrentThread调用将回调到Java的代码括起来.这样可以正常工作,但对于我们的应用程序(非常频繁地调用Java),每次附加和分离的开销都很大.
在几个地方(比如这里和这里)描述了一个优化,它建议使用基于线程本地存储的机制来消除这个问题:基本上每次触发本机回调时,都会测试线程是否已经附加到JVM:如果没有,它将附加到JVM,并且线程本地存储机制用于在线程退出时自动分离线程.我已经实现了这一点,但是虽然附加和分离似乎正确发生,但这会导致Java端的线程泄漏.我相信我正在做正确的事情,并且正在努力寻找可能出错的地方.我一直在抨击这个问题一段时间,我会非常感谢任何见解.
我已经以减少的形式重新创建了问题.下面是本机层的代码.我们这里有一个包装器,它封装了为当前线程返回JNIEnv指针的过程,使用POSIX线程本地存储机制自动分离线程(如果它尚未连接).有一个回调类充当Java回调方法的代理.(我已经使用回调到静态Java方法,以消除创建和删除对Java对象的全局对象引用的额外复杂性,这与此问题无关).最后有一个JNI方法,在调用时,构造一个回调,并创建一个新的本机线程并等待它完成.这个新创建的线程调用回调一次然后退出.
#include <jni.h>
#include <iostream>
#include <pthread.h>
using namespace std;
/// Class to automatically handle getting thread-specific JNIEnv instance,
/// and detaching it when no longer required
class JEnvWrapper
{
public:
static JEnvWrapper &getInstance()
{
static JEnvWrapper wrapper;
return wrapper;
}
JNIEnv* getEnv(JavaVM *jvm)
{
JNIEnv *env = 0;
jint result = jvm->GetEnv((void **) &env, JNI_VERSION_1_6);
if (result != JNI_OK)
{
result = jvm->AttachCurrentThread((void **) …Run Code Online (Sandbox Code Playgroud) 我对JNI非常熟悉,我很想看到java.lang包中某些本机方法的机器特定实现.Thread#currentThread(), 例如.
我在[JDK_HOME]/jre/bin中找到了一堆DLL,但就像我说的那样,我试图找到源代码.
有谁知道可以找到原生源代码的位置?它是否可用,或者它是否被Sun分类(oops我的意思是"我们在其中赢得它"Oracle)?
仅基于性能,大约有多少"简单"的java行是进行JNI调用的等效性能?
或者尝试以更具体的方式表达问题,如果是简单的java操作,例如
someIntVar1 = someIntVar2 + someIntVar3;
Run Code Online (Sandbox Code Playgroud)
给出了一个"CPU工作"索引1,那个JNI调用开销的典型(球场)"CPU工作"索引是什么?
此问题忽略了等待本机代码执行所花费的时间.在电话用语中,它严格来说是呼叫的"旗帜下降"部分,而不是"呼叫率".
提出这个问题的原因是有一个"经验法则",当你知道本地成本(来自直接测试)和给定操作的java成本时,知道何时打算尝试编写JNI调用.它可以帮助您快速避免编写JNI调用的麻烦,只是发现callout开销消耗了使用本机代码的任何好处.
有些人对CPU,RAM等的变化感到困惑.这几乎与问题无关 - 我要求java代码行的相对成本.如果CPU和RAM很差,它们对java和JNI都很差,因此环境因素应该平衡.JVM版本也属于"无关"类别.
这个问题不是要求以纳秒为单位的绝对时间,而是以"简单java代码行"为单位的球场"工作努力".