通過ANR來查看死鎖 – Android移動開發技術文章_手機開發 Android移動開發教學課程

 

死鎖通常很難查找。但是在Android我們可以ANR來得到traces.txt。在traces.txt中可以查看那些線程在wait,當然死鎖的線程也在其中。這樣對查找死鎖大大提供瞭方便。

註意:方式ANR後,在手機中就會生成如下文件data\anr\traces.txt

下面直接給出實例。

文件1

DeadLockTraceActivity.java文件

package com.gameloft.robin;

import android.app.Activity;

import android.os.Bundle;

import android.os.Handler;

public class DeadLockTraceActivity extends Activity {

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.deadlock_trace);

    }

   

String tag="robin";

  public void onResume()

    {

   

super.onResume();

   

new ThreadDeadLockExample().start();

   

Handler handler=new Handler();

   

Runnable run=new Runnable(){public void run(){forceWait();}};

   

handler.post(run);      

    }

    synchronized void forceWait()

    {

   

try {

wait(60000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

    }

}

文件2

ThreadDeadLockExample.java文件

package com.gameloft.robin;

import java.util.concurrent.locks.ReentrantLock;

import android.util.Log;

public class ThreadDeadLockExample{

    private final ReentrantLock lockA = new ReentrantLock(true);

    private final ReentrantLock lockB = new ReentrantLock(true);

    String tag="robin";

    void start()

    {

   

Log.i(tag, "ThreadDeadLockExample start");

   

new ThreadA("ThreadA").start();

   

new ThreadB("ThreadB").start();

    }

    class ThreadA extends Thread

    {

   

ThreadA(String name)

   

{

   

super(name);

   

}

public void run()

{

Log.i(tag, "try to lock A"+" in ThreadA");

lockA.lock();

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

Log.i(tag, "lock A successful"+" in ThreadA");

Log.i(tag, "try to lock B"+" in ThreadA");

lockB.lock();

Log.i(tag, "lock B successful"+" in ThreadA");

lockB.unlock();

Log.i(tag, "unlock B"+" in ThreadA");

lockA.unlock();

Log.i(tag, "unlock A"+" in ThreadA");

}

    }

    class ThreadB extends Thread

    {

   

ThreadB(String name)

   

{

   

super(name);

   

}

public void run()

{

Log.i(tag, "try to lock B "+" in ThreadB");

lockB.lock();

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

Log.i(tag, "lock B successful"+" in ThreadB");

Log.i(tag, "try to lock A"+" in ThreadB");

lockA.lock();

Log.i(tag, "lock A successful"+" in ThreadB");

lockA.unlock();

Log.i(tag, "unlock A"+" in ThreadB");

lockB.unlock();

Log.i(tag, "unlock B"+" in ThreadB");

}

    }

}

traces.txt 文件摘要

DALVIK THREADS:

"main" prio=5 tid=1 TIMED_WAIT

  | group="main" sCount=1 dsCount=0 s=N obj=0x400208b8 self=0xcdf0

  | sysTid=1732 nice=0 sched=0/0 cgrp=unknown handle=-1345026000

  at java.lang.Object.wait(Native Method)

  – waiting on <0x4a5ba4b0> (a com.gameloft.robin.DeadLockTraceActivity)

  at java.lang.Object.wait(Object.java:326)

  at com.gameloft.robin.DeadLockTraceActivity.forceWait(DeadLockTraceActivity.java:24)

  at com.gameloft.robin.DeadLockTraceActivity$1.run(DeadLockTraceActivity.java:18)

  at android.os.Handler.handleCallback(Handler.java:587)

  at android.os.Handler.dispatchMessage(Handler.java:92)

  at android.os.Looper.loop(Looper.java:123)

  at android.app.ActivityThread.main(ActivityThread.java:4633)

  at java.lang.reflect.Method.invokeNative(Native Method)

  at java.lang.reflect.Method.invoke(Method.java:521)

  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)

  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

  at dalvik.system.NativeStart.main(Native Method)

 

"ThreadB" prio=5 tid=10 WAIT

  | group="main" sCount=1 dsCount=0 s=N obj=0x4a5bf868 self=0x2174f8

  | sysTid=1741 nice=0 sched=0/0 cgrp=unknown handle=2192952

  at java.lang.Object.wait(Native Method)

  – waiting on <0x4a5bf980> (a java.lang.VMThread)

  at java.lang.Thread.parkFor(Thread.java:1535)

  at java.lang.LangAccessImpl.parkFor(LangAccessImpl.java:48)

  at sun.misc.Unsafe.park(Unsafe.java:317)

  at java.util.concurrent.locks.LockSupport.park(LockSupport.java:131)

  at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:790)

  at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:823)

  at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1153)

  at java.util.concurrent.locks.ReentrantLock$FairSync.lock(ReentrantLock.java:200)

  at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:261)

  at com.gameloft.robin.ThreadDeadLockExample$ThreadB.run(ThreadDeadLockExample.java:61)

 

"ThreadA" prio=5 tid=9 WAIT

  | group="main" sCount=1 dsCount=0 s=N obj=0x4a5bf438 self=0x216858

  | sysTid=1740 nice=0 sched=0/0 cgrp=unknown handle=2189720

  at java.lang.Object.wait(Native Method)

  – waiting on <0x4a5bf590> (a java.lang.VMThread)

  at java.lang.Thread.parkFor(Thread.java:1535)

  at java.lang.LangAccessImpl.parkFor(LangAccessImpl.java:48)

  at sun.misc.Unsafe.park(Unsafe.java:317)

  at java.util.concurrent.locks.LockSupport.park(LockSupport.java:131)

  at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:790)

  at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:823)

  at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1153)

  at java.util.concurrent.locks.ReentrantLock$FairSync.lock(ReentrantLock.java:200)

  at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:261)

at com.gameloft.robin.ThreadDeadLockExample$ThreadA.run(ThreadDeadLockExample.java:35)

 

摘自 robin的專欄

發佈留言