kee*_*lar 16 c++ java arrays java-native-interface multithreading
当使用JNI桥接c ++和Java时,我们总是希望避免不必要的复制.我发现GetPrimitiveArrayCritical可能会给我们很高的机会不复制数组.但我不完全理解这里记录的限制:
在调用GetPrimitiveArrayCritical之后,本机代码在调用ReleasePrimitiveArrayCritical之前不应该运行很长一段时间.我们必须将这对函数中的代码视为在"关键区域"中运行.在关键区域内,本机代码不能调用其他JNI函数,也不能调用可能导致当前线程阻塞并等待另一个Java线程的任何系统调用.(例如,当前线程不能对另一个Java线程正在写入的流调用read.)
这些限制使得本机代码更有可能获得阵列的未复制版本,即使VM不支持固定.
我的问题是:
延长一段时间的确切含义是什么?
那么这是否意味着我们可以安全地调用其他JNI函数或系统调用,它们永远不会导致当前线程阻塞并等待另一个Java线程?
GetPrimitiveArrayCritical是线程安全的吗?
使用GetPrimitiveArrayCritical而不是GetArrayRegion时,我应该知道什么吗?
小智 18
这里要理解的关键是你在这块内存上获得一个关键部分(例如一个锁).
延长的时间段旨在表明,一旦你持有这个锁,你就会阻止JVM执行常规操作.所以你应该尽快做你需要做的任何处理.你肯定不想做一些可能会阻止的操作,例如,当你将系统完全停止时.
你可能能够逃脱它,因为我怀疑这个锁做的主要事情是防止垃圾收集,但是文档很清楚,它不支持调用其他JNI函数的行为.因此,您可能会发现您的代码在JVM的一个版本中运行,而在其他版本中运行.
因为这是获取锁(关键部分),是的,它是线程安全的.因为它是锁,你不应该持有太长时间(见1).
GetArrayRegion将始终为您提供副本,GetPrimitiveArrayCritical 可能会给您一个副本或者可能会给您一个直接指针.它不确定的原因是它为JVM实现者提供了更多的未来灵活性,以避免直接指针,如果它们会过多地影响一般VM性能(即可能对某些垃圾收集器造成太大影响,使其值得允许锁定).
Ale*_*sky 11
GetPrimitiveArrayCritical将阻止所有现有的垃圾收集器.(实验性的Shenandoah收集器通常不会阻塞.)阻塞垃圾收集器将阻止所有对象分配(一旦垃圾堆积起来).
因此,使用规则GetPrimitiveArrayCritical如下:
GetPrimitiveArrayCritical完全否定了性能优势.然而,从正确的角度来看,失速是安全的(与死锁相反).Get*Critical和Release*Critical方法,它们是线程安全的.null并mode正确设置,因为Get*Critical允许方法失败和/或进行复制,就像Get*ArrayElements.GetPrimitiveArrayCritical,请创建一个运行时选项以Get*ArrayElements代替使用.即使您没有遇到GetPrimitiveArrayCritical引起的拖延,您的用户也可能会遇到.-Xcheck:jni如果在关键区域内调用JNI函数,Java标志将发出警告.忽略文档说明有时可以在关键区域内调用JNI函数.事实并非如此.
Java 8标志-XX:+PrintJNIGCStalls -XX:+PrintGCDetails将打印有关停滞分配和集合的有用日志消息.要查找的消息可以从src/share/vm/memory/gcLocker.cpp中收集
在Java 9中,日志记录已更改.打开gc和jni的日志记录.要查找的消息可以从src/share/vm/gc/shared/gcLocker.cpp收集
更多信息:
| 归档时间: |
|
| 查看次数: |
4086 次 |
| 最近记录: |