0% found this document useful (0 votes)
39 views16 pages

How To Use JNI As A Bridge Between Java and C++ - by Sumit Datta - The Startup - Medium

The document discusses using JNI as a bridge between Java and C++ code. It provides an example of calling a C++ function from Java that calculates the volume of a shape. It shows the Java code to declare the native function, load the C++ library, and call the function. It then shows generating the C++ header file, implementing the C++ function, and compiling it into a shared library. Finally, it discusses how the C++ code could call back a method on the original Java object.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
39 views16 pages

How To Use JNI As A Bridge Between Java and C++ - by Sumit Datta - The Startup - Medium

The document discusses using JNI as a bridge between Java and C++ code. It provides an example of calling a C++ function from Java that calculates the volume of a shape. It shows the Java code to declare the native function, load the C++ library, and call the function. It then shows generating the C++ header file, implementing the C++ function, and compiling it into a shared library. Finally, it discusses how the C++ code could call back a method on the original Java object.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 16

17/5/23, 11:31 How to use JNI as a bridge between Java and C++ | by Sumit Datta | The Startup | Medium

Open in app

Member-only story
Search Medium

How to use JNI as a bridge between Java and


C++
Sumit Datta · Follow
Published in The Startup
4 min read · Jan 28, 2020

Listen Share More

Many of the older software being used in Banking, Insurance and other industries have
been developed using programming languages such as C++, COBOL. Modernizing such
software — for e.g., containerizing and running them on Cloud — is a big challenge
because these are mostly procedural programs running as a monolith. At the same
time, you can’t really afford to rewrite the entire business logic in another
programming language like Java or Python or NodeJS. One path many people explore
is to use JNI to create a bridge between Java-based Spring Boots and existing C++
classes that has the business logic. While digging into the Internet, I found very few
articles on JNI with actual sample codes that went beyond Hello World. Hence this
article.

Java calling C++


Let’s say you have a Java program that calculates the volume of a given shape. However,
instead of writing your own implementation, you want to leverage an existing C++ code
that already does that. The first thing you do is declare a native function inside your
Java class with appropriate Request and Responses. Next, inside your Java class, you
load a System library (a .so file or a .dll file) that includes the implementation of this
native function in C++.

Here is the Java code.

https://medium.com/p/1378ca904202 1/16
17/5/23, 11:31 How to use JNI as a bridge between Java and C++ | by Sumit Datta | The Startup | Medium

package com.test;
public class JavaServer {
public static void main(String[] args) {
// TODO Auto-generated method stub
JavaServer client = new JavaServer();
RequestData request = new RequestData();
request.setRadius(5);
request.setShape("Hemisphere");
ResponseData response = client.calculatevolume_in_cplusplus(request);
System.out.println("Response-> " + "Volume-> " + response.getVolume()
+ " Status->" + response.getStatus());
}

static {
System.loadLibrary("nativevolumecalculator");

}
public JavaServer() {

System.out.println("JavaServer created");
}

public com.test.ResponseData
calculatevolume_in_java(com.test.RequestData request) {
System.out.println("Java -> Calculate Volume called");

ResponseData response = new ResponseData();


if (request.getShape().equals("Sphere")) {

response.setVolume((4*22*request.getRadius()*request.getRadius()*reque
st.getRadius())/(3*7));
}

else {
// Assume the shape is Hemisphere
response.setVolume((2*22*request.getRadius()*request.getRadius()*reque
st.getRadius())/(3*7));
}

response.setStatus("OK");

https://medium.com/p/1378ca904202 2/16
17/5/23, 11:31 How to use JNI as a bridge between Java and C++ | by Sumit Datta | The Startup | Medium

return response;
}

private native com.test.ResponseData


calculatevolume_in_cplusplus(com.test.RequestData request);

Once you write the Java code, you have to generate the corresponding C++ header file
for the native function. To do so, put the following plugin configuration inside your
POM file in Maven.

<plugin>

<artifactId>maven-compiler-plugin</artifactId>
<configuration>

<compilerArgs>

<arg>-h</arg>
<arg>.</arg>

</compilerArgs>
</configuration>

</plugin>

Maven will generate a C++ header file (com_test_JavaServer.h) with following content.

/* DO NOT EDIT THIS FILE - it is machine generated */


#include <jni.h>
/* Header for class com_test_JavaServer */

#ifndef _Included_com_test_JavaServer
#define _Included_com_test_JavaServer
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_test_JavaServer
* Method: calculatevolume_in_cplusplus
* Signature: (Lcom/test/RequestData;)Lcom/test/ResponseData;
*/
https://medium.com/p/1378ca904202 3/16
17/5/23, 11:31 How to use JNI as a bridge between Java and C++ | by Sumit Datta | The Startup | Medium

JNIEXPORT jobject JNICALL


Java_com_test_JavaServer_calculatevolume_1in_1cplusplus
(JNIEnv *, jobject, jobject);

#ifdef __cplusplus
}
#endif
#endif

You will notice that the C++ API signature returns a jobject and accepts a Pointer to
JNIEnv, a reference to jobject (Java object) that called this C++ method and a reference
to jobject that contains Request data.

Here is the implementation of the function in C++

#include "com_test_JavaServer.h"
#include "string.h"
#include "stdlib.h"

JNIEXPORT jobject JNICALL JNICALL


Java_com_test_JavaServer_calculatevolume_1in_1cplusplus (JNIEnv *env,
jobject obj, jobject input) {

printf("C -> Calculate Volume called\n");

// Get the Input data


jclass requestDataClass = env->GetObjectClass(input);
jmethodID methodRequestDataGetRadius = env-
>GetMethodID(requestDataClass, "getRadius", "()I");
if (methodRequestDataGetRadius == NULL) {
printf("getRadius method does not exists, so returning
\n");
return NULL;
}
jmethodID methodRequestDataGetShape = env-
>GetMethodID(requestDataClass, "getShape", "()Ljava/lang/String;");
if (methodRequestDataGetShape == NULL) {
printf("getShape method does not exists, so returning
\n");
return NULL;
}
jint radius = (jint)env->CallObjectMethod(input,
methodRequestDataGetRadius);
printf("Radius is %d\n", radius);
jstring shape = (jstring)env->CallObjectMethod(input,
methodRequestDataGetShape);

https://medium.com/p/1378ca904202 4/16
17/5/23, 11:31 How to use JNI as a bridge between Java and C++ | by Sumit Datta | The Startup | Medium

// Convert jstring shape into C string


jboolean iscopy;
const char * cshape = env->GetStringUTFChars(shape, &iscopy);
printf("Shape is %s\n", cshape);
// Create return object
jclass responseDataClass =
env->FindClass("com/test/ResponseData");
jobject responseData = env->AllocObject(responseDataClass);

// Get the method Ids to be set


jmethodID methodSetVolume = env-
>GetMethodID(responseDataClass, "setVolume","(D)V");
if (methodSetVolume == NULL) {
printf("setVolume method does not exists, so returning
\n");
return NULL;
}
jmethodID methodSetStatus = env-
>GetMethodID(responseDataClass, "setStatus","(Ljava/lang/String;)V");
if (methodSetStatus == NULL) {
printf("setStatus method does not exists, so returning
\n");
return NULL;
}

// Set the values in Return object


double volume = (4*22*radius*radius*radius)/(3*7);
printf ("Volume is %f\n", volume);
env->CallObjectMethod(responseData, methodSetVolume,
((4*22*radius*radius*radius)/(3*7)));
const char* cstatus = "OK";
env->CallObjectMethod(responseData, methodSetStatus, env-
>NewStringUTF(cstatus));

return responseData;
}

Here is the makefile.

#!/bin/sh
g++ -c -fPIC -fpermissive -I/usr/lib/jvm/java-11-openjdk-amd64/include
-I/usr/lib/jvm/java-11-openjdk-amd64/include/linux
calculate_volume_cplusplus.c -o calculate_volume_cplusplus.o

g++ -shared -fPIC -fpermissive -o libnativevolumecalculator.so


calculate_volume_cplusplus.o -lc

https://medium.com/p/1378ca904202 5/16
17/5/23, 11:31 How to use JNI as a bridge between Java and C++ | by Sumit Datta | The Startup | Medium

Keep both jar file and the .so file in the same directory (though not necessarily always)
and run the following command

java -Djava.library.path=. -classpath ./javaserver-0.0.1-


SNAPSHOT.jar:. com.test.JavaServer

You will see the Volume calculated by the C++ code being printed by Java class.

C++ calling Java


Now, let’s make things a little more interesting. Let’s say the C++ code wants to invoke a
member function of the calling Java object (this is also called callback). As you would
have noticed, the second parameter in the C++ function passes the reference to calling
Java object.

JNIEXPORT jobject JNICALL


Java_com_test_JavaServer_calculatevolume_1in_1cplusplus
(JNIEnv *, jobject, jobject);

Put the following code inside the function implementation in C++

// Let's see what would have been the volume if it was calculated by
the Java program
printf("Let's see what would have been the volume if it was
calculated by the Java program\n");
printf("Start\n");
jclass javaServerClass = env->GetObjectClass(obj);
jmethodID methodCalculateVolumeInJava = env-
>GetMethodID(javaServerClass, "calculatevolume_in_java", "
(Lcom/test/RequestData;)Lcom/test/ResponseData;");
if (methodCalculateVolumeInJava == NULL) {
printf("calculatevolume_in_java method does not exists, so returning
\n");
return NULL;
}
responseData = env->CallObjectMethod(obj,
methodCalculateVolumeInJava, input);

jmethodID methodGetVolume = env->GetMethodID(responseDataClass,


"getVolume","()D");
https://medium.com/p/1378ca904202 6/16
17/5/23, 11:31 How to use JNI as a bridge between Java and C++ | by Sumit Datta | The Startup | Medium

if (methodGetVolume == NULL) {
printf("getVolume method does not exists, so returning \n");
return NULL;
}
jdouble javaVolume = (jdouble)env->CallDoubleMethod(responseData,
methodGetVolume);
printf ("Java Volume %f\n", javaVolume);
printf("End\n");

In the above code, we are calling the calculatevolume_in_java member function of


JavaServer class from the C++ code. Compile and run as before and verify that it is
working as expected.

Jni

Follow

Written by Sumit Datta


33 Followers · Writer for The Startup

Loves dabbling in new technologies. All views expressed are mine.

More from Sumit Datta and The Startup

https://medium.com/p/1378ca904202 7/16
17/5/23, 11:31 How to use JNI as a bridge between Java and C++ | by Sumit Datta | The Startup | Medium

Sumit Datta in The Startup

How to create Kubernetes Objects using Kubernetes API


Kubernetes is now the defacto “Application Server” when you build Cloud Native applications
using technologies such as Docker…

· 10 min read · May 19, 2020

71

https://medium.com/p/1378ca904202 8/16
17/5/23, 11:31 How to use JNI as a bridge between Java and C++ | by Sumit Datta | The Startup | Medium

Zulie Rane in The Startup

If You Want to Be a Creator, Delete All (But Two) Social Media Platforms
In October 2022, during the whole Elon Musk debacle, I finally deleted Twitter from my phone.
Around the same time, I also logged out of…

· 8 min read · Apr 18

20K 371

https://medium.com/p/1378ca904202 9/16
17/5/23, 11:31 How to use JNI as a bridge between Java and C++ | by Sumit Datta | The Startup | Medium

Nitin Sharma in The Startup

Goodbye ChatGPT: Here Are (New) AI Tools That Will Blow Your Mind
I bet that 99% of the readers are not familiar with any of these tools.

· 6 min read · Apr 4

6.6K 86

https://medium.com/p/1378ca904202 10/16
17/5/23, 11:31 How to use JNI as a bridge between Java and C++ | by Sumit Datta | The Startup | Medium

Sumit Datta

Digitalization of Things — A PoV on how to build the solution


As the number of connected devices, i.e, devices that can connect to another system over
Internet, leapfrogged in recent times, it has…

5 min read · May 8

See all from Sumit Datta

See all from The Startup

Recommended from Medium

https://medium.com/p/1378ca904202 11/16
17/5/23, 11:31 How to use JNI as a bridge between Java and C++ | by Sumit Datta | The Startup | Medium

Andrew Visokih in Dev Genius

Java/Kotlin/GraalVm and Golang.


There are a lot of stories that Golang is faster then Java. I saw many benchmarks, that tells nothing
and just compare particular…

10 min read · Dec 20, 2022

45 1

Christian Göhring in CodeX

A Practical Guide To Containerize Your C++ Application With Docker


If you have C++ code that you want to deploy as a Docker container, this guide will help you to
write your first Dockerfile and build and…

10 min read · Dec 31, 2022

60

Lists

https://medium.com/p/1378ca904202 12/16
17/5/23, 11:31 How to use JNI as a bridge between Java and C++ | by Sumit Datta | The Startup | Medium

Staff Picks
303 stories · 65 saves

Stories to Help You Level-Up at Work


19 stories · 24 saves

Self-Improvement 101
20 stories · 59 saves

Productivity 101
20 stories · 51 saves

David Marko

7 years with Vaadin in production. Do we still enjoy it?


It’s been 7 years since we deployed our first Vaadin app for production. The whole process has
been more than interesting. We developed the…

· 3 min read · Feb 9

10

https://medium.com/p/1378ca904202 13/16
17/5/23, 11:31 How to use JNI as a bridge between Java and C++ | by Sumit Datta | The Startup | Medium

Nishant Aanjaney Jalan in Towards Dev

Kotlin is the Future of Back-end Development.


Strict typing, named parameters, multi-paradigm language

5 min read · Jan 8

808 18

https://medium.com/p/1378ca904202 14/16
17/5/23, 11:31 How to use JNI as a bridge between Java and C++ | by Sumit Datta | The Startup | Medium

Burak in ITNEXT

WebSockets in Android with OkHttp and ViewModel


In this article, we’ll implement WebSocket with OkHttp and view model in Android. WebSocket is
bidirectional. It is a stateful protocol…

5 min read · Jan 21

115 3

Jorge Luis Castro Medina

Modern Android App Development in 2023


Set of good practices, guides, and tools to create modern Android apps.

13 min read · Jan 23

1K 10

https://medium.com/p/1378ca904202 15/16
17/5/23, 11:31 How to use JNI as a bridge between Java and C++ | by Sumit Datta | The Startup | Medium

See more recommendations

https://medium.com/p/1378ca904202 16/16

You might also like