Android App Crashes Suddenly while running?
The other posters have covered the out-of-memory issues. I'll just add that to debug your native code, one quick-and-dirty way is to add log messages at various checkpoints. Here's an example from one of my native cpp files:
#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");
....
}
Finally, you will also need to add -llog
to your LOCAL_LDLIBS variable in the relevant *.mk
file. Then, you can get log messages from your native library in logcat.
UPDATE: After seeing your updates, I think you should use the above technique to pepper log messages into your native encode()
method to see exactly where it's crashes.
Based on Update #2, it is pretty clear that you have failed to unpin an array in your JNI. This means that you are using the Get<Type>ArrayElements
and have failed to match 1 or more of these calls with Release<Type>ArrayElements
.
As a result, the ReferenceTable is overflowing. Look for places where you are calling Get and not calling Release. For example you could be calling GetIntArrayElements
but failing to call ReleaseIntArrayElements
when you are finished.
It is hard to tell without complete source code exactly what is happening, but perhaps Romain Guy's answer here on Google Groups will help.
onLowMemory()
is called when the entire system is running out of memory, not when your process is running out of memory. Each app is limited to a fixed amount of RAM (24 MB on a Nexus One for instance). If you use up these 24 MB but the system still has more RAM available, you will get anOutOfMemoryError
but notonLowMemory()
.
The 24mb limit is pretty much set in stone for applications on < Honeycomb. If you are targeting API 11 or higher you can ask for more memory by declaring that a large heap be allocated for your application. It is not mentioned in documentation but adding android:largeHeap="true"
to your application
tag in your Manifest.xml will do this (although it is not guaranteed).
Note: on modified firmware (custom ROMs) it is possible for that value to be lower or higher. I believe on the Samsung Galaxy Nexus it is 48mb by default, but as a general rule staying within 24mb is a safe assumption. There is also a great post on the Sony Ericsson explaining the technical differences between Gingerbread and Ice Cream Sandwich (RAM is a topic covered in-depth).
Good luck, I hope this at least helps you track down the issue.
I don't have enough rep to comment on other people's answers, but I think Error 454's answer is pretty close.
I had a similar problem with my own app with application restarting with no message. My problem was caused by an array overflow where I was trying to access index n+1
in an array of n
objects in my native code. The fact that no error is reported by the JVM also indicates it caused by your native code.
This question: c++ Jni Reference Table overflow has a very similar error log to your update 2, further indicating that your error lies in not having matched your get and release calls.
If you don't understand what the JNI pinned reference table
is, I'd like to direct your attention to the JNI Specification sections titled "Accessing Java Objects", and the following section "Accessing Primitive Arrays".
Finally, some snippets of your native code where you access primitive data arrays would be useful to help solve your problem, but in the meantime I'd like draw your attention to the final comment on the answer to ReferenceTable overflow (max=512) JNI which reads:
GetObjectArrayElement
returns object with local reference on it, so you need to delete local reference. But you should do that only when you are done with array elements. So you should putDeleteLocalRef(oneDim)
afterreleaseIntArrayElements(oneDim)
.
So please, double check that you have matched Get/Release calls when you access your array elements and, when you no longer need access to it, delete the local reference. It is possible that you are hitting the end of the JNI pinned reference table because you are not deleting old objects. Remember, JNI is just a c interface for Java, so you have to help out the garbage collection for your native code.