1

メモリ不足の状態で発生すると思われる Android アプリケーションの不可解なクラッシュをデバッグしようとしています。問題のアプリのソースは、https://bitbucket.org/stativ/chmupocasiから入手できます。アプリのパッケージはcz.jirkovsky.lukas.chmupocasi

電話のメモリが不足し始め、最近のアプリのリスト (ホームボタンを長押しした後に表示されるもの) からアプリケーションを再度開いてみると、アプリケーションがクラッシュします。

Android Studio を使用してアプリケーションをデバッグしようとしましたが、メイン アクティビティの onCreate() と onStart() のいずれかのブレークポイントに到達する前にアプリケーションが常にクラッシュし、デバッグできなくなります。さらに悪いことに、logcat にも情報が含まれていません。アプリがクラッシュしたときに表示される唯一の関連行は次のとおりです。

I/ActivityManager(  428): Displayed cz.jirkovsky.lukas.chmupocasi/.MainActivity: +1s45ms (total +23m23s835ms)

完全な logcat はhttp://pastebin.com/TtSuqxCWで入手できます。

最後に、Androidのダイアログ「残念ながらアプリケーションが停止しました」が表示されたときに、アプリケーションがクラッシュした後、デバッガをアプリケーションに接続しようとしました。コードがどのスレッドでも実行されていません。「エクスポートスレッド」に含まれるものは次のとおりです。

<1> main@830017304224, prio=5, in group 'main', status: 'RUNNING'
  at android.os.BinderProxy.transact(Binder.java:-1)
  at android.app.ActivityManagerProxy.handleApplicationCrash(ActivityManagerNative.java:3147)
  at com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException(RuntimeInit.java:76)
  at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693)
  at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)
  at dalvik.system.NativeStart.main(NativeStart.java:-1)

<10> Binder_2@830026133152, prio=5, in group 'main', status: 'RUNNING'
  at dalvik.system.NativeStart.run(NativeStart.java:-1)

<9> Binder_1@830026131496, prio=5, in group 'main', status: 'RUNNING'
  at dalvik.system.NativeStart.run(NativeStart.java:-1)

<8> FinalizerWatchdogDaemon@830026116408 daemon, prio=5, in group 'system', status: 'WAIT'
  at java.lang.Object.wait(Object.java:-1)
  at java.lang.Object.wait(Object.java:364)
  at java.lang.Daemons$FinalizerWatchdogDaemon.run(Daemons.java:214)
  at java.lang.Thread.run(Thread.java:856)

<7> FinalizerDaemon@830026115976 daemon, prio=5, in group 'system', status: 'WAIT'
  at java.lang.Object.wait(Object.java:-1)
  at java.lang.Object.wait(Object.java:401)
  at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:102)
  at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:73)
  at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:169)
  at java.lang.Thread.run(Thread.java:856)

<6> ReferenceQueueDaemon@830026115560 daemon, prio=5, in group 'system', status: 'WAIT'
  at java.lang.Object.wait(Object.java:-1)
  at java.lang.Object.wait(Object.java:364)
  at java.lang.Daemons$ReferenceQueueDaemon.run(Daemons.java:129)
  at java.lang.Thread.run(Thread.java:856)

<5> Compiler@830026115320 daemon, prio=5, in group 'system', status: 'WAIT'
  at dalvik.system.NativeStart.run(NativeStart.java:-1)

<3> Signal Catcher@830026114840 daemon, prio=5, in group 'system', status: 'WAIT'
  at dalvik.system.NativeStart.run(NativeStart.java:-1)

<2> GC@830026114616 daemon, prio=5, in group 'system', status: 'WAIT'
  at dalvik.system.NativeStart.run(NativeStart.java:-1)

メイン スレッドを調べてみると、未処理の例外が ThreadGroup のどこかにあることがわかります。

 No such instance field: 'nthreads'

このようなクラッシュをデバッグする方法や、それに関する詳細情報を取得する方法はありますか?

4

1 に答える 1

1

私は最終的に解決策を見つけました。それは実際には2つの別々の問題でした。

1 つ目は、私のデバイス (Huawei Y300) が、logcat を使用して取得できるスタック トレースを記録しなかったことです。これは、今日の初めに行った再起動によって解決された可能性があります。または、可能性は低いですが、ログ経由android.util.Logでデバッグ情報を記録しようとしたという事実によって解決されました。

2つ目はクラッシュそのものです。クラッシュからスタック トレースを取得した後、問題は非常に簡単に修正できました。デバッガーを使用して取得した以前の情報では、スレッドに関する問題が指摘されていましたが、実際の原因は次の例外でした。

android.app.Fragment$InstantiationException: Unable to instantiate fragment cz.jirkovsky.lukas.chmupocasi.RetainFragment: make sure class name exists, is public, and has an empty constructor that is public

本当の原因は、RetainFragmentパッケージが非公開だったことです。ただし、から継承するすべてのクラスFragmentは public クラスまたは public static inner classes である必要があります

そうでない場合、ひどく噛まれる可能性があります。その理由は、クラスがパッケージ プライベートの場合は正常に動作しているように見えても、Fragmentメモリ不足の状態でメモリを再利用するために破棄された後に a を再作成すると失敗するためです。

最後の教訓は、IDE の言うことを常に聞くべきではないということです。なぜなら、このフラグメント クラスをパッケージ プライベートにすることができると Android Studio が教えてくれた後にバグを導入したからです。

于 2013-09-12T18:18:01.747 に答える