Java Language Calling Java methods from C++ (callback)


Calling a Java method from native code is a two-step process :

  1. obtain a method pointer with the GetMethodID JNI function, using the method name and descriptor ;
  2. call one of the Call*Method functions listed here.

Java code

/*** ***/

package com.example.jni;

public class JNIJavaCallback {
    static {
    public static void main(String[] args) {
        new JNIJavaCallback().callback();

    public native void callback(); 

    public static void printNum(int i) {
        System.out.println("Got int from C++: " + i);
    public void printFloat(float i) {
        System.out.println("Got float from C++: " + i);

C++ code

// com_example_jni_JNICppCallback.cpp

#include <iostream>
#include "com_example_jni_JNIJavaCallback.h"

using namespace std;

JNIEXPORT void JNICALL Java_com_example_jni_JNIJavaCallback_callback(JNIEnv *env, jobject jthis) {
    jclass thisClass = env->GetObjectClass(jthis);

    jmethodID printFloat = env->GetMethodID(thisClass, "printFloat", "(F)V");
    if (NULL == printFloat)
    env->CallVoidMethod(jthis, printFloat, 5.221);

    jmethodID staticPrintInt = env->GetStaticMethodID(thisClass, "printNum", "(I)V");
    if (NULL == staticPrintInt)
    env->CallVoidMethod(jthis, staticPrintInt, 17);


Got float from C++: 5.221
Got int from C++: 17

Getting the descriptor

Descriptors (or internal type signatures) are obtained using the javap program on the compiled .class file. Here is the output of javap -p -s com.example.jni.JNIJavaCallback :

Compiled from ""
public class com.example.jni.JNIJavaCallback {
  static {};
    descriptor: ()V

  public com.example.jni.JNIJavaCallback();
    descriptor: ()V

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V

  public native void callback();
    descriptor: ()V

  public static void printNum(int);
    descriptor: (I)V  // <---- Needed

  public void printFloat(float);
    descriptor: (F)V  // <---- Needed