Digital Edition

SYS-CON.TV
Managing Objects Between Java and C
Building the Java API on top of the native API

If you've ever used JNI, you know how to manage the primitive data types between Java and the native language. As you delve into JNI, particularly when developing a Java API on top of a native API, you need to know how to manage the objects between Java and the native language. This article takes you to the next level and walks you through the step-by-step process of managing the objects between Java and C.

Why JNI
Platform independence and flexibility are the popular buzzwords in the industry and programmers want to prune their code. Everyone wants to program in their favorite language, unfortunately you can't always stick to your selection, as some components of an application have to be programmed in a completely different language or some components are only available in a different language. The solution to these situations is JNI. The Java Native Interface (JNI) is the native programming interface for Java that's part of the JDK. JNI allows Java code that runs within a Java Virtual Machine to operate with applications and libraries written in other languages, such as C or C++.

In addition, if you want to do some system-level programming with Java, you'll definitely end up using JNI somewhere. JNI is essential for bridging the gap between Java and the native functions. It allows you to write some code in a native language and then talk to that native code through Java.

Real-Life Scenario
When I wanted to develop a wireless mail solution for a particular mail server, I realized that Java was well suited for developing wireless solutions; however, that mail server had a C API, not a Java API. I then started writing the Java API using JNI on top of the C API. The main obstacle I faced was while passing the objects between Java and C. This article explains how I overcame this obstacle. By the end of this article you'll be familiar with the process of managing objects between Java and C. To understand this article you should be familiar with the basic concepts in JNI (see the Resources section for the JNI documentation).

Why Do You Need to Manage the Objects Between Java and C?
If you're developing the API, sometimes you may need to store an object in Java that you created in C; for example, a mail API. First log into the server with a username and password, then you get the session. Say you wanted to store that session in Java for later use, e.g., for reading or writing an e-mail. If you save the session in Java, you can then pass this session to C to read or write e-mail, etc.

Managing the Objects Between Java and C
You should already know how to pass the primitive types between Java and C (otherwise see the Resources section); it's straightforward. Unfortunately you can't directly convert the objects between Java and C like the primitives. You can indirectly store the C object memory location in Java through a long variable. Later, if you want to pass that object to C, simply pass the memory location. From the memory location you can retrieve the C object.

To maintain the same object in Java and C, create some object in Java and declare a long variable in it to hold the memory location of the object created in C.

I'll illustrate this in detail with the mail example. The first part explains how to fill the Java object from C and the second part explains how to get the C object out of the Java object (to help you understand, I bifurcated each section into a Java side and a C side).

Filling a Java Object from a C Object
Figure 1 shows the different steps involved in this process.

The following example discusses these steps in more detail:

  • Declare a global long variable:

    public long nativeSession;

  • Declare a native method:

    public void native jniLogin(String server, String userName, String password);

  • Define a Java API method to expose the native method:

    
    	public void login(String server, String userName, String password) {
    		jniLogin(server, userName, String password);
    	}
    

    Listing 1 provides a nativeSession variable, which will hold the session object that actually gets created in C through the native method jniLogin. Once we create the session object in C, we'll fill this nativeSession variable that's declared in Listing 1 with the memory location of the C object. I'll discuss this in-depth later.

    I won't explain the step about creating the header file out of a Java file using the javah command (see Resources for this information), so I'll jump directly to the C implementation of this native method.

    Let's see the C implementation of the native method jniLogin:

  • Create the native Object:

    
    	Session msession = NULL;
                connect(mserver, muserName, mpassword, &msession);
    

  • Get the memory location of the object:

    jlong sessionLocation = (jlong)msession;

  • Get the Java object from the parameters:

    jclass cls = (*env)->GetObjectClass(env, obj);

  • Fill the Java objects long variable with a memory location:

    
    	jfieldID fid =(*env)->GetFieldID(env, cls,"nativeSession","J");
                (*env)->SetLongField(env,obj,fid,sessionLocation);
    

    In line 8 of Listing 2, I'm declaring the Session(C) object. In line 14, to connect to a particular mail server, we're passing the values of the server, the user name, and the password to the connect method. If the given user name and password is valid, the msession object gets filled. Note that the function "Connect" is already defined in the C API of the mail server. Now we have the session object that logged into the server in C. In line 15 we're getting the memory location of the msession object. When you do (jlong)msession, it gives the memory location of the msession object. In line 20 we are getting the Java object that called this C function. In line 21, we're getting the long field(variable) "nativeSession" that we declared in Session(Java). In line 20 we're setting the long variable with the variable sessionLocation. Now the variable nativeSession of Session(Java) object holds the memory location of the msession(C) object.

    Getting the C Object Back Out of the Java Object
    Figure 2 explains the different steps involved in this process.

    The following example provides a clearer picture:

  • Declare the native method with the long variable that holds the memory location of the native object through the native method:

    public void native jniSendMail(Object o, String to, String subject, String body);

  • Define a Java API method to expose the native method and pass the long variable to the native method:

    
    public void sendMail(String to, String subject, String body) {
    	jniSendMail(this, to, subject, body);
    }
    

    Let's say you wanted to send an e-mail with the session that logged in through the login method. For that we are passing the session object (with "this" keyword) to the jniSendMail method in Listing 3. Notice that session object has the nativeSession variable that holds the memory location of the native session object. With that we can send the e-mail. Let's see how we can get the native session back from this object in the next steps:

  • Get the Java object from the parameters:

    jclass cls = (*env)->GetObjectClass(env, sessionobj);

  • Get the long variable from the Java object that holds the memory location of the native object:

    
    	jfieldID fid =(*env)->GetFieldID(env, cls,"nativeSession","J");
                jlong session = (*env)->GetLongField(env,obj,fid);
    

  • Get the native object from that memory location and reuse it:

    
    	Session *  msession = (Session)session;
                sendMail(msession, mto, msubject, mbody);
    

    In line 14 of Listing 4, we're getting the Session(Java) class. In line 15, we're getting the variable nativeSession. Line 16 provides the value of the nativeSession variable that has the memory location of the native session. Line 18 has the C object from the memory location, since the long variable session holds the memory location of the native session object. When you typecast with (Session)session, it reads the object from the memory location. Now we have the C object. With this in line 19 we are calling the SendMail function with the values msession, mto, msubject, and mbody, which sends the e-mail to the address specified in the field "mto". Note that "SendMail" is the function that's already defined in the C API of the mail server.

    Resources

  • Java Native Interface tutorial: http://java.sun.com/docs/books/tutorial/native1.1/TOC.html
  • Java Native Interface Specification: http://java.sun.com/j2se/1.4.2/docs/guide/jni/
  • About Hari Gottipati
    Hari K Gottipati is a software professional, consultant, speaker and freelance writer who specializes in Java, mobile computing, cloud computing, virtualization and Ajax. Proven Java enterprise lead, competitive analyst, technical architect and loves coding. Expert in analyzing market landscape for startup ideas and molding them into successful products with the technical/competitive advantage. Regularly writes for Syscon media, O'Reilly publications and his quotes can be often found in various technology news/magazines. Well known blogger and his blogs can be found at sys-con.com, onjava.com and xml.com. Speaks at various events on latest technologies including Mobile, Cloud computing, Ajax, Web 2.0, Web OS and of course Java. Hari serves on technical advisory board for various small to medium size companies where he provides technical vision for the future. Worked for many wireless startups, as well as big companies including Yahoo, Travelocity, and Motorola. Passionate about technologies and spends most of his time exploring bleeding edge software technologies.

    In order to post a comment you need to be registered and logged in.

    Register | Sign-in

    Reader Feedback: Page 1 of 1

    Session *msession = (Session)session;

    Session - C object
    session - memory location where "Session" object is stored.

    The above line reads the object which stored in memory location. "session" holds the memory location value which is long field. In earlier step I stored Session object into the memory location(session). So we know that memory location holds Session object. So you get back your object.

    The session(long variable holds memory location of Session object) value is passed from Java to C. If you notice the previous steps I am storing the memory location(line 21,22 of listing 2) of the object into the variable "nativeSession" which is a Java variable declared in Java Session class(Look the source code for Java Session class).

    I think you are not storing the object properly into the variable. If you coul provide the complete code I can tell why you are getting the error.

    If you have still questions shoot out an email to me at harikrishna@gmail.com, I am happy to help you out.

    How do u type-cast objects in C and reuse them again as in

    Session *msession = (Session)session;

    This gives me a compiler error "conversion to non-scalar type requested", any ways to solve this issue, EXACTLY same error when trying to reuse this object.




    ADS BY GOOGLE
    Subscribe to the World's Most Powerful Newsletters

    ADS BY GOOGLE

    As DevOps methodologies expand their reach across the enterprise, organizations face the daunting ch...
    As Marc Andreessen says software is eating the world. Everything is rapidly moving toward being soft...
    You know you need the cloud, but you’re hesitant to simply dump everything at Amazon since you know ...
    ChatOps is an emerging topic that has led to the wide availability of integrations between group cha...
    The need for greater agility and scalability necessitated the digital transformation in the form of ...
    In his keynote at 18th Cloud Expo, Andrew Keys, Co-Founder of ConsenSys Enterprise, provided an over...
    The cloud era has reached the stage where it is no longer a question of whether a company should mig...
    Coca-Cola’s Google powered digital signage system lays the groundwork for a more valuable connection...
    In his session at 21st Cloud Expo, Raju Shreewastava, founder of Big Data Trunk, provided a fun and ...
    While some developers care passionately about how data centers and clouds are architected, for most,...
    "Since we launched LinuxONE we learned a lot from our customers. More than anything what they respon...
    Is advanced scheduling in Kubernetes achievable?Yes, however, how do you properly accommodate every ...
    DevOps is under attack because developers don’t want to mess with infrastructure. They will happily ...
    "As we've gone out into the public cloud we've seen that over time we may have lost a few things - w...
    In his session at 21st Cloud Expo, Michael Burley, a Senior Business Development Executive in IT Ser...
    Sanjeev Sharma Joins June 5-7, 2018 @DevOpsSummit at @Cloud Expo New York Faculty. Sanjeev Sharma is...
    We are given a desktop platform with Java 8 or Java 9 installed and seek to find a way to deploy hig...
    "I focus on what we are calling CAST Highlight, which is our SaaS application portfolio analysis too...
    "Cloud4U builds software services that help people build DevOps platforms for cloud-based software a...
    The question before companies today is not whether to become intelligent, it’s a question of how and...