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.
Ugly JNI
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 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!
Powerful P/invoke on. NET platform
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 write a DLL in C language to adapt.
Not inferior to P/invoke's JNA
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.
JNA Quick 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
JNA example
Example 1
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!
Example 2
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 rather than 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 ++.
The following line is output by the Java language.
JNA technical decryption
How JNA works
JNA is a Java class library built on the basis of JNI technology. It allows you to conveniently use Java to directly 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.
In JNA, it provides a dynamic C language forwarder that can automatically implement data type ing 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.
JNA technical difficulties
1. The current path is under the project rather than the bin output directory.
2. Data Structure correspondence:
Table corresponding to the Data Types of Java-C and Operating Systems
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
JNA Programming 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 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 C-language functions in Java, data in Java format must be provided in strict accordance with the number of memory required by C language. Use the Java data type to perfectly simulate the C language data type.
JNA already provides a large number of data types that match the C language.
The first principle of cross-platform and cross-language calls is to use basic and simple data types as much as possible, so as to transmit as little data as possible across languages and platforms!
Only you can save yourself.
If your program contains complex data types and massive cross-platform data transmission. Then you must write some other fa-ade interfaces to simplify the data types to be passed and the data volume to be passed.
Otherwise, it is difficult to improve both the implementation difficulty and the program performance.
JNI 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 C language can call Java code.
While JNA can only implement Java to access C functions. As a Java framework, it naturally cannot implement C language to call Java code. 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.