JNA does not support mapping of c++ classes, so if you're using c++ library you will need a jni wrapper
如果你需要大量的内存拷贝。例如,你调用一个方法返回一个大字节缓冲区,你改变了其中的一些内容,然后你需要调用另一个使用这个字节缓冲区的方法。这需要您将这个缓冲区从 c 复制到 java,然后将它从 java 复制回 c。在这种情况下,jni 将在性能上获胜,因为您可以在 c 中保留和修改这个缓冲区,而无需复制。
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:
动态 C/C + +/COM 互操作: 调用 C + + 方法,创建 C + + 对象(以及来自 Java 的子类 C + + 类!)
使用泛型的简单类型映射(包括更好的指针模型)
全面支持 JNAerator
适用于 Windows,Linux,MacOSX,Solaris,Android
至于内存复制,我相信 JNA 支持直接的 ByteBuffers,因此可以避免内存复制。
因此,我仍然认为,只要有可能,最好使用 JNA 或 BridJ,如果性能很关键,最好还是恢复为 jni,因为如果需要频繁调用本机函数,性能损失是显而易见的。
很难回答这样一个一般性的问题。我认为最明显的区别是,使用 JNI 时,类型转换是在 Java/本机边界的本机端实现的,而使用 JNA 时,类型转换是在 Java 中实现的。如果您已经对用 C 编程感到非常舒服,并且必须自己实现一些本机代码,那么我假设 JNI 看起来不会太复杂。如果您是一名 Java 程序员,并且只需要调用第三方本机库,那么使用 JNA 可能是避免 JNI 可能不那么明显的问题的最简单的方法。
Although I've never benchmarked any differences, I would because of the design, at least suppose that type conversion with JNA in some situations will perform worse than with JNI. For example when passing arrays, JNA will convert these from Java to native at the beginning of each function call and back at the end of the function call. With JNI, you can control yourself when a native "view" of the array is generated, potentially only creating a view of a part of the array, keep the view across several function calls and at the end release the view and decide if you want to keep the changes (potentially requiring to copy the data back) or discard the changes (no copy required). I know you can use a native array across function calls with JNA using the Memory class, but this will also require memory copying, which may be unnecessary with JNI. The difference may not be relevant, but if your original goal is to increase application performance by implementing parts of it in native code, using a worse performing bridge technology seems not to be the most obvious choice.
正如其他人已经指出的,JNA 是为了方便。在使用 JNA 时,不需要编译或编写本机代码。JNA 的本地库加载器也是我所见过的最好/最容易使用的加载器之一。不幸的是,你似乎不能在 JNI 上使用它。(这就是我编写 an alternative for System.loadLibrary()的原因,它使用 JNA 的路径约定,并支持从类路径(即 jar)无缝加载。)
A more "complex" example where the native function sums up an integer array of 4 values still showed that JNI performance is 3 times faster than JNA. The reduced advantage was probably because of how you access arrays in JNI: my example created some stuff and released it again during each summing operation.
In my specific application, JNI proved far easier to use. I needed to read and write continuous streams to and from a serial port -- and nothing else. Rather than try to learn the very involved infrastructure in JNA, I found it much easier to prototype the native interface in Windows with a special-purpose DLL that exported just six functions: