Подтвердить что ты не робот

Android App Crashes Неожиданно во время работы?

Что делает мое приложение? Приложение, которое я разрабатываю, является типичным клиент-серверным приложением, которое взаимодействует с сервером Windows, используя Wi-Fi. Приложение имеет несколько операций и действительно предъявляет высокие требования к памяти и процессору, то есть к собственным вызовам кодирования/декодирования speex.

В чем моя проблема? Проблема в том, что приложение неожиданно перезагружается при работе абсолютно нормально. Иногда при нормальной работе внезапно я вижу (в logcat), что вызывается класс Constructor of Application (класс, который расширяет класс API-приложений). Это приводит к сбою моего приложения, поскольку все глобальные данные хранятся в самом классе приложения.

Что я наделал? Первое, что поразило меня, было то, что Android чувствует, что у них мало памяти, поэтому он закрывает мое приложение, а затем автоматически перезапускает его. Поэтому я реализовал onLowMemory() класса Application. Но к моему удивлению это никогда не называется..

В чем основная проблема? Основная проблема заключается в том, что Nothing is printed on LogCat. Похоже, что даже сам Android не знает, почему он перезапустил мое уже запущенное приложение?

Что может быть возможной причиной этого внезапного перезапуска? Как я могу избежать этого?

Я работаю над Galaxy Y, и версия API 2.3.6. Мой AndroidManizest.xml выглядит как

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="some.package.MyApp"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:maxSdkVersion="15"
        android:minSdkVersion="10"
        android:targetSdkVersion="10" />

    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.RECORD_VIDEO" />

    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />

    <application
        android:name="some.package.MyApp"
        android:icon="@drawable/display_image"
        android:label="@string/app_name" >
        <activity
            android:name="some.package.LoginActivity"
            android:configChanges="keyboardHidden|orientation"
            android:label="@string/app_name"
            android:screenOrientation="user" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="some.package.BuddyListActivity"
            android:configChanges="keyboardHidden|orientation"
            android:label="@string/app_name"
            android:screenOrientation="user"
            android:theme="@android:style/Theme.Black.NoTitleBar" >

            <!--
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            -->
        </activity>
        <activity
            android:name="some.package.SessionWindowActivity"
            android:configChanges="keyboardHidden|orientation"
            android:label="@string/app_name"
            android:screenOrientation="user"
            android:theme="@android:style/Theme.Black.NoTitleBar" >

            <!--
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            -->
        </activity>
    </application>

</manifest>

EDIT Я только что увидел следующий вывод в LogCat после использования CheckJNI,

06-26 17:27:30.023: I/remove(24544): Sending Signal : 13 **//App Working fine here**
06-26 17:27:32.148: D/dalvikvm(24544): GC_CONCURRENT freed 446K, 49% free 3384K/6599K, external 1057K/1076K, paused 3ms+4ms
06-26 17:27:39.531: W/dalvikvm(24544): **HeapWorker may be wedged: 7374ms spent** inside LsomePackageName/modules/AudioPlayer;.finalize()V
06-26 17:27:40.023: I/remove(24544): Sending Signal : 13
06-26 17:27:40.218: D/dalvikvm(24544): GC_CONCURRENT freed 479K, 49% free 3383K/6599K, external 1057K/1076K, paused 9ms+5ms 
06-26 17:27:42.343: E/RoobrooApp(24670): Application Instance created **//Restarted** 
06-26 17:27:42.351: I/ApplicationPackageManager(24670): cscCountry is not German : INS

UPDATE Продолжая экспериментировать на одном шаге, я намеренно выделил очень большой объем памяти для двойного массива. Но, к моему удивлению, ни onLowMemory() не вызывался, ни приложение перезапускалось, вместо этого я получил исключениеOfMemoryException. Если onLowMemory() никогда не вызывается, почему он там?

Еще одна проблема заключается в том, что после перезагрузки ОС уже запускает BuddyListActivity вместо LoginActivity... Помощь действительно нужна....

ОБНОВЛЕНИЕ 2 Я только что увидел следующий журнал ошибок, я действительно не знаю, что это значит..

06-29 12:07:28.398: W/dalvikvm(19308): ReferenceTable overflow (max=1024)
06-29 12:07:28.398: W/dalvikvm(19308): Last 10 entries in JNI pinned array reference table:
06-29 12:07:28.398: W/dalvikvm(19308):  1014: 0x405b0280 cls=[B (340 bytes)
06-29 12:07:28.398: W/dalvikvm(19308):  1015: 0x405b03d8 cls=[S (660 bytes)
06-29 12:07:28.398: W/dalvikvm(19308):  1016: 0x405d8208 cls=[B (340 bytes)
06-29 12:07:28.398: W/dalvikvm(19308):  1017: 0x405d8360 cls=[S (660 bytes)
06-29 12:07:28.398: W/dalvikvm(19308):  1018: 0x405f8b08 cls=[B (340 bytes)
06-29 12:07:28.398: W/dalvikvm(19308):  1019: 0x405f8c60 cls=[S (660 bytes)
06-29 12:07:28.398: W/dalvikvm(19308):  1020: 0x405f8ef8 cls=[B (340 bytes)
06-29 12:07:28.398: W/dalvikvm(19308):  1021: 0x405ff698 cls=[S (660 bytes)
06-29 12:07:28.398: W/dalvikvm(19308):  1022: 0x405f9050 cls=[B (340 bytes)
06-29 12:07:28.398: W/dalvikvm(19308):  1023: 0x405ff930 cls=[S (660 bytes)
06-29 12:07:28.398: W/dalvikvm(19308): JNI pinned array reference table summary (1024 entries):
06-29 12:07:28.398: W/dalvikvm(19308):     1 of [B 20B
06-29 12:07:28.398: W/dalvikvm(19308):   508 of [B 340B (508 unique)
06-29 12:07:28.398: W/dalvikvm(19308):     3 of [B 348B (3 unique)
06-29 12:07:28.406: W/dalvikvm(19308):   511 of [S 660B (511 unique)
06-29 12:07:28.406: W/dalvikvm(19308):     1 of [S 668B
06-29 12:07:28.406: W/dalvikvm(19308): Memory held directly by tracked refs is 511712 bytes
06-29 12:07:28.406: E/dalvikvm(19308): Failed adding to JNI pinned array ref table (1024 entries)
06-29 12:07:28.406: I/dalvikvm(19308): "Thread-14" prio=5 tid=12 RUNNABLE
06-29 12:07:28.406: I/dalvikvm(19308):   | group="main" sCount=0 dsCount=0 obj=0x4050e548 self=0x2240b8
06-29 12:07:28.406: I/dalvikvm(19308):   | sysTid=19953 nice=-19 sched=0/0 cgrp=[fopen-error:2] handle=1905240
06-29 12:07:28.406: I/dalvikvm(19308):   | schedstat=( 207153329 82244881 1015 )
06-29 12:07:28.406: I/dalvikvm(19308):   at some.package.MyApp.speex.SpeexEncoder.encode(Native Method)
06-29 12:07:28.406: I/dalvikvm(19308):   at some.package.MyApp.speex.SpeexEncoder.encodeFrame(SpeexEncoder.java:51)
06-29 12:07:28.406: I/dalvikvm(19308):   at some.package.MyApp.models.Session.capturedAudioReceived(Session.java:656)
06-29 12:07:28.406: I/dalvikvm(19308):   at some.package.MyApp.modules.AudioCapturer.run(AudioCapturer.java:118)
06-29 12:07:28.406: I/dalvikvm(19308):   at java.lang.Thread.run(Thread.java:1019)
06-29 12:07:28.406: E/dalvikvm(19308): VM aborting
06-29 12:07:29.726: W/AudioTrack(19308): obtainBuffer() track 0x1d3520 disabled, restarting
06-29 12:07:30.351: W/dalvikvm(19308): threadid=4: spin on suspend #1 threadid=1 (pcf=0)
06-29 12:07:30.898: W/AudioTrack(19308): obtainBuffer() track 0x1d3520 disabled, restarting
06-29 12:07:31.101: W/dalvikvm(19308): threadid=4: spin on suspend #2 threadid=1 (pcf=0)
06-29 12:07:31.101: I/dalvikvm(19308): "Signal Catcher" daemon prio=5 tid=4 RUNNABLE
06-29 12:07:31.101: I/dalvikvm(19308):   | group="system" sCount=0 dsCount=0 obj=0x40510490 self=0x159898
06-29 12:07:31.101: I/dalvikvm(19308):   | sysTid=19312 nice=0 sched=0/0 cgrp=[fopen-error:2] handle=1575600
06-29 12:07:31.101: I/dalvikvm(19308):   | schedstat=( 1556395 4913328 26 )
06-29 12:07:31.101: I/dalvikvm(19308):   at dalvik.system.NativeStart.run(Native Method)
06-29 12:07:31.101: I/dalvikvm(19308): "main" prio=5 tid=1 RUNNABLE
06-29 12:07:31.101: I/dalvikvm(19308):   | group="main" sCount=1 dsCount=0 obj=0x40022198 self=0xcec8
06-29 12:07:31.101: I/dalvikvm(19308):   | sysTid=19308 nice=0 sched=0/0 cgrp=[fopen-error:2] handle=-1345006496
06-29 12:07:31.101: I/dalvikvm(19308):   | schedstat=( 5364166234 3306213349 13647 )
06-29 12:07:31.101: I/dalvikvm(19308):   at android.media.AudioTrack.native_write_short(Native Method)
06-29 12:07:31.101: I/dalvikvm(19308):   at android.media.AudioTrack.write(AudioTrack.java:943)
06-29 12:07:31.101: I/dalvikvm(19308):   at some.package.MyApp.modules.AudioPlayer.onPeriodicNotification(AudioPlayer.java:163)
06-29 12:07:31.101: I/dalvikvm(19308):   at android.media.AudioTrack$NativeEventHandlerDelegate$1.handleMessage(AudioTrack.java:1084)
06-29 12:07:31.101: I/dalvikvm(19308):   at android.os.Handler.dispatchMessage(Handler.java:99)
06-29 12:07:31.101: I/dalvikvm(19308):   at android.os.Looper.loop(Looper.java:130)
06-29 12:07:31.101: I/dalvikvm(19308):   at android.app.ActivityThread.main(ActivityThread.java:3687)
06-29 12:07:31.101: I/dalvikvm(19308):   at java.lang.reflect.Method.invokeNative(Native Method)
06-29 12:07:31.101: I/dalvikvm(19308):   at java.lang.reflect.Method.invoke(Method.java:507)
06-29 12:07:31.101: I/dalvikvm(19308):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
06-29 12:07:31.101: I/dalvikvm(19308):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
06-29 12:07:31.101: I/dalvikvm(19308):   at dalvik.system.NativeStart.main(Native Method)
06-29 12:07:31.851: W/dalvikvm(19308): threadid=4: spin on suspend #3 threadid=1 (pcf=0)
06-29 12:07:31.851: I/dalvikvm(19308): "Signal Catcher" daemon prio=5 tid=4 RUNNABLE
06-29 12:07:31.851: I/dalvikvm(19308):   | group="system" sCount=0 dsCount=0 obj=0x40510490 self=0x159898
06-29 12:07:31.851: I/dalvikvm(19308):   | sysTid=19312 nice=0 sched=0/0 cgrp=[fopen-error:2] handle=1575600
06-29 12:07:31.851: I/dalvikvm(19308):   | schedstat=( 2868652 6927485 37 )
06-29 12:07:31.851: I/dalvikvm(19308):   at dalvik.system.NativeStart.run(Native Method)
06-29 12:07:31.851: I/dalvikvm(19308): "main" prio=5 tid=1 RUNNABLE
06-29 12:07:31.851: I/dalvikvm(19308):   | group="main" sCount=1 dsCount=0 obj=0x40022198 self=0xcec8
06-29 12:07:31.851: I/dalvikvm(19308):   | sysTid=19308 nice=0 sched=0/0 cgrp=[fopen-error:2] handle=-1345006496
06-29 12:07:31.851: I/dalvikvm(19308):   | schedstat=( 5364166234 3306213349 13647 )
06-29 12:07:32.000: I/dalvikvm(19308):   at android.media.AudioTrack.native_write_short(Native Method)
06-29 12:07:32.015: I/dalvikvm(19308):   at android.media.AudioTrack.write(AudioTrack.java:943)
06-29 12:07:32.031: I/dalvikvm(19308):   at some.package.MyApp.modules.AudioPlayer.onPeriodicNotification(AudioPlayer.java:163)
06-29 12:07:32.039: I/dalvikvm(19308):   at android.media.AudioTrack$NativeEventHandlerDelegate$1.handleMessage(AudioTrack.java:1084)
06-29 12:07:32.054: I/dalvikvm(19308):   at android.os.Handler.dispatchMessage(Handler.java:99)
06-29 12:07:32.054: I/dalvikvm(19308):   at android.os.Looper.loop(Looper.java:130)
06-29 12:07:32.062: W/AudioTrack(19308): obtainBuffer() track 0x1d3520 disabled, restarting
06-29 12:07:32.070: I/dalvikvm(19308):   at android.app.ActivityThread.main(ActivityThread.java:3687)
06-29 12:07:32.093: I/dalvikvm(19308):   at java.lang.reflect.Method.invokeNative(Native Method)
06-29 12:07:32.101: I/dalvikvm(19308):   at java.lang.reflect.Method.invoke(Method.java:507)
06-29 12:07:32.109: I/dalvikvm(19308):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
06-29 12:07:32.125: I/dalvikvm(19308):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
06-29 12:07:32.132: I/dalvikvm(19308):   at dalvik.system.NativeStart.main(Native Method)
06-29 12:07:32.890: W/dalvikvm(19308): threadid=4: spin on suspend #4 threadid=1 (pcf=0)
06-29 12:07:32.890: I/dalvikvm(19308): "Signal Catcher" daemon prio=5 tid=4 RUNNABLE
06-29 12:07:32.890: I/dalvikvm(19308):   | group="system" sCount=0 dsCount=0 obj=0x40510490 self=0x159898
06-29 12:07:32.890: I/dalvikvm(19308):   | sysTid=19312 nice=0 sched=0/0 cgrp=[fopen-error:2] handle=1575600
06-29 12:07:32.890: I/dalvikvm(19308):   | schedstat=( 5340582 316192616 59 )
06-29 12:07:32.898: I/dalvikvm(19308):   at dalvik.system.NativeStart.run(Native Method)
06-29 12:07:32.898: I/dalvikvm(19308): "main" prio=5 tid=1 RUNNABLE
06-29 12:07:32.898: I/dalvikvm(19308):   | group="main" sCount=1 dsCount=0 obj=0x40022198 self=0xcec8
06-29 12:07:32.898: I/dalvikvm(19308):   | sysTid=19308 nice=0 sched=0/0 cgrp=[fopen-error:2] handle=-1345006496
06-29 12:07:32.898: I/dalvikvm(19308):   | schedstat=( 5364166234 3306213349 13647 )
06-29 12:07:32.929: I/dalvikvm(19308):   at android.media.AudioTrack.native_write_short(Native Method)
06-29 12:07:32.945: I/dalvikvm(19308):   at android.media.AudioTrack.write(AudioTrack.java:943)
06-29 12:07:32.953: I/dalvikvm(19308):   at some.package.MyApp.modules.AudioPlayer.onPeriodicNotification(AudioPlayer.java:163)

Решение Что ж, тестирование для измененного кода все еще продолжается, и пока все выглядит позитивно. Проблема была в JNI (я думаю). @n.Collins выражение "Тот факт, что JVM не сообщает об ошибке, также указывает на то, что она вызвана вашим собственным кодом". Был одним из наиболее правильных указателей на решение. Я действительно благодарю всех людей, которые ответили на это, так или иначе, мне помогли. Я действительно удалил множество других ошибок, пытаясь решить эту проблему, все благодаря сообществу.

4b9b3361

Ответ 1

Основываясь на обновлении №2, довольно ясно, что вам не удалось отменить массив в вашем JNI. Это означает, что вы используете Get<Type>ArrayElements и не смогли выполнить 1 или более из этих вызовов с помощью Release<Type>ArrayElements.

В результате ссылочная таблица переполнена. Ищите места, где вы вызываете Get и не вызываете Release. Например, вы могли бы вызывать GetIntArrayElements, но не смогли вызвать ReleaseIntArrayElements, когда вы закончите.

Ответ 2

Трудно сказать без полного исходного кода, что именно происходит, но, возможно, ответ Ромен Гай здесь в Google Groups поможет.

onLowMemory() вызывается, когда вся система заканчивается а не когда ваш процесс заканчивается из памяти. Каждое приложение ограниченный фиксированным объемом ОЗУ (например, 24 МБ на Nexus One). Если вы используете эти 24 МБ, но система все еще имеет больше доступной оперативной памяти, вы получите OutOfMemoryError, но не onLowMemory().

Предел 24 МБ в значительной степени установлен в камне для приложений на < Honeycomb. Если вы ориентируетесь на API 11 или выше, вы можете запросить больше памяти, объявив, что для вашего приложения будет выделена большая куча. Он не упоминается в документации, но добавление android:largeHeap="true" в тэг application в вашем манифесте .xml сделает это (хотя это не гарантируется).

Примечание: на модифицированной прошивке (пользовательские ПЗУ) это значение может быть ниже или выше. Я считаю, что Samsung Galaxy Nexus по умолчанию равен 48 Мб, но, как правило, пребывание в пределах 24 МБ является безопасным предположением. В Sony Ericsson есть также отличный пост, объясняющий технические различия между Gingerbread и Ice Cream Sandwich (оперативная память - это тема, которая подробно освещена).

Удачи, надеюсь, это по крайней мере поможет вам выявить проблему.

Ответ 3

Другие плакаты покрывали проблемы с памятью. Я просто добавлю, что для отладки собственного кода одним быстрым и грязным способом является добавление сообщений журнала на разных контрольных точках. Вот пример из одного из моих родных файлов cpp:

#include <android/log.h>

...

// Set to 1 to enable debug log traces...
#define DEBUG  0

#define LOG_TAG         "yourNativeCodeLogTag"
#if DEBUG
#define LOG_ERROR(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#define LOG_WARN(...)   __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
#define LOG_INFO(...)   __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOG_DEBUG(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#else // if !DEBUG
#define LOG_ERROR(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#define LOG_WARN(...)   __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
#define LOG_INFO(...)   
#define LOG_DEBUG(...) 
#endif // DEBUG

...

extern "C"
JNIEXPORT void JNICALL Java_com_whatever_package_YourClassName_jniInitializeLibrary(JNIEnv * env, jobject thiz, /* other irrelevant stuff here */)                 
{    
    LOG_DEBUG("Initializing native library.\n");
    ....
}

Наконец, вам также нужно добавить -llog в вашу переменную LOCAL_LDLIBS в соответствующем файле *.mk. Затем вы можете получать сообщения журнала из своей родной библиотеки в logcat.

UPDATE: после просмотра ваших обновлений, я думаю, вы должны использовать вышеупомянутую технику, чтобы перенести сообщения журнала в свой собственный метод encode(), чтобы увидеть, где именно он сбой.

Ответ 4

У меня недостаточно комментариев, чтобы прокомментировать ответы других людей, но я думаю, что Ответ на ошибку 454 довольно близок.

У меня была аналогичная проблема с моим собственным приложением с перезапуском приложения без сообщения. Моя проблема вызвана переполнением массива, когда я пытался получить доступ к индексу n+1 в массиве объектов n в моем собственном коде. Тот факт, что JVM не сообщает об ошибке, также указывает на то, что он вызван вашим собственным кодом.

Этот вопрос: С++ Jni Reference Table overflow имеет очень похожий журнал ошибок для вашего обновления 2, что еще раз указывает на то, что ваша ошибка заключается в том, что вы не соглашаетесь на получение и выпуск вызовы.

Если вы не понимаете, что такое JNI pinned reference table, я хотел бы обратить ваше внимание на разделы JNI Specification под названием "Доступ к объектам Java" и следующий раздел "Доступ к примитивным массивам" .

Наконец, некоторые фрагменты вашего собственного кода, в которых вы обращаетесь к примитивным массивам данных, были бы полезны для решения вашей проблемы, но тем временем я хотел бы обратить ваше внимание на окончательный комментарий к ответу на Переполнение ReferenceTable (max = 512) JNI, которое гласит:

GetObjectArrayElement возвращает объект с локальной ссылкой на него, поэтому вам нужно удалить локальную ссылку. Но вы должны это делать только тогда, когда вы закончите с элементами массива. Поэтому после releaseIntArrayElements(oneDim) вы должны поместить DeleteLocalRef(oneDim).

Поэтому, пожалуйста, дважды проверьте, что вы получили вызовы Get/Release при доступе к элементам массива и, когда вам больше не нужен доступ к нему, удалите локальную ссылку. Возможно, вы попадаете в конец справочной таблицы JNI, поскольку вы не удаляете старые объекты. Помните, JNI - это просто интерфейс c для Java, поэтому вам нужно помочь в сборке мусора для вашего собственного кода.

Ответ 5

Одна вещь, которая может быть проблемой, заключается в том, что, возможно, ваше приложение вылетает где-то внутри native code, и это внезапно остановит ваше приложение без какого-либо сообщения, и ничего не будет напечатано в Logcat.

У меня была та же проблема, пытаясь декодировать некоторую bitmaps, и Android разбился где-то внутри native code, и приложение останавливается, не вызывая никакого сообщения.

Относительно onLowMemory() Ответы @Tom покрывают его.