Reputation: 15
My app runs fine on first run. Then when I terminate it and run it again, it just brings up the force close window. After I force close the app, it runs fine again. The app alternates between force close and runs fine.
am I missing some cleanup before the app terminates?
following is some of my code (contains three classes, foobar,actionview & actionthread:
foobar.java:
public class foobar extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(new ActionView(this));
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onStop() {
super.onStop();
}
}
public class ActionView extends SurfaceView implements SurfaceHolder.Callback {
private ActionThread actionThread;
public ActionView(Context context)
{
super(context);
getHolder().addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder)
{
actionThread = new ActionThread(holder,this);
actionThread.setRunning(true);
actionThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
boolean retry = true;
while(retry)
{
try
{
actionThread.join();
retry=false;
}
catch(InterruptedException e)
{
}
}
}
protected void displayGameState(Canvas canvas)
{
//code...
}
public void updateGameState()
{
//code..
if something happens then
actionThread.setRunning(false);
((Activity)getContext()).finish();
}
}
ActionThread.java:
public class ActionThread extends Thread {
private boolean threadIsRunning;
private SurfaceHolder surfaceHolder;
private ActionView actionView;
private final static int MAX_FPS = 50;
private final static int MAX_FRAME_SKIPS = 5;
private final static int FRAME_PERIOD = 1000/MAX_FPS;
private static final String TAG = ActionThread.class.getSimpleName();
public ActionThread(SurfaceHolder holder, ActionView actionView) {
this.actionView= actionView;
surfaceHolder = holder;
}
public void setRunning(boolean running)
{
threadIsRunning = running;
}
@Override
public void run()
{
long tickCount = 0L;
long totalFramesSkipped = 0L;
Canvas canvas = null;
long beginTime; //time the cycle began
long timeDiff; //time it took for cycle to execute
int sleepTime; //milliseconds to sleep (< 0 if time it took to complete cycle is longer than FRAME_PERIOD
int framesSkipped; //# of frames being skipped
while(threadIsRunning)
{
tickCount++;
try
{
canvas = surfaceHolder.lockCanvas();
synchronized(surfaceHolder)
{
beginTime = System.currentTimeMillis();
framesSkipped = 0;
actionView.updateGameState();
actionView.displayGameState(canvas);
//calc how long the cycle took
timeDiff = System.currentTimeMillis() - beginTime;
//calc sleep time
sleepTime = (int)(FRAME_PERIOD - timeDiff);
if(sleepTime > 0)
{
//if sleepTime > 0 , didn't fall behind. Try to sleep
try
{
Thread.sleep(sleepTime);
}
catch(InterruptedException e){}
}
while(sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS)
{ //fell behind and need to catch up (update without displaying)
actionView.updateGameState();
sleepTime+=FRAME_PERIOD; //add frame period to check if in next frame
framesSkipped++;
totalFramesSkipped++;
}
}
}
finally
{
if(canvas != null)
{
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
Here is the logcat error:
05-03 22:47:45.449: D/dalvikvm(30596): GC_EXTERNAL_ALLOC freed <1K, 43% free 3126K/5447K, external 36955K/38794K, paused 32ms
05-03 22:47:45.488: I/dalvikvm-heap(30596): Clamp target GC heap from 43.427MB to 42.000MB
05-03 22:47:45.488: D/dalvikvm(30596): GC_FOR_MALLOC freed 0K, 43% free 3126K/5447K, external 37165K/38794K, paused 18ms
05-03 22:47:45.535: D/dalvikvm(30596): GC_EXTERNAL_ALLOC freed <1K, 43% free 3126K/5447K, external 37165K/38794K, paused 29ms
05-03 22:47:45.574: I/dalvikvm-heap(30596): Clamp target GC heap from 43.674MB to 42.000MB
05-03 22:47:45.582: D/dalvikvm(30596): GC_FOR_MALLOC freed 0K, 43% free 3126K/5447K, external 37418K/38794K, paused 18ms
05-03 22:47:45.613: D/dalvikvm(30596): GC_EXTERNAL_ALLOC freed <1K, 43% free 3126K/5447K, external 37244K/38794K, paused 30ms
05-03 22:47:45.652: I/dalvikvm-heap(30596): Clamp target GC heap from 43.804MB to 42.000MB
05-03 22:47:45.652: D/dalvikvm(30596): GC_FOR_MALLOC freed 0K, 43% free 3126K/5447K, external 37551K/38794K, paused 17ms
05-03 22:47:45.684: D/dalvikvm(30596): GC_EXTERNAL_ALLOC freed <1K, 43% free 3126K/5447K, external 37551K/38794K, paused 27ms
05-03 22:47:45.699: E/dalvikvm-heap(30596): 258908-byte external allocation too large for this process.
05-03 22:47:45.723: I/dalvikvm-heap(30596): Clamp target GC heap from 43.804MB to 42.000MB
05-03 22:47:45.723: D/dalvikvm(30596): GC_FOR_MALLOC freed <1K, 43% free 3126K/5447K, external 37551K/38794K, paused 17ms
05-03 22:47:45.723: D/GraphicsJNI(30596): Waiting for heap walker to free more memory
05-03 22:47:45.723: D/GraphicsJNI(30596): Heap walker done, retry to allocate
05-03 22:47:45.754: D/dalvikvm(30596): GC_EXTERNAL_ALLOC freed <1K, 43% free 3126K/5447K, external 37298K/38794K, paused 27ms
05-03 22:47:45.793: I/dalvikvm-heap(30596): Clamp target GC heap from 43.804MB to 42.000MB
05-03 22:47:45.793: D/dalvikvm(30596): GC_FOR_MALLOC freed 0K, 43% free 3126K/5447K, external 37551K/38794K, paused 17ms
05-03 22:47:45.832: D/dalvikvm(30596): GC_EXTERNAL_ALLOC freed <1K, 43% free 3126K/5447K, external 37551K/38794K, paused 26ms
05-03 22:47:45.840: E/dalvikvm-heap(30596): 313968-byte external allocation too large for this process.
05-03 22:47:45.871: I/dalvikvm-heap(30596): Clamp target GC heap from 43.804MB to 42.000MB
05-03 22:47:45.871: D/dalvikvm(30596): GC_FOR_MALLOC freed 0K, 43% free 3126K/5447K, external 37551K/38794K, paused 17ms
05-03 22:47:45.871: D/GraphicsJNI(30596): Waiting for heap walker to free more memory
05-03 22:47:45.871: D/GraphicsJNI(30596): Heap walker done, retry to allocate
05-03 22:47:45.902: D/dalvikvm(30596): GC_EXTERNAL_ALLOC freed <1K, 43% free 3126K/5447K, external 37551K/38794K, paused 30ms
05-03 22:47:45.910: E/dalvikvm-heap(30596): 313968-byte external allocation too large for this process.
05-03 22:47:45.941: I/dalvikvm-heap(30596): Clamp target GC heap from 43.804MB to 42.000MB
05-03 22:47:45.941: D/dalvikvm(30596): GC_FOR_MALLOC freed 0K, 43% free 3126K/5447K, external 37551K/38794K, paused 17ms
05-03 22:47:45.941: E/GraphicsJNI(30596): VM won't let us allocate 313968 bytes
05-03 22:47:45.957: D/AndroidRuntime(30596): Shutting down VM
05-03 22:47:45.957: W/dalvikvm(30596): threadid=1: thread exiting with uncaught exception (group=0x4001e560)
05-03 22:47:45.965: E/AndroidRuntime(30596): FATAL EXCEPTION: main
05-03 22:47:45.965: E/AndroidRuntime(30596): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.graphics.Bitmap.nativeCreate(Native Method)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.graphics.Bitmap.createBitmap(Bitmap.java:507)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.graphics.Bitmap.createBitmap(Bitmap.java:474)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:379)
05-03 22:47:45.965: E/AndroidRuntime(30596): at com.somecomany.foobar.Element.Element.resizeBitmap(Element.java:48)
05-03 22:47:45.965: E/AndroidRuntime(30596): at com.somecomany.foobar.Element.Element.<init>(Element.java:31)
05-03 22:47:45.965: E/AndroidRuntime(30596): at com.somecomany.foobar.Element.MobileElement.<init>(MobileElement.java:24)
05-03 22:47:45.965: E/AndroidRuntime(30596): at com.somecomany.foobar.ActionView.surfaceCreated(ActionView.java:156)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.SurfaceView.updateWindow(SurfaceView.java:543)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.SurfaceView.dispatchDraw(SurfaceView.java:348)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.View.draw(View.java:6883)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.widget.FrameLayout.draw(FrameLayout.java:357)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.View.draw(View.java:6883)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.widget.FrameLayout.draw(FrameLayout.java:357)
05-03 22:47:45.965: E/AndroidRuntime(30596): at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2106)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.ViewRoot.draw(ViewRoot.java:1562)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.ViewRoot.performTraversals(ViewRoot.java:1298)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.ViewRoot.handleMessage(ViewRoot.java:1911)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.os.Handler.dispatchMessage(Handler.java:99)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.os.Looper.loop(Looper.java:130)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.app.ActivityThread.main(ActivityThread.java:3821)
05-03 22:47:45.965: E/AndroidRuntime(30596): at java.lang.reflect.Method.invokeNative(Native Method)
05-03 22:47:45.965: E/AndroidRuntime(30596): at java.lang.reflect.Method.invoke(Method.java:507)
05-03 22:47:45.965: E/AndroidRuntime(30596): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
05-03 22:47:45.965: E/AndroidRuntime(30596): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
05-03 22:47:45.965: E/AndroidRuntime(30596): at dalvik.system.NativeStart.main(Native Method)
05-03 22:47:49.996: I/Process(30596): Sending signal. PID: 30596 SIG: 9
Upvotes: 1
Views: 717
Reputation: 15476
From the log, it looks like you have a memory leak while creating bitmaps, which happens when you have some large sized Objects hanging around, perhaps through static data structures when the application is run the second time.
Another variant scenario is when you reference the Context or Activity in a static variable, which basically would prevent the previous Activity from being garbage collected.
This happens because when you "exit" an app in Android, its process is not necessarily terminated. So that when you run it again, the OS can skip some time-consuming steps, and the app can be launched faster. This is good when you keep some of your data around for quick reuse, and this is very bad when you inadvertently keep some of your (huge) data around and then try to recreate those data again, that's when things go boom.
Upvotes: 1
Reputation: 13101
Try to set the Activity's LaunchMode to SingleTop.
And you should release the resources when the Activity onDestroy. good luck.
Upvotes: 0