@@ -103,6 +103,42 @@ jobject o_log_format_json = nullptr;
103103jobject o_log_format_text = nullptr ;
104104jobject o_log_callback = nullptr ;
105105
106+ // ---------------------------------------------------------------------------
107+ // JNI global-ref lifecycle tables
108+ //
109+ // Every entry here is promoted to a JNI global ref in JNI_OnLoad and released
110+ // in JNI_OnUnload. Keep these in sync with the declarations above; ordering
111+ // within each table only matters for the human reader.
112+ // ---------------------------------------------------------------------------
113+ static jclass *const g_global_class_refs[] = {
114+ &c_llama_model, &c_string, &c_hash_map, &c_map, &c_set,
115+ &c_entry, &c_iterator, &c_integer, &c_float, &c_biconsumer,
116+ &c_llama_error, &c_log_level, &c_log_format, &c_error_oom,
117+ };
118+
119+ static jobject *const g_global_object_refs[] = {
120+ &o_utf_8,
121+ &o_log_level_debug, &o_log_level_info, &o_log_level_warn, &o_log_level_error,
122+ &o_log_format_json, &o_log_format_text,
123+ };
124+
125+ // Maps every object that is fetched from a Java static field on load to the
126+ // (class, field) pair it should be looked up from.
127+ struct static_object_binding {
128+ jobject *target;
129+ jclass *cls;
130+ jfieldID *field;
131+ };
132+
133+ static const static_object_binding g_static_object_bindings[] = {
134+ {&o_log_level_debug, &c_log_level, &f_log_level_debug},
135+ {&o_log_level_info, &c_log_level, &f_log_level_info},
136+ {&o_log_level_warn, &c_log_level, &f_log_level_warn},
137+ {&o_log_level_error, &c_log_level, &f_log_level_error},
138+ {&o_log_format_json, &c_log_format, &f_log_format_json},
139+ {&o_log_format_text, &c_log_format, &f_log_format_text},
140+ };
141+
106142/* *
107143 * Returns the jllama_context wrapper for the Java LlamaModel object.
108144 * Used by the delete path and any method that needs jctx directly.
@@ -454,21 +490,12 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
454490 goto error;
455491 }
456492
457- // create references
458- c_llama_model = (jclass)env->NewGlobalRef (c_llama_model);
459- c_string = (jclass)env->NewGlobalRef (c_string);
460- c_hash_map = (jclass)env->NewGlobalRef (c_hash_map);
461- c_map = (jclass)env->NewGlobalRef (c_map);
462- c_set = (jclass)env->NewGlobalRef (c_set);
463- c_entry = (jclass)env->NewGlobalRef (c_entry);
464- c_iterator = (jclass)env->NewGlobalRef (c_iterator);
465- c_integer = (jclass)env->NewGlobalRef (c_integer);
466- c_float = (jclass)env->NewGlobalRef (c_float);
467- c_biconsumer = (jclass)env->NewGlobalRef (c_biconsumer);
468- c_llama_error = (jclass)env->NewGlobalRef (c_llama_error);
469- c_log_level = (jclass)env->NewGlobalRef (c_log_level);
470- c_log_format = (jclass)env->NewGlobalRef (c_log_format);
471- c_error_oom = (jclass)env->NewGlobalRef (c_error_oom);
493+ // Promote local class refs (from FindClass) to global refs in one pass.
494+ // c_standard_charsets is intentionally omitted: only used to look up
495+ // f_utf_8 in this function and never referenced again.
496+ for (jclass *p : g_global_class_refs) {
497+ *p = (jclass)env->NewGlobalRef (*p);
498+ }
472499
473500 // find constructors
474501 cc_hash_map = env->GetMethodID (c_hash_map, " <init>" , " ()V" );
@@ -513,25 +540,18 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
513540 }
514541
515542 o_utf_8 = env->NewStringUTF (" UTF-8" );
516- o_log_level_debug = env->GetStaticObjectField (c_log_level, f_log_level_debug);
517- o_log_level_info = env->GetStaticObjectField (c_log_level, f_log_level_info);
518- o_log_level_warn = env->GetStaticObjectField (c_log_level, f_log_level_warn);
519- o_log_level_error = env->GetStaticObjectField (c_log_level, f_log_level_error);
520- o_log_format_json = env->GetStaticObjectField (c_log_format, f_log_format_json);
521- o_log_format_text = env->GetStaticObjectField (c_log_format, f_log_format_text);
543+ for (const auto &b : g_static_object_bindings) {
544+ *b.target = env->GetStaticObjectField (*b.cls , *b.field );
545+ }
522546
523547 if (!(o_utf_8 && o_log_level_debug && o_log_level_info && o_log_level_warn && o_log_level_error &&
524548 o_log_format_json && o_log_format_text)) {
525549 goto error;
526550 }
527551
528- o_utf_8 = env->NewGlobalRef (o_utf_8);
529- o_log_level_debug = env->NewGlobalRef (o_log_level_debug);
530- o_log_level_info = env->NewGlobalRef (o_log_level_info);
531- o_log_level_warn = env->NewGlobalRef (o_log_level_warn);
532- o_log_level_error = env->NewGlobalRef (o_log_level_error);
533- o_log_format_json = env->NewGlobalRef (o_log_format_json);
534- o_log_format_text = env->NewGlobalRef (o_log_format_text);
552+ for (jobject *p : g_global_object_refs) {
553+ *p = env->NewGlobalRef (*p);
554+ }
535555
536556 if (env->ExceptionCheck ()) {
537557 env->ExceptionDescribe ();
@@ -564,28 +584,12 @@ JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
564584 return ;
565585 }
566586
567- env->DeleteGlobalRef (c_llama_model);
568- env->DeleteGlobalRef (c_string);
569- env->DeleteGlobalRef (c_hash_map);
570- env->DeleteGlobalRef (c_map);
571- env->DeleteGlobalRef (c_set);
572- env->DeleteGlobalRef (c_entry);
573- env->DeleteGlobalRef (c_iterator);
574- env->DeleteGlobalRef (c_integer);
575- env->DeleteGlobalRef (c_float);
576- env->DeleteGlobalRef (c_biconsumer);
577- env->DeleteGlobalRef (c_llama_error);
578- env->DeleteGlobalRef (c_log_level);
579- env->DeleteGlobalRef (c_log_format);
580- env->DeleteGlobalRef (c_error_oom);
581-
582- env->DeleteGlobalRef (o_utf_8);
583- env->DeleteGlobalRef (o_log_level_debug);
584- env->DeleteGlobalRef (o_log_level_info);
585- env->DeleteGlobalRef (o_log_level_warn);
586- env->DeleteGlobalRef (o_log_level_error);
587- env->DeleteGlobalRef (o_log_format_json);
588- env->DeleteGlobalRef (o_log_format_text);
587+ for (jclass *p : g_global_class_refs) {
588+ env->DeleteGlobalRef (*p);
589+ }
590+ for (jobject *p : g_global_object_refs) {
591+ env->DeleteGlobalRef (*p);
592+ }
589593
590594 if (o_log_callback != nullptr ) {
591595 env->DeleteGlobalRef (o_log_callback);
0 commit comments