: junc++ion overview

JunC++ion Technology

On this page we're going to delve a bit deeper into the technologies that underpin JunC++ion and we're going to contrast JunC++ion's integration approach with a few other popular integration approaches.

Let's take a look at a contrived C++ code snippet that uses Java through JunC++ion-generated C++ proxy types.

java::lang::String  createRecord( const char * first,
                                  const char * last,
                                  int age )
{
    java::lang::String  result(_use_java_ctor);

    if( first ) {
        result = result.append(first);
        if( last ) {
            result = result.append(" ");
        }
    }
    if( last ) {
        result = result.append( last.toUpperCase() );
    }

    return result.append(", age ").append( java::lang::Integer::toString(age, 10));
}
        

You could of course do the same thing faster and more conveniently in C/C++, but we wanted to show you how similar to Java code the C++ code could look. Please note that C string literals can be used as arguments in Java calls and that we return an actual Java object (via proxy) from the function invocation.

You can later look at the code generator and runtime documentation to find out why we used _use_java_ctor in the above snippet and why we did not use new to create the result string.

But first we want to make sure to communicate how the integration between C++ and Java works at runtime. The diagram below illustrates what is going on when your C++ code tries to talk to the Java side.

The connection between Java and C++

Your own application code is written in C++. In the snippet above, that would be the createRecord function. You previously generated C++ proxy types (java::lang::Integer, java::lang::String) using the code generator—we'll leave aside for now how you did that—and you just use these proxy types like normal C++ objects by creating instances and calling their methods or dereferencing their fields.

Internally, these calls get delegated to utility functions in the JunC++ion runtime library. This delegation allows us to keep the proxy types nice and thin. The runtime library eventually issues one or more Java Native Interface (JNI) calls on behalf of your function call and returns the results to you. Please note that the JVM is running within the user process. In other words, there is no inter-process communication involved.

You can find a more detailed comparison of Codemesh's use of JNI and handwritten JNI here.

Fastest Possible

All this happens blazingly fast when compared to alternative integration approaches. JNI has a poor reputation when it comes to reliability and performance. Yet the fact remains that it is the fastest way of crossing the language boundary by far. By using a proven and tested runtime library and generated code to invoke the Java Native Interface we also make sure to obey best practices and avoid many of the performance traps and all of the memory leaks and crashes that plague hand-written JNI code.

If your unit of work on the Java side is not totally trivial you will hardly see any performance degradation at all in the integrated application. Similarly, any Java code that works with databases or network resources won't be seeing a measurable performance hit from being used in C++.

It goes without saying that you or a Java API vendor can implement a problem-specific, hand-optimized integration solution that is faster than JunC++ion or JNI. Nevertheless, we maintain that among generic integration approaches the JunC++ion approach is the best performing.

Most Secure

The in-process nature of the integration also means that you do not have to worry about new security vulnerabilities due to the integration. There are no ports to be opened, firewalls to be configured, or certificates to be installed just to secure the integration solution. As long as you take a little bit of care with your runtime configuration, your threat profile is essentially the superset of a pure C++ application's and a pure Java application's threat profiles.

Most Complete And Most Sparse

Would you ever try to expose 3,000 Java types to a C++ application via SOAP or a custom network protocol? Of course not, that would be crazy. You might use these approaches when you have a few high-level service APIs that need to be remotely accessible.

The code generator does not care whether it generates 3 or 3,000 proxy types. Well, that's not completely true: you might have to give it more heap to generate a large proxy type set. Other than that, its built-in understanding of Java makes sure you end up with what you need and only what you need.

You can prune down the proxy type set to just the types you wish to code to. The code generator will make sure that the generated types do not contain any element referencing types that you did not generate. It is very easy to define the set of types you want to generate once you understand how to best express your intent.

Mature Configuration Framework

The Java Runtime Environment has many options—classpath is just the best known one—and you might have to use many of them to configure your integrated application's JVM. The JunC++ion runtime offers a mature configuration API that allows you to hardcode settings in your application, use configuration files, pick up settings from the environment, or even from shared libraries when they get loaded.