Skip to content

Commit e80a8bc

Browse files
committed
Table-driven JNI global ref lifecycle in JNI_OnLoad/OnUnload
Replaces 14 hand-written NewGlobalRef + 7 GetStaticObjectField + 7 NewGlobalRef + 21 DeleteGlobalRef calls with iteration over three small tables: g_global_class_refs, g_global_object_refs, g_static_object_bindings. Adding a new global ref is now a single-line table edit instead of touching four separate places. https://claude.ai/code/session_01TBELeBieKqvMwp1Ez8HgSk
1 parent 9c47649 commit e80a8bc

1 file changed

Lines changed: 54 additions & 50 deletions

File tree

‎src/main/cpp/jllama.cpp‎

Lines changed: 54 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,42 @@ jobject o_log_format_json = nullptr;
103103
jobject o_log_format_text = nullptr;
104104
jobject 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

Comments
 (0)