+/* Callback for `pthread_key_create'. It frees the data contained in
+ * `jvm_env_key' and prints a warning if the reference counter is not zero. */
+static void cjni_jvm_env_destroy (void *args) /* {{{ */
+{
+ cjni_jvm_env_t *cjni_env;
+
+ if (args == NULL)
+ return;
+
+ cjni_env = (cjni_jvm_env_t *) args;
+
+ if (cjni_env->reference_counter > 0)
+ {
+ ERROR ("java plugin: cjni_jvm_env_destroy: "
+ "cjni_env->reference_counter = %i;", cjni_env->reference_counter);
+ }
+
+ if (cjni_env->jvm_env != NULL)
+ {
+ ERROR ("java plugin: cjni_jvm_env_destroy: cjni_env->jvm_env = %p;",
+ (void *) cjni_env->jvm_env);
+ }
+
+ /* The pointer is allocated in `cjni_thread_attach' */
+ free (cjni_env);
+} /* }}} void cjni_jvm_env_destroy */
+
+/* Register ``native'' functions with the JVM. Native functions are C-functions
+ * that can be called by Java code. */
+static int cjni_init_native (JNIEnv *jvm_env) /* {{{ */
+{
+ jclass api_class_ptr;
+ int status;
+
+ api_class_ptr = (*jvm_env)->FindClass (jvm_env, "org/collectd/api/Collectd");
+ if (api_class_ptr == NULL)
+ {
+ ERROR ("cjni_init_native: Cannot find API class `org/collectd/api/Collectd'.");
+ return (-1);
+ }
+
+ status = (*jvm_env)->RegisterNatives (jvm_env, api_class_ptr,
+ jni_api_functions, (jint) jni_api_functions_num);
+ if (status != 0)
+ {
+ ERROR ("cjni_init_native: RegisterNatives failed with status %i.", status);
+ return (-1);
+ }
+
+ return (0);
+} /* }}} int cjni_init_native */
+
+/* Create the JVM. This is called when the first thread tries to access the JVM
+ * via cjni_thread_attach. */
+static int cjni_create_jvm (void) /* {{{ */
+{
+ JNIEnv *jvm_env;
+ JavaVMInitArgs vm_args;
+ JavaVMOption vm_options[jvm_argc];
+
+ int status;
+ size_t i;
+
+ if (jvm != NULL)
+ return (0);
+
+ status = pthread_key_create (&jvm_env_key, cjni_jvm_env_destroy);
+ if (status != 0)
+ {
+ ERROR ("java plugin: cjni_create_jvm: pthread_key_create failed "
+ "with status %i.", status);
+ return (-1);
+ }
+
+ jvm_env = NULL;
+
+ memset (&vm_args, 0, sizeof (vm_args));
+ vm_args.version = JNI_VERSION_1_2;
+ vm_args.options = vm_options;
+ vm_args.nOptions = (jint) jvm_argc;
+
+ for (i = 0; i < jvm_argc; i++)
+ {
+ DEBUG ("java plugin: cjni_create_jvm: jvm_argv[%zu] = %s",
+ i, jvm_argv[i]);
+ vm_args.options[i].optionString = jvm_argv[i];
+ }
+
+ status = JNI_CreateJavaVM (&jvm, (void *) &jvm_env, (void *) &vm_args);
+ if (status != 0)
+ {
+ ERROR ("java plugin: cjni_create_jvm: "
+ "JNI_CreateJavaVM failed with status %i.",
+ status);
+ return (-1);
+ }
+ assert (jvm != NULL);
+ assert (jvm_env != NULL);
+
+ /* Call RegisterNatives */
+ status = cjni_init_native (jvm_env);
+ if (status != 0)
+ {
+ ERROR ("java plugin: cjni_create_jvm: cjni_init_native failed.");
+ return (-1);
+ }
+
+ DEBUG ("java plugin: The JVM has been created.");
+ return (0);
+} /* }}} int cjni_create_jvm */
+