Skip to content

Commit 174fd85

Browse files
committed
Update MonoVM GC bridge
It works! Build: dotnet build -c Release -p:DotNetTargetFramework=net8.0 -t:Prepare dotnet build -c Release -p:DotNetTargetFramework=net8.0 dotnet publish --self-contained -p:UseMonoRuntime=true -p:DotNetTargetFramework=net8.0 \ -p:UseAppHost=true -p:ErrorOnDuplicatePublishOutputFiles=false \ samples/Hello-Java.Base/Hello-Java.Base.csproj -r osx-x64 Run: JAVA_INTEROP_GREF_LOG=g.txt ./samples/Hello-Java.Base/bin/Release/osx-x64/publish/Hello-Java.Base `g.txt` contains: … *take_weak obj=0x10560dc70; handle=0x7f7f42f15148 +w+ grefc 8 gwrefc 1 obj-handle 0x7f7f42f15148/G -> new-handle 0x7f7f43008401/W from thread '(null)'(1) take_weak_global_ref_jni -g- grefc 7 gwrefc 1 handle 0x7f7f42f15148/G from thread '(null)'(1) take_weak_global_ref_jni *try_take_global obj=0x10560dc70 -> wref=0x7f7f43008401 handle=0x0 -w- grefc 7 gwrefc 0 handle 0x7f7f43008401/W from thread '(null)'(1) take_global_ref_jni Finalizing PeerReference=0x0/G IdentityHashCode=0x70dea4e Instance=0x59b98e2b Instance.Type=Hello.MyJLO
1 parent 22ffe25 commit 174fd85

File tree

2 files changed

+72
-68
lines changed

2 files changed

+72
-68
lines changed

src/Java.Interop/Java.Interop/JniObjectReferenceControlBlock.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ internal struct JniObjectReferenceControlBlock {
1313

1414
public static unsafe JniObjectReferenceControlBlock* Alloc ()
1515
{
16-
return (JniObjectReferenceControlBlock*)NativeMemory.AllocZeroed (1, (uint) Size);
16+
return (JniObjectReferenceControlBlock*) NativeMemory.AllocZeroed (1, (uint) Size);
1717
}
1818

1919
public static unsafe void Free (ref JniObjectReferenceControlBlock* value)

src/java-interop/java-interop-gc-bridge-mono.cc

Lines changed: 71 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,16 @@ using namespace xamarin::android;
3030

3131
typedef struct MonoJavaGCBridgeInfo {
3232
MonoClass *klass;
33-
MonoClassField *handle;
34-
MonoClassField *handle_type;
35-
MonoClassField *refs_added;
36-
MonoClassField *weak_handle;
33+
MonoClassField *jniObjectReferenceControlBlock;
3734
} MonoJavaGCBridgeInfo;
3835

36+
typedef struct JniObjectReferenceControlBlock {
37+
jobject handle;
38+
int handle_type;
39+
jobject weak_handle;
40+
int refs_added;
41+
} JniObjectReferenceControlBlock;
42+
3943
#define NUM_GC_BRIDGE_TYPES (4)
4044

4145
struct JavaInteropGCBridge {
@@ -366,13 +370,10 @@ java_interop_gc_bridge_register_bridgeable_type (
366370
MonoJavaGCBridgeInfo *info = &bridge->mono_java_gc_bridge_info [i];
367371

368372
info->klass = mono_class_from_mono_type (type);
369-
info->handle = mono_class_get_field_from_name (info->klass, const_cast<char*> ("handle"));
370-
info->handle_type = mono_class_get_field_from_name (info->klass, const_cast<char*> ("handle_type"));
371-
info->refs_added = mono_class_get_field_from_name (info->klass, const_cast<char*> ("refs_added"));
372-
info->weak_handle = mono_class_get_field_from_name (info->klass, const_cast<char*> ("weak_handle"));
373373

374-
if (info->klass == NULL || info->handle == NULL || info->handle_type == NULL ||
375-
info->refs_added == NULL || info->weak_handle == NULL)
374+
info->jniObjectReferenceControlBlock = mono_class_get_field_from_name (info->klass, const_cast<char*> ("jniObjectReferenceControlBlock"));
375+
376+
if (info->klass == NULL || info->jniObjectReferenceControlBlock == NULL)
376377
return -1;
377378
bridge->num_bridge_types++;
378379
return 0;
@@ -780,6 +781,18 @@ get_gc_bridge_info_for_object (JavaInteropGCBridge *bridge, MonoObject *object)
780781
return get_gc_bridge_info_for_class (bridge, mono_object_get_class (object));
781782
}
782783

784+
static JniObjectReferenceControlBlock*
785+
get_gc_control_block_for_object (JavaInteropGCBridge *bridge, MonoObject *obj)
786+
{
787+
MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (bridge, obj);
788+
if (bridge_info == NULL)
789+
return NULL;
790+
791+
JniObjectReferenceControlBlock *control_block;
792+
mono_field_get_value (obj, bridge_info->jniObjectReferenceControlBlock, &control_block);
793+
return control_block;
794+
}
795+
783796
typedef mono_bool (*MonodroidGCTakeRefFunc) (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id);
784797

785798
static MonodroidGCTakeRefFunc take_global_ref;
@@ -788,12 +801,11 @@ static MonodroidGCTakeRefFunc take_weak_global_ref;
788801
static mono_bool
789802
take_global_ref_java (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id)
790803
{
791-
MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (bridge, obj);
792-
if (bridge_info == NULL)
804+
JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (bridge, obj);
805+
if (control_block == NULL)
793806
return 0;
794807

795-
jobject weak;
796-
mono_field_get_value (obj, bridge_info->weak_handle, &weak);
808+
jobject weak = control_block->weak_handle;
797809

798810
jobject handle = env->CallObjectMethod (weak, bridge->WeakReference_get);
799811
log_gref (bridge, "*try_take_global_2_1 obj=%p -> wref=%p handle=%p\n", obj, weak, handle);
@@ -808,25 +820,22 @@ take_global_ref_java (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj,
808820
java_interop_gc_bridge_weak_gref_log_delete (bridge, weak, get_object_ref_type (env, weak), thread_name, thread_id, "take_global_ref_java");
809821
env->DeleteGlobalRef (weak);
810822
weak = NULL;
811-
mono_field_set_value (obj, bridge_info->weak_handle, &weak);
812823

813-
mono_field_set_value (obj, bridge_info->handle, &handle);
814-
815-
int type = JNIGlobalRefType;
816-
mono_field_set_value (obj, bridge_info->handle_type, &type);
824+
control_block->weak_handle = weak;
825+
control_block->handle = handle;
826+
control_block->handle_type = JNIGlobalRefType;
817827

818828
return handle != NULL;
819829
}
820830

821831
static mono_bool
822832
take_weak_global_ref_java (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id)
823833
{
824-
MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (bridge, obj);
825-
if (bridge_info == NULL)
834+
JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (bridge, obj);
835+
if (control_block == NULL)
826836
return 0;
827837

828-
jobject handle;
829-
mono_field_get_value (obj, bridge_info->handle, &handle);
838+
jobject handle = control_block->handle;
830839

831840
jobject weaklocal = env->NewObject (bridge->WeakReference_class, bridge->WeakReference_init, handle);
832841
jobject weakglobal = env->NewGlobalRef (weaklocal);
@@ -838,22 +847,20 @@ take_weak_global_ref_java (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject
838847

839848
java_interop_gc_bridge_gref_log_delete (bridge, handle, get_object_ref_type (env, handle), thread_name, thread_id, "take_weak_global_ref_2_1_compat");
840849
env->DeleteGlobalRef (handle);
841-
842-
mono_field_set_value (obj, bridge_info->weak_handle, &weakglobal);
850+
control_block->handle = NULL;
851+
control_block->weak_handle = weakglobal;
843852

844853
return 1;
845854
}
846855

847856
static mono_bool
848857
take_global_ref_jni (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id)
849858
{
850-
MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (bridge, obj);
851-
if (bridge_info == NULL)
859+
JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (bridge, obj);
860+
if (control_block == NULL)
852861
return 0;
853862

854-
jobject weak;
855-
mono_field_get_value (obj, bridge_info->handle, &weak);
856-
863+
jobject weak = control_block->handle;
857864
jobject handle = env->NewGlobalRef (weak);
858865
log_gref (bridge, "*try_take_global obj=%p -> wref=%p handle=%p\n", obj, weak, handle);
859866

@@ -868,22 +875,20 @@ take_global_ref_jni (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj,
868875
thread_name, thread_id, "take_global_ref_jni");
869876
env->DeleteWeakGlobalRef (weak);
870877

871-
mono_field_set_value (obj, bridge_info->handle, &handle);
878+
control_block->handle = handle;
879+
control_block->handle_type = JNIGlobalRefType;
872880

873-
int type = JNIGlobalRefType;
874-
mono_field_set_value (obj, bridge_info->handle_type, &type);
875881
return handle != NULL;
876882
}
877883

878884
static mono_bool
879885
take_weak_global_ref_jni (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id)
880886
{
881-
MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (bridge, obj);
882-
if (bridge_info == NULL)
887+
JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (bridge, obj);
888+
if (control_block == NULL)
883889
return 0;
884890

885-
jobject handle;
886-
mono_field_get_value (obj, bridge_info->handle, &handle);
891+
jobject handle = control_block->handle;
887892

888893
log_gref (bridge, "*take_weak obj=%p; handle=%p\n", obj, handle);
889894

@@ -896,10 +901,8 @@ take_weak_global_ref_jni (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *
896901
thread_name, thread_id, "take_weak_global_ref_jni");
897902
env->DeleteGlobalRef (handle);
898903

899-
mono_field_set_value (obj, bridge_info->handle, &weak);
900-
901-
int type = JNIWeakGlobalRefType;
902-
mono_field_set_value (obj, bridge_info->handle_type, &type);
904+
control_block->handle = weak;
905+
control_block->handle_type = JNIWeakGlobalRefType;
903906

904907
return 1;
905908
}
@@ -921,17 +924,18 @@ get_add_reference_method (JavaInteropGCBridge *bridge, JNIEnv *env, jobject obj,
921924
}
922925

923926
static mono_bool
924-
add_reference (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, MonoJavaGCBridgeInfo *bridge_info, MonoObject *reffed_obj)
927+
add_reference (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, JniObjectReferenceControlBlock *control_block, MonoObject *reffed_obj)
925928
{
926929
MonoClass *klass = mono_object_get_class (obj);
927930

928-
jobject handle;
929-
mono_field_get_value (obj, bridge_info->handle, &handle);
931+
jobject handle = control_block->handle;
930932

931933
jmethodID add_method_id = get_add_reference_method (bridge, env, handle, klass);
932934
if (add_method_id) {
933-
jobject reffed_handle;
934-
mono_field_get_value (reffed_obj, bridge_info->handle, &reffed_handle);
935+
JniObjectReferenceControlBlock *reffed_control_block = get_gc_control_block_for_object (bridge, reffed_obj);
936+
if (reffed_control_block == NULL)
937+
return 0;
938+
jobject reffed_handle = reffed_control_block->handle;
935939
env->CallVoidMethod (handle, add_method_id, reffed_handle);
936940
#if DEBUG
937941
if (bridge->gref_log_level > 1)
@@ -979,28 +983,30 @@ gc_prepare_for_java_collection (JavaInteropGCBridge *bridge, JNIEnv *env, int nu
979983
/* add java refs for items on the list which reference each other */
980984
for (int i = 0; i < num_sccs; i++) {
981985
MonoGCBridgeSCC *scc = sccs [i];
982-
MonoJavaGCBridgeInfo *bridge_info = NULL;
986+
987+
JniObjectReferenceControlBlock *control_block = NULL;
988+
983989
/* start at the second item, ref j from j-1 */
984990
for (int j = 1; j < scc->num_objs; j++) {
985-
bridge_info = get_gc_bridge_info_for_object (bridge, scc->objs [j-1]);
986-
if (bridge_info != NULL && add_reference (bridge, env, scc->objs [j-1], bridge_info, scc->objs [j])) {
987-
mono_field_set_value (scc->objs [j-1], bridge_info->refs_added, &ref_val);
991+
control_block = get_gc_control_block_for_object (bridge, scc->objs [j-1]);
992+
if (control_block != NULL && add_reference (bridge, env, scc->objs [j-1], control_block, scc->objs [j])) {
993+
control_block->refs_added = ref_val;
988994
}
989995
}
990996
/* ref the first from the last */
991997
if (scc->num_objs > 1) {
992-
bridge_info = get_gc_bridge_info_for_object (bridge, scc->objs [scc->num_objs-1]);
993-
if (bridge_info != NULL && add_reference (bridge, env, scc->objs [scc->num_objs-1], bridge_info, scc->objs [0])) {
994-
mono_field_set_value (scc->objs [scc->num_objs-1], bridge_info->refs_added, &ref_val);
998+
control_block = get_gc_control_block_for_object (bridge, scc->objs [scc->num_objs-1]);
999+
if (control_block != NULL && add_reference (bridge, env, scc->objs [scc->num_objs-1], control_block, scc->objs [0])) {
1000+
control_block->refs_added = ref_val;
9951001
}
9961002
}
9971003
}
9981004

9991005
/* add the cross scc refs */
10001006
for (int i = 0; i < num_xrefs; i++) {
1001-
MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (bridge, sccs [xrefs [i].src_scc_index]->objs [0]);
1002-
if (bridge_info != NULL && add_reference (bridge, env, sccs [xrefs [i].src_scc_index]->objs [0], bridge_info, sccs [xrefs [i].dst_scc_index]->objs [0])) {
1003-
mono_field_set_value (sccs [xrefs [i].src_scc_index]->objs [0], bridge_info->refs_added, &ref_val);
1007+
JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (bridge, sccs [xrefs [i].src_scc_index]->objs [0]);
1008+
if (control_block != NULL && add_reference (bridge, env, sccs [xrefs [i].src_scc_index]->objs [0], control_block, sccs [xrefs [i].dst_scc_index]->objs [0])) {
1009+
control_block->refs_added = ref_val;
10041010
}
10051011
}
10061012

@@ -1041,19 +1047,18 @@ gc_cleanup_after_java_collection (JavaInteropGCBridge *bridge, JNIEnv *env, int
10411047
sccs [i]->is_alive = 0;
10421048
for (int j = 0; j < sccs [i]->num_objs; j++) {
10431049
MonoObject *obj = sccs [i]->objs [j];
1044-
MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (bridge, obj);
1045-
if (bridge_info == NULL)
1050+
1051+
JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (bridge, obj);
1052+
if (control_block == NULL)
10461053
continue;
10471054

1048-
jobject jref;
1049-
mono_field_get_value (obj, bridge_info->handle, &jref);
1055+
jobject jref = control_block->handle;
10501056
if (jref) {
10511057
alive++;
10521058
if (j > 0)
10531059
assert (sccs [i]->is_alive);
10541060
sccs [i]->is_alive = 1;
1055-
int refs_added;
1056-
mono_field_get_value (obj, bridge_info->refs_added, &refs_added);
1061+
int refs_added = control_block->refs_added;
10571062
if (refs_added) {
10581063
jmethodID clear_method_id = get_clear_references_method (bridge, env, jref);
10591064
if (clear_method_id) {
@@ -1201,13 +1206,12 @@ gc_bridge_class_kind (MonoClass *klass)
12011206
static mono_bool
12021207
gc_is_bridge_object (MonoObject *object)
12031208
{
1204-
void *handle;
12051209

1206-
MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (mono_bridge, object);
1207-
if (bridge_info == NULL)
1208-
return 0;
1210+
JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (mono_bridge, object);
1211+
if (control_block == NULL)
1212+
return 0;;
12091213

1210-
mono_field_get_value (object, bridge_info->handle, &handle);
1214+
void *handle = control_block->handle;
12111215
if (handle == NULL) {
12121216
#if DEBUG
12131217
MonoClass *mclass = mono_object_get_class (object);

0 commit comments

Comments
 (0)