gpt4 book ai didi

java - 使用 GetPrimitiveArrayCritical 和 GetArrayRegion 之间的权衡是什么?

转载 作者:IT老高 更新时间:2023-10-28 22:25:15 50 4
gpt4 key购买 nike

当使用 JNI 桥接 c++ 和 Java 时,我们总是希望避免不必要的复制。我发现 GetPrimitiveArrayCritical 可能会给我们很大的机会不复制数组。但我不完全理解它的限制记录 here :

After calling GetPrimitiveArrayCritical, the native code should not run for an extended period of time before it calls ReleasePrimitiveArrayCritical. We must treat the code inside this pair of functions as running in a "critical region." Inside a critical region, native code must not call other JNI functions, or any system call that may cause the current thread to block and wait for another Java thread. (For example, the current thread must not call read on a stream being written by another Java thread.)

These restrictions make it more likely that the native code will obtain an uncopied version of the array, even if the VM does not support pinning.

我的问题是:

  1. 延长时间的确切含义是什么?

  2. 那么这是否意味着我们可以安全地调用其他不会导致当前线程阻塞并等待另一个 Java 线程的 JNI 函数或系统调用?

  3. GetPrimitiveArrayCritical 线程安全吗?

  4. 在使用 GetPrimitiveArrayCritical 而不是 GetArrayRegion 时我应该知道什么?

最佳答案

GetPrimitiveArrayCritical 将阻止所有现有的垃圾收集器。 (实验性的 Shenandoah 收集器通常不会阻塞。)阻塞垃圾收集器将阻塞所有对象分配(一旦垃圾堆积)。

因此,GetPrimitiveArrayCritical的使用规则如下:

  1. 不要调用任何 JNI 函数。 各个部分的文档没有充分强调这一点,但这是您必须遵守的规则。原因是 JNI 函数可能会分配内存,尤其是本地引用。因为没有记录哪些 JNI 函数分配了内存,或者分配了多少内存,所以您不能调用其中的任何一个。据说,函数 EnsureLocalCapacity 可以预先分配本地引用来解决这个问题,但没有人记录如何使用它。不要在临界区内调用除 GetPrimitiveArrayCritical、GetStringCritical、ReleasePrimitiveArrayCritical 和 ReleaseStringCritical 之外的 JNI 函数,否则会死锁。
  2. 不要以任何其他方式阻塞可能需要从堆中分配内存的代码。这主要是禁止阻塞在同一 VM 中运行的 Java 代码。可以想象(但我不能肯定),您可以阻止未分配的 Java 代码。
  3. 您可以从其他线程调用 JNI 函数,只要您不阻塞等待这些线程。调用 JNI 函数的线程可能会停止。请参阅下一点。
  4. 在关键区域花费太多时间会导致其他线程停止。根据您正在运行的线程数量及其分配率,您可以在关键区域花费的时间可能会有所不同.在单线程应用程序中,或在执行很少分配的多线程应用程序中,您可以安全地在临界区中无限期地花费时间。然而,在其他情况下,您将暂停线程,以至于 GetPrimitiveArrayCritical 的性能优势将被完全抵消。然而,从正确性的角度来看,拖延是安全的(与死锁相反)。
  5. 您可以嵌套 Get*CriticalRelease*Critical 方法,它们是线程安全的。
  6. 检查 null 的返回值并正确设置 mode,因为允许 Get*Critical 方法失败和/或复制,就像 Get*ArrayElements
  7. 如果您正在编写库并正在考虑使用 GetPrimitiveArrayCritical,请创建一个运行时选项以改用 Get*ArrayElements 即使您不要遇到由 GetPrimitiveArrayCritical 引起的停滞,您的用户可能会遇到这种情况。

如果您在关键区域内调用 JNI 函数,Java 标志 -Xcheck:jni 会发出警告。忽略说明有时可以在关键区域内调用 JNI 函数的文档。不是。

Java 8 标志 -XX:+PrintJNIGCStalls -XX:+PrintGCDetails 将打印有关停滞分配和收集的有用日志消息。要查找的消息可以从 src/share/vm/memory/gcLocker.cpp 收集。

在 Java 9 中,日志记录发生了变化。打开 gc 和 jni 的日志记录。要查找的消息可以从 src/share/vm/gc/shared/gcLocker.cpp 收集。

更多信息:

关于java - 使用 GetPrimitiveArrayCritical 和 Get<PrimitiveType>ArrayRegion 之间的权衡是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23258357/

50 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com