Android app crashes with WIN DEATH after memory-intensive activity - android

Summary
I work on an Android app which, as one of its features, involves users marking up an image and saving it. This process involves some heavy canvas drawImage() calls (sometimes on an image around 12 MB+ uncompressed) as well as lots of encoding and decoding of data. The image data also cached in the Android file system and passed from Java to JavaScript through a JavaScriptInterface.
However, with an LG G Pad X8.3 running Android 5.0.2, we are getting lots of crashing. When it crashes, the log says "WIN DEATH" and it goes back to the home screen without showing any "Unfortunately, ___ has stopped" message. Our "WIN DEATH" is preceded by a win death of the InputMethod and before that a "WIN DEATH" of com.lge.launcher2.Launcher. It is intermittent, but frequent enough to be a big problem.
Details
(1) It seems to happen after the heavy image saving manipulation, but not immediately after
(2) It happens more often when the keyboard is brought up. Is something about bringing up the keyboard causing it to crash?
(3) When watching the memory usage in Android Studio as the app is running, nothing is too out of the ordinary. When it crashes, there is still free memory available in the graph.
(3) We tried using largeHeap in our manifest, but that did not eliminate the crashing.
(4) Memory usage is between 10 and 20 MB.
(5) I can add around 32 million numbers to a JavaScript array before the web view crashes. That's at least 240 MB (8 bytes per JS number). When it crashes, it shows a blank screen, as opposed to the crash I am trying to fix where it brings you back to the home screen.
(6) There is a well publicized memory leak (or a couple, actually) in this version of Android, but LG does not offer upgrades for this model.
(7) We have tried optimizing the code to use as little memory as possible, but the crashing remains.
(8) The crash logs always contain similar information around the crash.
02-08 12:13:01.642 1850-1850/? I/PhoneApp﹕ onTrimMemory: 5
02-08 12:13:01.642 1850-1850/? I/PhoneApp﹕ trim memory
02-08 12:13:01.652 945-965/? I/ActivityManager﹕ Process com.google.android.partnersetup (pid 23908) has died
02-08 12:13:01.682 945-16584/? I/ActivityManager﹕ Process com.google.android.apps.plus (pid 23756) has died
02-08 12:13:01.692 1850-1850/? I/PhoneApp﹕ onTrimMemory: 10
02-08 12:13:01.692 1850-1850/? I/PhoneApp﹕ trim memory
02-08 12:13:01.712 945-2088/? I/ActivityManager﹕ Process com.lge.p2p (pid 24102) has died
02-08 12:13:01.742 945-2041/? I/ActivityManager﹕ Process com.google.android.gms.wearable (pid 23833) has died
02-08 12:13:01.752 1850-1850/? I/PhoneApp﹕ onTrimMemory: 15
...
02-08 12:11:06.862 22936-22936/com.mycompany.ourapp W/IInputConnectionWrapper﹕ getTextBeforeCursor on inactive InputConnection
...
02-08 12:11:06.912 20890-20890/? D/Cliptray Manager﹕ isAvailable() UserHandle.myUserId() = 0, isOwner = true
02-08 12:11:06.912 1961-8134/? I/Cliptray Service﹕ Standard mode!! ClipTray is Supported!
02-08 12:11:06.912 1961-8134/? D/Cliptray Service﹕ isAvailable() mLastIsOwner = true
02-08 12:11:06.912 1961-8134/? I/Cliptray Service﹕ Owner!! ClipTray is Supported! mIsOwnerClipTray = true
02-08 12:11:06.912 1961-8134/? D/Cliptray Service﹕ ignore packageName : com.mycompany.ourapp
...
02-08 12:12:39.782 22936-22936/com.mycompany.ourapp I/Choreographer﹕ Skipped 35 frames! The application may be doing too much work on its main thread.
...
02-08 12:13:02.622 945-2086/? I/WindowState﹕ WIN DEATH: Window{8dce4a3 u0 com.lge.launcher2/com.lge.launcher2.Launcher}
...
02-08 12:13:02.872 945-1922/? I/WindowState﹕ WIN DEATH: Window{393167d2 u0 InputMethod}
...
02-08 12:13:03.052 1979-1979/? D/QC_RIL_OEM_HOOK﹕ The connection to the service got disconnected unexpectedly!
02-08 12:13:03.052 1961-1961/? D/QC_RIL_OEM_HOOK﹕ The connection to the service got disconnected unexpectedly!
02-08 12:13:03.052 1850-1850/? D/QC_RIL_OEM_HOOK﹕ The connection to the service got disconnected unexpectedly!
02-08 12:13:03.052 1850-1850/? D/QC_RIL_OEM_HOOK﹕ The connection to the service got disconnected unexpectedly!
02-08 12:13:03.072 945-945/? W/InputMethodManagerService﹕ Session failed to close due to remote exception
android.os.DeadObjectException
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(Binder.java:496)
at com.android.internal.view.IInputMethodSession$Stub$Proxy.finishSession(IInputMethodSession.java:305)
at com.android.server.InputMethodManagerService.finishSessionLocked(InputMethodManagerService.java:1463)
at com.android.server.InputMethodManagerService.clearClientSessionLocked(InputMethodManagerService.java:1454)
at com.android.server.InputMethodManagerService.clearCurMethodLocked(InputMethodManagerService.java:1480)
at com.android.server.InputMethodManagerService.onServiceDisconnected(InputMethodManagerService.java:1499)
at android.app.LoadedApk$ServiceDispatcher.doDeath(LoadedApk.java:1391)
at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1405)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at com.android.server.SystemServer.run(SystemServer.java:302)
at com.android.server.SystemServer.main(SystemServer.java:203)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
...
02-08 12:13:03.132 945-2088/? I/ActivityManager﹕ Process com.google.process.gapps (pid 21317) has died
...
02-08 12:13:03.182 1405-1405/? D/LGKeyguardUnlockMethodController﹕ onTrustChanged with userId : 0 , getUserTrustIsManaged : false ,getUserHasTrust : false
...
02-08 12:13:03.452 362-1705/? V/AudioFlinger﹕ 22936 died, releasing its sessions
02-08 12:13:03.452 362-1705/? V/AudioFlinger﹕ pid 1850 # 0
02-08 12:13:03.452 362-1705/? V/AudioFlinger﹕ pid 22936 # 1
02-08 12:13:03.452 362-1705/? V/AudioFlinger﹕ removing entry for pid 22936 session 520
02-08 12:13:03.452 362-1705/? V/AudioFlinger﹕ purging stale effects
02-08 12:13:03.452 362-1705/? V/AudioFlinger﹕ remove track (4097) and delete from mixer
02-08 12:13:03.452 945-2086/? I/WindowState﹕ WIN DEATH: Window{3eafa2d1 u0 com.mycompany.ourapp/com.mycompany.ourapp.MainActivity}
The memory leak that may be partially responsible: https://code.google.com/p/android/issues/detail?id=79729
Question
What could be causing the app to crash in this way? Is it a memory issue? is anything in the log output that I've copied here relevant?
Has anyone else had this problem and solved it? Is the Android 5.0.x/1.x memory leak bug responsible?
I wish I could be more specific, but the code is proprietary and the problem isn't (or hasn't yet been) localized to any one particular code sample. If more information is needed about a particular issue, please ask.
Update
I've noticed that there are a bunch of Choreographer messages in the logs about it doing too much work, but they are relatively small frame skips (~ 35 frames) and the last message occurs a full 20 seconds before the app crashed.
Update 2-10-16
We are now trying to reuse canvas objects in case they are not garbage collected, and we are also calling System.gc() when onTrimMemory is called with TRIM_MEMORY_RUNNING_LOW. This seems to have reduced the crashing to some degree, but still frequently enough to be concerning. Most of all, I would like to understand why it seems to randomly use up too much memory and crash. I've added the onTrimMemory lines to the log output below, which show it going from low to critical in a span of 100 ms. If this only happened when actually performing the memory-intensive actions, that would make sense, but it happens sometimes long after the user process has finished.

Pulling my hair out over here, trying to get a HTML Canvas based application running in CrossWalk on a Fire TV Stick. The app would run fine then crash after 30 minutes of use with this error. I was able to fix it but my use case is pretty specific, either way it may help folks who show up here later.
TL;DR: Reduce the size of textures being loaded into and out of the GPU.
I had a fullscreen canvas element running PixiJS, working essentially as a slideshow. The problem came from a single slide type, where large images with transparency would animate over a fixed background. After logging the CPU/GPU usage in Chrome's timeline feature I could see that the textures were being loaded into and out of the GPU all the time to accomplish the affect. Ultimately, I was able to resolve the issue by completely removing the background image element from canvas, and just displaying it in a div behind the canvas. The affect was identical, but the performance was improved significantly and this problem disappeared afterwards.

You are dealing with large bitmaps and loading all of them at run
time. You have to deal very carefully with large bitmaps by loading
the size that you need not the whole bitmap at once and then do
scaling.
Huge JavaScript Cause This
Given that you are working with limited memory, ideally you only want to load a lower resolution version in memory. The lower resolution version should match the size of the UI component that displays it. An image with a higher resolution does not provide any visible benefit, but still takes up precious memory and incurs additional performance overhead due to additional on the fly scaling.
Please check Managing Bitmap Memory.
You are using lots of canvas at once that's why this problem .

This used to happen with me, even after i used the large heap attribute in application manifest and it stopped to happen when i reset all the variable to null after finishing using them.
I don`t know your code but i would advise you to re-use the same variables and make sure you clean up after every operation and when done, because keeping in the memory large unused files is not good.

Related

Media volume either 0% or 100%

I have a custom android AOSP ROM with a peculiar problem: The volume can only be set to either 0% or 100%. As a result, the volume buttons just turn the sound on or off. If I use the volume slider instead, and the volume is not muted, it jumps immediately to 100%. The volume is not reduced even momentarily.
Interestingly, the volume for ringtones and alarms is not affected and can be set as usual.
The problem occurs via headphones, internal speakers, and HDMI out.
I tried setprop ro.config.media_vol_steps 30, and that does work in that it changes the number of volume steps in the slider - but it does not affect the output volume. I found nothing in logcat, this is the only suspicious thing (I set the volume via slider to a low value):
02-08 06:18:43.117 1813 2298 V audio_hw_primary: out_set_parameters: routing=1024
02-08 06:18:43.670 22493 22493 I vol.Events: writeEvent touch_level_changed STREAM_MUSIC 3
02-08 06:18:44.127 22493 22493 I vol.Events: writeEvent touch_level_done STREAM_MUSIC 3
02-08 06:18:46.575 22493 22493 I vol.Events: writeEvent dismiss_dialog touch_outside
02-08 06:18:46.581 22493 24066 I vol.Events: writeEvent active_stream_changed UNKNOWN_STREAM_-1
02-08 06:18:46.695 1813 2298 V audio_hw_primary: out_set_parameters: routing=1024
02-08 06:18:49.842 1813 2298 D audio_hw_primary: out_standby
What could cause this? E.g. does the hardware report the current volume back to the UI (then it could be a driver problem)?
In your ROM, a fixed-volume (full) is set. Its a resource configuration. Usually done for HDMI devices.

How to handle :java.util.concurrent.TimeoutException: android.os.BinderProxy.finalize() timed out after 10 seconds errors?

We're seeing a number of TimeoutExceptions in GcWatcher.finalize, BinderProxy.finalize, and PlainSocketImpl.finalize. 90+% of them happen on Android 4.3. We're getting reports of this from Crittercism from users out in the field.
The error is a variation of: "com.android.internal.BinderInternal$GcWatcher.finalize() timed out after 10 seconds"
java.util.concurrent.TimeoutException: android.os.BinderProxy.finalize() timed out after 10 seconds
at android.os.BinderProxy.destroy(Native Method)
at android.os.BinderProxy.finalize(Binder.java:459)
at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:187)
at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:170)
at java.lang.Thread.run(Thread.java:841)
So far we haven't had any luck reproducing the problem in house or figuring out what might have caused it.
Any ideas what can cause this?
Any idea how to debug this and find out which part of the app causes this?
Anything that sheds light on the issue helps.
More Stacktraces:
1 android.os.BinderProxy.destroy
2 android.os.BinderProxy.finalize Binder.java, line 482
3 java.lang.Daemons$FinalizerDaemon.doFinalize Daemons.java, line 187
4 java.lang.Daemons$FinalizerDaemon.run Daemons.java, line 170
5 java.lang.Thread.run Thread.java, line 841
2
1 java.lang.Object.wait
2 java.lang.Object.wait Object.java, line 401
3 java.lang.ref.ReferenceQueue.remove ReferenceQueue.java, line 102
4 java.lang.ref.ReferenceQueue.remove ReferenceQueue.java, line 73
5 java.lang.Daemons$FinalizerDaemon.run Daemons.java, line 170
6 java.lang.Thread.run
3
1 java.util.HashMap.newKeyIterator HashMap.java, line 907
2 java.util.HashMap$KeySet.iterator HashMap.java, line 913
3 java.util.HashSet.iterator HashSet.java, line 161
4 java.util.concurrent.ThreadPoolExecutor.interruptIdleWorkers ThreadPoolExecutor.java, line 755
5 java.util.concurrent.ThreadPoolExecutor.interruptIdleWorkers ThreadPoolExecutor.java, line 778
6 java.util.concurrent.ThreadPoolExecutor.shutdown ThreadPoolExecutor.java, line 1357
7 java.util.concurrent.ThreadPoolExecutor.finalize ThreadPoolExecutor.java, line 1443
8 java.lang.Daemons$FinalizerDaemon.doFinalize Daemons.java, line 187
9 java.lang.Daemons$FinalizerDaemon.run Daemons.java, line 170
10 java.lang.Thread.run
4
1 com.android.internal.os.BinderInternal$GcWatcher.finalize BinderInternal.java, line 47
2 java.lang.Daemons$FinalizerDaemon.doFinalize Daemons.java, line 187
3 java.lang.Daemons$FinalizerDaemon.run Daemons.java, line 170
4 java.lang.Thread.run
Full disclosure - I'm the author of the previously mentioned talk in TLV DroidCon.
I had a chance to examine this issue across many Android applications, and discuss it with other developers who encountered it - and we all got to the same point: this issue cannot be avoided, only minimized.
I took a closer look at the default implementation of the Android Garbage collector code, to understand better why this exception is thrown and on what could be the possible causes. I even found a possible root cause during experimentation.
The root of the problem is at the point a device "Goes to Sleep" for a while - this means that the OS has decided to lower the battery consumption by stopping most User Land processes for a while, and turning Screen off, reducing CPU cycles, etc. The way this is done - is on a Linux system level where the processes are Paused mid run. This can happen at any time during normal Application execution, but it will stop at a Native system call, as the context switching is done on the kernel level. So - this is where the Dalvik GC joins the story.
The Dalvik GC code (as implemented in the Dalvik project in the AOSP site) is not a complicated piece of code. The basic way it work is covered in my DroidCon slides. What I did not cover is the basic GC loop - at the point where the collector has a list of Objects to finalize (and destroy). The loop logic at the base can be simplified like this:
take starting_timestamp,
remove object for list of objects to release,
release object - finalize() and call native destroy() if required,
take end_timestamp,
calculate (end_timestamp - starting_timestamp) and compare against a hard coded timeout value of 10 seconds,
if timeout has reached - throw the java.util.concurrent.TimeoutException and kill the process.
Now consider the following scenario:
Application runs along doing its thing.
This is not a user facing application, it runs in the background.
During this background operation, objects are created, used and need to be collected to release memory.
Application does not bother with a WakeLock - as this will affect the battery adversely, and seems unnecessary.
This means the Application will invoke the GC from time to time.
Normally the GC runs is completed without a hitch.
Sometimes (very rarely) the system will decide to sleep in the middle of the GC run.
This will happen if you run your application long enough, and monitor the Dalvik memory logs closely.
Now - consider the timestamp logic of the basic GC loop - it is possible for the device to start the run, take a start_stamp, and go to sleep at the destroy() native call on a system object.
When it wakes up and resumes the run, the destroy() will finish, and the next end_stamp will be the time it took the destroy() call + the sleep time.
If the sleep time was long (more than 10 seconds), the java.util.concurrent.TimeoutException will be thrown.
I have seen this in the graphs generated from the analysis python script - for Android System Applications, not just my own monitored apps.
Collect enough logs and you will eventually see it.
Bottom line:
The issue cannot be avoided - you will encounter it if your app runs in the background.
You can mitigate by taking a WakeLock, and prevent the device from sleeping, but that is a different story altogether, and a new headache, and maybe another talk in another con.
You can minimize the problem by reducing GC calls - making the scenario less likely (tips are in the slides).
I have not yet had the chance to go over the Dalvik 2 (a.k.a ART) GC code - which boasts a new Generational Compacting feature, or performed any experiments on an Android Lollipop.
Added 7/5/2015:
After reviewing the Crash reports aggregation for this crash type, it looks like these crashes from version 5.0+ of Android OS (Lollipop with ART) only account for 0.5% of this crash type. This means that the ART GC changes has reduced the frequency of these crashes.
Added 6/1/2016:
Looks like the Android project has added a lot of info on how the GC works in Dalvik 2.0 (a.k.a ART).
You can read about it here - Debugging ART Garbage Collection.
It also discusses some tools to get information on the GC behavior for your app.
Sending a SIGQUIT to your app process will essentially cause an ANR, and dump the application state to a log file for analysis.
We see this constantly, all over our app, using Crashlytics. The crash usually happens way down in platform code. A small sampling:
android.database.CursorWindow.finalize() timed out after 10 seconds
java.util.regex.Matcher.finalize() timed out after 10 seconds
android.graphics.Bitmap$BitmapFinalizer.finalize() timed out after 10 seconds
org.apache.http.impl.conn.SingleClientConnManager.finalize() timed out after 10 seconds
java.util.concurrent.ThreadPoolExecutor.finalize() timed out after 10 seconds
android.os.BinderProxy.finalize() timed out after 10 seconds
android.graphics.Path.finalize() timed out after 10 seconds
The devices on which this happens are overwhelmingly (but not exclusively) devices manufactured by Samsung. That could just mean that most of our users are using Samsung devices; alternately it could indicate a problem with Samsung devices. I'm not really sure.
I suppose this doesn't really answer your questions, but I just wanted to reinforce that this seems quite common, and is not specific to your application.
I found some slides about this issue.
http://de.slideshare.net/DroidConTLV/android-crash-analysis-and-the-dalvik-garbage-collector-tools-and-tips
In this slides the author tells that it seems to be a problem with GC, if there are a lot of objects or huge objects in heap. The slide also include a reference to a sample app and a python script to analyze this issue.
https://github.com/oba2cat3/GCTest
https://github.com/oba2cat3/logcat2memorygraph
Furthermore I found a hint in comment #3 on this side: https://code.google.com/p/android/issues/detail?id=53418#c3
Here is an effective solution from didi to solve this problem, Since this bug is very common and difficult to find the cause, It looks more like a system problem, Why can't we ignore it directly?Of course we can ignore it, Here is the sample code:
final Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler =
Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
if (t.getName().equals("FinalizerWatchdogDaemon") && e instanceof TimeoutException) {
} else {
defaultUncaughtExceptionHandler.uncaughtException(t, e);
}
}
});
By setting a special default uncaught exception handler, application can change the way in which uncaught exceptions are handled for those threads that would already accept whatever default behavior the system provided. When an uncaught TimeoutException is thrown from a thread named FinalizerWatchdogDaemon, this special handler will block the handler chain, the system handler will not be called, so crash will be avoided.
Through practice, no other bad effects were found. The GC system is still working, timeouts are alleviated as CPU usage decreases.
For more details see: https://mp.weixin.qq.com/s/uFcFYO2GtWWiblotem2bGg
We solved the problem by stopping the FinalizerWatchdogDaemon.
public static void fix() {
try {
Class clazz = Class.forName("java.lang.Daemons$FinalizerWatchdogDaemon");
Method method = clazz.getSuperclass().getDeclaredMethod("stop");
method.setAccessible(true);
Field field = clazz.getDeclaredField("INSTANCE");
field.setAccessible(true);
method.invoke(field.get(null));
}
catch (Throwable e) {
e.printStackTrace();
}
}
You can call the method in Application's lifecycle, like attachBaseContext().
For the same reason, you also can specific the phone's manufacture to fix the problem, it's up to you.
Broadcast Receivers timeout after 10 seconds. Possibly your doing an asynchronous call (wrong) from a broadcast receiver and 4.3 actually detects it.
One thing which is invariably true is that at this time, the device would be suffocating for some memory (which is usually the reason for GC to most likely get triggered).
As mentioned by almost all authors earlier, this issue surfaces when Android tries to run GC while the app is in background. In most of the cases where we observed it, user paused the app by locking their screen.
This might also indicate memory leak somewhere in the application, or the device being too loaded already.
So the only legitimate way to minimize it is:
to ensure there are no memory leaks, and
to reduce the memory footprint of the app in general.
try {
Class<?> c = Class.forName("java.lang.Daemons");
Field maxField = c.getDeclaredField("MAX_FINALIZE_NANOS");
maxField.setAccessible(true);
maxField.set(null, Long.MAX_VALUE);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
The finalizeQueue may be too long
i think that java may require GC.SuppressFinalize() & GC.ReRegisterForFinalize() to let user reduce the finalizedQueue length explicitly
if the JVM' source code is available, may implement these method ourself, such as android ROM maker
It seems like a Android Runtime bug. There seems to be finalizer that runs in its separate thread and calls finalize() method on objects if they are not in the current frame of the stacktrace.
For example following code(created to verify this issue) ended with the crash.
Let's have some cursor that do something in finalize method(e.g. SqlCipher ones, do close() which locks to the database that is currently in use)
private static class MyCur extends MatrixCursor {
public MyCur(String[] columnNames) {
super(columnNames);
}
#Override
protected void finalize() {
super.finalize();
try {
for (int i = 0; i < 1000; i++)
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
And we do some long running stuff having opened cursor:
for (int i = 0; i < 7; i++) {
new Thread(new Runnable() {
#Override
public void run() {
MyCur cur = null;
try {
cur = new MyCur(new String[]{});
longRun();
} finally {
cur.close();
}
}
private void longRun() {
try {
for (int i = 0; i < 1000; i++)
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
This causes following error:
FATAL EXCEPTION: FinalizerWatchdogDaemon
Process: la.la.land, PID: 29206
java.util.concurrent.TimeoutException: MyCur.finalize() timed out after 10 seconds
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:371)
at java.lang.Thread.sleep(Thread.java:313)
at MyCur.finalize(MessageList.java:1791)
at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:222)
at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:209)
at java.lang.Thread.run(Thread.java:762)
The production variant with SqlCipher is very similiar:
12-21 15:40:31.668: E/EH(32131): android.content.ContentResolver$CursorWrapperInner.finalize() timed out after 10 seconds
12-21 15:40:31.668: E/EH(32131): java.util.concurrent.TimeoutException: android.content.ContentResolver$CursorWrapperInner.finalize() timed out after 10 seconds
12-21 15:40:31.668: E/EH(32131): at java.lang.Object.wait(Native Method)
12-21 15:40:31.668: E/EH(32131): at java.lang.Thread.parkFor$(Thread.java:2128)
12-21 15:40:31.668: E/EH(32131): at sun.misc.Unsafe.park(Unsafe.java:325)
12-21 15:40:31.668: E/EH(32131): at java.util.concurrent.locks.LockSupport.park(LockSupport.java:161)
12-21 15:40:31.668: E/EH(32131): at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:840)
12-21 15:40:31.668: E/EH(32131): at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:873)
12-21 15:40:31.668: E/EH(32131): at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1197)
12-21 15:40:31.668: E/EH(32131): at java.util.concurrent.locks.ReentrantLock$FairSync.lock(ReentrantLock.java:200)
12-21 15:40:31.668: E/EH(32131): at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:262)
12-21 15:40:31.668: E/EH(32131): at net.sqlcipher.database.SQLiteDatabase.lock(SourceFile:518)
12-21 15:40:31.668: E/EH(32131): at net.sqlcipher.database.SQLiteProgram.close(SourceFile:294)
12-21 15:40:31.668: E/EH(32131): at net.sqlcipher.database.SQLiteQuery.close(SourceFile:136)
12-21 15:40:31.668: E/EH(32131): at net.sqlcipher.database.SQLiteCursor.close(SourceFile:510)
12-21 15:40:31.668: E/EH(32131): at android.database.CursorWrapper.close(CursorWrapper.java:50)
12-21 15:40:31.668: E/EH(32131): at android.database.CursorWrapper.close(CursorWrapper.java:50)
12-21 15:40:31.668: E/EH(32131): at android.content.ContentResolver$CursorWrapperInner.close(ContentResolver.java:2746)
12-21 15:40:31.668: E/EH(32131): at android.content.ContentResolver$CursorWrapperInner.finalize(ContentResolver.java:2757)
12-21 15:40:31.668: E/EH(32131): at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:222)
12-21 15:40:31.668: E/EH(32131): at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:209)
12-21 15:40:31.668: E/EH(32131): at java.lang.Thread.run(Thread.java:762)
Resume: Close cursors ASAP. At least on Samsung S8 with Android 7 where the issue have been seen.
For classes that you create (ie. are not part of the Android) its possible to avoid the crash completely.
Any class that implements finalize() has some unavoidable probability of crashing as explained by #oba. So instead of using finalizers to perform cleanup, use a PhantomReferenceQueue.
For an example check out the implementation in React Native: https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/jni/DestructorThread.java

Out of Memory Error while loading bitmaps

i have an android app with 3 acitivtys:
A1 --starts--> A2 --starts--> A3 --when finished his process: starts--> A1
(so i don't "finish();" an app. i start the next activitys with "startActivity(..);" the whole time after userinteraction)
so there is a loop in these 3 activitys.
On each Activity, i display 3-9 pictures, located on the SD-card, which i load with my following function:
try
{
Uri selectedImageURI = Uri.parse(strImagePath);
File imgFile = new File(getRealPathFromURI(selectedImageURI, c));
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
ivTmp.setImageBitmap(myBitmap);
}catch (Exception e)
{
return null;
}
This all works.
But sometimes (after looping a few times through my activitys), my app crashes..
Logcat tells me:
01-16 13:42:15.863: DEBUG/dalvikvm(23161): GC_BEFORE_OOM freed 10K, 9% free 59019K/64400K, paused 29ms, total 30ms
01-16 13:42:15.863: ERROR/dalvikvm-heap(23161): Out of memory on a 8018704-byte allocation.
01-16 13:42:15.863: ERROR/AndroidRuntime(23161): FATAL EXCEPTION: main
java.lang.OutOfMemoryError
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:502)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:355)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:785)
at android.content.res.Resources.loadDrawable(Resources.java:1965)
at android.content.res.Resources.getDrawable(Resources.java:660)
at android.widget.ImageView.resolveUri(ImageView.java:616)
at android.widget.ImageView.setImageResource(ImageView.java:349)
at <MyApp>.MyActivity$6.run(MyActivity.java:143)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5039)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
Someone can give my some tips how to handle the crashes?
Maybe its because my activitys are set to state "paused" instead of closing them correctly?
for quick fix you can add
android:largeHeap="true" in your manifest application tag
link here:
I face OOM problem for my table in kindle and nook
Heap size (large)
android:largeHeap="true"
there specification is mentioned to use larger heap link here:
edit: use Caching Bitmaps technique link here
I had the similar problem while displaying high resolution images. I have searched and applied all the android bitmap solutions given in http://developer.android.com/training/displaying-bitmaps/index.html and the following caches mekanism in the link. but none of them work. not any right solution anywhere. Then I figured out that the problem is : I couldnt use the drawable folder structure right. I was keeping high resolution images in mdpi and hdpi folders . this cause android scale up the images to the ultra sizes. 100 kb image was causing 20 mb increase in memory thanks to the android monitor / memory section.
so I have added these ultra resolution images to xxhdpi folder , then It was FIXED suddenly. then my image slider work flawlessly
Yeah android doesnt immediately destroy activities when they are not visible to the user, but there are a number of lifecycle methods that are called depending on the current state. Check out http://developer.android.com/guide/components/activities.html#Lifecycle
You could try finishing the activities in onStop() or onDestroy() as these will be called when the activity is not visible and when the system runs low on memory respectively. :-)
This is due to the high resolution of image you have to scaling the bitmap use the following code
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
int h = 100; // height in pixels
int w = 100; // width in pixels
Bitmap photoBitMap = Bitmap.createScaledBitmap(myBitmap,h, w, true);
ivTmp.setImageBitmap(photoBitMap);

How to improve memory usage with BitmapFactory.decodebyteArray()?

In a thread i'm fetching a jpg image (from a socket) and putting it in a byte array datas[].
Then i make a bitmap and send it to my ui to display it in an imageview :
Thread side :
bundle.putParcelable("image", BitmapFactory.decodeByteArray(this.datas, 0, jpgSize,this.bitmapOption));
message.what = ThreadMessages.MSG_IMAGE_AVAILABLE;
message.setData(bundle);
this.uiHandler.sendMessage(message);
The bitmap option is defined as following :
this.bitmapOption = new BitmapFactory.Options();
this.bitmapOption.inPurgeable = true;
ui side :
cameraView.setImageBitmap((Bitmap) bundle.getParcelable("image"));
As far i know it's works fine on phone with android 2.x and 4.0.x. But i have made some test with a galaxyTab 8.9 (android 3.1) and my activitie is killed by the system due to a high memory usage :
01-30 14:12:02.311: I/ActivityManager(72): Process my.package (pid 1175) has died.
01-30 14:12:02.321: I/WindowManager(72): WIN DEATH: Window{41140848 my.package/my.package.DisplayOneCam paused=false}
01-30 14:12:02.331: I/WindowManager(72): WIN DEATH: Window{410f5020 my.package/my.package.main paused=false}
01-30 14:12:02.331: I/WindowManager(72): WIN DEATH: Window{41033308 my.package/my.package.DisplayCameras paused=false}
01-30 14:12:02.371: I/ActivityManager(72): Start proc my.package for activity my.package/.DisplayCameras: pid=1209 uid=10036 gids={3003, 1015}
01-30 14:12:02.371: I/ActivityManager(72): Low Memory: No more background processes.
01-30 14:12:02.391: I/WindowManager(72): WINDOW DIED Window{410f5020 my.package/my.package.main paused=false}
The fetched bitmap is not a very high res pictures (800*600 max) but it is displayed at least at 10 fps (more if it's possible).
Using the inPurgeable option lets me avoid the OOM crash (i had it before using inPurgeable) but it not seem to be enough .
Using inSampleSize (like explained in Strange out of memory issues) don't seems to be a solution because it resize the image, and i need a image which take the entire space of the imageview.
How can i improve my memory usage knowing that i'm receiving a jpg in a byte array and i need to display it in a imageview ?
Note : i don't need/want to resize the bitmap, the received jpg is already well sized.
Note 2 : Triggering system.gc() after each decodeByteArray seems to solve th eproblem, but it's ugly and performance are slowing down drasticly
Using Parcelable to send large amounts of data in Intents is a bad idea and is likely to result in poor performance. You would be better to store the image to persistent storage, and pass a URI to the stored image instead of the image data itself.
There is some more info on this in how do you pass images (bitmaps) between android activities using bundles?
There is no need to use a Bundle if you're only passing the Message within your application process. Simply pass your Bitmap in Message.obj.

listactivity is stuttering caused by WindowManager

i have a question regarding some weird logcat outputs.
Scenario:
I have a listactivity with images and textviews, etc. The images are loaded by Fedor's implementation of LazyList. I changed his cache to a LRUMap from commons.
On scrolling i got sometimes a stuttering and logcats shows me a lot of this messages:
V/WindowManager( 2482): Dsptch > Window{48267640 <packagename to Listactivity> paused=false}
V/InputDevice( 2482): ID[0]=0(0) Up(1=>0)
Any ideas what these messages mean?
Thx in advance

Categories

Resources