Tag: jni

Java中的虚拟操纵杆

您是否听说过具有Java包装的Windows虚拟操纵杆? 我正在尝试PPJOY,它工作得很好,但后来我需要使用JNI来使它从Java工作,而且暂时看起来并不容易。 谢谢!

了解JNI参数的安全访问

我正在研究HotSpot在JNI代码运行时如何执行垃圾收集和/或堆压缩。 似乎众所周知,可以随时在Java中移动对象。 我试图明白,如果JNI受到垃圾收集效果的影响。 存在许多JNI函数来明确地防止垃圾收集; 例如GetPrimitiveArrayCritical 。 如果引用确实是volatile,那么这样的函数是有意义的。 然而,如果他们不是,那就毫无意义。 关于这个问题似乎存在大量相互矛盾的信息,我正试图解决这个问题。 JNI代码在安全点运行并且可以继续运行,除非它回调到Java或调用某些特定的JVM方法,此时可以停止它以防止离开安全点(感谢Nitsan的注释)。 JVM在停止世界暂停期间用于阻止线程的机制 上面让我觉得垃圾收集将与JNI代码同时运行。 那不可能是安全的,对吗? 为了实现本地引用,Java VM为从Java到本机方法的每次控制转换创建了一个注册表。 注册表将不可移动的本地引用映射到Java对象,并防止对象被垃圾回收。 传递给本机方法的所有Java对象(包括那些作为JNI函数调用结果返回的对象)都会自动添加到注册表中。 在本机方法返回后删除注册表,允许其所有条目被垃圾回收。 https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/design.html#wp16789 好的,所以local引用是不可移动的,但是没有说明压缩。 JVM必须确保将作为参数从Java™传递到本机方法的对象以及由本机代码创建的任何新对象仍可由GC访问。 为了处理GC要求,JVM分配一个称为“本地参考根集”的小型专用存储区域。 在以下情况下创建本地引用根集: 线程首先附加到JVM(线程的“最外层”根集)。 发生每个J2N转换。 JVM使用以下命令初始化为J2N转换创建的根集: 对调用者的对象或类的本地引用。 对作为参数传递给本机方法的每个对象的本地引用。 除非使用PushLocalFrame JNI函数创建新的“本地框架”,否则在本机代码中创建的新本地引用将添加到此J2N根集。 http://www.ibm.com/support/knowledgecenter/en/SSYKE2_5.0.0/com.ibm.java.doc.diagnostics.50/diag/understanding/jni_transitions_j2n.html 好的,所以IBM将传递的对象存储在local reference root set但它没有讨论内存压缩。 这只是说对象不会被垃圾收集。 GC可能随时决定是否需要压缩垃圾收集堆。 压缩涉及将对象从一个地址物理移动到另一个地址。 这些对象可能由JNI本地或全局引用引用。 为了允许安全地进行压缩,JNI引用不是指向堆的直接指针。 至少一个间接级别将本机代码与对象移动隔离开来。 如果本机方法需要获得对象内部的直接可寻址性,则情况会更复杂。 在需要对大型原始数组进行快速共享访问的情况下,直接寻址或固定堆的要求是典型的。 一个例子可能包括屏幕缓冲区。 在这些情况下,可以使用JNI关键部分,这对程序员提出了额外的要求,如JNI对这些函数的描述中所规定的那样。 有关详细信息,请参阅JNI规范。 GetPrimitiveArrayCritical返回Java™数组的直接堆地址,禁用垃圾收集,直到调用相应的ReleasePrimitiveArrayCritical。 GetStringCritical返回java.lang.String实例的直接堆地址,在调用ReleaseStringCritical之前禁用垃圾收集。 http://www.ibm.com/support/knowledgecenter/SSYKE2_6.0.0/com.ibm.java.doc.diagnostics.60/diag/understanding/jni_copypin.html 好的,所以IBM基本上说JNI传递的对象可以随时移动! HotSpot怎么样? GetArrayElements系列函数被记录为复制数组,或者将它们固定到位(并且这样做可以防止压缩垃圾收集器移动它们)。 它被记录为GetPrimitiveArrayCritical的更安全,限制性更小的替代方案。 但是,我想知道哪些虚拟机和/或垃圾收集器(如果有的话)实际固定数组而不是复制它们。 哪些VM或GC支持JNI固定? […]

如何从java调用c ++function

我有一个主要是GUI的Java程序,它显示了从c ++命令行工具写入xml文件的数据。 现在我想在java程序中添加一个按钮来刷新数据。 这意味着我的程序必须调用c ++function。 是通过系统调用从java调用程序的最佳方法吗? c ++程序将为mac os和windows编译,并且应始终与java程序位于同一目录中。 我想生成一个可执行文件,可以将c程序存储在jar中并从我的程序中调用吗?

使用eclipse调试OpenJDK源代码

在我的项目中,我想使用eclipse调试OpenJDK版本8的C / C ++源代码。 为此,我做了以下事情: 使用此自述 –with-debug-level=slowdebug使用–with-debug-level=slowdebug编译OpenJDK8。 将源码makefile项目导入eclipse 创建了一个eclipse运行配置,对已编译的OpenJDK的java.exe执行gdb并定位示例java程序。 在这个配置中我附加了JDK源代码目录路径,这样eclipse就可以将调试符号转换为源代码行并查看它们(显然) 通过这种方法,我可以通过java.c等文件的代码进行调试。 我的问题是,我仍然无法通过本机代码进行调试。 例如java.lang.System.currentTimeMillis() 。 对我来说,看起来这些库没有包含在eclipse gdb-run中。 我试图手动运行gdb,它仍然无法通过该代码部分进行调试。 有没有人有同样的行为,或曾经尝试调试JDK源代码? 我想我在这里遗漏了一些东西……也许我的方法对于这个任务来说是不正确的? 很高兴听到有关如何正确调试JDK源代码的任何提议。 先谢谢你。

JNI:将字节从c ++传递给java

HANDLE hFile = CreateFileA(“C:\\myfile.zip”, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); const int size = GetFileSize(hFile, NULL); char* buffer = new char[size]; DWORD read; ReadFile(hFile, buffer, size, &read, NULL); jclass cls = …; jmethodID id = …; jbyteArray arr = env->NewByteArray(size); env->GetByteArrayRegion(arr, 0, size, (jbyte*) buffer); env->CallStaticVoidMethod(cls, id, arr); 问题是字节数​​组在java方面只包含空字节,有没有人知道为什么? 编辑:哦,我的不好应该是SetByteArrayRegion,对不起! 现在都在工作:)

通过JNI接口共享输出流

我正在编写一个通过JNI接口使用C ++库的Java应用程序。 C ++库创建了Foo类型的对象,它们通过JNI传递给Java。 假设库具有输出function void Foo::print(std::ostream &os) 我有一个Java OutputStream out 。 如何从Java调用Foo::print以使输出显示out ? 有没有办法将OutputStream强制转换为JNI层中的std::ostream ? 我可以在缓冲区中捕获JNI层的输出,然后将其复制到out吗?

如何识别JNI全局引用内存泄漏的原因?

我正在使用Tomcat,在停止我的Web应用程序之后,仍然会引用我的Web应用程序的类加载器实例。 结果是不会释放大量的内存(主要与静态数据相关)。 迟早会导致OutOfMemoryError 。 我进行了heap dump ,我意识到它由JNI全局引用保存 , 可以防止类加载器被垃圾回收 。 我的应用程序不使用JNI 。 我也没有使用Apache Tomcat Native Library 。 我正在使用Sun / Oracle JDK。 我想跟踪这个全球参考的原因/来源。 (我的猜测是JVM内部引用了类加载器 – 但是为什么/在哪里?)。 题: 有哪些方法/工具集可以实现这一目标? UPDATE 似乎bestsss是正确的,jvm调试模式引入了JNI全局引用。 这帮助了我,但它没有回答这个问题所以我仍然很想回答一个可能对将来有帮助的问题。

如何在Java中使用.Net dll

我在vb.net中创建了dll。 我如何在JAVA中使用它的function。 我在google上搜索时发现了一些JNI,但没有得到它。 是否有任何简单的文档与示例。

如何从c调用Java函数

我坚持这个,我需要从c / c ++调用Java函数。 在示例和教程中,我只看到一个java app调用ac方法,并且在同一个方法中调用另一个java方法,但我想要做的是从代码的任何部分调用java方法。 这就是我所拥有的: static JNIEnv mEnv; static jclass mClassAndroidActivity; static mMethodSayHello; JNIEXPORT void JNICALL JNI_FUNCTION(AndroidActivity_nativeInit)(JNIEnv* env, jobject obj, int width, int height) { mEnv = env; jclass cls = (*env)->GetObjectClass(env, obj); mClassAndroidActivity = (*env)->NewGlobalRef(env, cls); mMethodSayHello = (*env)->GetMethodID (env, mClassAndroidActivity, “SayHello”, “(Ljava/lang/String;)V”); } //this method is called from a cpp void […]

如何通过JNI加载JVM失败时如何收到错误消息?

我想检索一条错误消息,解释为什么jvm无法加载。 从这里提供的示例: http://java.sun.com/docs/books/jni/html/invoke.html 我提取了这个例子: /* Create the Java VM */ res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); if (res < 0) { // retrieve verbose error here? fprintf(stderr, "Can't create Java VM\n"); exit(1); } 在我的具体情况下,我在vm_args中提供了无效的参数,并希望看到我在命令行上看到的内容:“无法识别的选项:-foo = bar” 在进一步测试时,看起来jvm正在将我想要的消息放入stdout或stderr。 我相信我需要捕获stdout和stderr来获取我正在寻找的错误(除非当然有一种更简单的方法)。 我正在使用C ++进行编码,因此如果有人能够展示将错误捕获到字符串流中的方法,那将是理想的。 谢谢,兰迪