Introduced
Let's introduce a new Java framework-jna that accesses native code.
The JNA (Java Native Access) framework is an open-source Java framework that is developed by SUN and is built on the basis of classic JNI.
JNA Project Address: https://jna.dev.java.net/
Very powerful, easy to use, functionally similar to the. NET P/invoke.
I can't . JNI
We know that using JNI calls. dll/.so Sharing class libraries is very, very cumbersome and painful.
If you have an existing. dll/.so file, if you use the JNI technology call, we first need to write another in C. dll/.so shared library, using the SUN-defined data structure instead of the C language, calling functions advertised in the existing dll/so.
Then load the adapter dll/so in Java, and then write the Java native function as the proxy for the function in the DLL.
There are 2 tedious steps to invoke native code in Java.
Therefore, few Java programmers are willing to write Java programs that invoke native functions in the dll/.so library. This also makes the Java language lackluster on the client side. It can be said that JNI is a major weakness of Java!
. NET powerful on the platform P/invoke
And on the. NET platform, the powerful P/invoke technology makes our Java programmers very envious. Using P/invoke technology, you can directly invoke a function in a DLL by simply writing a. NET function, plus a declared callout.
You do not need to use the C language to write DLLs to fit.
Not inferior to P/invoke of the JNA
Now, there is no need to envy the p/invoke mechanism of. NET. JNA reduced the call to the Dll/.so shared library to the same level as P/invoke.
With JNA, you do not need to write an adapter. dll/.so, just write an interface and some code in Java, and as a proxy for the. dll/.so, you can call dll/so in a Java program.
JNA Quick Start
Now let's go straight into the JNA world.
You just need to download a jar package and you can easily invoke the C function in the dynamic-link library using the powerful features of JNA.
1, download Jna.jar.
Here in Https://jna.dev.java.net/servlets/ProjectDocumentList?folderID=7408&expandFolder=7408&folderID=0
2, now you are ready to use JNA.
In order to facilitate you to refer to JNA Java class Library, I produced the "JNA3.09API Reference manual", is in CHM format. You can download the http://download.csdn.net/source/900438 here
JNA Example
Example 1
Now let's run a JNA program and feel the power of it.
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, execute, you can see the console print out the
Hello, World
Note, however, that this program actually prints the above characters using the printf function in the C run-time library of Msvcrt.dll.
Look, how simple, no need to write a line of C code, you can directly in Java to call the external dynamic link library functions!
Example 2
The above example uses the dynamic link library that comes with the operating system, and now we'll try to write a dynamic link library ourselves.
1, select the C + + language in VS and choose Create a WIN32 program. Select the DLL type.
2, the published 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 pass in a Unicode encoded character array. Then print a Chinese character on the console.
3, build the DLL. Then copy the generated DLL files to the Eclipse project and place them 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 [email protected] * 2008-11-23 PM 05:07:14 *testdll1.dll * * public class Testdl L1service {public interface TestDll1 extends Library {/** * current path is under 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 Co Nstructor 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 me we cannot be evil"); } }
5, execute this Java class. You can see the following output under the console:
God says, Hello world!.
Hheeh me, we can't be evil.
6, the above line is the C language using C + + std::wcout output.
The following line is output from the Java language.
JNA Technology Decryption
JNA Working principle JNA is built on JNI technology based on a Java class Library, which makes it easy for you to use Java direct access to functions in the dynamic-link library.
Using JNI, you must manually write a dynamic-link library in C that maps the Java data types in the C language.
In JNA, it provides a dynamic C language-written forwarder that automatically implements data type mappings for Java and C. You no longer need to write a C dynamic link library.
Of course, this also means that using JNA technology can have a slight performance penalty than invoking a dynamic-link library using JNI technology. The speed may be several times lower. But the impact is small.
JNA Technical Difficulties
1, the current path is under the project, not the bin output directory.
2, the corresponding relationship of data structure:
java-c and the operating system data type of the corresponding table
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 mapping of common data types. |
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 a dll/.so file as a Java interface.
A DLL is a collection of C functions, a container, which is consistent with the concept of an interface.
We define such an interface,
Public interface TestDll1 extends Library { /** * The current path is under the project, not the bin output directory. */ TestDll1 INSTANCE = (TestDll1) native.loadlibrary ("TestDll1", testdll1.class); public void Say (WString value);
If the DLL outputs a function in stdcall mode, it inherits Stdcalllibrary. Otherwise, the default Library interface is inherited.
A common static constant is required inside the interface: instance.
TestDll1 INSTANCE = (TestDll1) native.loadlibrary ("TestDll1", Testdll1.class);
With this constant, an instance of this interface can be obtained, thereby using the method of the interface. The function that calls the external DLL!
Attention:
1, the Native.loadlibrary () function has 2 parameters:
1, the name of the DLL or. so file, but without the suffix name. This is consistent with the JNI specification because the suffix name is not allowed to cross the operating system platform.
The path to the search DLL is:
1) Root Path of the project
2) The global path of the operating system,
3) The path specified by path.
2, the second parameter is the Class type of this interface.
JNA uses this Class type to dynamically create an instance of an interface based on the specified dll/.so file.
2, in the interface you just need to define the function or public variables you need, and what you don't need can be undefined.
public void Say (WString value);
The type of the parameter and the return value should be the same as the type of the C function in the DLL.
This is the difficulty of JNA, and even all cross-platform calls.
Here, the function parameter of the C language is: wchar_t *.
The corresponding Java type in JNA is wstirng.
The difficulty of all cross-platform and cross-language calls
Programmers who have cross-lingual, cross-platform development know that the difficulty of cross-platform and language invocation is the problem caused by inconsistent data types between different languages. The failure of most cross-platform calls is the result of this problem.
In this connection, no matter what language or technical programme, this problem cannot be solved.
This requires careful development and design by the programmer. This is the responsibility of the programmer.
Common cross-platform calls are:
1, Java calls a function in the C language DLL,. So dynamic link library.
2,. NET calls the functions in the C language DLL,. So dynamic link library through P/invoke.
3, through the WEBService, in the c,c++,java,.net and other languages between the call.
WebService is the data that is passed in XML format.
Even powerful P/invoke or WebService can encounter a lot of difficulties in encountering complex data types and large data volumes.
Because of the complex data types of a language, it is difficult to express it in another language. This is the nature of cross-platform invocation issues.
For example, in WEBService calls, many languages, such as Java,. NET, have a class library or tool that automatically implements the mapping between the java/.net type and the XML type.
However, in a real-world programming environment, these automatic conversion tools are often inadequate if the types are very complex.
Either Object-xml mapping errors.
Either map out a lot of memory.
Therefore, I personally do not quite catch a cold on these object-xml mapping frameworks.
I now use WEBService to extract data-building objects from XML directly using the XML processing tool. Or, conversely, build XML data manually based on the attribute values in Object.
The same is true of the invocation problem between Java and C language.
Java to invoke C-language functions, you must strictly follow the C language requirements of the amount of memory to provide Java-formatted data. The data type of the C language is perfectly modeled with the Java data type.
JNA has provided a large number of types that match the C language data type.
JNI still can't be wasted .
We have seen the strength of JNA. How shabby the JNI is compared to it!
However, there are some requirements that must be resorted to by JNI.
JNA is a framework built on the basis of JNI technology.
Using JNI technology, you can not only implement Java access to C functions, but also implement C language calling Java code.
And JNA can only implement Java access C function, as a Java framework, naturally cannot implement the C language calls Java code. At this point, you still need to use JNI technology.
JNI is the foundation of JNA. is the technical foundation for Java and C interoperability