title: How to get a jclass in JNI from class residing in an OSGi bundle
body: <p>In C/C++ you need a <code>jclass</code> value in order to register native functions to a Java class with methods declared <code>native</code>.</p>
  
  <p>Consider this Java class:</p>
  
  <pre><code>public class Native {
    public native int f(int i);
  }
  </code></pre>
  
  <p>To register a native C/C++ function for <code>Native.f()</code> we need to call this on C++ side:</p>
  
  <pre><code>JNIEnv* env = ...;
  jclass nativeClass = ...;
  
  JNINativeMethod nativeMethod = {
    (char*) "f",
    (char*) "(I)I",
    (void*) Java_org_example_Native_f // The native C function
  };
  
  env-&gt;RegisterNatives(nativeClass, &amp;nativeMethod, 1);
  </code></pre>
  
  <p>The problematic part is to get the <code>jclass</code> value if the class is not accessible from the default class loader. This not the case if the class <code>Native</code> resides in an OSGi bundle loaded inside an OSGi container (e.g. Equinox) running inside the JVM.</p>
  
  <p>To get to the class, I use a Java function to return the <code>Class&lt;?&gt;</code> instance of my class:</p>
  
  <pre><code>public class Helper {
    public static Class&lt;?&gt; getNativeClass() {
      // Find bundle from system bundle context.
      Bundle bundle = ... // details left out.
  
      return bundle.loadClass("org.example.Native");
    }
  }
  </code></pre>
  
  <p>This function resides in a class outside the OSGi container. Calling this function from the C++ side using JNI gives us a <code>jobject</code> which is an instance of <code>java.lang.Class&lt;&gt;</code>.</p>
  
  <pre><code>// Load the `Helper` class.
  jclass helperClass = env-&gt;FindClass("org.example.Helper");
  
  // Get the method `Helper.getNativeClass()`.
  jmethodId mid = env-&gt;GetStaticMethodID(helperClass,
                                         "getNativeClass",
                                         "()Ljava/lang/Class;");
  
  // Call `Helper.getNativeClass()`.
  jobject nativeClassInstance = env-&gt;CallStaticObjectMethod(helperClass, mid);
  </code></pre>
  
  <p>The problem is that we really need a 'jclass' value (not a <code>jobject</code> value). To get it, I instantiate an object of my <code>Native</code> class and get the <code>jclass</code> from that.</p>
  
  <pre><code>// This is the jclass for 'java.lang.Class&lt;&gt;'.
  jclass classClass = env-&gt;GetObjectClass(nativeClassInstance);
  
  // Now get the method id for function 'newInstance()'
  jmethodId newInstanceMid = env-&gt;GetMethodID(helperClass,
                                              "newInstance",
                                              "()Ljava/lang/Object;");
  
  // Instantiate our 'Native' class calling 'Class&lt;Native&gt;.newInstance()'.
  jobject nativeInstance = env-&gt;CallObjectMethod(classClass,
                                                 nativeClassInstance,
                                                 newInstanceMid);
  
  // Now, I can get the desired 'jclass' of my 'Native' class.
  jclass nativeClass = env-&gt;GetObjectClass(nativeInstance);
  </code></pre>
  
  <p>But this only works because I can instantiate my <code>Native</code> class.</p>
  
  <p>Any ideas how to get the desired <code>jclass</code> without having to instantiate an object of the <code>Native</code> class?</p>