Skip to content

Representing Java Classes

gershnik-smartsheet edited this page May 21, 2016 · 7 revisions

Once you declared Java types as is explained in Declaring Java Types you will need to use the corresponding Java "class object" (represented by the jclass type in raw JNI). Following the SmJNI philosophy there are multiple ways of doing so from very low level (barely above raw JNI) to a very high. At the simplest level you can do this

JNIEnv * env = ...;
//Method 1. Exact equivalent of JNI's FindClass. Returns null-like object on failure
java_class<jSomething> cls = java_class<jSomething>::find(env);
if (cls)
{
    ...
}

//Method 2. Recommended if you want simple loading. This will throw exception on failure
java_class<jSomething> cls = java_runtime::find_class<jSomething>(env);

//Method 3, advanced. Load using your own custom way of loading things
java_class<jSomething> cls(env, [] (JNIEnv * env) {
    //Load class here using your custom way
    return ...jclass object...;
});

Note that you don't need to pass any class names in. You already declared what the class name is when you defined jSomething.

Unless you are doing something one time accessing classes this way is wasteful and inefficient, however. You will spend time locating the class object every time this code is run. If you made a mistake you will only discover it when this code is run which might be a rare or hard to reproduce scenario. A better approach in almost all cases is to use early binding. This essentially mimics how native dynamic libraries are loaded by the OS loader. Everything is located and hooked up at once in JNI_OnLoad call. Let's use this approach for jSomething and jSomethingElse.

//Declare designated types to represent each class object

struct ClassOfSomething : public java_runtime::simple_java_class<jSomething>
{
    ClassOfSomething(JNIEnv * env):
        simple_java_class(env)
    {} 
};

struct ClassOfSomethingElse : public java_runtime::simple_java_class<jSomethingElse>
{
    ClassOfSomethingElse(JNIEnv * env):
        simple_java_class(env)
    {} 
};

//"Table" of all classes we use
typedef java_class_table<ClassOfSomething, ClassOfSomethingElse> java_classes;

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
{
    ...other things...

    //Load everything in the table
    java_classes::init(env);

   
    ...other things...
}

With this in place you can easily get to a given class from anywhere like this

const auto & cls = java_classes.get<ClassOfSomething>();

Clone this wiki locally