Assume that we need to implement some java method in native code and expose it to user. We know that all work is done by native side, i.e. the only responsibility of java code is to pass user-supplied arguments to native code and return result back. According to this, java layer may be implemented in two ways:
By using of native methods that are directly exposed to user:
public native Object doSmth(Object arg0, Object arg1);
By using of thin public wrapper around private native method:
public Object doSmth(Object arg0, Object arg1) {
return nativeDoSmth(arg0, arg1);
}
private native Object nativeDoSmth(Object arg0, Object arg1);
I've seen both approaches in real projects and even both former and latter in the same project.
So, my question is: does any of mentioned alternatives have some technical or performance or maintainability advantages, that should encourage to use only one variant. Or maybe it is all just a matter of taste?
The rule is that a method should be made provided unless it is needed. One of the main reasons for this is that in a future release of an API etc., you can always make a private function public, but you can almost never make a previous public function private without breaking existing code.
Native methods are Java™ methods that start in a language other than Java. Native methods can access system-specific functions and APIs that are not available directly in Java. The use of native methods limits the portability of an application, because it involves system-specific code.
The Java language supports five distinct access levels for methods: private, private protected, protected, public, and, if left unspecified, "friendly".
Native Method Stacks. An implementation of the Java Virtual Machine may use conventional stacks, colloquially called "C stacks," to support native methods (methods written in a language other than the Java programming language).
So, my question is: does any of mentioned alternatives have some technical or performance or maintainability advantages, that should encourage to use only one variant.
Maintainability advantage is the key here. As stated in the comments, the object exposes its behavior. How it is implemented is not the user's business. This gives you more flexibility.
Suppose that in the future (see: maintainability) you find that you want/need to adjust the method such that it does something before and/or after the native call. In the first approach, you will need to deprecate the method and create a new one. In the second second approach, you just add whatever you need in the method and the user doesn't care.
As for performance, in theory, the first approach is faster because it's 1 less call. In practice, it's completely negligible.
I think it's mostly a personal style choice. If you consider the following code:
rattias-macbookpro:tst rattias$ diff Test1.cl Test1.class rattias-macbookpro:tst rattias$ vi Test1.java
public class Test1 {
public static void main(String[] args) {
Test2 t = new Test2();
t.m();
}
}
public class Test2 {
public native void m();
}
Compiling this produces a Test1.class
which is identical to the one produced when Test2
is defined as follows:
public class Test2 {
public void m() {
}
}
This means that you could change the implementation to be native, pure java, a pure java wrapper to a native private method, at any point in time without affecting the users. There may be a question to whether an entire public API function needs to be native, vs. just a portion of the computation, but again that can be changed at any point.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With