Common problems and solutions for using JNI under Linux

Source: Internet
Author: User

JNI is an interface between Java and C/s + + programming, which makes it easy to implement Java calls to C + + languages. Specific use methods, there are many tutorials on the Internet, do not do too much introduction. This blog only focuses on common issues in the process of using JNI.

1. Generate header file with command: Javah*.class

This is wrong. Running the above command prompts: Java.lang.IllegalArgumentException:Not a valid class Name:SegNative.class error. The cause of the error is the same as running the program with the Java command, only the prefix can be indicated, without giving the. class suffix.

2. Version issues

Some of the JNI methods in Jdk6 and jdk7 differ slightly, paying attention to conversions. For example, the method of getting a string in C Getstringutfchars is different in two JDK versions. The old Jdk6 version is used in the following ways:

[CPP]View PlainCopyprint?
    1. char* name= (char*) (*env)->getstringutfchars (env,name,null);

In Jdk7, the method call becomes:

[CPP]View PlainCopyprint?
    1. Const char* name=env->getstringutfchars (name,0);

Other version problems and function parameter meanings can be obtained by viewing the API for more comprehensive information.

3. The jni.h header file cannot be found by compiling source files with g++

You can use the-I option at compile time to specify the directory where the jni.h header files are located:

[CPP]View PlainCopyprint?
    1. g++-i/usr/local/jdk1.7.0_25/include/...

4. Using g++ to compile source files cannot find Jni_md.h

This is because the Jni_md.h header file is referenced in jni.h, and the header file and jni.h are not in a directory, so we also need to specify the Jni_md.h directory:

[CPP]View PlainCopyprint?
    1. g++-i/usr/local/jdk1.7.0_25/include/-i/usr/local/jdk1.7.0_25/include/linux/...

You can see that jni_md.h is placed under directory Linux with Jni.h peers.

5. Dynamic-link libraries are not generated

To generate a dynamic-link library, you need to declare the-shared option at compile time:

[CPP]View PlainCopyprint?
    1. g++-i/usr/local/jdk1.7.0_25/include/-i/usr/local/jdk1.7.0_25/include/linux/segnative.cpp–shared–o lib***.so

In addition, we do not need to be a corresponding. o file, directly specify the name of the dynamic link library.

6. Compiling the dynamic link library error: couldnot read Symbols:bad value

You need to specify an option at compile time:-fpic.

[CPP]View PlainCopyprint?
    1. g++-i/usr/local/jdk1.7.0_25/include/-i/usr/local/jdk1.7.0_25/include/linux/segnative.cpp–shared–o lib***.so- FPIC

7. Dynamic link library not found at run time

There are two main causes of this problem:

    • The generated dynamic link library has the wrong name: The dynamic-link library We declare in the Java language if it is named a, we need to declare the dynamic-link library name as liba.so at compile time, or we will get an error.
    • The path is not correct, and Java cannot find the dynamic link library. Java will look for a dynamic link library in a specific directory, and you can print Java.library.path to see in which directories Java will look for a dynamic link library:

[CPP]View PlainCopyprint?
    1. System.out.println (System.getproperty ("Java.library.path"));

My Computer prints the result:

.:/ Opt/intel/impi/3.2.1.009/lib/:/usr/local/cuda/lib/:/root/nvidia_cuda_sdk/lib/:/root/nvidia_cuda_sdk/common/lib /:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib

We can see that the relevant Lib is included under this path. It is particularly important to note that the first path is., which means that Java looks for the relevant dynamic link library under the current path. So as long as we put together the dynamic link library and the. class file, there is no problem finding the dynamic link library. If the current directory is not included in the print, we can specify the current directory by modifying Ld_library_path.

In addition, we can specify in the process of running:

[CPP]View PlainCopyprint?
    1. Java–djava.library.path= "/home/savedlib/" Executablefile

Using this method, the program can specify a dynamic-link library that is not in the current directory.

8. How to return a string array

We use localization to not only calculate, we also need to return results. If the returned result is a string array, you can do this in the following code:

[CPP]View PlainCopyprint?
  1. Jniexport jobjectarray jnicall java_segment_segment (jnienv *env, Jobject obj, jstring Name, Jint Seg_len, Jint Stride)
  2. {
  3. Const char* name=env->getstringutfchars (name,0);
  4. int clip_num;
  5. name_list* head,*temp; //struct is a linked list that contains only a single char array
  6. Creadwav Wavfile;
  7. Head=wavfile.segment (Name,seg_len,stride,&clip_num);
  8. //1 The class that gets the string
  9. Jclass Str_cls=env->findclass ("java/lang/string");
  10. if (str_cls==null) return NULL;
  11. //2 Sets the element that returns the result to the string type
  12. Jobjectarray Result=env->newobjectarray (clip_num,str_cls,null);
  13. if (result==null) return NULL;
  14. Temp=head;
  15. For (int i=0;i<clip_num;i++)
  16. {
  17. //3 gets a string from char*
  18. Jstring Sn=env->newstringutf (temp->name);
  19. //4 String to return the result
  20. Env->setobjectarrayelement (RESULT,I,SN);
  21. temp=temp->next;
  22. }
  23. return result;
  24. }

As can be seen from the code, the method of returning a string array is simple: first declare the returned result as an array, each element of the array is a string, and then assign a value to each element. In addition, we should also pay attention to the version of the problem, at the time of writing according to their own JDK version of the appropriate function, you can see jni.h to understand the parameters of the relevant function.

9. Reading a string array

Suppose we need to read a series of strings from a string array, the local function parameter has one: Jobjectarraynames, and the type is an array of object. In local code access, you need to first convert it to jstring, and then in the local string array to constchar*, the code is as follows:

[CPP]View PlainCopy print?
    1. int file_num=env->getarraylength (Names);
    2. for (int i=0;i<file_num;i++)
    3. {
    4. Jstring name= (jstring) env->getobjectarrayelement (names,i);
    5. Const char* name=env->getstringutfchars (name,0);
    6. }

As we can see, the process of accessing a string array is simple: first to get the length of the string array, and then to get each string, because the returned result is of type object, we need to strongly convert it to jstring type, and then convert the jstring type to constchar* Type can be used in local functions.

10. Returning an array of custom objects

This is probably the most complex scenario in the JNI application. Returning a custom object is cumbersome, and adding an array complicates the situation. We use an example to explain how to return an array of custom objects. First define a Java class that represents the object to be returned:

[Java]View PlainCopyprint?
  1. Public class Feature
  2. {
  3. private String name;
  4. private int length;
  5. private float[] data;
  6. Public Feature ()
  7. {
  8. }
  9. Public String getName ()
  10. {
  11. return this.name;
  12. }
  13. public int getlength ()
  14. {
  15. return this.length;
  16. }
  17. public float[] GetData ()
  18. {
  19. return This.data;
  20. }
  21. }

The object has three member variables, one is a string, one is an int, and the other is a float array. There is also a default constructor and three get functions that return the value of the related member variable, respectively. The following is the actual procedure for the local function:

[CPP]View PlainCopyprint?
  1. 1 Get Feature class
  2. Jclass Feature_cls=env->findclass ("feature");
  3. if (feature_cls==null) return NULL;
  4. 2 Creating an array of element type feature
  5. Jobjectarray Result=env->newobjectarray (file_num,feature_cls,null);
  6. if (result==null) return NULL;
  7. 3 getting the default constructor for the feature class
  8. Jmethodid Constructor=env->getmethodid (Feature_cls,"<init>","() V");
  9. if (constructor==null) return NULL;
  10. 4 Get the three member variables of feature
  11. Jfieldid Nameid=env->getfieldid (feature_cls,"name","ljava/lang/string;");
  12. if (nameid==null) return NULL;
  13. Jfieldid Lengthid=env->getfieldid (feature_cls,"Length","I"); int
  14. if (lengthid==null) return NULL;
  15. Jfieldid Dataid=env->getfieldid (feature_cls,"data","[F"); Float array
  16. if (dataid==null) return NULL;
  17. for (int i=0;i<file_num;i++)
  18. {
  19. //5 Creating a new feature object
  20. Jobject Feature_obj=env->newobject (Feature_cls,constructor);
  21. //6 Setting the value of a member variable for an object
  22. Env->setobjectfield (Feature_obj,nameid,env->newstringutf (head->name));
  23. Env->setintfield (feature_obj,lengthid,head->length);
  24. Jfloatarray Floatarray=env->newfloatarray (head->length);
  25. Env->setfloatarrayregion (Floatarray,0,head->length,head->data);
  26. Env->setobjectfield (Feature_obj,dataid,floatarray);
  27. //7 Assignment for each element of an array
  28. Env->setobjectarrayelement (Result,i,feature_obj);
  29. }

In fact, the key operation is the creation and assignment of the custom object, and the operation of the array is similar to the previous one. In order to create a custom object, we need to take advantage of the object's constructor, because the purpose of the constructor is to create a new object. In order to assign values to the member variables of an object, we need to obtain these member variables and then assign values based on their type. For a more detailed explanation, refer to: http://dolphin-ygj.iteye.com/blog/519489.

Common problems and solutions for using JNI under Linux

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.