JavaData & JavaJNI Data Type Mapping to C/C++

JNI Data Type Mapping to C/C++

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

The concept of function and data type is the basic building block of any programming language. When working with heterogeneous languages’ features, bridging their differences is crucial. JNI (Java Native Interface) provides a native interface through which Java communicates with other languages. In JNI, the first hurdle of establishing communication with languages other than Java is the distinctive feature of data type and function mapping between two unmatched programming languages. This communication difference begins with its data type and function representation because they are the basic structure of any code. Here we shall use C/C++ as the native language support for Java while working with JNI. The article tries to explicate function and data type mapping between Java and C/C++ with some appropriate examples.

Native Method Naming Conventions

Declaring a native method inside a Java code is as simple as adding just the native keyword. The complexity creeps in as soon as mapping occurs with the native language. The code looks mangled beyond recognition. Let’s get into the details and try to identify some of its common pattern.

As we know, C/C++ header files for the native method declared in the Java code are auto generated by the javah tool. The function naming scheme in the header file is mapped based on the following conventions:

  • the native method name always begins with ‘Java’ as the first word.
  • The package/sub package separator for the fully qualified name is separated by an underscore character.
  • For an overloaded method name, it begins with ‘Java’ as the first word, then fully qualified package/sub package name separated by underscore characters, and at the end, two underscore characters with the mangled method’s signature.

Undoubtedly, the native method signature is clumsy in appearance, yet the scheme has a logical pattern. Because they are auto generated with the javah tool, programmers need not worry about the naming convention. What we can do while implementing the methods in the C/C++ file is simply copy-paste the function prototype from the header file and concentrate on defining our logic rather than brooding over complexity. However, to get a glimpse of native method naming convention, observe the following Java file and its corresponding C/C++ header file generated through the javah tool.

package org.in.jnitest;

public class JavaJNITest {
   private native void method1();
   private native void method2(String str);
   private native int[] OverloadedMethod(int[] intArray,
      int intValue);
   private native double OverloadedMethod(int intValue,
      String strArray[], String str);
   private native double OverloadedMethod(double
      doubleValue, String str);
   private native double OverloadedMethod(short
      shortArray, String str);
}




/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_in_jnitest_JavaJNITest */

#ifndef _Included_org_in_jnitest_JavaJNITest
#define _Included_org_in_jnitest_JavaJNITest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     org_in_jnitest_JavaJNITest
 * Method:    method1
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_org_in_jnitest_JavaJNITest_method1
   (JNIEnv *, jobject);

/*
 * Class:      org_in_jnitest_JavaJNITest
 * Method:     method2
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_org_in_jnitest_JavaJNITest_method2
   (JNIEnv *, jobject, jstring);

/*
 * Class:     org_in_jnitest_JavaJNITest
 * Method:    OverloadedMethod
 * Signature: ([II)[I
 */
JNIEXPORT jintArray JNICALL Java_org_in_jnitest_JavaJNITest_OverloadedMethod___3II
   (JNIEnv *, jobject, jintArray, jint);

/*
 * Class:     org_in_jnitest_JavaJNITest
 * Method:    OverloadedMethod
 * Signature: (I[Ljava/lang/String;Ljava/lang/String;)D
 */
JNIEXPORT jdouble JNICALL Java_org_in_jnitest_JavaJNITest_OverloadedMethod__I_3Ljava_lang_String_2Ljava_lang_String_2
   (JNIEnv *, jobject, jint, jobjectArray, jstring);

/*
 * Class:     org_in_jnitest_JavaJNITest
 * Method:    OverloadedMethod
 * Signature: (DLjava/lang/String;)D
 */
JNIEXPORT jdouble JNICALL Java_org_in_jnitest_JavaJNITest_OverloadedMethod__DLjava_lang_String_2
   (JNIEnv *, jobject, jdouble, jstring);

/*
 * Class:     org_in_jnitest_JavaJNITest
 * Method:    OverloadedMethod
 * Signature: (SLjava/lang/String;)D
 */
JNIEXPORT jdouble JNICALL Java_org_in_jnitest_JavaJNITest_OverloadedMethod__SLjava_lang_String_2
   (JNIEnv *, jobject, jshort, jstring);

#ifdef __cplusplus
}
#endif
#endif

In case of overloaded methods, observe the function naming scheme. The comment section before each method declaration gives a hint to the method naming scheme. A closer look would reveal the pattern followed.

Data Type Mapping

The mapping between Java data types and data types used in native code is pretty straightforward. The naming scheme remains the same: the native data type name is preceded by the character ‘j’, followed by all lowercase data type name equivalent to Java. JNI also includes another data type named jsize, which stores the length or an array or string.

Java primitive data type Native primitive data type Description
void void None
byte jbyte 8-bit signed. Range is -27 to 27 – 1
int jint 32-bit signed. Range is -231 to 231 – 1
float jfloat 32 bits. Represent a real number as small as 1.4 x 10-45 and as big as 3.4 x 1038 (approx.), positive or negative
double jdouble 64 bits. Represent a real number as small as 4.9 x 10-324 and as big as 1.7 x 10308 (approx.), positive or negative
char jchar 16-bit unsigned. Range is 0 to 65535
long jlong 64-bit signed. Range -263 to 263 – 1
short jshort 16-bit signed. Range is -215 to 215 – 1
boolean jboolean Unsigned 8 bits. true and false

In case of reference types, JNI defines a few of the most common references, such as string or class, and so forth. Other references are mapped to the JNI jobject. String, Class, and Throwable are just exceptional reference types that otherwise can be handled by jobject.

Java Reference type JNI type Description
java.lang.object jobject Any Java object
java.lang.String jstring String representation
java.lang.Class jclass Java class object
java.lang.Throwable jthrowable Java throwable object

JNI uses jarray for a generic array type that represents the Java array type. Another data type, named jvalue, is nothing but a union type defined in C/C++.

Conclusion

These are some of the primary yet very vital concepts to begin coding in JNI. Although data types of most languages are more or less similar, when it comes to mapping between two different languages, the question always arises about how they are mapped. Observe that the classic C/C++ data type naming is not followed in JNI. The representation may be the same, yet the naming scheme differs. Here, we have refreshed the concept, thus paving way for more hands on work in the next set of articles.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories