且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用JNI而不是JNA来调用本机代码?

更新时间:2023-12-03 23:40:40


  1. JNA不支持c ++类的映射,所以如果你正在使用c ++库你将需要一个jni包装器

  2. 如果你需要大量的内存复制。例如,您调用一个返回大字节缓冲区的方法,更改其中的某些内容,然后需要调用另一个使用此字节缓冲区的方法。这将要求您将此缓冲区从c复制到java,然后将其从java复制回c。在这种情况下,jni将在性能上获胜,因为你可以在c中保留和修改这个缓冲区,而不需要复制。

这些是我的问题遇到了。也许还有更多。但总的来说,jna和jni之间的表现并没有那么不同,所以无论你在哪里使用JNA,都要使用它。



EDIT



这个答案似乎很受欢迎。所以这里有一些补充:


  1. 如果你需要映射C ++或COM,那么JNAerator的创建者Oliver Chafic就有一个库,叫做 BridJ 。它仍然是一个年轻的库,但它有许多有趣的功能:


    • 动态C / C ++ / COM互操作:调用C ++方法,创建C ++对象(和子类)来自Java的C ++类!)

    • 使用泛型的直接类型映射(包括更好的指针模型)

    • 完整的JNAerator支持

    • 适用于Windows,Linux,MacOS X,Solaris,Android


  2. 至于内存复制,我相信JNA支持直接ByteBuffers,因此可以避免内存复制。

所以,我仍然认为,只要有可能,***使用JNA或者BridJ,如果性能很关键,则恢复为jni,因为如果你需要经常调用本机函数,性能就会受到影响。


JNA seems a fair bit easier to use to call native code compared to JNI. In what cases would you use JNI over JNA?

  1. JNA does not support mapping of c++ classes, so if you're using c++ library you will need a jni wrapper
  2. If you need a lot of memory copying. For example, you call one method which returns you a large byte buffer, you change something in it, then you need to call another method which uses this byte buffer. This would require you to copy this buffer from c to java, then copy it back from java to c. In this case jni will win in performance because you can keep and modify this buffer in c, without copying.

These are the problems I've encountered. Maybe there's more. But in general performance is not that different between jna and jni, so wherever you can use JNA, use it.

EDIT

This answer seems to be quite popular. So here are some additions:

  1. If you need to map C++ or COM, there is a library by Oliver Chafic, creator of JNAerator, called BridJ. It is still a young library, but it has many interesting features:
    • Dynamic C / C++ / COM interop : call C++ methods, create C++ objects (and subclass C++ classes from Java!)
    • Straightforward type mappings with good use of generics (including much nicer model for Pointers)
    • Full JNAerator support
    • works on Windows, Linux, MacOS X, Solaris, Android
  2. As for memory copying, I believe JNA supports direct ByteBuffers, so memory copying can be avoided.

So, I still believe that wherever possible, it is better to use JNA or BridJ, and revert to jni if performance is critical, because if you need to call native functions frequently, performance hit is noticeable.