Tag: jni

使用Java JNI时是否可以调试核心转储?

我的应用程序主要是Java,但对于某些计算,它使用C ++库。 我们的环境是在RedHat 3上运行的Java 1.6(很快就是RedHat 5)。 我的问题是C ++库不是线程安全的。 为了解决这个问题,我们运行多个单线程“工作”流程,并让他们从中央工作管理器开始工作,也是用C ++编写的。 我们的Java应用程序通过第三方产品调用C ++ Work Manager。 出于各种原因,我们希望重新编写C ++ Work Manager和worker。 我赞成用Java编写它们,在每个worker中使用JNI来调用C ++库。 主要问题是如果C ++库核心转储会发生什么。 不幸的是,这很常见,我们需要能够看到C ++库中的哪一行导致了这个问题,例如通过检查GDB之类的回溯。 我的同事认为,分析核心转储是不可能的,因为像GDB这样的工具不了解Java生成的核心文件。 我希望他们错了,但在进一步推动我的想法之前我需要确定。 分析Java / JNI生成的核心转储的最佳方法是什么?

Java JNI – 将C中分配的资源与java对象相关联?

我想在C中分配一些内存并使其与java对象实例相关联,如下所示: void configure(JNIEnv *object, jobject obj, ….) { char *buf = new char[1024]; // associated with somehow } 然后在java对象被垃圾收集时释放内存 – 我可以通过从java对象的finalize()方法调用JNI函数来实现。 问题是,如何将C指针与java对象相关联? 在对象中保留一个长字段并将指针强制转换为长 ? 有没有更好的办法?

通过JNI将C ++类返回给Java

我目前正在项目中使用C ++和Java,并且我希望能够将包含在C ++中的对象发送到我的Java接口,以便通过GUI修改它,然后用C ++发送修改。 到目前为止,我已经通过JNI接口向Java返回任何内容,int或布尔值。 这次我必须通过界面发送一个对象。 我已经在C ++和Java中提供了类似的类定义。 我想知道如何创建对象,以便我可以在Java中使用它。 在C ++中我有: JNIEXPORT MyObject JNICALL Java_ca_X_Y_Z_C_1getMyObject(JNIEnv* env, jclass, jint number); Java会调用此函数,以便从C ++端获取对象(该对象包含在单例中,可以轻松访问)。 在Java端,我只是简单地调用这个方法, MyObject anObject = C_getMyObject(3); 哪个应该返回我新创建的对象。 当我进行实际调用时,Java当前返回一个UnsatisfiedLinkError。 怎么了?

C ++和Java之间的低延迟IPC

在以下情况下,实现C ++ / Java IPC的最佳方法是什么? (有人最近问了一个类似的问题 ,但我的要求更具体) 我有两个程序 – 一个用C ++编写,另一个用Java编写 – 需要相互通信。 两者都在同一台机器上运行。 程序相互发送消息。 消息通常很短(少于几百字节),但可能大小为100KB或更多。 消息不需要被确认(即,不是像HTTP那样的请求/响应模型)。 例如,C ++程序向Java程序发送消息,Java程序可以通过稍后向C ++程序发送消息来进行回复 – 反之亦然。 一个理想的解决方案是:a)非常低的延迟,b)没有安全麻烦(用户不必授权打开端口等)和c)将是平台无关的。 我的第一个想法是使用套接字 – 每个程序都充当另一个程序的服务器。 套接字比其他forms的IPC有更多的开销,我不知道如果让系统自动分配端口号,服务器将如何通知客户端端口号。 我也考虑过命名管道 ,但它们在不同平台上不受支持(至少不一致)。 JNI看起来像一个选项,但它可以跨越流程边界吗? 有什么建议么? 谢谢! 后续问题 如果我使用套接字,我是否需要打开两个套接字以允许异步通信,如上所述?

长期存在的Java WeakReferences

我目前正在尝试在我的应用程序中诊断缓慢的内存泄漏。 我到目前为止的事实如下。 我从应用程序的4天运行中有一个堆转储。 这个堆转储包含~800个WeakReference对象,这些对象指向对象(所有相同的类型,我将这个问题称为Foo)保留40mb的内存。 Eclipse内存分析工具显示这些WeakReferences引用的每个Foo对象都不会被任何其他对象引用。 我的期望是这应该使这些Foo对象弱到可靠 ,因此它们应该在下一个GC收集。 这些Foo对象中的每一个都有一个时间戳,表明它们是在4天运行过程中分配的。 在此期间我也有日志确认垃圾收集正在发生。 我的应用程序正在创建大量的Foo对象,并且只有很小一部分在堆转储中以这种状态结束。 这告诉我,根本原因是某种竞争条件。 我的应用程序使用JNI调用本机库。 JNI代码在初始化初始化期间调用NewGlobalRef 4次以获取对它使用的Java类的引用。 尽管只是被WeakReferences引用(根据Eclipse Memory Analyzer Tool),但是可能导致这些Foo类无法收集的原因是什么? EDIT1: @mindas我使用的WeakReference等效于以下示例代码。 public class FooWeakRef extends WeakReference { public long longA; public long longB; public String stringA; public FooWeakRef(Foo xiObject, ReferenceQueue xiQueue) { super(xiObject, xiQueue); } } Foo没有终结器,只要WeakRefs尚未被清除,任何终结器都不会被考虑。 当一个对象弱到达时,它不能最终确定。 有关详情,请参阅此页面 。 @kasten在对象可以最终化之前清除弱引用。 我的堆转储表明这没有发生。 @jarnbjo我引用了WeakReference Javadoc: “假设垃圾收集器在某个时间点确定一个对象是弱可达的。那时它将primefaces地清除对该对象的所有弱引用以及对该对象可从其访问的任何其他弱可达对象的所有弱引用通过一系列强大而柔软的参考资料。“ 这告诉我,GC应该检测到我的Foo对象“弱可达”和“当时”清除弱引用这一事实。 […]

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中包装本机内存,我怎么知道何时可以安全地释放本机内存?

JNI UnsatisfiedLinkError

我想创建一个简单的JNI层。 我使用Visual Studio 2008创建了一个DLL(Win 32控制台应用程序项目类型,其中包含DLL)。 我在调用本机方法时遇到此exception: Exception occurred during event dispatching: java.lang.UnsatisfiedLinkError: com.tpd.vcdba.console.TaskScheduler.vcdbaTaskSch edulerNative.Hello()V at com.tpd.vcdba.console.TaskScheduler.vcdbaTaskSchedulerNative.Hello(Na tive Method) at com.tpd.vcdba.console.TaskScheduler.vcdbaTaskSchedulerUtil.isTaskExis ts(vcdbaTaskSchedulerUtil.java:118) at com.tpd.vcdba.console.Dialogs.schedulerWizardPage.scheduleTaskPage.wz Finish(scheduleTaskPage.java:969) at com.tpd.vcdba.console.wizard.vcdbaWizard.gotoFinish(vcdbaWizard.java: 434) at com.tpd.vcdba.console.wizard.wzActionPanel.actionPerformed(wzActionPa nel.java:163) at javax.swing.AbstractButton.fireActionPerformed(Unknown Source) 生成的头文件是: /* DO NOT EDIT THIS FILE – it is machine generated */ #include /* Header for class com_tpd_vcdba_console_TaskScheduler_vcdbaTaskSchedulerNative */ #ifndef _Included_com_tpd_vcdba_console_TaskScheduler_ […]

JNI_CreateJavaVM退出代码-1?

我在JNI_CreateJavaVM方法创建JVM时遇到问题,应用程序只是“程序”[4616] VnptTokenCplusplus.exe:Native已退出代码1(0x1)。“,有人能为我解释一下吗? #include #pragma comment(lib,”jvm”); JNIEnv* Vnpt_JavaCreateVM(); void Vnpt_JavaInvokeClass(JNIEnv* env); int main(){ JNIEnv* env = 0; env = Vnpt_JavaCreateVM(); Vnpt_JavaInvokeClass(env); getchar(); } JNIEnv* Vnpt_JavaCreateVM() { jint res; JavaVM* jvm; JNIEnv* env; JavaVMInitArgs args; JavaVMOption options[1]; args.version = JNI_VERSION_1_2; // JNI_VERSION_1_2 is interchangeable for this example args.nOptions = 1; options[0].optionString = “-Djava.class.path=.”; args.options = options; args.ignoreUnrecognized […]

Visual C ++错误:LNK2019,LNK2028和LNK1120

我正在开发一个基本应用程序来创建Java VM并使用JNI从C ++启动Java程序。 但是,我有一些编译错误: Error 6 error LNK2028: unresolved token (0A00000D) “extern “C” long __stdcall JNI_CreateJavaVM(struct JavaVM_ * *,void * *,void *)” (?JNI_CreateJavaVM@@$$J212YGJPAPAUJavaVM_@@PAPAXPAX@Z) referenced in function “public: bool __clrcall JarLauncher::launchJar(void)” (?launchJar@JarLauncher@@$$FQ$AAM_NXZ) Error 5 error LNK2028: unresolved token (0A00000C) “extern “C” long __stdcall JNI_GetDefaultJavaVMInitArgs(void *)” (?JNI_GetDefaultJavaVMInitArgs@@$$J14YGJPAX@Z) referenced in function “public: bool __clrcall JarLauncher::launchJar(void)” (?launchJar@JarLauncher@@$$FQ$AAM_NXZ) Error 7 […]

JNI无法在NetBeans上检测到__int64

我正在尝试编译一个本机库,以便在java(使用JNI)中使用它。 我已经按照本教程: https : //cnd.netbeans.org/docs/jni/beginning-jni-win.html 错误 当我尝试编译时,我有这个错误(见第4行): […] In file included from ../../Progra~2/Java/jdk1.8.0_91/include/jni.h:45:0, from HelloWorldNative.h:3, from HelloWorldNative.c:6: ../../Progra~2/Java/jdk1.8.0_91/include/win32/jni_md.h:34:9: error: unknown type name ‘__int64’ typedef __int64 jlong; ^ nbproject/Makefile-Debug.mk:66: recipe for target ‘build/Debug/Cygwin-Windows/HelloWorldNative.o’ failed […] 我可以在#include 之前添加一个typedef long long __int64来解决这个错误,但我认为有些东西我做错了。 代码 这是代码: 标头文件: /* DO NOT EDIT THIS FILE – it is machine generated */ typedef […]