java vm ext.cc_java – 如何调试:应用程序中的JNI DETECTED ERROR:使用无效的jobject

理想情况下,如何调试此类情况非常接近您所遵循的路径.

您要做的第一件事是通过adb或带有AndroidEnvironment构建操作的environment.txt文件启用gref日志(注意:使用后一选项有限制 – https://developer.xamarin.com/guides/android/advanced_topics/environment/#Overview):

adb shell setprop debug.mono.log gref

大!现在我们可以看到各个全局引用的生命周期(简称gref).这是一个起点.为了将来在这篇文章中的参考,让我们定义几个项目:

> gref – 全球参考

> wref – 弱全球参考

理想情况下,我们希望在物理设备上测试它,因为它将具有~52000 grefs的限制.而模拟器的限制为2000 grefs.如你想象的那样,如果你很快就越过这条线(你可能会这样),这可能会非常麻烦.

接下来,我们可以遵循我们想要了解的四条主要消息的惯例:

>从g-gref创建开始

>从-g-开始 – gref销毁

>从w-wref创建开始

>从-w-开始 – wref破坏

您可能还注意到,在这些行上有一个grefc值.这是指gref计数,即Xamarin.Android所做的总量.然后,您可以假设grefwc值为wref计数.让我们在一个小表中定义它:

> grefc – gref count

> grefwc – wref计数

让我们来看看这个语法的一个例子:

I/monodroid-gref(12405): +g+ grefc 108 gwrefc 0 obj-handle 0x40517468/L -> new-handle 0x40517468/L from at Java.Lang.Object.RegisterInstance(IJavaObject instance, IntPtr value, JniHandleOwnership transfer)

I/monodroid-gref(12405): at Java.Lang.Object.SetHandle(IntPtr value, JniHandleOwnership transfer)

I/monodroid-gref(12405): at Java.Lang.Object..ctor(IntPtr handle, JniHandleOwnership transfer)

I/monodroid-gref(12405): at Java.Lang.Thread+RunnableImplementor..ctor(System.Action handler, Boolean removable)

I/monodroid-gref(12405): at Java.Lang.Thread+RunnableImplementor..ctor(System.Action handler)

I/monodroid-gref(12405): at Android.App.Activity.RunOnUiThread(System.Action action)

I/monodroid-gref(12405): at Mono.Samples.Hello.HelloActivity.UseLotsOfMemory(Android.Widget.TextView textview)

I/monodroid-gref(12405): at Mono.Samples.Hello.HelloActivity.m__3(System.Object o)

I/monodroid-gref(12405): handle 0x40517468; key_handle 0x40517468: Java Type: `mono/java/lang/RunnableImplementor`; MCW type: `Java.Lang.Thread+RunnableImplementor`

I/monodroid-gref(12405): Disposing handle 0x40517468

I/monodroid-gref(12405): -g- grefc 107 gwrefc 0 handle 0x40517468/L from at Java.Lang.Object.Dispose(System.Object instance, IntPtr handle, IntPtr key_handle, JObjectRefType handle_type)

I/monodroid-gref(12405): at Java.Lang.Object.Dispose()

I/monodroid-gref(12405): at Java.Lang.Thread+RunnableImplementor.Run()

I/monodroid-gref(12405): at Java.Lang.IRunnableInvoker.n_Run(IntPtr jnienv, IntPtr native__this)

I/monodroid-gref(12405): at System.Object.c200fe6f-ac33-441b-a3a0-47659e3f6750(IntPtr , IntPtr )

I/monodroid-gref(27679): +w+ grefc 1916 gwrefc 296 obj-handle 0x406b2b98/G -> new-handle 0xde68f4bf/W from take_weak_global_ref_jni

I/monodroid-gref(27679): -w- grefc 1915 gwrefc 294 handle 0xde691aaf/W from take_global_ref_jni

The handle or obj-handle value is the JNI handle value, and the character after the ‘ /’ is the type of handle value: /L for local reference, /G for global references, and /W for weak global references.

现在让我们在考虑这个注意事项的情况下看看各种场景:

# Java instance is created and wrapped by a MCW

I/monodroid-gref(27679): +g+ grefc 2211 gwrefc 0 obj-handle 0x4066df10/L -> new-handle 0x4066df10/L from ...

I/monodroid-gref(27679): handle 0x4066df10; key_handle 0x4066df10: Java Type: `android/graphics/drawable/TransitionDrawable`; MCW type: `Android.Graphics.Drawables.TransitionDrawable`

# A GC is being performed...

I/monodroid-gref(27679): +w+ grefc 1953 gwrefc 259 obj-handle 0x4066df10/G -> new-handle 0xde68f95f/W from take_weak_global_ref_jni

I/monodroid-gref(27679): -g- grefc 1952 gwrefc 259 handle 0x4066df10/G from take_weak_global_ref_jni

# Object is still alive, as handle != null

# wref turned back into a gref

I/monodroid-gref(27679): *try_take_global obj=0x4976f080 -> wref=0xde68f95f handle=0x4066df10

I/monodroid-gref(27679): +g+ grefc 1930 gwrefc 39 obj-handle 0xde68f95f/W -> new-handle 0x4066df10/G from take_global_ref_jni

I/monodroid-gref(27679): -w- grefc 1930 gwrefc 38 handle 0xde68f95f/W from take_global_ref_jni

# Object is dead, as handle == null

# wref is freed, no new gref created

I/monodroid-gref(27679): *try_take_global obj=0x4976f080 -> wref=0xde68f95f handle=0x0

I/monodroid-gref(27679): -w- grefc 1914 gwrefc 296 handle 0xde68f95f/W from take_global_ref_jni

现在,您已了解在各种场景中可以看到的模式,它将帮助您了解无效作业时的情况.

现在是有趣的部分,但也可能是最难的部分:

现在,您需要在启用此日志记录时复制崩溃.

完成后,您需要收到收到的新错误消息和给您的句柄.在您的原始帖子中,它指的是:

JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0xd4fd90e0

但是,这个句柄可能会在问题的不同复制过程中发生变化.但是,一旦掌握了这个句柄,就可以使用像grep这样的工具来搜索句柄字符串:

0xd4fd90e0

完成此操作后,您可以通过上面的示例代码段查看此句柄的状态,并在相应区域中进行修复. (过早GC,手动处理对象等)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值