dvm aborts for acceesing stale reference

本文主要描述Android下由于线程同步问题引起的dvm访问已经销毁的对象的Issue.

文末, 会给出bug定位和参考解决方案.

可以做为MIB 系统BUG定位和分析参考资料.

 

Log标志

E dalvikvm: JNI ERROR (app bug): accessed stale global reference 0x%p (index %d in a table of size %d)

E dalvikvm: VM aborting

详细LOG和分析如下.

Log:

09-08 08:28:48.979 28320 28332 W MediaMetadataRetriever: MediaMetadataRetriever server died!

09-08 08:28:48.979 28169 28180 W IMediaDeathNotifier: media server died

09-08 08:28:48.979 28169 28180 W MediaMetadataRetriever: MediaMetadataRetriever server died!

09-08 08:28:48.979 28169 28180 W Camera  : Camera server died!

09-08 08:28:48.979 27992 28003 W IMediaDeathNotifier: media server died

09-08 08:28:48.979 27992 28003 E MediaPlayer: error (100, 0)

09-08 08:28:48.979 27992 28003 E MediaPlayer: Mediaserver died in 8 state

09-08 08:28:48.979   868  1521 W IMediaDeathNotifier: media server died

09-08 08:28:48.979   354  1539 W IMediaDeathNotifier: media server died

09-08 08:28:48.989 28396 28408 W IMediaDeathNotifier: media server died

09-08 08:28:48.999   354   917 I WindowManager: hardware key case

09-08 08:28:48.999 25720 25731 W AudioSystem: AudioFlinger server died!

09-08 08:28:48.999   868  2532 W AudioSystem: AudioFlinger server died!

09-08 08:28:48.999 28169 28333 W AudioSystem: AudioFlinger server died!

09-08 08:28:49.009 25720 25733 W AudioSystem: AudioPolicyService server died!

09-08 08:28:49.009   868  1521 W AudioSystem: AudioPolicyService server died!

09-08 08:28:49.009   354   365 W AudioEffect: IEffect died

09-08 08:28:49.009 27992 28004 W AudioSystem: AudioFlinger server died!

09-08 08:28:49.009   354  1103 W AudioSystem: AudioFlinger server died!

09-08 08:28:49.009   354  1103 E AudioEffectService: binderDied : AudioFlinger is dead.

09-08 08:28:49.009   354  1539 W AudioSystem: AudioPolicyService server died!

09-08 08:28:49.009   354   365 W AudioEffects-JNI: EVENT_ERROR

09-08 08:28:49.009   354   365 E dalvikvm: JNI ERROR (app bug): accessed stale global reference 0x17010a (index 49218 in a table of size 1638)

09-08 08:28:49.009  354   365 E dalvikvm: VM aborting

09-08 08:28:49.009   354   365 F libc    : Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1)

09-08 08:28:49.019 28396 28410 W AudioSystem: AudioFlinger server died!

09-08 08:28:49.039   123   251 E msm7627a.hwcomposer: isValidDestination: destination out of bound params

09-08 08:28:49.429 30394 30394 I DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

09-08 08:28:49.429 30394 30394 I DEBUG   : Build fingerprint: xxxxxxxxxxxxxxxxxxxxxxxxxxxxx:userdebug/release-keys'

09-08 08:28:49.429 30394 30394 I DEBUG   : pid: 354, tid: 365  >>> system_server <<<

09-08 08:28:49.429 30394 30394 I DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadd00d

09-08 08:28:49.429 30394 30394 I DEBUG   :  r0 00000000  r1 01468428  r2 00000000  r3 00000000

09-08 08:28:49.429 30394 30394 I DEBUG   :  r4 deadd00d  r5 408e2f68  r6 0000020c  r7 51811d00

09-08 08:28:49.429 30394 30394 I DEBUG   :  r8 00000001  r9 4d27ebbe  10 49041fb0  fp 51811c90

09-08 08:28:49.429 30394 30394 I DEBUG   :  ip 00000000  sp 51811a48  lr 4087e37b  pc 4087e37a  cpsr 60000030

09-08 08:28:49.429 30394 30394 I DEBUG   :  d0  74726f6261204d56  d1  000000000000006e

09-08 08:28:49.429 30394 30394 I DEBUG   :  d2  0000000000000075  d3  000000000000006c

09-08 08:28:49.429 30394 30394 I DEBUG   :  d4  00650074006e0069  d5  006c0061006e0072

09-08 08:28:49.429 30394 30394 I DEBUG   :  d6  006500690076002e  d7  00490049002e0077

09-08 08:28:49.429 30394 30394 I DEBUG   :  d8  0000000000000000  d9  0000000000000000

09-08 08:28:49.429 30394 30394 I DEBUG   :  d10 0000000000000000  d11 0000000000000000

09-08 08:28:49.429 30394 30394 I DEBUG   :  d12 0000000000000000  d13 0000000000000000

09-08 08:28:49.429 30394 30394 I DEBUG   :  d14 0000000000000000  d15 0000000000000000

09-08 08:28:49.429 30394 30394 I DEBUG   :  d16 4b09a5c200000001  d17 006800740065004d

09-08 08:28:49.429 30394 30394 I DEBUG   :  d18 000000000064006f  d19 0000017f73622a85

09-08 08:28:49.429 30394 30394 I DEBUG   :  d20 0000000000000000  d21 0000000000000001

09-08 08:28:49.429 30394 30394 I DEBUG   :  d22 ffffffff00000000  d23 ffffffff00000001

09-08 08:28:49.429 30394 30394 I DEBUG   :  d24 0000000000000000  d25 3ff00cccc0000000

09-08 08:28:49.429 30394 30394 I DEBUG   :  d26 c064200000000000  d27 3ff0111120000000

09-08 08:28:49.429 30394 30394 I DEBUG   :  d28 c0013f2a99247550  d29 bfc3748ac84f4e47

09-08 08:28:49.429 30394 30394 I DEBUG   :  d30 bc57a6b66a32bbb3  d31 be57e7d323800000

09-08 08:28:49.429 30394 30394 I DEBUG   :  scr 60000012

09-08 08:28:49.429 30394 30394 I DEBUG   :

09-08 08:28:49.739 30571 30571 E AudioHardwareMSM76XXA: failed to open AUTO_VOLUME_CONTROL /system/etc/AutoVolumeControl.txt: No such file or directory (2)

09-08 08:28:49.769 30571 30571 E QualcommCamera: Qint android::get_number_of_cameras(): E

09-08 08:28:49.969 30394 30394 I DEBUG   :          #00  pc 0005137a  /system/lib/libdvm.so (dvmAbort)

09-08 08:28:49.969 30394 30394 I DEBUG   :          #01  pc 00033238  /system/lib/libdvm.so (_ZNK16IndirectRefTable3getEPv)

09-08 08:28:49.969 30394 30394 I DEBUG   :          #02  pc 00055e3e  /system/lib/libdvm.so (_Z20dvmDecodeIndirectRefP6ThreadP8_jobject)

09-08 08:28:49.969 30394 30394 I DEBUG   :          #03  pc 0006bdb0  /system/lib/libdvm.so (_Z14dvmCallMethodVP6ThreadPK6MethodP6ObjectbP6JValueSt9__va_list)

09-08 08:28:49.969 30394 30394 I DEBUG   :          #04  pc 00055782  /system/lib/libdvm.so

09-08 08:28:49.969 30394 30394 I DEBUG   :          #05  pc 00001496  /system/lib/libaudioeffect_jni.so

09-08 08:28:49.969 30394 30394 I DEBUG   :          #06  pc 00001892  /system/lib/libaudioeffect_jni.so

09-08 08:28:49.969 30394 30394 I DEBUG   :          #07  pc 0004e16e  /system/lib/libmedia.so (_ZN7android11AudioEffect10binderDiedEv)

09-08 08:28:49.969 30394 30394 I DEBUG   :          #08  pc 0004e190  /system/lib/libmedia.so

09-08 08:28:49.969 30394 30394 I DEBUG   :          #09  pc 00018116  /system/lib/libbinder.so (_ZN7android8BpBinder14reportOneDeathERKNS0_8ObituaryE)

09-08 08:28:49.969 30394 30394 I DEBUG   :          #10  pc 00018186  /system/lib/libbinder.so (_ZN7android8BpBinder12sendObituaryEv)

09-08 08:28:49.979 30394 30394 I DEBUG   :          #11  pc 0001b200  /system/lib/libbinder.so (_ZN7android14IPCThreadState14executeCommandEi)

09-08 08:28:49.979 30394 30394 I DEBUG   :          #12  pc 0001b36e  /system/lib/libbinder.so (_ZN7android14IPCThreadState14joinThreadPoolEb)

09-08 08:28:49.979 30394 30394 I DEBUG   :          #13  pc 000204bc  /system/lib/libbinder.so

09-08 08:28:49.979 30394 30394 I DEBUG   :          #14  pc 0002331e  /system/lib/libutils.so (_ZN7android6Thread11_threadLoopEPv)

09-08 08:28:49.979 30394 30394 I DEBUG   :          #15  pc 000462ac  /system/lib/libandroid_runtime.so (_ZN7android14AndroidRuntime15javaThreadShellEPv)

09-08 08:28:49.979 30394 30394 I DEBUG   :          #16  pc 00023964  /system/lib/libutils.so

09-08 08:28:49.979 30394 30394 I DEBUG   :          #17  pc 00012e14  /system/lib/libc.so (__thread_entry)

09-08 08:28:49.979 30394 30394 I DEBUG   :          #18  pc 00012968  /system/lib/libc.so (pthread_create)

09-08 08:28:49.979 30394 30394 I DEBUG   :

09-08 08:28:49.979 30394 30394 I DEBUG   : code around pc:

09-08 08:28:49.979 30394 30394 I DEBUG   : 4087e358 34bcf8d3 efacf7cd 26001e73 2f01f813  ...4....s..&.../

09-08 08:28:49.979 30394 30394 I DEBUG   : 4087e368 42abb152 d0074416 4798e7f8 f7ff4c0a  R..B.D.....G.L..

09-08 08:28:49.979 30394 30394 I DEBUG   : 4087e378 7026ffa7 efa2f7cd 2006490c 44794a0c  ..&p.....I. .JyD

09-08 08:28:49.979 30394 30394 I DEBUG   : 4087e388 f7cd447a 2000ee5e ef1af7cd 58e54b05  zD..^.. .....K.X

09-08 08:28:49.979 30394 30394 I DEBUG   : 4087e398 2b006c6b e7e9d1e9 deadd00d 0005fc88  kl.+............

09-08 08:28:49.979 30394 30394 I DEBUG   :

09-08 08:28:49.979 30394 30394 I DEBUG   : code around lr:

09-08 08:28:49.979 30394 30394 I DEBUG   : 4087e358 34bcf8d3 efacf7cd 26001e73 2f01f813  ...4....s..&.../

09-08 08:28:49.979 30394 30394 I DEBUG   : 4087e368 42abb152 d0074416 4798e7f8 f7ff4c0a  R..B.D.....G.L..

09-08 08:28:49.979 30394 30394 I DEBUG   : 4087e378 7026ffa7 efa2f7cd 2006490c 44794a0c  ..&p.....I. .JyD

09-08 08:28:49.979 30394 30394 I DEBUG   : 4087e388 f7cd447a 2000ee5e ef1af7cd 58e54b05  zD..^.. .....K.X

09-08 08:28:49.979 30394 30394 I DEBUG   : 4087e398 2b006c6b e7e9d1e9 deadd00d 0005fc88  kl.+............

09-08 08:28:49.979 30394 30394 I DEBUG   :

09-08 08:28:49.979 30394 30394 I DEBUG   : memory map around addr deadd00d:

09-08 08:28:49.979 30394 30394 I DEBUG   : be942000-be963000 [stack]

09-08 08:28:49.979 30394 30394 I DEBUG   : (no map for address)

09-08 08:28:49.979 30394 30394 I DEBUG   : ffff0000-ffff1000 [vectors]

09-08 08:28:49.989 30394 30394 I DEBUG   :

09-08 08:28:49.989 30394 30394 I DEBUG   : stack:

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a08  00000000 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a0c  40091f89  /system/lib/libc.so

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a10  400bb74c  /system/lib/libc.so

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a14  400c0878 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a18  00000000 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a1c  40093191  /system/lib/libc.so

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a20  400bb580  /system/lib/libc.so

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a24  00000000 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a28  0000020c 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a2c  51811d00 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a30  00000001 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a34  40091fa7  /system/lib/libc.so

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a38  408ddfb8  /system/lib/libdvm.so

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a3c  51811c4b 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a40  df0027ad 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a44  00000000 

09-08 08:28:49.989 30394 30394 I DEBUG   : #00 51811a48  56900001  /dev/ashmem/AudioFlinger::Client (deleted)

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a4c  6c756e28 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a50  0000296c 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a54  00000000 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a58  00000000 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a5c  00000000 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a60  00000000 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a64  00000000 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a68  00000000 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a6c  00000000 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a70  00000000 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a74  00000000 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a78  00000000 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a7c  00000000 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a80  00000000 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a84  00000000 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a88  00000000 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a8c  00000000 

09-08 08:28:49.989 30394 30394 I DEBUG   :     51811a90  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811a94  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811a98  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811a9c  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811aa0  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811aa4  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811aa8  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811aac  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811ab0  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811ab4  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811ab8  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811abc  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811ac0  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811ac4  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811ac8  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811acc  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811ad0  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811ad4  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811ad8  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811adc  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811ae0  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811ae4  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811ae8  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811aec  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811af0  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811af4  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811af8  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811afc  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811b00  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811b04  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811b08  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811b0c  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811b10  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811b14  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811b18  00000000 

09-08 08:28:49.999 30394 30394 I DEBUG   :     51811b1c  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b20  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b24  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b28  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b2c  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b30  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b34  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b38  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b3c  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b40  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b44  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b48  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b4c  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b50  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b54  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b58  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b5c  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b60  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b64  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b68  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b6c  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b70  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b74  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b78  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b7c  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b80  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b84  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b88  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b8c  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b90  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b94  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b98  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811b9c  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811ba0  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811ba4  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811ba8  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811bac  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811bb0  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811bb4  00000000 

09-08 08:28:50.009 30394 30394 I DEBUG   :     51811bb8  00000000 

09-08 08:28:50.019   354   701 E AudioService: Media server started.

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811bbc  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811bc0  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811bc4  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811bc8  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811bcc  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811bd0  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811bd4  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811bd8  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811bdc  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811be0  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811be4  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811be8  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811bec  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811bf0  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811bf4  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811bf8  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811bfc  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c00  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c04  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c08  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c0c  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c10  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c14  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c18  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c1c  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c20  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c24  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c28  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c2c  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c30  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c34  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c38  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c3c  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c40  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c44  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c48  00000000 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c4c  4b09a5c2  /dev/ashmem/dalvik-mark-stack (deleted)

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c50  0000c042 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c54  00000666 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c58  0017010a 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c5c  4086023c  /system/lib/libdvm.so

09-08 08:28:50.019 30394 30394 I DEBUG   : #01 51811c60  0017010a 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c64  0000c042 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c68  00000666 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c6c  51811d00 

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c70  408ddfb8  /system/lib/libdvm.so

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c74  408e2f68  /system/lib/libdvm.so

09-08 08:28:50.019 30394 30394 I DEBUG   :     51811c78  0017010a 

09-08 08:28:50.029 30394 30394 I DEBUG   :     51811c7c  40882e41  /system/lib/libdvm.so

 

Call Stack from the log:

09-08 08:28:49.969 30394 30394 I DEBUG   :          #00  pc 0005137a  /system/lib/libdvm.so

dvmAbort

/opt/Weekly_Release/Integration/5855/LINUX_userdebug/dalvik/vm/Init.cpp:1863

 

09-08 08:28:49.969 30394 30394 I DEBUG   :          #01  pc 00033238  /system/lib/libdvm.so

IndirectRefTable::get(void*) const

/opt/Weekly_Release/Integration/5855/LINUX_userdebug/dalvik/vm/IndirectRefTable.cpp:163

 

09-08 08:28:49.969 30394 30394 I DEBUG   :          #02  pc 00055e3e  /system/lib/libdvm.so

dvmDecodeIndirectRef(Thread*, _jobject*)

/opt/Weekly_Release/Integration/5855/LINUX_userdebug/dalvik/vm/Jni.cpp:331

 

09-08 08:28:49.969 30394 30394 I DEBUG   :          #03  pc 0006bdb0  /system/lib/libdvm.so

dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)

/opt/Weekly_Release/Integration/5855/LINUX_userdebug/dalvik/vm/interp/Stack.cpp:486

 

09-08 08:28:49.969 30394 30394 I DEBUG   :          #04  pc 00055782  /system/lib/libdvm.so

CallStaticVoidMethodV

/opt/Weekly_Release/Integration/5855/LINUX_userdebug/dalvik/vm/Jni.cpp:2121

 

09-08 08:28:49.969 30394 30394 I DEBUG   :          #05  pc 00001496  /system/lib/libaudioeffect_jni.so

_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)

/opt/Weekly_Release/Integration/5855/LINUX_userdebug/dalvik/libnativehelper/include/nativehelper/jni.h:793

 

09-08 08:28:49.969 30394 30394 I DEBUG   :          #06  pc 00001892  /system/lib/libaudioeffect_jni.so

effectCallback

/opt/Weekly_Release/Integration/5855/LINUX_userdebug/frameworks/base/media/jni/audioeffect/android_media_AudioEffect.cpp:170

 

09-08 08:28:49.969 30394 30394 I DEBUG   :          #07  pc 0004e16e  /system/lib/libmedia.so

android::AudioEffect::binderDied()

/opt/Weekly_Release/Integration/5855/LINUX_userdebug/frameworks/base/media/libmedia/AudioEffect.cpp:348

 

09-08 08:28:49.969 30394 30394 I DEBUG   :          #08  pc 0004e190  /system/lib/libmedia.so

android::AudioEffect::EffectClient::binderDied(android::wp<android::IBinder> const&)

/opt/Weekly_Release/Integration/5855/LINUX_userdebug/frameworks/base/include/media/AudioEffect.h:429

 

09-08 08:28:49.969 30394 30394 I DEBUG   :          #09  pc 00018116  /system/lib/libbinder.so

android::BpBinder::reportOneDeath(android::BpBinder::Obituary const&)

/opt/Weekly_Release/Integration/5855/LINUX_userdebug/frameworks/base/libs/binder/BpBinder.cpp:282

 

09-08 08:28:49.969 30394 30394 I DEBUG   :          #10  pc 00018186  /system/lib/libbinder.so

android::BpBinder::sendObituary()

/opt/Weekly_Release/Integration/5855/LINUX_userdebug/frameworks/base/libs/binder/BpBinder.cpp:269

 

09-08 08:28:49.979 30394 30394 I DEBUG   :          #11  pc 0001b200  /system/lib/libbinder.so

android::IPCThreadState::executeCommand(int)

/opt/Weekly_Release/Integration/5855/LINUX_userdebug/frameworks/base/libs/binder/IPCThreadState.cpp:1061

 

09-08 08:28:49.979 30394 30394 I DEBUG   :          #12  pc 0001b36e  /system/lib/libbinder.so

android::IPCThreadState::joinThreadPool(bool)

/opt/Weekly_Release/Integration/5855/LINUX_userdebug/frameworks/base/libs/binder/IPCThreadState.cpp:468

 

09-08 08:28:49.979 30394 30394 I DEBUG   :          #13  pc 000204bc  /system/lib/libbinder.so

android::PoolThread::threadLoop()

/opt/Weekly_Release/Integration/5855/LINUX_userdebug/frameworks/base/libs/binder/ProcessState.cpp:67

 

09-08 08:28:49.979 30394 30394 I DEBUG   :          #14  pc 0002331e  /system/lib/libutils.so

android::Thread::_threadLoop(void*)

/opt/Weekly_Release/Integration/5855/LINUX_userdebug/frameworks/base/libs/utils/Threads.cpp:834

 

09-08 08:28:49.979 30394 30394 I DEBUG   :          #15  pc 000462ac  /system/lib/libandroid_runtime.so

android::AndroidRuntime::javaThreadShell(void*)

/opt/Weekly_Release/Integration/5855/LINUX_userdebug/frameworks/base/core/jni/AndroidRuntime.cpp:996

 

09-08 08:28:49.979 30394 30394 I DEBUG   :          #16  pc 00023964  /system/lib/libutils.so

thread_data_t::trampoline(thread_data_t const*)

/opt/Weekly_Release/Integration/5855/LINUX_userdebug/frameworks/base/libs/utils/Threads.cpp:127

 

09-08 08:28:49.979 30394 30394 I DEBUG   :          #17  pc 00012e14  /system/lib/libc.so

__thread_entry

/opt/Weekly_Release/Integration/5855/LINUX_userdebug/bionic/libc/bionic/pthread.c:217

 

09-08 08:28:49.979 30394 30394 I DEBUG   :          #18  pc 00012968  /system/lib/libc.so

pthread_create

/opt/Weekly_Release/Integration/5855/LINUX_userdebug/bionic/libc/bionic/pthread.c:357

Analysis

 

102    structBpBinder::Obituary {   @BpBinder.h

103       wp<DeathRecipient>recipient;     // It’s a wp.

104       void*cookie;

105       uint32_tflags;

106   };

 

83    /**

84    * This method allows you to add data that is transported through

85    * IPC along with your IBinder pointer.  When implementing a Binder

86    * object, override it to write your desired data in to @a outData.

87    * You can then call getConstantData() on your IBinder to retrieve

88    * that data, from any process.  You MUST return the number of bytes

89    * written in to the parcel (including padding).

90    */

91   classDeathRecipient :publicvirtualRefBase @Ibinder.h

92   {

93   public:

94       virtualvoidbinderDied(constwp<IBinder>&who) = 0;// pure virtual

95   };

 

243voidBpBinder::sendObituary() @BpBinder.cpp

244{

245   LOGV("Sending obituary for proxy %p handle %d, mObitsSent=%s\n",

246       this,mHandle,mObitsSent ?"true" :"false");

247

248   mAlive = 0;

249   if (mObitsSent)return;

250

251   mLock.lock();

252   Vector<Obituary>*obits =mObituaries;       //讣告Vector

253   if(obits !=NULL) {

254       LOGV("Clearing sent death notification: %p handle %d\n",this,mHandle);

255       IPCThreadState*self =IPCThreadState::self();

256       self->clearDeathNotification(mHandle,this);// Dead binder node shake hands protocol

257       self->flushCommands();

258       mObituaries =NULL;

259   }

260   mObitsSent =1;        //讣告已发送标志

261   mLock.unlock();

262

263   LOGV("Reporting death of proxy %p for %d recipients\n",

264       this,obits ?obits->size() : 0);

265

266   if (obits !=NULL) {          //针对每个讣告结点回调

267       constsize_t N =obits->size();

268       for (size_t i=0; i<N; i++) {

269           reportOneDeath(obits->itemAt(i));

270       }

271

272       deleteobits;

273   }

274}

 

Note:

linkToDeath/unlinkToDeath in cpp  add/remove item to/from  mObituaries in BpBinder.cpp.How java layer linkToDeath/unlinkToDeath is implemented? 

Answer:

They are implemented using JNI inframeworks/base/core/jni/android_util_Binder.cpp

276voidBpBinder::reportOneDeath(constObituary&obit) @BpBinder.cpp

277{

278   sp<DeathRecipient>recipient =obit.recipient.promote();     // promote the wp.

279   LOGV("Reporting death to recipient: %p\n",recipient.get());

280   if (recipient ==NULL)return;

281

282   recipient->binderDied(this);  // this - the dead binder node’s proxy.

283}

 

 

Overriden pure virtual function:

 

42

43classAudioEffect :publicRefBase @AudioEffect.h

44{

45public:

.....

144    /*

145    * Events used by callback function (effect_callback_t).

146    */

147   enumevent_type {

148       EVENT_CONTROL_STATUS_CHANGED = 0,

149       EVENT_ENABLE_STATUS_CHANGED =1,

150       EVENT_PARAMETER_CHANGED =2,

151       EVENT_ERROR =3

152   };

153

154   /* Callback function notifying client application of a change in effect engine state or

155    * configuration.

156    * An effect engine can be shared by several applications but only one has the control

157    * of the engine activity and configuration at a time.

158    * The EVENT_CONTROL_STATUS_CHANGED event is received when an application loses or

159    * retrieves the control of the effect engine. Loss of control happens

160    * if another application requests the use of the engine by creating an AudioEffect for

161    * the same effect type but with a higher priority. Control is returned when the

162    * application having the control deletes its AudioEffect object.

163    * The EVENT_ENABLE_STATUS_CHANGED event is received by all applications not having the

164    * control of the effect engine when the effect is enabled or disabled.

165    * The EVENT_PARAMETER_CHANGED event is received by all applications not having the

166    * control of the effect engine when an effect parameter is changed.

167    * The EVENT_ERROR event is received when the media server process dies.

168    *

169    * Parameters:

170    *

171    * event:   type of event notified (see enum AudioEffect::event_type).

172    * user:    Pointer to context for use by the callback receiver.

173    * info:    Pointer to optional parameter according to event type:

174    *  - EVENT_CONTROL_STATUS_CHANGED:  boolean indicating if control is granted (true)

175    *  or stolen (false).

176    *  - EVENT_ENABLE_STATUS_CHANGED: boolean indicating if effect is now enabled (true)

177    *  or disabled (false).

178    *  - EVENT_PARAMETER_CHANGED: pointer to a effect_param_t structure.

179    *  - EVENT_ERROR:  status_t indicating the error (DEAD_OBJECT when media server dies).

180    */

181

182   typedef void (*effect_callback_t)(int32_tevent,void*user,void *info);

.....

406    // Implements the IEffectClient interface

407   classEffectClient :publicandroid::BnEffectClientpublicandroid::IBinder::DeathRecipient

Note :

Implements the IEffectClient BnBinder, While IEffectClient BpBinder is used by AudioFlinger service side to manage the client connections.

Implements Ibinder::DeathRecipient to receive AudioFlinger binder node death notification.

  

408   {

409   public:

410

411       EffectClient(AudioEffect *effect) :mEffect(effect){} // pointer to external holder object.

Delegation design patterns?

 

Note :

C++ nested class.

Logical view                   object-model view

+------+<---+                  +------+<-------+------+

|      |    |                    |      |        +------+

+------+----+                  |      |        |      |

+------+                       |      |        +------+

|      |                |      |

+------+                       |      |

|      |                +------+      

|      |

+------+

 

412

413       // IEffectClient

414       virtualvoidcontrolStatusChanged(boolcontrolGranted) {

415           mEffect->controlStatusChanged(controlGranted);

416       }

417       virtualvoidenableStatusChanged(boolenabled) {

418           mEffect->enableStatusChanged(enabled);

419       }

420       virtualvoidcommandExecuted(uint32_tcmdCode,

421                                    uint32_tcmdSize,

422                                    void *pCmdData,

423                                    uint32_treplySize,

424                                    void *pReplyData) {

425           mEffect->commandExecuted(cmdCode,cmdSize,pCmdData,replySize,pReplyData);

426       }

427

428       // IBinder::DeathRecipient

429       virtualvoidbinderDied(constwp<IBinder>&who)

               {mEffect->binderDied();}

Note:

The binder node proxy is a wp, but the implementation doesn’t care the proxy, that is it doesn’t care which binder node is dead. So mIEffect should be considered.

 

430

431   private:

432       AudioEffect *mEffect;

433   };

 

436    friendclassEffectClient;    // Internal Adapter pattern??

437

438   // IEffectClient

439   voidcontrolStatusChanged(boolcontrolGranted);

440   voidenableStatusChanged(boolenabled);

441   voidcommandExecuted(uint32_tcmdCode,

442                        uint32_tcmdSize,

443                        void *pCmdData,

444                        uint32_treplySize,

445                        void *pReplyData);

446   voidbinderDied();

447

448

449   sp<IEffect>            mIEffect;          // IEffect binder interface

450   sp<EffectClient>       mIEffectClient;    // IEffectClient implementation

451   sp<IMemory>            mCblkMemory;       // shared memory for deferred parameter setting

452   effect_param_cblk_t*   mCblk;             // control block for deferred parameter setting

453};

 

342 voidAudioEffect::binderDied() @AudioEffect.cpp

343{

344   LOGW("IEffect died");

345   mStatus =NO_INIT;

346   if (mCbf) {

347       status_tstatus =DEAD_OBJECT;

348       mCbf(EVENT_ERROR,mUserData, &status);

349   }

350   mIEffect.clear();

351}

 

AudioEffect::set() is called in AudioEffect::AudioEffect() constructor in AudioEffect.cpp

88

89status_tAudioEffect::set(consteffect_uuid_t *type,

90               consteffect_uuid_t *uuid,

91               int32_tpriority,

92               effect_callback_tcbf,

93               void*user,

94               intsessionId,

95               audio_io_handle_tio)

96{

97   sp<IEffect>iEffect;

98   sp<IMemory>cblk;

99   intenabled;

100

101   LOGV("set %p mUserData: %p uuid: %p timeLow %08x",this,user,type,type ?type->timeLow : 0);

102

103   if (mIEffect != 0) {

104       LOGW("Effect already in use");

105       returnINVALID_OPERATION;

106   }

107

108   constsp<IAudioFlinger>&audioFlinger =AudioSystem::get_audio_flinger();

109   if (audioFlinger == 0) {

110       LOGE("set(): Could not get audioflinger");

111       returnNO_INIT;

112   }

113

114   if (type ==NULL &&uuid ==NULL) {

115       LOGW("Must specify at least type or uuid");

116       returnBAD_VALUE;

117   }

118

119   mPriority =priority;

120   mCbf =cbf;

121   mUserData =user;

122   mSessionId =sessionId;

123

124   memset(&mDescriptor, 0,sizeof(effect_descriptor_t));

125   memcpy(&mDescriptor.type,EFFECT_UUID_NULL,sizeof(effect_uuid_t));

126   memcpy(&mDescriptor.uuid,EFFECT_UUID_NULL,sizeof(effect_uuid_t));

127

128   if (type !=NULL) {

129       memcpy(&mDescriptor.type,type,sizeof(effect_uuid_t));

130   }

131   if (uuid !=NULL) {

132       memcpy(&mDescriptor.uuid,uuid,sizeof(effect_uuid_t));

133   }

134

135   mIEffectClient =newEffectClient(this);

136

137   iEffect =audioFlinger->createEffect(getpid(), (effect_descriptor_t *)&mDescriptor,

138           mIEffectClient,priority,io,mSessionId, &mStatus, &mId, &enabled);

139

140   if (iEffect == 0 || (mStatus !=NO_ERROR &&mStatus !=ALREADY_EXISTS)) {

141       LOGE("set(): AudioFlinger could not create effect, status: %d",mStatus);

142       returnmStatus;

143   }

144

145   mEnabled = (volatileint32_t)enabled;

146

147   mIEffect =iEffect;

148   cblk =iEffect->getCblk();

149   if (cblk == 0) {

150       mStatus =NO_INIT;

151       LOGE("Could not get control block");

152       returnmStatus;

153   }

154

155   mIEffect =iEffect;

156   mCblkMemory =cblk;

157   mCblk =static_cast<effect_param_cblk_t*>(cblk->pointer());

158   intbufOffset = ((sizeof(effect_param_cblk_t) -1) / sizeof(int) +1) *sizeof(int);

159   mCblk->buffer = (uint8_t *)mCblk +bufOffset;

160

161   iEffect->asBinder()->linkToDeath(mIEffectClient);

162   LOGV("set() %p OK effect: %s id: %d status %d enabled %d, ",this,mDescriptor.name,mId,mStatus,mEnabled);

163

164   returnmStatus;

165}

 

168AudioEffect::~AudioEffect()

169{

170   LOGV("Destructor %p",this);

171

172   if (mStatus ==NO_ERROR ||mStatus ==ALREADY_EXISTS) {

173           setEnabled(false);

174       if (mIEffect !=NULL) {

175           mIEffect->disconnect();

176           mIEffect->asBinder()->unlinkToDeath(mIEffectClient);

177       }

178        IPCThreadState::self()->flushCommands();

179   }

180   mIEffect.clear();

181   mIEffectClient.clear();

182   mCblkMemory.clear();

183}

Note:

clear is the method of sp<> in frameworks/base/include/utils/StrongPointer.h

 

In android_media_AudioEffect.cpp

43structfields_t {

44   // these fields provide access from C++ to the...

45   jclass   clazzEffect;         // AudioEffect class

46   jmethodIDmidPostNativeEvent;  // event post callback method

47   jfieldID fidNativeAudioEffect;// stores in Java the native AudioEffect object

48   jfieldID fidJniData;          // stores in Java additional resources used by the native AudioEffect

49   jclass   clazzDesc;           // AudioEffect.Descriptor class

50   jmethodIDmidDescCstor;        // AudioEffect.Descriptor class constructor

51};

52staticfields_tfields;

53

54structeffect_callback_cookie {

55   jclass     audioEffect_class// AudioEffect class

56   jobject    audioEffect_ref;   // AudioEffect object instance

57 }

 

59// ------------------------------------------------------------------------

60classAudioEffectJniStorage {

61   public:

62       effect_callback_cookiemCallbackData;

63

64   AudioEffectJniStorage() {

65   }

66

67   ~AudioEffectJniStorage() {

68   }

69

70};

 

effectCallback is setup in

251staticjint

252android_media_AudioEffect_native_setup(JNIEnv *env,jobjectthiz,jobjectweak_this,

253       jstringtype,jstringuuid,jintpriority,jintsessionId,jintArrayjId,jobjectArrayjavadesc)

 

{

...

    lpJniStorage =newAudioEffectJniStorage();

293   if (lpJniStorage ==NULL) {

294       LOGE("setup: Error creating JNI Storage");

295       gotosetup_failure;

296   }

297

298   lpJniStorage->mCallbackData.audioEffect_class = (jclass)env->NewGlobalRef(fields.clazzEffect);

299   // we use a weak reference so the AudioEffect object can be garbage collected.

300   lpJniStorage->mCallbackData.audioEffect_ref = env->NewGlobalRef(weak_this);

Note:

Save the class and instance references.

NewGloablRef promote the weak reference?

No!!!

NewGlobalRef has two use here:

1. new a global reference of the weak reference to prevent the java instance from being garbage collected;

2. The JNI method arg is a local reference and should use only in this thread or the JNI method. Using the global reference, other thread can access the java instance.

 

From IBM Java Diagnotics Guide:

JNI weak global references

Weak global references are a special type of global reference. They can be used in any thread and can be used between native function calls, but do not act as GC roots. The GC disposes of an object that is referred to by a weak global reference at any time if the object does not have a strong reference elsewhere.

You must use weak global references with caution. If the object referred to by a weak global reference is garbage collected, the reference becomes a null reference. A null reference can only safely be used with a subset of JNI functions. To test if a weak global reference has been collected, use the IsSameObject JNI function to compare the weak global reference to the null value.

It is not safe to call most JNI functions with a weak global reference, even if you have tested that the reference is not null, because the weak global reference could become a null reference after it has been tested or even during the JNI function. Instead, a weak global reference should always be promoted to a strong reference before it is used. You can promote a weak global reference using the NewLocalRef or NewGlobalRef JNI functions.

Weak global references use memory and must be freed with the DeleteWeakGlobalRef JNI function when it is no longer needed. Failure to free weak global references causes a slow memory leak, eventually leading to out-of-memory exceptions.

For information and warnings about the use of JNI global weak references, see the JNI specification.

301

302   LOGV("setup: lpJniStorage: %p audioEffect_ref %p audioEffect_class %p, &mCallbackData %p",

303           lpJniStorage,

304           lpJniStorage->mCallbackData.audioEffect_ref,

305           lpJniStorage->mCallbackData.audioEffect_class,

306           &lpJniStorage->mCallbackData);

307

308   if (jId ==NULL) {

309       LOGE("setup: NULL java array for id pointer");

310       lStatus =AUDIOEFFECT_ERROR_BAD_VALUE;

311       gotosetup_failure;

312   }

313

314    // create the native AudioEffect object

315   lpAudioEffect =newAudioEffect(typeStr,

316                                   uuidStr,

317                                   priority,

318                                   effectCallback,

319                                   &lpJniStorage->mCallbackData,

320                                   sessionId,

321                                   0);

...

}

&lpJniStorage->mCallbackData for arg (void *) user.

 

android_media_AudioEffect_native_setup is called inAudioEffect::AudioEffect()@ AudioEffect.java

 

367    publicAudioEffect(UUIDtype,UUIDuuid,intpriority,intaudioSession)

368           throwsIllegalArgumentException,UnsupportedOperationException,

369           RuntimeException {

370       int[]id =new int[1];

371       Descriptor[]desc =newDescriptor[1];

372       // native initialization

373       intinitResult =native_setup(newWeakReference<AudioEffect>(this),

374               type.toString(),uuid.toString(),priority,audioSession,id,

375               desc);

 

Note:

newWeakReference<AudioEffect>(this) is a weak reference java object, the java AudioEffect object weak pointer pass to native method.

 

effectCallback() @android_media_AudioEffect.cpp

95// --------------------------------------------------------

96staticvoideffectCallback(intevent,void*user,void *info) {

97

98   effect_param_t *p;

99   intarg1 = 0;

100   intarg2 = 0;

101   jobjectobj =NULL;

102   jbyteArrayarray =NULL;

103   jbyte *bytes;

104   boolparam;

105   size_tsize;

106

107   effect_callback_cookie *callbackInfo = (effect_callback_cookie *)user;

108   JNIEnv *env =AndroidRuntime::getJNIEnv();

109

110   LOGV("effectCallback: callbackInfo %p, audioEffect_ref %p audioEffect_class %p",

111           callbackInfo,

112           callbackInfo->audioEffect_ref,

113           callbackInfo->audioEffect_class);

114

115   if (!user || !env) {

116       LOGW("effectCallback error user %p, env %p",user,env);

117       return;

118   }

119

120   switch (event) {

121   caseAudioEffect::EVENT_CONTROL_STATUS_CHANGED:

122       if (info == 0) {

123           LOGW("EVENT_CONTROL_STATUS_CHANGED info == NULL");

124           gotoeffectCallback_Exit;

125       }

126       param = *(bool *)info;

127       arg1 = (int)param;

128       LOGV("EVENT_CONTROL_STATUS_CHANGED");

129       break;

130   caseAudioEffect::EVENT_ENABLE_STATUS_CHANGED:

131       if (info == 0) {

132           LOGW("EVENT_ENABLE_STATUS_CHANGED info == NULL");

133           gotoeffectCallback_Exit;

134       }

135       param = *(bool *)info;

136       arg1 = (int)param;

137       LOGV("EVENT_ENABLE_STATUS_CHANGED");

138       break;

139   caseAudioEffect::EVENT_PARAMETER_CHANGED:

140       if (info == 0) {

141           LOGW("EVENT_PARAMETER_CHANGED info == NULL");

142           gotoeffectCallback_Exit;

143       }

144       p = (effect_param_t *)info;

145       if (p->psize == 0 || p->vsize == 0) {

146           gotoeffectCallback_Exit;

147       }

148       // arg1 contains offset of parameter value from start of byte array

149       arg1 =sizeof(effect_param_t) + ((p->psize - 1) / sizeof(int) +1) *sizeof(int);

150       size =arg1 + p->vsize;

151       array =env->NewByteArray(size);

152       if (array ==NULL) {

153           LOGE("effectCallback: Couldn't allocate byte array for parameter data");

154           gotoeffectCallback_Exit;

155       }

156       bytes =env->GetByteArrayElements(array,NULL);

157       memcpy(bytes, p,size);

158       env->ReleaseByteArrayElements(array,bytes, 0);

159       obj =array;

160       LOGV("EVENT_PARAMETER_CHANGED");

161      break;

162   caseAudioEffect::EVENT_ERROR:

163       LOGW("EVENT_ERROR");

164       break;

165   }

166

167   env->CallStaticVoidMethod(

168       callbackInfo->audioEffect_class,

169       fields.midPostNativeEvent,

170       callbackInfo->audioEffect_ref,event,arg1,arg2,obj);

 

Note:

1. Arg1, arg2, obj is not used for EVENT_ERROR. callbackInfo->audioEffect_ref is the first arg in va_list.

2. callbackInfo’s fields as follows.

// Java AudioEffect class reference.

298    lpJniStorage->mCallbackData.audioEffect_class = (jclass)env->NewGlobalRef(fields.clazzEffect);

299   // we use a weak reference sothe AudioEffect object can be garbage collected.

300   lpJniStorage->mCallbackData.audioEffect_ref = env->NewGlobalRef(weak_this);

3. Java Method saved in midPostNativeEvent is postEventFromNative.

// Get the postEvent method

206   fields.midPostNativeEvent =env->GetStaticMethodID(

207           fields.clazzEffect,

208           "postEventFromNative","(Ljava/lang/Object;IIILjava/lang/Object;)V");

 

171

172effectCallback_Exit:

173   if (array) {

174       env->DeleteLocalRef(array);

175   }

176

177   if (env->ExceptionCheck()) {

178       env->ExceptionDescribe();

179       env->ExceptionClear();

180   }

181}

 

In dalvik/libnativehelper/include/nativehelper/jni.h

498/*

499 * C++ object wrapper.

500 *

501 * This is usually overlaid on a C struct whose first element is a

502 * JNINativeInterface*. We rely somewhat on compiler behavior.

503 */

504struct_JNIEnv {

505   /* do not rename this; it does not seem to be entirely opaque */

506   const structJNINativeInterface*functions;

507

508#if defined(__cplusplus)

...

789    voidCallStaticVoidMethod(jclassclazz,jmethodIDmethodID, ...)

790   {

791       va_listargs;

792       va_start(args,methodID);

793       functions->CallStaticVoidMethodV(this,clazz,methodID,args);

794       va_end(args);

795   }

796   voidCallStaticVoidMethodV(jclassclazz,jmethodIDmethodID,va_listargs)

797   { functions->CallStaticVoidMethodV(this,clazz,methodID,args); }

...

}

 

"Functions" is typedJNINativeInterface *,

/*

161 * Table of interface function pointers.

162 */

163structJNINativeInterface {

164   void*      reserved0;

165   void*      reserved1;

166   void*      reserved2;

167   void*      reserved3;

...

 

358    void        (*CallStaticVoidMethod)(JNIEnv*,jclass,jmethodID, ...);

359   void        (*CallStaticVoidMethodV)(JNIEnv*,jclass,jmethodID,va_list);

360   void        (*CallStaticVoidMethodA)(JNIEnv*,jclass,jmethodID,jvalue*);

...

}

 

In dalvik/vm/Jni.cpp

2994/*

2995 * ===========================================================================

2996 *     Function tables

2997 * ===========================================================================

2998 */

2999

3000staticconst structJNINativeInterfacegNativeInterface = {

3001   NULL,

3002   NULL,

3003   NULL,

3004   NULL,

3159    CallStaticVoidMethod,

3160   CallStaticVoidMethodV,

3161   CallStaticVoidMethodA

}

2072/*

2073 * Call a static method.

2074 */

2075#defineCALL_STATIC(_ctype,_jname,_retfail,_retok,_isref)               \

2076   static_ctypeCallStatic##_jname##Method(JNIEnv*env,jclassjclazz,    \

2077       jmethodIDmethodID, ...)                                            \

2078   {                                                                       \

2079       UNUSED_PARAMETER(jclazz);                                           \

2080       ScopedJniThreadStatets(env);                                       \

2081       JValueresult;                                                      \

2082       va_listargs;                                                       \

2083       va_start(args,methodID);                                           \

2084       dvmCallMethodV(ts.self(), (Method*)methodID,NULL,true, &result,args);\

2085       va_end(args);                                                       \

2086       if (_isref && !dvmCheckException(ts.self()))                        \

2087           result.l = (Object*)addLocalReference(ts.self(),result.l);           \

2088       return_retok;                                                      \

2089   }                                                                       \

2090   static_ctypeCallStatic##_jname##MethodV(JNIEnv*env,jclassjclazz,   \

2091       jmethodIDmethodID,va_listargs)                                   \

2092   {                                                                       \

2093       UNUSED_PARAMETER(jclazz);                                           \

2094       ScopedJniThreadStatets(env);                                       \

2095       JValueresult;                                                      \

2096       dvmCallMethodV(ts.self(), (Method*)methodID,NULL,true, &result,args);\

2097       if (_isref && !dvmCheckException(ts.self()))                        \

2098           result.l = (Object*)addLocalReference(ts.self(),result.l);           \

2099       return_retok;                                                      \

2100   }                                                                       \

2101   static_ctypeCallStatic##_jname##MethodA(JNIEnv*env,jclassjclazz,   \

2102       jmethodIDmethodID,jvalue*args)                                   \

2103   {                                                                       \

2104       UNUSED_PARAMETER(jclazz);                                           \

2105       ScopedJniThreadStatets(env);                                       \

2106       JValueresult;                                                      \

2107       dvmCallMethodA(ts.self(), (Method*)methodID,NULL,true, &result,args);\

2108       if (_isref && !dvmCheckException(ts.self()))                        \

2109           result.l = (Object*)addLocalReference(ts.self(),result.l);           \

2110       return_retok;                                                      \

2111   }

2112CALL_STATIC(jobject,Object,NULL, (jobject)result.l,true);

2113CALL_STATIC(jboolean,Boolean, 0,result.z,false);

2114CALL_STATIC(jbyte,Byte, 0,result.b,false);

2115CALL_STATIC(jchar,Char, 0,result.c,false);

2116CALL_STATIC(jshort,Short, 0,result.s,false);

2117CALL_STATIC(jint,Int, 0,result.i,false);

2118CALL_STATIC(jlong,Long, 0,result.j,false);

2119CALL_STATIC(jfloat,Float,0.0f,result.f,false);

2120CALL_STATIC(jdouble,Double,0.0,result.d,false);

2121CALL_STATIC(void,Void, , ,false);

 

In dalvik/vm/interp/Stack.cpp

429/*

430 * Issue a method call with a variable number of arguments. We process

431 * the contents of "args" by scanning the method signature.

432 *

433 *Pass in NULL for "obj" on calls to static methods.

434 *

435 * We don't need to take the class as an argument because, in Dalvik,

436 * we don't need to worry about static synchronized methods.

437 */

438voiddvmCallMethodV(Thread*self,constMethod*method,Object*obj,

439   boolfromJni,JValue*pResult,va_listargs)

440{

441   const char*desc = &(method->shorty[1]);// [0] is the return type.

442   intverifyCount = 0;

443   ClassObject*clazz;

444   u4*ins;

445

446   clazz =callPrep(self,method,obj,false);

447   if (clazz ==NULL)

448       return;

449

450   /* "ins" for new frame start at frame pointer plus locals */

451   ins = ((u4*)self->interpSave.curFrame) +

452          (method->registersSize -method->insSize);

453

454   //LOGD(" FP is %p, INs live at >= %p", self->interpSave.curFrame, ins);

455

456   /* put "this" pointer into in0 if appropriate */

457   if (!dvmIsStaticMethod(method)) {

458#ifdefWITH_EXTRA_OBJECT_VALIDATION

459       assert(obj !=NULL &&dvmIsHeapAddress(obj));

460#endif

461       *ins++ = (u4)obj;

462       verifyCount++;

463   }

464

465   while (*desc !='\0') {

466       switch (*(desc++)) {

467           case'D':case'J': {

468               u8val =va_arg(args,u8);

469               memcpy(ins, &val,8);      // EABI prevents direct store

470               ins +=2;

471               verifyCount +=2;

472               break;

473           }

474           case'F': {

475               /* floats were normalized to doubles; convert back */

476               float f = (float)va_arg(args,double);

477               *ins++ =dvmFloatToU4(f);

478               verifyCount++;

479               break;

480           }

481           case'L': {    /* 'shorty' descr uses L for all refs, incl array */

482               void*arg =va_arg(args,void*);

483               assert(obj ==NULL ||dvmIsHeapAddress(obj));

484               jobjectargObj =reinterpret_cast<jobject>(arg);

485               if (fromJni)

486                   *ins++ = (u4)dvmDecodeIndirectRef(self,argObj);

487               else

488                   *ins++ = (u4)argObj;

489               verifyCount++;

490               break;

491           }

492           default: {

493               /* Z B C S I -- all passed as 32-bit integers */

494               *ins++ =va_arg(args,u4);

495               verifyCount++;

496               break;

497           }

498       }

499   }

500

501#ifndefNDEBUG

502   if (verifyCount !=method->insSize) {

503       LOGE("Got vfycount=%d insSize=%d for %s.%s",verifyCount,

504           method->insSize,clazz->descriptor,method->name);

505       assert(false);

506       gotobail;

507   }

508#endif

509

510   //dvmDumpThreadStack(dvmThreadSelf());

511

512   if (dvmIsNativeMethod(method)) {

513       TRACE_METHOD_ENTER(self,method);

514       /*

515        * Because we leave no space for local variables, "curFrame" points

516        * directly at the method arguments.

517        */

518       (*method->nativeFunc)((u4*)self->interpSave.curFrame,pResult,

519                             method,self);

520       TRACE_METHOD_EXIT(self,method);

521   } else {

522       dvmInterpret(self,method,pResult);

523   }

524

525#ifndefNDEBUG

526bail:

527#endif

528   dvmPopFrame(self);

529}

530

dvmDecodeIndirectRef()@dalvik/vm/Jni.cpp

301/*

302 * Convert an indirect reference to an Object reference. The indirect

303 * reference may be local, global, or weak-global.

304 *

305 * If "jobj" is NULL, or is a weak global reference whose reference has

306 * been cleared, this returns NULL. If jobj is an invalid indirect

307 * reference, kInvalidIndirectRefObject is returned.

308 *

309 * Note "env" may be NULL when decoding global references.

310 */

311Object*dvmDecodeIndirectRef(Thread*self,jobjectjobj) {

312   if (jobj ==NULL) {

313       returnNULL;

314   }

315

316   switch (indirectRefKind(jobj)) {

317   casekIndirectKindLocal:

318       {

319           Object*result =self->jniLocalRefTable.get(jobj);

320           if (UNLIKELY(result ==NULL)) {

321               LOGE("JNI ERROR (app bug): use of deleted local reference (%p)",jobj);

322               dvmAbort();

323           }

324           returnresult;

325       }

326   casekIndirectKindGlobal:

327       {

328           // TODO: find a way to avoid the mutex activity here

329           IndirectRefTable*pRefTable = &gDvm.jniGlobalRefTable;

330           ScopedPthreadMutexLocklock(&gDvm.jniGlobalRefLock);

331           Object*result =pRefTable->get(jobj);

332           if (UNLIKELY(result ==NULL)) {

333               LOGE("JNI ERROR (app bug): use of deleted global reference (%p)",jobj);

334               dvmAbort();

335           }

336           returnresult;

337       }

338   casekIndirectKindWeakGlobal:

339       {

340           // TODO: find a way to avoid the mutex activity here

341           IndirectRefTable*pRefTable = &gDvm.jniWeakGlobalRefTable;

342           ScopedPthreadMutexLocklock(&gDvm.jniWeakGlobalRefLock);

343           Object*result =pRefTable->get(jobj);

344           if (result ==kClearedJniWeakGlobal) {

345               result =NULL;

346           }else if (UNLIKELY(result ==NULL)) {

347               LOGE("JNI ERROR (app bug): use of deleted weak global reference (%p)",jobj);

348               dvmAbort();

349           }

350           returnresult;

351       }

352   casekIndirectKindInvalid:

353   default:

354       if (UNLIKELY(gDvmJni.workAroundAppJniBugs)) {

355           // Assume an invalid local reference is actually a direct pointer.

356           return reinterpret_cast<Object*>(jobj);

357       }

358       LOGW("Invalid indirect reference %p in decodeIndirectRef",jobj);

359       dvmAbort();

360       returnkInvalidIndirectRefObject;

361   }

362}

 

IndirectRefTable::get() @dalvik/vm/IndirectRefTable.cpp

135/*

136 * Get the referent of an indirect ref from the table.

137 *

138 * Returns kInvalidIndirectRefObject if iref is invalid.

139 */

140Object*IndirectRefTable::get(IndirectRefiref)const {

141   IndirectRefKindkind =indirectRefKind(iref);

142   if (kind !=kind_) {

143       if (iref ==NULL) {

144           LOGW("Attempt to look up NULL %s reference",indirectRefKindToString(kind_));

145           returnkInvalidIndirectRefObject;

146       }

147       if (kind ==kIndirectKindInvalid) {

148           LOGE("JNI ERROR (app bug): invalid %s reference %p",

149                   indirectRefKindToString(kind_),iref);

150           abortMaybe();

151           returnkInvalidIndirectRefObject;

152       }

153       // References of the requested kind cannot appear within this table.

154       returnkInvalidIndirectRefObject;

155   }

156

157   u4topIndex =segmentState.parts.topIndex;

158   u4index =extractIndex(iref);

159   if (index >=topIndex) {

160       /* bad -- stale reference? */

161       LOGE("JNI ERROR (app bug): accessed stale %s reference %p (index %d in a table of size %d)",

162               indirectRefKindToString(kind_),iref,index,topIndex);

163       abortMaybe();

Note:

Dvm abort here for the issue!!

164       returnkInvalidIndirectRefObject;

165   }

166

167   Object*obj =table_[index].obj;

168   if (obj ==NULL) {

169       LOGI("JNI ERROR (app bug): accessed deleted %s reference %p",

170               indirectRefKindToString(kind_),iref);

171       abortMaybe();

172       returnkInvalidIndirectRefObject;

173   }

174

175   u4serial =extractSerial(iref);

176   if (serial !=table_[index].serial) {

177       LOGE("JNI ERROR (app bug): attempt to use stale %s reference %p",

178               indirectRefKindToString(kind_),iref);

179       abortMaybe();

180       returnkInvalidIndirectRefObject;

181   }

182

183   returnobj;

184}

 

If, get object non-null, the continuing process is message delivery and queuing.

We can see the effect_ref arg is one AudioEffect instance.

postEventFromNative() @ AudioEffect.java

1152    // ---------------------------------------------------------

1153   // Java methods called from the native side

1154   // --------------------

1155   @SuppressWarnings("unused")

1156   private static voidpostEventFromNative(Objecteffect_ref,intwhat,

1157           intarg1,intarg2,Objectobj) {

1158       AudioEffecteffect = (AudioEffect) ((WeakReference)effect_ref).get();

1159       if (effect ==null) {

1160           return;

1161       }

1162       if (effect.mNativeEventHandler !=null) {

1163           Message m =effect.mNativeEventHandler.obtainMessage(what,arg1,

1164                   arg2,obj);

1165           effect.mNativeEventHandler.sendMessage(m);

1166       }

1167

1168   }

 

In dalvik/vm/Jni.cpp

1471/*

1472 * Add a reference to the global list.

1473 */

1474staticjobjectNewGlobalRef(JNIEnv*env,jobjectjobj) {

1475   ScopedJniThreadStatets(env);

1476   Object*obj =dvmDecodeIndirectRef(ts.self(),jobj);

1477   returnaddGlobalReference(obj);

1478}

 

2664/*

2665 * Create a new weak global reference.

2666 */

2667staticjweakNewWeakGlobalRef(JNIEnv*env,jobjectjobj) {

2668   ScopedJniThreadStatets(env);

2669   Object *obj =dvmDecodeIndirectRef(ts.self(),jobj);

2670   return (jweak)addWeakGlobalReference(obj);

2671}

 

By now, if NewGlobalRefed, the JavaAudioEffect can’t be garbage collected, if the JavaAudioEffect is not finalized, the JniAudioEffect can’t be destructed. So far so puzzled!!

Light!

We can see the native_release also call DeleteGlobalRef besides native_finalize. That’s it!

Native_release is called in the Java layer to delete global ref, so the garbage collection can collect the unused java object in java layer.

 

// --------------------------------------------------------------------------

430static voidandroid_media_AudioEffect_native_finalize(JNIEnv *envjobjectthiz) {

431   LOGV("android_media_AudioEffect_native_finalize jobject: %x\n", (int)thiz);

432

433    // delete the AudioEffect object

434   AudioEffect*lpAudioEffect = (AudioEffect *)env->GetIntField(

435       thiz,fields.fidNativeAudioEffect);

436   if (lpAudioEffect) {

437       LOGV("deleting AudioEffect: %x\n", (int)lpAudioEffect);

438       deletelpAudioEffect;

439   }

440

441   // delete the JNI data

442   AudioEffectJniStorage*lpJniStorage = (AudioEffectJniStorage *)env->GetIntField(

443       thiz,fields.fidJniData);

444   if (lpJniStorage) {

445       // delete global refs created in native_setup

446       env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioEffect_class);

447       env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioEffect_ref);

448       LOGV("deleting pJniStorage: %x\n", (int)lpJniStorage);

449       deletelpJniStorage;

450   }

451}

452

453// -----------------------------------------------------------------------

454static voidandroid_media_AudioEffect_native_release(JNIEnv *envjobjectthiz) {

455

456   // do everything a call to finalize would

457   android_media_AudioEffect_native_finalize(env,thiz);

458   // + reset the native resources in the Java object so any attempt to access

459   // them after a call to release fails.

460   env->SetIntField(thiz,fields.fidNativeAudioEffect, 0);

461   env->SetIntField(thiz,fields.fidJniData, 0);

462}

 

By now, the issue is clear. When JavaAudioEffect is released and finalized, ifAudioEffect::~AudioEffect() is called with mStatus!=NO_ERROR, the unlinkToDeath will not be called, binderDied will be called and access the destroyed JavaAudioEffect.

The Next step is to find when AudioEffect::~AudioEffect() is called with mStatus!=NO_ERROR. The Effect is used in /packages/apps/MusicFX/src/com/android/musicfx/ControlPanelEffect.java. In AudioEffect.cpp, only in BinderDied() set mStatus=NO_INIT. So It maybe a thread sync issue. When BinderDied is called and mStatus is assigned with NO_INIT, if the thread is scheduled out, the JavaAudioEffect.release is called and it’s GlobalRef is deleted, CppAudioEffect is destructed, JavaAudioEffect is finalized and destroyed, and thread schedule occurs, the BinderDied Thread continues to execute with deleted mUserData(JniStorageData), and to get deleted JavaAudioEffect reference, the dvmAbort occurs.

linkToDeath/unlinkToDeath/Half ofsendObituary are mLock protected and thread safe. When sendObituary is calling or has called binderDied() callback, there is no need to unlinkToDeath, because mObituaries vector has been null assigned.

The Final Handling

From the call stack, we can see the control flow is handling AudioEffect binder death notification.

Denote the thread as BinderThread_365.

#05

effectCallback calls

167    env->CallStaticVoidMethod(

168        callbackInfo->audioEffect_class,

169        fields.midPostNativeEvent,

170        callbackInfo->audioEffect_ref, event, arg1, arg2, obj);

to invoke AudioEffect_J::postEventFromNative().

#01

Object* IndirectRefTable::get(IndirectRef iref) const {

       .....

157    u4 topIndex = segmentState.parts.topIndex;

158    u4 index = extractIndex(iref);            // $2-->

159    if (index >= topIndex) {

160        /* bad -- stale reference? */

161        LOGE("JNI ERROR (app bug): accessed stale %s reference %p (index %d in a table of size %d)",

162                indirectRefKindToString(kind_), iref, index, topIndex);

163        abortMaybe();         // *****dvmAbort()*****

164        return kInvalidIndirectRefObject;

165    }

       .....

}

When the exection is at the point to get AudioEffect@AudioEffect.java object(AudioEffect_J for simple) referred by callbackInfo->audioEffect_ref

and if AudioEffect_J is destroyed, the dvm aborts with log "dalvikvm: JNI ERROR (app bug): accessed stale global reference 0x17010a (index 49218 in a table of size 1638)" 

 

Now analyze the cause. Take #07 at first.

android::AudioEffect::binderDied() @ AudioEffect.cpp

342void AudioEffect::binderDied()

343{

344    LOGW("IEffect died");

 

345    mStatus = NO_INIT;   // <--$1

346    if (mCbf) {

347        status_t status = DEAD_OBJECT;

348        mCbf(EVENT_ERROR, mUserData, &status);

349    }

350    mIEffect.clear();

351}

If at some time, BinderThread_365 assign mStatus with NO_INIT and is scheduled out between $1 and $2.

 

Introduce another thread Thread_M.

In the initializing stage, Thread_M do the following(list needed only):

a. call android_media_AudioEffect_native_setup with new <WeakReference>AudioEffect_J as arg weak_this;

b. In android_media_AudioEffect_native_setup,

298    lpJniStorage->mCallbackData.audioEffect_class = (jclass)env->NewGlobalRef(fields.clazzEffect);

299    // we use a weak reference so the AudioEffect object can be garbage collected.

300    lpJniStorage->mCallbackData.audioEffect_ref = env->NewGlobalRef(weak_this);

NewGlobalRef has two use here:

1. new a global reference of the weak reference to prevent the java instance from being garbage collected;

2. The JNI method arg is a local reference and used only in this thread or the JNI method. Using the global reference, other thread(BinderThread_365, etc) in the same process can access the java instance .

c. new AudioEffect with &lpJniStorage->mCallbackData(saved as AudioEffect_C::mUserData) and effectCallback(int event, void* userdata, void *info).

d. In AudioEffect::set()@AudioEffect.cpp, mIEffectClient=new EffectClient(), audioFlinger->createEffect(), and linkToDeath(mIEffectClient).

 

After AudioEffect_J is useless, in the deinitialzing stage, Thread_M does

a. call AudioEffect_J::native_release and native_finalize to delete the AudioEffect_C object and unlinkToDeath.

168AudioEffect::~AudioEffect()

169{

170    LOGV("Destructor %p", this);

171

172    if (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS) {

173        setEnabled(false);

174        if (mIEffect != NULL) {

175            mIEffect->disconnect();

176            mIEffect->asBinder()->unlinkToDeath(mIEffectClient);

177        }

178         IPCThreadState::self()->flushCommands();

179    }

180    mIEffect.clear();

181    mIEffectClient.clear();

182    mCblkMemory.clear();

183}

b. DeleteGlobalRef, that is removing the referrence from the jniGlobalRefTable, which will cause the AudioEffect_J instance is only weakly referred when it is not used in java layer, so dvm gc can collect it and AudioEffect_J instance destroyed.

c. delete lpJniStorage.

 

By now, the issue is clear, it is a thread sync problem.

When binder death notification arrives, BinderThread_365 handles it. When execution is between $1 and $2, it is scheduled out.

At this time, in Thread_M, AudioEffect_J::release, AudioEffect_C destructed, dvm gc works, AudioEffect_J destroyed.

When BinderThread_365 continues and uses the destroyed AudioEffect_J referrence, dvm aborts.

 

reference solution.

Use AudioEffect::mLock to sync AudioEffect::~AudioEffect() and AudioEffect::BinderDied().

The Autolock in ~AudioEffect() will prevent the native_finalize when binder death handling.

168AudioEffect::~AudioEffect()

169{

170    LOGV("Destructor %p", this);

171    Mutex::Autolock autolock(mLock);

       ...

   }

342void AudioEffect::binderDied()

343{

344    LOGW("IEffect died");

       Mutex::Autolock autolock(mLock);

       ...

   }

---end

 

AudioRecord/AudioTrack, MediaRecorder/MediaPlayer, Visualizer/AudioEffect use the same design structures.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值