Welcome!

Java IoT Authors: Liz McMillan, Yeshim Deniz, Pat Romanski, Elizabeth White, Zakia Bouachraoui

Related Topics: Java IoT

Java IoT: Article

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/
  • More Stories By 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.

    Comments (2) View Comments

    Share your thoughts on this story.

    Add your comment
    You must be signed in to add a comment. Sign-in | Register

    In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


    Most Recent Comments
    Hari Gottipati 02/25/05 09:15:40 PM EST

    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 [email protected], I am happy to help you out.

    Varun Mehta 02/11/05 03:46:29 AM EST

    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.

    IoT & Smart Cities Stories
    The Founder of NostaLab and a member of the Google Health Advisory Board, John is a unique combination of strategic thinker, marketer and entrepreneur. His career was built on the "science of advertising" combining strategy, creativity and marketing for industry-leading results. Combined with his ability to communicate complicated scientific concepts in a way that consumers and scientists alike can appreciate, John is a sought-after speaker for conferences on the forefront of healthcare science,...
    Machine learning has taken residence at our cities' cores and now we can finally have "smart cities." Cities are a collection of buildings made to provide the structure and safety necessary for people to function, create and survive. Buildings are a pool of ever-changing performance data from large automated systems such as heating and cooling to the people that live and work within them. Through machine learning, buildings can optimize performance, reduce costs, and improve occupant comfort by ...
    René Bostic is the Technical VP of the IBM Cloud Unit in North America. Enjoying her career with IBM during the modern millennial technological era, she is an expert in cloud computing, DevOps and emerging cloud technologies such as Blockchain. Her strengths and core competencies include a proven record of accomplishments in consensus building at all levels to assess, plan, and implement enterprise and cloud computing solutions. René is a member of the Society of Women Engineers (SWE) and a m...
    Poor data quality and analytics drive down business value. In fact, Gartner estimated that the average financial impact of poor data quality on organizations is $9.7 million per year. But bad data is much more than a cost center. By eroding trust in information, analytics and the business decisions based on these, it is a serious impediment to digital transformation.
    DXWorldEXPO LLC announced today that Ed Featherston has been named the "Tech Chair" of "FinTechEXPO - New York Blockchain Event" of CloudEXPO's 10-Year Anniversary Event which will take place on November 12-13, 2018 in New York City. CloudEXPO | DXWorldEXPO New York will present keynotes, general sessions, and more than 20 blockchain sessions by leading FinTech experts.
    Apps and devices shouldn't stop working when there's limited or no network connectivity. Learn how to bring data stored in a cloud database to the edge of the network (and back again) whenever an Internet connection is available. In his session at 17th Cloud Expo, Ben Perlmutter, a Sales Engineer with IBM Cloudant, demonstrated techniques for replicating cloud databases with devices in order to build offline-first mobile or Internet of Things (IoT) apps that can provide a better, faster user e...
    Bill Schmarzo, Tech Chair of "Big Data | Analytics" of upcoming CloudEXPO | DXWorldEXPO New York (November 12-13, 2018, New York City) today announced the outline and schedule of the track. "The track has been designed in experience/degree order," said Schmarzo. "So, that folks who attend the entire track can leave the conference with some of the skills necessary to get their work done when they get back to their offices. It actually ties back to some work that I'm doing at the University of ...
    Charles Araujo is an industry analyst, internationally recognized authority on the Digital Enterprise and author of The Quantum Age of IT: Why Everything You Know About IT is About to Change. As Principal Analyst with Intellyx, he writes, speaks and advises organizations on how to navigate through this time of disruption. He is also the founder of The Institute for Digital Transformation and a sought after keynote speaker. He has been a regular contributor to both InformationWeek and CIO Insight...
    Rodrigo Coutinho is part of OutSystems' founders' team and currently the Head of Product Design. He provides a cross-functional role where he supports Product Management in defining the positioning and direction of the Agile Platform, while at the same time promoting model-based development and new techniques to deliver applications in the cloud.
    Andrew Keys is Co-Founder of ConsenSys Enterprise. He comes to ConsenSys Enterprise with capital markets, technology and entrepreneurial experience. Previously, he worked for UBS investment bank in equities analysis. Later, he was responsible for the creation and distribution of life settlement products to hedge funds and investment banks. After, he co-founded a revenue cycle management company where he learned about Bitcoin and eventually Ethereal. Andrew's role at ConsenSys Enterprise is a mul...