I have a situation that seems rather strange. I will try to provide enough details, so that someone smarter than me can explain this. Basically here is the setup:
OS: Android 2.2 Froyo
Device: SGS Vibrant
Application: OpenGL-ES 1.1
And here is the problem: I can successfully render a fairly complex scene, and it can run endlessly for hours without leaking any memory. Dalvikvm shows up in the logcat once every 3-5 minutes and there would have been no problem unless I try to exit my application and run it again. In fact I can restart my application 2 times, but on the third time, I get GL_OUT_OF_MEMORY.
I have tracked the error down to the gl.glDrawArrays() call. I can confirm that the gl.glGetError() returns 0 prior to the DrawArrays call in question, and it will return 1285 (GL_OUT_OF_MEMORY) after the DrawArrays call.
Naturally, I have thought that I am not cleaning up the resources and releasing OpenGL context. Here is what I do when the application is being shut down.
for(int x=0; x<buffers.length; x++){
if(gl.glIsBuffer(buffers[x])){
gl.glDeleteBuffers(1, buffers, x);
buffers[x]=0;
}
}
for(int y=0; y<textures.length; y++){
if(gl.glIsTexture(textures[y])){
gl.glDeleteTextures(1, textures, y);
textures[y]=0;
}
}
System.out.println("ERROR: "+gl.glGetError());
finish();
When I run my application the first two times, I do not get any error returned at shutdown. However on the 3rd try, I get the aforementioned error, which I tracked down to the gl.glDrawArrays() call.
Here is a brief summary of what happens during the 3rd run:
Objects 1-56 go through their respective gl.glDrawArrays() calls like hot knives through butter. No errors generated.
Objects 57-64 generate a GL_OUT_OF_MEMORY error. The objects get rendered, but the texture is black.
I am more than sure that I am deleting all of the Buffers and Textures at app shutdown. I am also confident that this error is not specific to one 3D model, as I have tried skipping model #57, but then #58 will still get this error.
Please help, as I am running out of ideas!
I just found out GL_OUT_OF_MEMORY can be set if you first pass the NULL pointer to glVertexAttribPointer.
No error before drawArrays, GL_OUT_OF_MEMORY after. (tested on Galaxy S2 4.1.2, GLES2) Maybe that's what's going on for some reason after a while in your program?
this took me forever to find... TODO: more unit tests :)
GL_OUT_OF_MEMORY after a call to glDrawArrays. Why?
It is really hard to say but from what I have learned, this error occurs when you are having too many polygons in memory, or at least, same vertices are being defined n times. Since you said you're having a complex scene; this problem is probably a memory problem.
One solution could be to use glDrawElements() and let your scene reduce the amount of vertices by letting your polygons share same vertices when necessary. In this way your memory is lowered and it is possible that this fixes the problem.
I found that glDrawArrays() was setting GL_OUT_OF_MEMORY when glVertexAttribPointer() was being called with a non-null pointer. This turned out to be because a different bit of code had called glBindBuffer() to use a vertex array object but then hadn't unbound the buffer afterwards. A call to glBindBuffer(GL_ARRAY_BUFFER, 0) fixed the problem.
Can also happen if you have incorrect glVertexAttribPointer calls on Android. I got this error , when I incorrectly passed ST attributes to a previously prepared normal attribute (duplicate glVertexAttribPointer calls to prepare the normal attribute, the second should have bound to the ST attribute).
Related
We are seeing frequent timing issues in our nightly UI tests. The tests often fail because events performed by the java.awt.Robot have not completed before the test code tries to verifying the results.
We are code like using:
Point p = cb.getLocationOnScreen();
int m = 5;
if (cb.getWidth()<5||cb.getHeight()<5)
m=3;
System.out.println("Click at " + (p.x+m) + "," + (p.y+m));
robot.mouseMove(p.x + m, p.y + m);
robot.mousePress(MouseEvent.BUTTON1_MASK);
robot.mouseRelease(MouseEvent.BUTTON1_MASK);
robot.waitForIdle();
Thread.sleep(100);
// Verify results...
We keep having the bump up the Thread.sleep to ensure things complete on the event thread (things like clicking on a button or typing text) despite the java.awt.Robot.waitForIdle() call.
I found this question (Does java.awt.Robot.waitForIdle() wait for events to be dispatched?) which says to use java.awt.Toolkit.realSync(), but this is not an accessible method and with Java 9 coming, I'd rather not add any unnecessary reflection to our tests.
Are there better solutions? Or do people use realSync() or just increase the wait time until tests pass reliably?
UPDATE
I tried using sun.awt.SunToolkit.realSync(), but it is hanging in some tests and never returning. It looks like the EventThread is painting borders and such.
Looks like my only solution is to bump the sleep time up until the test can actually pass reliably. Yuck.
UPDATE 2
I figured out the first hang I had with realSync(). It was a problem in our code, where some paint code called a get method that called a set method which queued up another paint. Repeat forever.
Fixed our code and realSync() worked for a while, sort of. It still seems to return before it should. No idea why and I have no work around.
Also, I've seen realSync() hang and time out on my Linux box running under Java 1.7, but it works under Java 1.8. Very reliable tool here. /s
So, back the to original question. What is a decent way to tell when UI updates are done?
I came to the conclusion that I did need to use SunToolkit.realSync() and it seems to work correctly for Java 9 as well.
It seems, although I couldn't find any hard evidence, that realSync() waits for all graphics related threads while Robot.waitForIdle() and SwingUntilities.invokeLater() only wait for the Java EventThread to finish it's work.
If someone comes up with a better answer, I'd being will to accept that instead of my answer.
I spent 4 full days trying everything I can to figure out the memory leak in an app I'm developing, but things stopped making sense a long time ago.
The app I'm developing is of social nature, so think profile Activities (P) and list Activities with data - for example badges (B). You can hop from profile to a badge list to other profiles, to other lists, etc.
So imagine a flow like this P1 -> B1 -> P2 -> B2 -> P3 -> B3, etc. For consistency, I'm loading profiles and badges of the same user, so each P page is the same and so is each B page.
The general gist of the problem is: after navigating for a bit, depending on the size of each page, I get an out-of-memory exception in random places - Bitmaps, Strings, etc - it doesn't seem to be consistent.
After doing everything imaginable to figure out why I am running out of memory, I have come up with nothing. What I don't understand is why Android isn't killing P1, B1, etc if it runs out of memory upon loading and instead crashes. I would expect these earlier activities to die and be resurrected if I ever Back to them via onCreate() and onRestoreInstanceState().
Let alone this - even if I do P1 -> B1 -> Back -> B1 -> Back -> B1, I still get a crash. This indicates some sort of a memory leak, yet even after dumping hprof and using MAT and JProfiler, I can't pinpoint it.
I've disabled loading of images from the web (and increased the test data loaded to make up for it and make the test fair) and made sure the image cache uses SoftReferences. Android actually tries to free up the few SoftReferences it has, but right before it crashes out of memory.
Badge pages get data from the web, load it into an array of EntityData from a BaseAdapter and feed it to a ListView (I'm actually using CommonsWare's excellent MergeAdapter, but in this Badge activity, there is really only 1 adapter anyway, but I wanted to mention this fact either way).
I've gone through the code and was not able to find anything that would leak. I cleared and nulled everything I could find and even System.gc() left and right but still the app crashes.
I still don't understand why inactive activities that are on the stack don't get reaped, and I'd really love to figure that out.
At this point, I'm looking for any hints, advice, solutions... anything that could help.
Thank you.
I still don't understand why inactive activities that are on the stack
don't get reaped, and I'd really love to figure that out.
This is not how things work. The only memory management that impacts activity lifecycle is the global memory across all processes, as Android decides that it is running low on memory and so need to kill background processes to get some back.
If your application is sitting in the foreground starting more and more activities, it is never going into the background, so it will always hit its local process memory limit before the system ever comes close to killing its process. (And when it does kill its process, it will kill the process hosting all the activities, including whatever is currently in the foreground.)
So it sounds to me like your basic problem is: you are letting too many activities run at the same time, and/or each of those activities is holding on to too many resources.
You just need to redesign your navigation to not rely on stacking up an arbitrary number of potentially heavy-weight activities. Unless you do a serious amount of stuff in onStop() (such as calling setContentView() to clear out the activity's view hierarchy and clear variables of whatever else it may be holding on to), you are just going to run out of memory.
You may want to consider using the new Fragment APIs to replace this arbitrary stack of activities with a single activity that more tightly manages its memory. For example if you use the back stack facilities of fragments, when a fragment goes on the back stack and is no longer visible, its onDestroyView() method is called to completely remove its view hierarchy, greatly reducing its footprint.
Now, as far as you crashing in the flow where you press back, go to an activity, press back, go to another activity, etc and never have a deep stack, then yes you just have a leak. This blog post describes how to debug leaks: http://android-developers.blogspot.com/2011/03/memory-analysis-for-android.html
Some tips:
Make sure you are not leak activity context.
Make sure you are don't keep references on bitmaps. Clean all of your ImageView's in Activity#onStop, something like this:
Drawable d = imageView.getDrawable();
if (d != null) d.setCallback(null);
imageView.setImageDrawable(null);
imageView.setBackgroundDrawable(null);
Recycle bitmaps if you don't need them anymore.
If you use memory cache, like memory-lru, make sure it is not using to much memory.
Not only images take alot of memory, make sure you don't keep too much other data in memory. This easily can happens if you have infinite lists in your app. Try to cache data in DataBase.
On android 4.2, there is a bug(stackoverflow#13754876) with hardware acceleration, so if you use hardwareAccelerated=true in your manifest it will leak memory. GLES20DisplayList - keep holding references, even if you did step (2) and no one else is referencing to this bitmap. Here you need:
a) disable hardware acceleration for api 16/17;
or
b) detach view that holding bitmap
For Android 3+ you can try to use android:largeHeap="true" in your AndroidManifest. But it will not solve your memory problems, just postpone them.
If you need, like, infinite navigation, then Fragments - should be your choice. So you will have 1 activity, which will just switch between fragments. This way you will also solve some memory issues, like number 4.
Use Memory Analyzer to find out the cause of your memory leak.
Here is very good video from Google I/O 2011: Memory management for Android Apps
If you dealing with bitmaps this should be a must read: Displaying Bitmaps Efficiently
Bitmaps are often the culprit for memory errors on Android, so that would be a good area to double check.
Are you holding some references to each Activity? AFAIK this is a reason which keeps Android from deleting activities from the stack.
We're you able to reproduce this error on other devices as well? I've experienced some strange behaviour of some android devices depending on the ROM and/or hardware manufacturer.
I think the problem maybe a combination of many factors stated here in the answers are what is giving you problems. Like #Tim said, a (static) reference to an activity or an element in that activity can cause the GC to skip the Activity. Here is the article discussing this facet. I would think the likely issue comes from something keeping the Activity in an "Visible Process" state or higher, which will pretty much guaranty that the Activity and its associated resources never get reclaimed.
I went through the opposite problem a while back with a Service, so that's what got me going on this thought: there is something keeping your Activity high on the process priority list so that it won't be subject to the system GC, such as a reference (#Tim) or a loop (#Alvaro). The loop doesn't need to be an endless or long running item, just something that runs a lot like a recursive method or cascaded loop (or something along those lines).
EDIT: As I understand this, onPause and onStop are called as needed automatically by Android. The methods are there mainly for you to overide so that you can take care of what you need to before the hosting process is stopped (saving variables, manually saving state, etc.); but note that it is clearly stated that onStop (along with onDestroy) may not be called in every case. Additionally, if the hosting process is also hosting an Activity, Service, etc. that has a "Forground" or "Visible" status, the OS might not even look at stopping the process/thread. For example: an Activity and a Service are both luanched in the same process and the Service returns START_STICKY from onStartCommand() the process automatically takes at least a visible status. That might be the key here, try declaring a new proc for the Activity and see if that changes anything. Try adding this line to the declaration of your Activity in the Manifest as: android:process=":proc2" and then run the tests again if your Activity shares a process with anything else. The thought here is that if you've cleaned up your Activity and are pretty sure that the problem is not your Activity then something else is the problem and its time to hunter for that.
Also, I can't remember where I saw it (if I even saw it in the Android docs) but I remember something about a PendingIntentreferencing an Activity may cause an Activity to behave this way.
Here is a link for the onStartCommand() page with some insights on the process non-killing front.
One of the things that really helped the memory issue in my case ended up being setting inPurgeable to true for my Bitmaps. See Why would I ever NOT use BitmapFactory's inPurgeable option? and the answer's discussion for more info.
Dianne Hackborn's answer and our subsequent discussion (also thanks, CommonsWare) helped clarify certain things I was confused about, so thank you for that.
so the only thing i can really think of is if you have a static variable that references directly or indirectly to the context. Even something so much as a reference to part of the application. I'm sure you have already tried it but i will suggest it just in case, try just nulling out ALL of your static variables in the onDestroy() just to make sure the garbage collector gets it
The biggest source of memory leak I have found was caused by some global, high level or long-standing reference to the context. If you are keeping "context" stored in a variable anywhere, you may encounter unpredictable memory leaks.
Try passing getApplicationContext() to anything that needs a Context. You might have a global variable that is holding a reference to your Activities and preventing them from being garbage collected.
I encountered the same problem with you. I was working on a instant messaging app, for the same contact, it is possible to start a ProfileActivity in a ChatActivity, and vice versa.
I just add a string extra into the intent to start another activity, it takes the information of class type of starter activity, and the user id. For example, ProfileActivity starts a ChatActivity, then in ChatActivity.onCreate, I mark the invoker class type 'ProfileActivity' and user id, if it's going to start an Activity, I would check whether it is a 'ProfileActivity' for the user or not. If so, just call 'finish()' and go back to the former ProfileActivity instead of creating a new one.
Memory leak is another thing.
I am developing a game on android, 'Space RPG' - currently only seeing this error pop up on most Galaxy S4s, and HTC Ones. This is all Java.
The game will stall, when I try to debug the process and suspend the thread in question, it won't suspend, and a spin-on-suspend error happens.
The thread dump lets me see that it was inside a certain while loop that is taking a desired 'end position' and iterating backwards at an ever increasing distance step to find a 'start position'.
This is where things get annoying. I can verify that the loop can not run indefinitely, even though the condition is while(true), it is not possible for it to run more than maybe 200 iterations before my break gets called (this assertion being backed up by the code working on every other phone I have tried).
To help ease my mind on this matter, I added a simple incremented variable inside the loop, and if it ever goes above 1000 it will log something out so I can see that it DID run too many times, just in case some variable was set badly or something.
When this counter code is present, NO crash/hang occurs. Nor do I see any logs indicating it ran over 1000 times.
If I remove this counter, the hang occurs every time after 5-10 seconds of playing [in which the while loop will have run maybe 10 times, though that varies].
My question is therefore, what the hell is going on? :P
Why would these newer phones (but seemingly none of the older phones) have a problem with a loop that is doing valid work and doesn't last long, when there is no incremented variable in there. How could the thread possibly stall in that loop, and how does having an extra counter variable fix the issue?
This work is being done on the opengl render thread, in case that is important.
I have reports of this happening on most S4s, but there is at least one S4 out there where it didn't happen. The one I am using today it IS happening. This makes me wonder if it could possibly be to do with the specific android, java, dalvik or something else on the phone but I unfortunately dont have any details from the S4 where it worked.
Any help, guidance, thoughts or further reading on stuff like this would be appreciated, thanks a lot.
float vel = 1.0f; // final velocity is 1. We are working backwards to find out what the starting velocity will need to be.
int i = 0;
double xmath = Math.sin(rot* (Math.PI/180.0f)); // component of velocity for x,y direction based on rotation
double ymath = Math.cos(rot* (Math.PI/180.0f));
while (true) {
/* with this section uncommented, the stall never happens...
++i;
if (i>1000) {
// Something went rather wrong
vel = 91.0f; // LOG WAS HERE, now has a fallback value justincase
break;
}
*/
vel *= 1.2f;
dx -= vel* xmath;
dy += vel* ymath;
if (distance < (float)Math.sqrt(dx*dx+dy*dy)) {
break;
}
}
// Give the ship a velocity that is appropriate for the distance remaining
_AI.Ship.Velocity = vel;
This is probably http://b.android.com/58726.
The bug has full details; in short: some vendors appear to use a modified version of the Dalvik VM. Changes made to the JIT compiler prevent thread suspension from occurring in certain situations.
The litmus test for this issue is to compare the standard retail device against the "pure Android" Google Play Edition of the GS4 and HTC1. If the former shows the broken behavior, but the latter works correctly, you are likely seeing a vendor-specific problem.
The workaround is to do what you've done: make the code less efficient so it doesn't fall into the "optimized" case. Ideally the app would runtime-select a different code path for devices without the issue, but I don't know of a good way to detect the problem at run time.
I have worked on a simple application. It application includes diffrent levels that can be solved by placing some components inside a canvas, dragging them to the right place and so on.
The application is working fine, but when trying it on my HTC Desire 2.2, I sometimes get the warning message:
Sorry:
Activity xxxxx is not respoding.
Force Close - Wait
If I press the wait-button and let it be for some seconds (up to ~30 sec sometimes), then it runs without any problems. I donĀ“t know where I should start debugging the code, since it happenes only once in a while.
I have read the stuff in google developer site and it was just mostly very general stuff that did not really help.
any ideas?
since, I was not able to debug the problem myself, I am going to post the most important parts of the application. Please check and let me know If I need to post more classes.
//Evrything else
Bitmap bitmap;
GraphicObject.Coordinates coords;
for (GraphicObject graphic : _graphics) {
bitmap = graphic.getGraphic();
coords = graphic.getCoordinates();
canvas.drawBitmap(bitmap, coords.getX(), coords.getY(), null);
}
// draw current graphic at last...
if (_currentGraphic != null) {
bitmap = _currentGraphic.getGraphic();
coords = _currentGraphic.getCoordinates();
canvas.drawBitmap(bitmap, coords.getX(), coords.getY(), null);
}
Android has a relatively good profiler support built in.
When you know the place where this ADNR will show up (e.g. with in one method of your activity, you can put that block in a tracing block:
Debug.startMethodTracing("xyz");
<your code goes here>
Debug.stopMethodTracing()
This will upon activation write a trace file to /sdcard/xyz.trace
You can later (after such a ADNR occurred) obtain it via
adb pull /sdcard/xyz.trace
and analyze it via
traceview xyz.trace
Within the traceview screen, you see the method with its called methods and you can then see the timings.
See http://developer.android.com/guide/developing/tools/adb.html and http://developer.android.com/guide/developing/tools/traceview.html
Are you doing network connections on the main thread? Or Time.sleep()'s. Or extremely long running calculations?
Something in your app's main thread is taking more than 5 (or is it 10?) seconds to complete.
I think you are creating the 30 second sleep on the main thread, if so, the application will be unresponsive for about 30 seconds and the android system will show force close dialog will show up after 5 second. Try creating the 30 second pause and action on a new thread. Check android developers site for more information about threads.
And if you don't know where to start debugging, check your logcat log and search for errors or warnings. Check this -> http://www.droidnova.com/debugging-in-android-using-eclipse,541.html for some information about logcat.
Hope that helped. :) Good luck.
Edit: Then i think that you should put the functions that the wait button performs inside a new thread, so that the application becomes responsive instantly and the child thread remains unresponsive, which doesnt matter.
Edit Again: oh, i get it now, sorry for the misunderstanding, so you are not sure where the problem is, try searching for any network connections, sleep/pauses in your code. Oh, and connect your phone to your computer, run the app by pressing F5 and try to search for warnings or errors in logcat just when the force close box opens. And try to copy the logcat log and send it to me, and ill check whats wrong.
You can use the new StrictMode to detect what is causing your UI thread to hang.
Take a look at this link.
It is only available for GingerBread (API level 9), so you can just test it on the emulator, perform the necessary cleanup, and then remove the StrictMode code
How can I find out who created a Thread in Java?
Imagine the following: You use ~30 third party JARs in a complex plugin environment. You start it up, run lots of code, do some calculations and finally call shutdown().
This life-cycle usually works fine, except that on every run some (non-daemonic) threads remain dangling. This would be no problem if every shutdown was the last shutdown, I could simply run System.exit() in that case. However, this cycle may run several times and it's producing more garbage every pass.
So, what should I do? I see the threads in Eclipse's Debug View. I see their stack traces, but they don't contain any hint about their origin. No creator's stack trace, no distinguishable class name, nothing.
Does anyone have an idea how to address this problem?
Okay, I was able to solve (sort of) the problem on my own: I put a breakpoint into
Thread.start()
and manually stepped through each invocation. This way I found out pretty quickly that Class.forName() initialized lot of static code which in return created these mysterious threads.
While I was able to solve my problem I still think the more general task still remains unaddressed.
I religiously name my threads (using Thread(Runnable, String), say), otherwise they end up with a generic and somewhat useless name. Dumping the threads will highlight what's running and (thus) what's created them. This doesn't solve 3rd party thread creation, I appreciate.
EDIT: The JavaSpecialist newsletter addressed this issue recently (Feb 2015) by using a security manager. See here for more details
MORE: A couple of details for using the JavaSpecialist technique: The SecurityManager API includes "checkAccess(newThreadBeingCreated)" that is called on the thread creator's thread. The new thread already has its "name" initialized. So in that method, you have access to both the thread creator's thread, and the new one, and can log / print etc. When I tried this the code being monitored started throwing access protection exceptions; I fixed that by calling it under a AccessController.doPriviledged(new PrivilegedAction() { ... } where the run() method called the code being monitored.
When debuging your Eclipse application, you can stop all thread by clicking org.eclipse.equinox.launcher.Main field in the debug view.
Then from there, for each thread you can see the stack trace and goes up to the thred run method.
Sometimes this can help and sometimes not.
As Brian said, it a good practice to name threads because it's the only way to easily identify "who created them"
Unfortunately it doesn't. Within Eclipse I see all the blocking threads, but their stack traces only reflect their internal state and (apparently) disclose no information about the location of their creation. Also from a look inside the object (using the Variables view) I was unable to elicit any further hints.
For local debugging purposes, one can attach a debugger to a Java application as early as possible.
Set a non-suspending breakpoint at the end of java.lang.Thread#init(java.lang.ThreadGroup, java.lang.Runnable, java.lang.String, long, java.security.AccessControlContext, boolean) that will Evaluate and log the following:
"**" + getName() + "**\n" + Arrays.toString(Thread.currentThread().getStackTrace())
This will out the thread name and how the thread is created (stacktrace) that one can just scan through.