Introduction
We will introduce you to JNA, the latest Java framework for accessing local code.
The JNA (Java Native access) Framework is an open-source Java framework developed by Sun and built on the basis of the classic JNI.
JNA Project address: https://jna.dev.java.net/
Very powerful and easy to use, similar to. Net P/invoke.
UnbearableJNI
We know that using JNI to call. dll/. So shared class libraries is very troublesome and painful.
If there is an existing. dll /. so file, if you use JNI technology to call, we first need to use another C language to write one. dll /. so shared library, uses the data structure specified by Sun to replace the data structure of C language, and calls the functions published in the existing dll/SO.
Then load the adapter dll/so in Java, and write the Java Native function as the proxy of the function in the DLL.
After two tedious steps, you can call local code in Java.
Therefore, few Java programmers are willing to write Java programs that call native functions in the DLL/. So library. This also makes the Java language useless on the client. It can be said that JNI is a major weakness of Java!
. NetPowerful platformsP/invoke
On the. NET platform, the powerful P/invoke technology makes our Java programmers very envy. Using P/invoke technology, you only need to compile a. net function, and add a declaration annotation, you can directly call the function in the DLL.
You do not need to use the C language to compile the DLL for adaptation.
Not inferiorP/invokeOfJNA
Now, you don't need to envy the. net p/invoke mechanism any more. JNA reduces the call to the DLL/. So shared library to the same extent as P/invoke.
To use JNA, you do not need to write the adaptation. dll /. so, you only need to write an interface and some code in Java,. dll /. so proxy, you can call dll/so in the Java program.
JNAQuick Start
Now let's go directly to the JNA world.
You only need to download a jar package and use the powerful functions of JNA to conveniently call the C function in the dynamic link library.
1. Download JNA. jar.
Https://jna.dev.java.net/servlets/ProjectDocumentList here? Folderid = 7408 & expandfolder = 7408 & folderid = 0
2. Now you can use JNA.
To facilitate your reference to the JNA Java class library, I have created the jna3.09api reference manual in chm format. You can download http://download.csdn.net/source/900438 here
JNAExample
Example1
Now let's run a JNA program and feel its power.
1. Introduce the JNA. jar package in the Java project.
2. Create a class:
import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.Platform; /** Simple example of native library declaration and usage. */ public class HelloWorld { public interface CLibrary extends Library { CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class); void printf(String format, Object... args); } public static void main(String[] args) { CLibrary.INSTANCE.printf("Hello, World\n"); for (int i=0;i < args.length;i++) { CLibrary.INSTANCE.printf("Argument %d: %s\n", i, args[i]); } } }
3. Run the command. The output is displayed on the console.
Hello, world
However, please note that this program actually uses the printf function in the C Runtime Library msvcrt. DLL to print out the above characters.
Look, it's easy. You can directly call functions in the external dynamic link library in Java without writing a line of C code!
Example2
The above example uses the dynamic link library provided by the operating system. Now we can try writing a dynamic link library by ourselves.
1. Select C ++ in Vs and create a Win32 program. Select the DLL type.
2. The released C function is:
# Define mylibapi extern "C" _ declspec (dllexport)
Mylibapi void say (wchar_t * pvalue );
The implementation of this function is:
Void say (wchar_t * pvalue ){
STD: wcout. imbue (STD: locale ("CHS "));
STD: wcout <L "God says:" <pvalue <STD: Endl;
}
It needs to input a Unicode character array. Then print a Chinese character in the console.
3. Generate the DLL. Copy the generated DLL file to the Eclipse project and place it under the project.
4. Write the following code in Eclipse:
Import COM. sun. JNA. library; import COM. sun. JNA. native; import COM. sun. JNA. wstring; /*** @ author Shen Dongliang Edward Shen shendl_s@hotmail.com * 05:07:14 * testdll1.dll */public class testdll1service {public interface testdll1 extends library {/*** the current path is under the project, instead of the bin output directory. */Testdll1 instance = (testdll1) native. loadlibrary ("testdll1", testdll1.class); Public void say (wstring value);}/***/Public testdll1service () {// todo auto-generated constructor stub}/*** @ Param ARGs */public static void main (string [] ARGs) {// todo auto-generated method stub testdll1.instance. say (New wstring ("Hello world! "); System. Out. println (" hheeh I can't do anything ");}}
5. Execute this Java class. The following output is displayed in the console:
God said: Hello world!
Hheeh, I can't do anything.
6. The above line is output by Using STD: wcout of C ++ in C language.
The following line is output by the Java language.
JNATechnical decryption
JNAWorking PrincipleJNAIs created inJNIAJavaClass Library, which allows you to conveniently useJavaDirectly access functions in the dynamic link library.
If JNI is used, you must manually write a dynamic link library in C to map the Java data type in C.
JNA provides a dynamic C-language forwarder that can automatically map data types between Java and C. You no longer need to write a C dynamic link library.
Of course, this also means that the use of JNA technology is slightly inferior to the use of JNI technology to call the dynamic link library. The speed may be several times lower. But it has little impact.
JNATechnical difficulties
1. The current path is under the project rather than the bin output directory.
2. Data Structure correspondence:
Java-CTable corresponding to the Operating System Data Type
Java type |
C type |
Native Representation |
Boolean |
Int |
32-bit integer (customizable) |
Byte |
Char |
8-bit integer |
Char |
Wchar_t |
Platform-dependent |
Short |
Short |
16-bit integer |
Int |
Int |
32-bit integer |
Long |
Long long, _ int64 |
64-bit integer |
Float |
Float |
32-bit floating point |
Double |
Double |
64-bit floating point |
Buffer Pointer |
Pointer |
Platform-dependent (32-or 64-bit pointer to memory) |
<T> [] (array of primitive type) |
Pointer Array |
32-or 64-bit pointer to memory (argument/return) Contiguous memory (struct Member) |
In addition to the above types, JNA also supports common data type ing. |
String |
Char * |
Nul-terminated array (native encoding or JNA. Encoding) |
Wstring |
Wchar_t * |
Nul-terminated array (UNICODE) |
String [] |
Char ** |
Null-terminated array of C strings |
Wstring [] |
Wchar_t ** |
Null-terminated array of wide c strings |
Structure |
Struct * Struct |
Pointer to struct (argument or return) (or explicitly) Struct by value (member of struct) (or explicitly) |
Union |
Union |
Same as Structure |
Structure [] |
Struct [] |
Array of structs, contiguous in memory |
Callback |
<T> (* FP )() |
Function pointer (Java or native) |
Nativemapped |
Varies |
Depends on Definition |
Nativelong |
Long |
Platform-dependent (32-or 64-bit integer) |
Pointertype |
Pointer |
Same as pointer |
JNAProgramming process
JNA regards a DLL/. So file as a Java interface.
DLL is a collection and container of C functions, which is consistent with the concept of interfaces.
We define such an interface,
Public interface testdll1 extends library {/*** the current path is under the project rather than the bin output directory. */Testdll1 instance = (testdll1) Native. loadlibrary ("testdll1", testdll1.class); Public void say (wstring value );}
If the DLL outputs the function in stdcall mode, it inherits stdcalllibrary. Otherwise, the default library interface is inherited.
The interface requires a public static constant: instance.
Testdll1 instance = (testdll1) Native. loadlibrary ("testdll1", testdll1.class );
Through this constant, you can obtain the instance of this interface and use the interface method. That is, the function that calls the external DLL!
Note:
1. The native. loadlibrary () function has two parameters:
1. The name of the DLL or. So file without the suffix. This complies with the JNI specification, because it cannot be used across operating system platforms with the suffix.
The DLL search path is:
1) Project root path
2) Global Path of the operating system,
3) path specified by path.
2. The second parameter is the class type of this interface.
Through this class type, JNA dynamically creates an interface instance based on the specified dll/. So file.
2. You only need to define the functions or public variables you need in the interface.
Public void say (wstring value );
The type of the parameter and return value should be the same as the type of the C function in the DLL.
This is JNA, and even all the difficulties in cross-platform calls.
Here, the function parameter of the C language is: wchar_t *.
The corresponding Java type in JNA is wstirng.
All difficulties in cross-platform and cross-language calls
Programmers with cross-language and cross-platform development know that the difficulty of cross-platform and language calling is caused by inconsistent data types between different languages. The failure of most cross-platform calls is caused by this problem.
This problem cannot be solved regardless of the language or technical solution.
This requires careful development and design by programmers. This is the programmer's responsibility.
Common cross-platform calls include:
1. Java calls the functions in the DLL and. So Dynamic Link Libraries written in C language.
2.. net uses P/invoke to call functions in the DLL and. So Dynamic Link Libraries written in C language.
3. Through WebService, it is called in various languages such as C, C ++, Java, and. net.
WebService transmits data in XML format.
Even if it is a powerful P/invoke or WebService, it will still encounter great difficulties in the transmission of complex data types and large data volumes.
Because the complex data types of one language are difficult to represent in another language. This is the essence of cross-platform calling.
For example, in WebService calls, many languages, such as Java and. net, have class libraries or tools that automatically implement ing between Java/. NET and XML types.
However, in a real programming environment, if the type is very complex, these automatic conversion tools often fail.
The object-XML ing is incorrect.
Or map out a large amount of memory.
Therefore, I am not familiar with these object-XML ing frameworks.
Currently, I am using WebService to directly use XML processing tools to extract data from XML to build objects. Or, in turn, construct XML data manually based on the attribute values in the object.
The same is true for calls between Java and C.
To call functions in the C language, Java data must be provided in strict accordance with the memory size required by the C language. Use the Java data type to perfectly simulate the Data Type of the C language.
JNA already provides a large number of data types that match the C language.
JNIStill cannot be abolished
We have seen the strength of JNA. How simple is JNI compared with it!
However, some requirements still have to resort to JNI.
JNA is a framework built on the basis of JNI technology.
Using JNI technology, not only Java can access C functions, but also Java code can be called in C language.
JNA can only implement Java to access C functions. As a Java framework, Java code cannot be called in C. In this case, you still need to use JNI technology.
JNI is the foundation of JNA. It is the technical basis for Java and C interoperability