当前位置: 首页 > 面试题库 >

使用来自JNI的GetDirectBufferAddress

秦博达
2023-03-14
问题内容

我正在尝试GetDirectBufferAddress从JNI层了解如何使用。为了理解,我构建了一个非常简单的示例:

public class my_image_info {
  static {
      System.loadLibrary("my_jni");
  }
  private java.nio.ByteBuffer image_info_bb;
  native static void initc( java.nio.ByteBuffer bb );
  my_image_info()
    {
    image_info_bb = java.nio.ByteBuffer.allocateDirect( 5 * 4 );
    initc( image_info_bb );
    }
  public java.nio.ByteBuffer getBB() {
    return image_info_bb;
  }
  static public void main(String argv[]) {
    my_image_info fii = new my_image_info();
    java.nio.ByteBuffer bb = fii.getBB();
    System.out.println("1: " + bb.getInt(0));
    System.out.println("2: " + bb.getInt(4));
    System.out.println("3: " + bb.getInt(8));
    System.out.println("4: " + bb.getInt(12));
    System.out.println("5: " + bb.getInt(16));
}

然后从本地JNI层:

JNIEXPORT void JNICALL Java_my_1image_1info_initc
  (JNIEnv *env, jclass cls, jobject jobj)
{
  int *iBuf = (*env)->GetDirectBufferAddress(env, jobj);
  iBuf[0] = -2;
  iBuf[1] = -1;
  iBuf[2] = 0;
  iBuf[3] = 1;
  iBuf[4] = 2;
}

如果我使用openjdk在此处(debian / linux wheezy amd64)运行此示例:

$ java -version
java version "1.6.0_34"
OpenJDK Runtime Environment (IcedTea6 1.13.6) (6b34-1.13.6-1~deb7u1)
OpenJDK 64-Bit Server VM (build 23.25-b01, mixed mode)

这是我看到的:

1: -16777217
2: -1
3: 0
4: 16777216
5: 33554432

我了解索引2和3的值。但是所有其他值对我来说都没有任何意义,我原本希望这样:

1: -2
2: -1
3: 0
4: 1
5: 2

我从JNI的ByteBuffer使用中误解了什么?


问题答案:

我从文档中错过的是默认情况下java.nio.ByteBuffer实际上是使用BIG_ENDIAN字节顺序。这就解释了我在LITTLE_ENDIAN系统上看到的行为。请参阅此处的参考。

我的代码现在显示为:

image_info_bb = java.nio.ByteBuffer.allocateDirect( 5 * 4 );
image_info_bb.order( java.nio.ByteOrder.LITTLE_ENDIAN );

看来,在默认情况下它始终是BIG_ENDIAN,并没有努力已经取得迄今提供的API
LITTLE_ENDIAN,如bug报告解释这里(JDK-5043362(BF)NewDirectByteBuffer总是有秩序ByteOrder.BIG_ENDIAN)。

文档最近已更新,以反映以下内容:

  • JDK-8225152:发行说明:JNI NewDirectByteBuffer创建直接缓冲区java.nio.ByteOrder.BIG_ENDIAN


 类似资料:
  • 问题内容: 我们的游戏引擎本身可以在android上本地运行。我们需要从调用某些Java函数通过的。 为了进行调用,我们从此处(GitHub)使用JNIHelper.h / cpp: JniHelper.h,JniHelper.cpp 例如,此C ++代码: 理想情况下,我们希望所有这些调用都发生在上,并在函数调用完成后将an 作为参数传递给参数,并再次使用返回值进行调用。 调用函数的理想方法:

  • 我不明白这是什么意思,也不明白为什么只有有时候才会发生。如有任何帮助,我们将不胜感激。很乐意分享更多细节。 我们已经能够在Android7.0设备上重现这次崩溃。但并不一致。

  • 问题内容: 我需要使用某些Java类中包含的逻辑。我找到了JNI,但该项目似乎最近没有更新。 有没有办法在Delphi本机应用程序中使用它?我使用Delphi 2009。 问题答案: 比JNI更新的解决方案是JNA,它还支持(Delphi)DLL的回调。我发现它易于使用。

  • 问题内容: 与JNI相比,JNA似乎更易于调用本机代码。在什么情况下,您将在JNA上使用JNI? 问题答案: JNA不支持c 类的映射,因此,如果您使用的是c 库,则需要一个jni包装器 如果需要大量内存复制。例如,您调用一个返回大字节缓冲区的方法,对其中的内容进行更改,然后需要调用使用此字节缓冲区的另一种方法。这将需要您将该缓冲区从c复制到java,然后再将其从java复制回到c。在这种情况下,

  • 线程名称:线程组1-1示例开始时间:2019-09-11 18:52:42英国夏令时加载时间:0连接时间:0延迟时间:0大小以字节为单位:0发送字节:0头大小以字节为单位:0主体大小以字节为单位:0示例计数:1错误计数:1数据类型(“text”“bin”“”):文本响应代码:000响应消息:javax.naming.nameNotFoundException:DynamicQueue/MyQueu

  • 我可以编译(带有一个我不理解的警告),但是我在尝试运行程序时得到一个ClassNotFoundException。 知道我做错了什么吗?