Java calls C function under Linux Platform

Source: Internet
Author: User

JNI is a shorthand for Java native interface that can be translated into Java native interfaces. Java can invoke libraries of C + + through JNI, which is undoubtedly a boon for Java programs with high performance requirements.

The use of JNI also has a price. It is known that Java programs are run on top of the JVM and can be platform agnostic. However, if the Java program calls the native code through JNI (such as C + +, etc.), the Java program loses platform independence. At a minimum, you need to recompile the native code section. Therefore, the application of JNI needs a good balance, not the last resort, please do not choose JNI, you can choose alternatives, such as TCP/IP for interprocess communication and so on. This is why the bottom of Google's Android platform is implemented with JNI, but he does not recommend that developers use JNI to develop applications on Android. Will lose Android's application platform independence.

The following is a detailed procedure for invoking the C-language dynamic link library in Java JNI under Linux.

1. Create a Java program (Hello.java) to define the native C + + function.

2, compile Hello.java with Javac to generate Hello.class.

3, using Javah with-JNI parameter compilation Hello.class generate Hello.h file, the file defines the function prototype C. It is necessary to implement the C function.

4, create HELLO.C, implement Hello.h defined function.

5, compile hello.c generate libhello.so.

6. Run Java program Hello in Java Virtual machine.

The first step is to define a Java class--Hello. It provides SayHello Method:

Two points should be noted at this time:

1. Writing local method declarations for each local method to be used is not a different declaration than a normal Java method interface, except that the native keyword must be specified as follows:

public native void SayHello (String strName);

In this function, we will say hello to someone according to the name of the person passed in.

2. The local code base must be loaded explicitly. Of course to call System.loadlibrary ("Hello"); notice not Lib at this time, nor. so!; We need to load this library in a static block of the class:

Static

{

System.loadlibrary ("Hello");

}

Together with the necessary exception handling, the following source file Hello.java is generated:

public class Hello

{

Static

{

System.loadlibrary ("Hello");

}

Local method of the Declaration

Public staitc native void SayHello (String strName);

}

Run the command javac Hello.java generate the Hello.class file.

The second step is to generate the local link library. The process is as follows:

1. To generate a Java local-based oral file for the class defined above, the Javah feature of the Javah,java compiler will generate the necessary declaration according to the Hello class, this command will generate the Hello.h file, we will include it in the code of the shared library, Javah do not make the default internal command, You need to specify the path, which is in the bin directory of the JDK, under my Linux environment, the command is as follows:

Javah Hello

However, the following error occurred:

Error:cannot Access Hello

class file for Hello not found

Javadoc:error-class Hello not found.

Error:no classes were specified on the command line. Try-help.

The reason is that Class_path did not add the current directory. So classpath must be specified as the current directory. or join the current path in the system Class_path. Execute the following command:

Javah-classpath. Hello

The first sentence of the content of the generated Hello.h file is #include <jni.h>
But GCC inside the default environment can not know what jni.h is, jni.h in the JDK $java_home/include below, you can go inside to see ~

2. Create a CPP file Hello.cpp under the same path as the Hello.h. Note that the automatically generated function name is long, and the beginning of the Java is uppercase, the case is very deadly must pay attention to. The contents are as follows:

#include "Hello.h"

#include <stdio.h>

Same as function declaration in Hello.h

Jniexport void Jnicall Java_hello_sayhello (jnienv * env, Jclass ARG, jstring instring)

{

Gets a pointer to the string UTF encoding from the instring string

Const Jbyte *STR =

(const jbyte *) Env->getstringutfchars (instring, Jni_false);

printf ("hello,%s/n", str);

Notifies the virtual machine that local code no longer needs to access the Java string through Str.

Env->releasestringutfchars (instring, (const char *) str);

Return

}

All JNI calls use the jnienv * type pointer, which is used to define the variable as env in the CPP file, which is the first parameter of any local method. The env pointer points to a function pointer table, which can be accessed directly by using the "-a" operator in the VC.

Jobject a handle to the Java object Localfunction instantiated in this Java code, equivalent to the this pointer.

The subsequent parameters are the parameters that are passed into the Java program in the local call, and in this case there is only one string parameter. For string arguments, because the Java string cannot be read directly in the local code, it must be converted to a C + + string or Unicode. Here are three functions that we often use to handle string types:

Const char* Getstringutfchars (jstring string,jboolean* iscopy)

3. Compile to build the shared library.

When using GCC, you must tell the compiler where to find the supporting files for this Java local method, and explicitly notify the compiler to generate location-independent code, which is compiled in my environment as follows:

g++-i/usr/lib/jvm/java-6-sun/include/linux/-i/usr/lib/jvm/java-6-sun/include/-fpic-c Hello.cpp

Generate HELLO.O

g++-shared-wl,-soname,libhello.so.1-o libhello.so.1.0 hello.o

Generate libhello.so.1.0

Next, copy the generated shared library to a standard file name

CP libhello.so.1.0 libhello.so

or use:

g++-i/usr/lib/jvm/java-6-sun/include/linux/-i/usr/lib/jvm/java-6-sun/include/-fpic-shared-o libLexical.so Lexical.cpp
Note Under Linux, the name of the dynamic link library must be lib****.so and must start with Lib!
4. Write a simple Java program to test our local methods.

Save the following source as Tosay.java:

public class Tosay

{

public static void Main (String argv[])

{

Hello.sayhello ("John");

}

}

Compile Tosay.java command JAVAC-CP with Javac. Tosay.java, generate Tosay.class.
Java Tosay is used just like a normal Java program.

Java Tosay

Exception in thread "main" Java.lang.NoClassDefFoundError:ToSay

caused By:java.lang.ClassNotFoundException:ToSay

At Java.net.urlclassloader$1.run (urlclassloader.java:202)

At java.security.AccessController.doPrivileged (Native Method)

At Java.net.URLClassLoader.findClass (urlclassloader.java:190)

At Java.lang.ClassLoader.loadClass (classloader.java:307)

At Sun.misc.launcher$appclassloader.loadclass (launcher.java:301)

At Java.lang.ClassLoader.loadClass (classloader.java:248)

Could not find the main class:tosay. Program would exit.

The reason is that classpath does not have a current path. After correcting, execute the following command:

JAVA-CP. Tosay

Exception in thread "main" Java.lang.UnsatisfiedLinkError:no Hello in Java.library.path

At Java.lang.ClassLoader.loadLibrary (classloader.java:1734)

At Java.lang.Runtime.loadLibrary0 (runtime.java:823)

At Java.lang.System.loadLibrary (system.java:1028)

At Hello.<clinit> (hello.java:6)

At Tosay.main (tosay.java:5)

Still error. Java.lang.UnsatisfiedLinkError:no hellonative in Java.library.path. This error is classic, because Java cannot find the library path ~: Obviously: libhello.so is placed in the current path ".", only Linux execution is not known in the current path to find.
A. Linux under Java.library.path and environment jdk/bin that path is not the same thing, there is another default variable Ld_library_path to save his information. And under Windows, first Java will find the current directory, and secondly, it will go to the address of the environment variable to find!
B. Due to the special path of Linux, workaround 1-Can call Sysout (System.getproperty ("Java.library.path")); To view! and copy the libxxxx.so into the catalogue.
2 Setting environment variables Export ld_library_path=.: $LD _library_path
3 You can specify the library location at a single execution time:
Java-djava.library.path=. -CP. Tosay

We'll see Hello,john appearing on the screen.
Attached: GCC parameter explanation (reprint):
The main thing is an option for the GCC command line:
-shared This option specifies to generate a dynamic connection library (let the connector generate the export symbol table of type T, and sometimes the export symbol of the weakly connected W type) without which the external program cannot connect. Equivalent to an executable file
L-fpic: represents compiled to a location-independent code, without this option, the compiled code is location-dependent, so dynamic loading is a way of copying code to meet the needs of different processes, but not to achieve the purpose of real code segment sharing.
L-l.: Indicates the library to be connected in the current directory
L-ltest: The compiler has an implicit naming convention when looking for dynamic connection libraries, which is to precede the given name with Lib, followed by. So to determine the name of the library
L Ld_library_path: This environment variable indicates that the dynamic connector can load the path of the dynamic library.
L Of course, if you have root permissions, you can modify the/etc/ld.so.conf file, and then call/sbin/ldconfig to achieve the same goal, but if you do not have root privileges, you can only use the output Ld_library_path method.
4. Attention
Call the dynamic library when there are several problems often encountered, and sometimes, clearly has the library's header file in the directory through the "-I" include, the library is located in the file through the "-l" parameter boot, and specified the "-L" library name, but through the LDD command to see, it is dead and alive can not find your designated link , you have to specify the directory of the dynamic library by modifying the Ld_library_path or/etc/ld.so.conf file. This is usually done to solve the problem where the library cannot be linked.

Java calls C function under Linux Platform

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.