首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >试图追踪漏油事故

试图追踪漏油事故
EN

Stack Overflow用户
提问于 2017-09-15 05:35:00
回答 1查看 1.1K关注 0票数 10

在大约10分钟的操作后,应用程序可靠崩溃,我遇到了问题,我正在试图找到崩溃的来源。

logcat似乎表明,崩溃是由于基于下面一行的grefs泄漏。

09-14 23:36:48.055 12383 12409 I单色体-gc: 46080个杰出的GREFs.>执行一个完整的GC!

这一行后面是重复GC活动的狂热,直到活动管理器终止应用程序为止,如下行所示。

"08-23 11:10:14.393 880 894 i ActivityManager: ActivityManager (adj 0):用户请求>错误后“(请注意,这一行是以前日志中的--我刚刚把它放在手边)

我尝试通过以下adb命令启用gref日志记录(正如https://developer.xamarin.com/guides/android/troubleshooting/troubleshooting/所建议的)

亚洲开发银行壳牌公司debug.mono.log gref,gc

但是,我在日志记录方面有两个问题

1)下面的日志条目似乎不包含任何有用的信息,这是gref日志的一个示例。注意,grefs指向的对象上没有任何堆栈跟踪或类型信息,如Xamarin网站上的故障排除示例所示。

2)启用gref日志会导致我的应用程序的主ui冻结。我已经重复了好几次这种行为,但是还没有弄清楚为什么会这样。在ide中我没有任何异常,只是冻结屏幕,然后是活动管理器强制完成我的主要活动。

(09-14 23:45:30.742 883 909 W ActivityManager:力竭整理活动>WheelchairQuickCollect.WheelchairQuickCollect/md580d5d820f0b3cedc88e4799f6dbbf8c>5.MainActivity )

有人对我如何识别什么是锁定UI线程有任何建议吗?

此外,任何想法,我如何确定什么是消耗了所有的grefs将非常感谢。即使是输入由这些参考文件链接的.net运行时或java对象的信息也是一个好的开始。

代码语言:javascript
复制
09-14 23:45:30.389 13759 14047 I monodroid-gref: +w+ grefc 1082 gwrefc 4 obj-handle 0x1018c6/G -> new-handle 0x2002d7/W from thread 'finalizer'(14047)

09-14 23:45:30.390 13759 14047 I monodroid-gref: +w+ grefc 1075 gwrefc 11 obj-handle 0x18ea/G -> new-handle 0x2f3/W from thread 'finalizer'(14047)

09-14 23:45:30.390 13759 14047 I monodroid-gref: -g- grefc 1075 gwrefc 11 handle 0x18ea/G from thread 'finalizer'(14047)

更新

非常感谢SushiHangover帮助我走上正确的道路。从那以后,我发现泄漏来自一个用于android库的usb串口的c#端口。几句评论。

  • 我能够通过禁用一些从android传感器API请求/处理度量的代码来避免锁定UI。不知道为什么会起作用,但我现在没时间想清楚。
  • 我在/data/user/0/package_name_here/files/.__override__/grefs.txt中找到了gref.txt日志。这与宿醉后的回答有点不同。不确定这是否是我正在运行的android版本(7.1.1)的结果。我通过在我的主要活动this.ApplicationContext.FilesDir.AbsolutePath方法中记录onCreate的结果来确定这个路径。
  • gref.txt日志非常冗长,没有任何类型的摘要,因此很难确定哪些对象实际泄漏。如果有人知道一个工具可以总结这个文件,那将是非常有帮助的。但是,我发现您可以强制dalvik缓存转储引用表的摘要(本地/全局)。要转储表,必须使用反射来调用dumpReferenceTables方法,如下所示。我在一个专门的任务中运行debugGlobalRefWorker,每10秒打印一次表。从转储的摘要部分,我能够快速识别泄漏对象的类型。然后,我使用gref.txt日志来了解对象最常见的分配位置。幸运的是,漏油量很大,所以很容易看出它是从哪里来的。

用于转储引用表的代码

代码语言:javascript
复制
    public void debugGlobalRefWorker()
    {
        while(true)
        {
            dumpGlobalRefTable();
            Task.Delay(10000).Wait();
        }
    }

    //dont create these in dumpGlobalRefTable otherwise they will clutter up the gref log
    Java.Lang.Reflect.Method dumpGREFTableMethod = Java.Lang.Class.ForName("dalvik.system.VMDebug").GetDeclaredMethod("dumpReferenceTables");
    Java.Lang.Object[] args = new Java.Lang.Object[0];

    public void dumpGlobalRefTable()
    {
        //          Java.Lang.Class cls = Java.Lang.Class.ForName("android.os.Debug");
        //          Java.Lang.Class cls = Java.Lang.Class.ForName("dalvik.system.VMDebug");
        //      var method = cls.GetDeclaredMethod("dumpReferenceTables");
        dumpGREFTableMethod.Invoke(null,args);
    }

示例表

代码语言:javascript
复制
09-18 12:20:36.091 29146 29174 I art     : global reference table dump:

09-18 12:20:36.091 29146 29174 I art     :   Last 10 entries (of 677):

09-18 12:20:36.091 29146 29174 I art     :       676: 0x7106a800 java.lang.Class<android.hardware.SensorEvent>

09-18 12:20:36.091 29146 29174 I art     :       675: 0x32c023c0 android.hardware.SensorEvent

09-18 12:20:36.091 29146 29174 I art     :       674: 0x32c04520 android.os.Bundle

09-18 12:20:36.091 29146 29174 I art     :       673: 0x32c06070 com.google.android.gms.internal.zzary

09-18 12:20:36.091 29146 29174 I art     :       672: 0x7104b448 java.lang.Class<android.widget.Toast>
...

09-18 12:20:36.091 29146 29174 I art     :   Summary:

09-18 12:20:36.091 29146 29174 I art     :         1 of android.runtime.UncaughtExceptionHandler

09-18 12:20:36.091 29146 29174 I art     :         2 of md57dcfd83abf19bfc45de0a46e73444d92.ServiceConnectionHelper (2 unique instances)

09-18 12:20:36.092 29146 29174 I art     :         1 of md526b7ac14cffc1a788e82c7b73f3add08.GoogleApiClientConnectionCallbacksImpl

09-18 12:20:36.092 29146 29174 I art     :         1 of md580d5d820f0b3cedc88e4799f6dbbf8c5.WheelchairConnectService_FLPCallbackHelper

09-18 12:20:36.092 29146 29174 I art     :         1 of md5e34b7f0d2ba7321e77528f2c21447828.AndroidBaroMeasurementProvider

09-18 12:20:36.092 29146 29174 I art     :         1 of md5e34b7f0d2ba7321e77528f2c21447828.AndroidMagUncalMeasurementProvider
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-09-15 08:13:48

gref文档对于如何获取细节的细节有点缺乏,因为事情已经发生了变化。

启用gref日志记录:

Logcat输出(通过adb logcat -s monodroid-gref进行过滤):

代码语言:javascript
复制
adb shell setprop debug.mono.log gref

注意:我从未见过它挂起UI线程或导致终止,但请尝试在运行应用程序之前启用它。

代码语言:javascript
复制
~~~~ 
09-14 23:40:19.656  4053  4053 I monodroid-gref: +g+ grefc 291 gwrefc 0 obj-handle 0x100019/I -> new-handle 0x100786/G from thread '(null)'(1)           
~~~~

详细信息在grefs.txt

代码语言:javascript
复制
+g+ grefc 291 gwrefc 0 obj-handle 0x100019/I -> new-handle 0x100786/G from thread '(null)'(1)
  at Android.Runtime.AndroidObjectReferenceManager.CreateGlobalReference (Java.Interop.JniObjectReference value) [0x00000] in <05a8ec13540f42fc8ec62ef099f948d3>:0
  at Java.Interop.JniObjectReference.NewGlobalRef () [0x00000] in <548a126e175845e0999036cd7abdeb57>:0
  at Android.Runtime.JNIEnv.NewGlobalRef (System.IntPtr jobject) [0x00000] in <05a8ec13540f42fc8ec62ef099f948d3>:0
  at Java.Lang.Object.RegisterInstance (Android.Runtime.IJavaObject instance, System.IntPtr value, Android.Runtime.JniHandleOwnership transfer, System.IntPtr& handle) [0x00000] in <05a8ec13540f42fc8ec62ef099f948d3>:0
  at Java.Lang.Object.SetHandle (System.IntPtr value, Android.Runtime.JniHandleOwnership transfer) [0x00000] in <05a8ec13540f42fc8ec62ef099f948d3>:0
  at Java.Lang.Object..ctor () [0x00000] in <05a8ec13540f42fc8ec62ef099f948d3>:0
  at Android_Gref_Test.JavaObjectWrapper..ctor () [0x00000] in /Users/Sushi/code/Projects/Android_Gref_Test/Android_Gref_Test/MainActivity.cs:45
  at Android_Gref_Test.MainActivity.Button_Click (System.Object sender, System.EventArgs e) [0x0003b] in /Users/Sushi/code/Projects/Android_Gref_Test/Android_Gref_Test/MainActivity.cs:33
  at Android.Views.View+IOnClickListenerImplementor.OnClick (Android.Views.View v) [0x00000] in <05a8ec13540f42fc8ec62ef099f948d3>:0
  at Android.Views.View+IOnClickListenerInvoker.n_OnClick_Landroid_view_View_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_v) [0x00000] in <05a8ec13540f42fc8ec62ef099f948d3>:0
  at System.Object.cf56947b-b824-4d0d-839a-1d6dd87a5b7c (System.IntPtr , System.IntPtr , System.IntPtr ) [0x00000] in <896ad1d315ca4ba7b117efb8dacaedcf>:0
handle 0x100786; key_handle 0x2ef9890: Java Type: `md505d171be8e81cafbccfb3a52eeebc2c5/JavaObjectWrapper`; MCW type: `Android_Gref_Test.JavaObjectWrapper`

这些详细信息位于应用程序数据文件(files/.__override__/grefs.txt)中的一个隐藏目录中。在同一时间点,这个目录是可以访问的,因此是一个报告的安全漏洞,并且进行了修补(Xamarin.Android 5.1.x),因此您现在需要应用程序级别或根访问来获得它。另外,如果写入的日志太多,Android将删除logcat消息,因此logcat中的gref列表可能会被删除,因此细节将存储在单独的文件中。

如果您有根访问权限,请使用adb pull

注意:通过abd root获得非生产版本仿真器的根访问权限。

代码语言:javascript
复制
adb pull /data/data/com.sushihangover.Android_Gref_Test/files/.__override__/grefs.txt ~/Desktop/grefs.txt

或者使用根shell

代码语言:javascript
复制
adb shell 
cd /data/data/com.sushihangover.Android_Gref_Test/files/.__override__/
cat grefs.txt

或者,如果您的应用程序包被标记为可调试:

代码语言:javascript
复制
adb shell
run-as com.sushihangover.Android_Gref_Test
cd files/.__override__
cat grefs.txt

Grefs.txt复制到公共dir:

注意:这只是一个简单的连续背景线程,把它放到你的Activity.OnCreate中,或者在一些基于调试的应用程序设置中设置它,等等.

代码语言:javascript
复制
#if DEBUG
    Task.Run(async () =>
    {
        const int seconds = 30;
        const string grefTag = "monodroid-gref";
        const string grefsFile = "grefs.txt";
        while (true)
        {
            var appDir = Application.ApplicationInfo.DataDir;
            var grefFile = Path.Combine("/data/data", PackageName, "files/.__override__", grefsFile);
            var grefFilePublic = Path.Combine(Environment.GetExternalStoragePublicDirectory(Environment.DirectoryDownloads).AbsolutePath, grefsFile);
            if (File.Exists(grefFile))
            {
                File.Copy(grefFile, grefFilePublic, true);
                Log.Debug(grefTag, $"adb pull {grefFilePublic} {grefsFile}");
            }
            else
                Log.Debug(grefTag, "no grefs.txt found, gref logging enabled? (adb shell setprop debug.mono.log gref)");
            await Task.Delay(seconds * 1000);
        }
    });
#endif

还可以通过以下方法将输出强制到另一个目录:

代码语言:javascript
复制
adb shell setprop debug.mono.log gref=/some/writable/path/grefs.txt
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46232314

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档