Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android JNI調用OpenCV,長時間運行內存異常,導致閃退的log分析和解決---(ReferenceTable overflow (max=1024)造成的)

Android JNI調用OpenCV,長時間運行內存異常,導致閃退的log分析和解決---(ReferenceTable overflow (max=1024)造成的)

編輯:關於Android編程

首先交代下問題背景,前些日子自己在android上搞了個入侵檢測玩。就是camera當作監控設備,每隔一定時間檢測是否有東西入侵,如果入侵率到一定程度就報警的東西。最近發現,每次運行超過20分鐘,app直接掛掉消失。下面附上核心完整log:

01-01 21:17:42.321 I/yan     ( 2588): /storage/sdcard0/InvadeDetect/ 1111111111111

01-01 21:17:42.650 E/PowerManagerService(  501): (GYP)enter sleep check_in_PowerMonitorHandler,mScreenIsOff=true;mScreenIsSwitchToOn=false mRequestSleepCount=4 mScreenOffTime=514309

01-01 21:17:43.008 D/NvOsDebugPrintf(  163): NvCamGrinder HAL_camera_device_enable_msg_type 3

01-01 21:17:43.008 D/NvOsDebugPrintf(  163): NvCamGrinder HAL_camera_device_enable_msg_type 3

01-01 21:17:43.057 I/dalvikvm-heap( 2588): Grow heap (frag case) to 18.527MB for 1228816-byte allocation

01-01 21:17:43.057 W/dalvikvm( 2588): JNI: pin count on array 0x410f1fd8 ([I) is now 1019

01-01 21:17:43.063 W/dalvikvm( 2588): JNI: pin count on array 0x410f1fd8 ([I) is now 1019

01-01 21:17:43.066 D/dalvikvm( 2588): GC_CONCURRENT freed 5780K, 45% free 7740K/14060K, paused 2ms+2ms, total 9ms

01-01 21:17:43.324 W/dalvikvm( 2588): ReferenceTable overflow (max=1024)

01-01 21:17:43.324 W/dalvikvm( 2588): JNI pinned array reference table (0x5d4440a8) dump:

01-01 21:17:43.324 W/dalvikvm( 2588):   Last 10 entries (of 1024):

01-01 21:17:43.324 W/dalvikvm( 2588):      1023: 0x410f1f70 char[] (3 elements)

01-01 21:17:43.324 W/dalvikvm( 2588):      1022: 0x40c622e8 char[] (1 elements)

01-01 21:17:43.325 W/dalvikvm( 2588):      1021: 0x40c62268 char[] (1 elements)

01-01 21:17:43.325 W/dalvikvm( 2588):      1020: 0x40c61648 char[] (1 elements)

01-01 21:17:43.325 W/dalvikvm( 2588):      1019: 0x40e28ab8 char[] (5 elements)

01-01 21:17:43.325 W/dalvikvm( 2588):      1018: 0x410f1fd8 int[] (307200 elements)

01-01 21:17:43.325 W/dalvikvm( 2588):      1017: 0x410f1fd8 int[] (307200 elements)

01-01 21:17:43.325 W/dalvikvm( 2588):      1016: 0x410f1fd8 int[] (307200 elements)

01-01 21:17:43.325 W/dalvikvm( 2588):      1015: 0x410f1fd8 int[] (307200 elements)

01-01 21:17:43.325 W/dalvikvm( 2588):      1014: 0x410f1fd8 int[] (307200 elements)

01-01 21:17:43.325 W/dalvikvm( 2588):   Summary:

01-01 21:17:43.326 W/dalvikvm( 2588):         3 of char[] (1 elements) (3 unique instances)

01-01 21:17:43.326 W/dalvikvm( 2588):         1 of char[] (3 elements)

01-01 21:17:43.326 W/dalvikvm( 2588):         1 of char[] (5 elements)

01-01 21:17:43.326 W/dalvikvm( 2588):      1019 of int[] (307200 elements) (1 unique instances)

01-01 21:17:43.326 E/dalvikvm( 2588): Failed adding to JNI pinned array ref table (1024 entries)

01-01 21:17:43.326 I/dalvikvm( 2588): "Thread-183" prio=5 tid=14 RUNNABLE

01-01 21:17:43.326 I/dalvikvm( 2588):   | group="main" sCount=0 dsCount=0 obj=0x40f89e08 self=0x5a6ca710

01-01 21:17:43.327 I/dalvikvm( 2588):   | sysTid=3823 nice=0 sched=0/0 cgrp=apps handle=1517075840

01-01 21:17:43.327 I/dalvikvm( 2588):   | state=R schedstat=( 967539651465 45738384690 224828 ) utm=95515 stm=1238 core=2

01-01 21:17:43.327 I/dalvikvm( 2588):   at libcore.icu.NativeDecimalFormat.open(Native Method)

01-01 21:17:43.327 I/dalvikvm( 2588):   at libcore.icu.NativeDecimalFormat.(NativeDecimalFormat.java:123)

01-01 21:17:43.327 I/dalvikvm( 2588):   at java.text.DecimalFormat.initNative(DecimalFormat.java:556)

01-01 21:17:43.327 I/dalvikvm( 2588):   at java.text.DecimalFormat.(DecimalFormat.java:551)

01-01 21:17:43.327 I/dalvikvm( 2588):   at java.text.DecimalFormat.(DecimalFormat.java:529)

01-01 21:17:43.328 I/dalvikvm( 2588):   at org.mo.invadedetect.CameraActivity.getRate(CameraActivity.java:513)

01-01 21:17:43.328 I/dalvikvm( 2588):   at org.mo.invadedetect.CameraActivity$CheckProcessThread.run(CameraActivity.java:402)

01-01 21:17:43.328 I/dalvikvm( 2588): 

01-01 21:17:43.328 E/dalvikvm( 2588): VM aborting

01-01 21:17:43.328 F/libc    ( 2588): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1), thread 3823 (Thread-183)

01-01 21:17:43.430 I/DEBUG   (  157): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

01-01 21:17:43.430 I/DEBUG   (  157): Build fingerprint: 'generic/pluto/pluto:4.2.2/JDQ39/eng.ztetd.20131210.002516:eng/release-keys'

01-01 21:17:43.430 I/DEBUG   (  157): Revision: '0'

01-01 21:17:43.431 I/DEBUG   (  157): pid: 2588, tid: 3823, name: Thread-183  >>> org.mo.invadedetect <<<

01-01 21:17:43.431 I/DEBUG   (  157): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadd00d

01-01 21:17:43.553 I/DEBUG   (  157):     r0 00000000  r1 00000000  r2 deadd00d  r3 00000000

01-01 21:17:43.553 I/DEBUG   (  157):     r4 4081cb58  r5 0000020c  r6 00000000  r7 4081cec0

01-01 21:17:43.553 I/DEBUG   (  157):     r8 5c775c54  r9 5c675e38  sl 5a6ca720  fp 5c775c6c

01-01 21:17:43.553 I/DEBUG   (  157):     ip 00004000  sp 5c775598  lr 4004f3f9  pc 407a927c  cpsr 600b0030

01-01 21:17:43.554 I/DEBUG   (  157):     d0  74726f6261204d56  d1  6a2e79746976696e

01-01 21:17:43.554 I/DEBUG   (  157):     d2  656d61432e746375  d3  697669746341616c

01-01 21:17:43.554 I/DEBUG   (  157):     d4  7fefffffffffffff  d5  7fefffffffffffff

01-01 21:17:43.554 I/DEBUG   (  157):     d6  c7efffffe0000000  d7  0000000000000000

01-01 21:17:43.555 I/DEBUG   (  157):     d8  3e6041893a83126f  d9  c0100000ffffffff

01-01 21:17:43.555 I/DEBUG   (  157):     d10 bff3441350a65936  d11 3fd34413509f79fe

01-01 21:17:43.555 I/DEBUG   (  157):     d12 3ddb7cdfd9d7bdbb  d13 0000000000000000

01-01 21:17:43.555 I/DEBUG   (  157):     d14 0000000000000000  d15 0000000000000000

01-01 21:17:43.555 I/DEBUG   (  157):     d16 0000000000000000  d17 4330000000000000

01-01 21:17:43.555 I/DEBUG   (  157):     d18 3fb0000000000000  d19 fffc0000fffc0000

01-01 21:17:43.555 I/DEBUG   (  157):     d20 0000000300000004  d21 0000000100000002

01-01 21:17:43.556 I/DEBUG   (  157):     d22 0707070703030303  d23 0000027f0000027f

01-01 21:17:43.556 I/DEBUG   (  157):     d24 fffe0000ffff0000  d25 fffc0000fffd0000

01-01 21:17:43.556 I/DEBUG   (  157):     d26 0000028000000280  d27 0000028000000280

01-01 21:17:43.556 I/DEBUG   (  157):     d28 0000000200000003  d29 0000000000000001

01-01 21:17:43.556 I/DEBUG   (  157):     d30 0000000000000000  d31 0000000000000000

01-01 21:17:43.557 I/DEBUG   (  157):     scr 60000013

01-01 21:17:43.561 I/DEBUG   (  157): 

01-01 21:17:43.561 I/DEBUG   (  157): backtrace:

01-01 21:17:43.562 I/DEBUG   (  157):     #00  pc 0004527c  /system/lib/libdvm.so (dvmAbort+75)

01-01 21:17:43.562 I/DEBUG   (  157):     #01  pc 00048499  /system/lib/libdvm.so

01-01 21:17:43.562 I/DEBUG   (  157):     #02  pc 0004a7e5  /system/lib/libdvm.so

01-01 21:17:43.562 I/DEBUG   (  157):     #03  pc 0003b87f  /system/lib/libdvm.so

01-01 21:17:43.562 I/DEBUG   (  157):     #04  pc 00016117  /system/lib/libjavacore.so

01-01 21:17:43.562 I/DEBUG   (  157):     #05  pc 00019471  /system/lib/libjavacore.so

01-01 21:17:43.563 I/DEBUG   (  157):     #06  pc 0001979b  /system/lib/libjavacore.so

01-01 21:17:43.563 I/DEBUG   (  157):     #07  pc 0001d850  /system/lib/libdvm.so (dvmPlatformInvoke+112)

01-01 21:17:43.563 I/DEBUG   (  157):     #08  pc 0004ca1d  /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+396)

01-01 21:17:43.563 I/DEBUG   (  157):     #09  pc 000381d5  /system/lib/libdvm.so (dvmCheckCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+8)

01-01 21:17:43.563 I/DEBUG   (  157):     #10  pc 00026c60  /system/lib/libdvm.so

01-01 21:17:43.564 I/DEBUG   (  157):     #11  pc 0002ab4c  /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)

01-01 21:17:43.564 I/DEBUG   (  157):     #12  pc 0005f2b1  /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+272)

01-01 21:17:43.564 I/DEBUG   (  157):     #13  pc 0005f2db  /system/lib/libdvm.so (dvmCallMethod(Thread*, Method const*, Object*, JValue*, ...)+20)

01-01 21:17:43.564 I/DEBUG   (  157):     #14  pc 00053e57  /system/lib/libdvm.so

01-01 21:17:43.564 I/DEBUG   (  157):     #15  pc 0000e408  /system/lib/libc.so (__thread_entry+72)

01-01 21:17:43.564 I/DEBUG   (  157):     #16  pc 0000daf4  /system/lib/libc.so (pthread_create+160)

01-01 21:17:43.565 I/DEBUG   (  157): 

01-01 21:17:43.565 I/DEBUG   (  157): stack:

01-01 21:17:43.565 I/DEBUG   (  157):          5c775558  00000001  

01-01 21:17:43.565 I/DEBUG   (  157):          5c77555c  4007a1b4  /system/lib/libc.so

01-01 21:17:43.565 I/DEBUG   (  157):          5c775560  4007a1b4  /system/lib/libc.so

01-01 21:17:43.565 I/DEBUG   (  157):          5c775564  4007a1b4  /system/lib/libc.so

01-01 21:17:43.565 I/DEBUG   (  157):          5c775568  4007a1b4  /system/lib/libc.so

01-01 21:17:43.566 I/DEBUG   (  157):          5c77556c  4004f3f9  /system/lib/libc.so (__sflush_locked+36)

01-01 21:17:43.566 I/DEBUG   (  157):          5c775570  4007a254  /system/lib/libc.so

01-01 21:17:43.566 I/DEBUG   (  157):          5c775574  4007a1b4  /system/lib/libc.so

01-01 21:17:43.567 I/DEBUG   (  157):          5c775578  00000000  

01-01 21:17:43.567 I/DEBUG   (  157):          5c77557c  400503c9  /system/lib/libc.so (_fwalk+32)

01-01 21:17:43.567 I/DEBUG   (  157):          5c775580  4081cb58  /system/lib/libdvm.so

01-01 21:17:43.567 I/DEBUG   (  157):          5c775584  0000020c  

01-01 21:17:43.567 I/DEBUG   (  157):          5c775588  00000000  

01-01 21:17:43.567 I/DEBUG   (  157):          5c77558c  4081cec0  /system/lib/libdvm.so

01-01 21:17:43.567 I/DEBUG   (  157):          5c775590  df0027ad  

01-01 21:17:43.568 I/DEBUG   (  157):          5c775594  00000000  

01-01 21:17:43.568 I/DEBUG   (  157):     #00  5c775598  00000000  

01-01 21:17:43.568 I/DEBUG   (  157):          5c77559c  6c756e28  

01-01 21:17:43.568 I/DEBUG   (  157):          5c7755a0  0000296c  

01-01 21:17:43.569 I/DEBUG   (  157):          5c7755a4  00000000  

01-01 21:17:43.569 I/DEBUG   (  157):          5c7755a8  00000000  

01-01 21:17:43.569 I/DEBUG   (  157):          5c7755ac  00000000  

01-01 21:17:43.569 I/DEBUG   (  157):          5c7755b0  00000000  

01-01 21:17:43.569 I/DEBUG   (  157):          5c7755b4  00000000  

01-01 21:17:43.570 I/DEBUG   (  157):          5c7755b8  00000000  

01-01 21:17:43.570 I/DEBUG   (  157):          5c7755bc  00000000  

01-01 21:17:43.570 I/DEBUG   (  157):          5c7755c0  00000000  

01-01 21:17:43.570 I/DEBUG   (  157):          5c7755c4  00000000  

01-01 21:17:43.570 I/DEBUG   (  157):          5c7755c8  00000000  

01-01 21:17:43.571 I/DEBUG   (  157):          5c7755cc  00000000  

01-01 21:17:43.571 I/DEBUG   (  157):          5c7755d0  00000000  

01-01 21:17:43.571 I/DEBUG   (  157):          5c7755d4  00000000  

01-01 21:17:43.571 I/DEBUG   (  157):          ........  ........

01-01 21:17:43.571 I/DEBUG   (  157):     #01  5c7757b0  40c61bc8  /dev/ashmem/dalvik-heap (deleted)

01-01 21:17:43.572 I/DEBUG   (  157):          5c7757b4  000009b9  

01-01 21:17:43.572 I/DEBUG   (  157):          5c7757b8  9b900019  

01-01 21:17:43.572 I/DEBUG   (  157):          5c7757bc  40c61ba8  /dev/ashmem/dalvik-heap (deleted)

01-01 21:17:43.572 I/DEBUG   (  157):          5c7757c0  00000000  

01-01 21:17:43.572 I/DEBUG   (  157):          5c7757c4  00000000  

01-01 21:17:43.572 I/DEBUG   (  157):          5c7757c8  9b900019  

01-01 21:17:43.573 I/DEBUG   (  157):          5c7757cc  407ae7e9  /system/lib/libdvm.so

01-01 21:17:43.573 I/DEBUG   (  157):     #02  5c7757d0  5b1ed1a8  

01-01 21:17:43.573 I/DEBUG   (  157):          5c7757d4  5a6ca710  

01-01 21:17:43.574 I/DEBUG   (  157):          5c7757d8  00000000  

01-01 21:17:43.574 I/DEBUG   (  157):          5c7757dc  00000001  

01-01 21:17:43.574 I/DEBUG   (  157):          5c7757e0  5b1ed1a8  

上面log裡stack往下還有,我就不貼了。首先交代下,在這之前我並不知道問題是由ReferenceTable overflow (max=1024)造成的。拿到log後搜關鍵字"fatal"(除此外還可搜fault、error、fail),很幸運直接定位到了問題:VM aborting虛擬機直接掛掉了,Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1), thread 3823 (Thread-183),第一感覺是內存是不是洩漏或溢出了。順著這個線索往下找,看到關鍵字backtrace,凡是backtrace下帶pc字樣的地址都可以用NDK中或linux下的arm-linux-androideabi-addr2line工具將地址映射成函數名字。

01-01 21:17:43.561 I/DEBUG   (  157): backtrace:
01-01 21:17:43.562 I/DEBUG   (  157):     #00  pc 0004527c  /system/lib/libdvm.so (dvmAbort+75)
01-01 21:17:43.562 I/DEBUG   (  157):     #01  pc 00048499  /system/lib/libdvm.so
01-01 21:17:43.562 I/DEBUG   (  157):     #02  pc 0004a7e5  /system/lib/libdvm.so
01-01 21:17:43.562 I/DEBUG   (  157):     #03  pc 0003b87f  /system/lib/libdvm.so
01-01 21:17:43.562 I/DEBUG   (  157):     #04  pc 00016117  /system/lib/libjavacore.so
01-01 21:17:43.562 I/DEBUG   (  157):     #05  pc 00019471  /system/lib/libjavacore.so
01-01 21:17:43.563 I/DEBUG   (  157):     #06  pc 0001979b  /system/lib/libjavacore.so
01-01 21:17:43.563 I/DEBUG   (  157):     #07  pc 0001d850  /system/lib/libdvm.so (dvmPlatformInvoke+112)
01-01 21:17:43.563 I/DEBUG   (  157):     #08  pc 0004ca1d  /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+396)
01-01 21:17:43.563 I/DEBUG   (  157):     #09  pc 000381d5  /system/lib/libdvm.so (dvmCheckCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+8)
01-01 21:17:43.563 I/DEBUG   (  157):     #10  pc 00026c60  /system/lib/libdvm.so
01-01 21:17:43.564 I/DEBUG   (  157):     #11  pc 0002ab4c  /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)
01-01 21:17:43.564 I/DEBUG   (  157):     #12  pc 0005f2b1  /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+272)
01-01 21:17:43.564 I/DEBUG   (  157):     #13  pc 0005f2db  /system/lib/libdvm.so (dvmCallMethod(Thread*, Method const*, Object*, JValue*, ...)+20)
01-01 21:17:43.564 I/DEBUG   (  157):     #14  pc 00053e57  /system/lib/libdvm.so
01-01 21:17:43.564 I/DEBUG   (  157):     #15  pc 0000e408  /system/lib/libc.so (__thread_entry+72)
01-01 21:17:43.564 I/DEBUG   (  157):     #16  pc 0000daf4  /system/lib/libc.so (pthread_create+160)

backtrace下面列的從#16到#00,是一個堆棧式調用,#16在棧底所以是最先進棧,即最先調用的,然後是#15依次類推。從上面來看都是libc.so和libdvm.so出的問題,這些都是系統標准的一般不可能出問題。如果是自己生成的so的話,還真可能是自己的so造成的內存異常,稍後我會貢獻一個示例,順便介紹下addr2line的使用。

所以我懷疑找錯了方向,那不是在VM掛掉之前log裡就有異常了?往上看,看到Failed adding to JNI pinned array ref table (1024 entries),不能夠將jni裡指向的數組引用添加。再往上找看到關鍵的一句:ReferenceTable overflow (max=1024),經查是引用計數器溢出了,最大為1024.即java的內存管理機制是基於引用的,需要計數器來記錄引用的次數。在overflow這句話得後面當引用計數達到1024時還dump出了最近的10個引用,Summary了哪些引用有多少個,可以看到有1019個對int[]數組的引用,剩下的是對char[]的引用。我恍然大悟,我在jni裡不停的通過下面來接收int數組,將其轉為opencv的mat矩陣:

	jint *cbuf;
	cbuf = env->GetIntArrayElements(buf, false);
	if(cbuf == NULL)
	{
		return ;
	}
	Mat mat(h, w, CV_8UC4, (unsigned char*)cbuf);
卻一直沒有釋放。想到這,又搜了下資料,參考這裡 在原有代碼基礎上增加釋放cbuf的語句就ok了:env->ReleaseIntArrayElements(buf, cbuf, 0);

參考Android NDK之JNI陷阱 在用到NewByteArray類似方法時一定要DeleteLocalRef(),使用GetByteArrayELement時(本文即使如此)要用ReleaseByteArrayElements來進行釋放。

稍後,會介紹Android和JNI層的OpenCV交互時,關於怎麼傳數據的兩種方法,本例中使用的是傳int數組的方法,如果有圖片需要返回,就再返回一個jnitArray。

結語: 碰到內存洩漏或異常的問題不要怕,尋根探源只要能定位到問題便解決了一大半了。正如六祖曰煩惱即菩提,李小龍說問題即答案,當你真正明白了問題,也就找到了答案!呵呵,漫漫程序路, 何嘗不是如此呢。。。

--------------------------------------------------------本文系原創,轉載請注明作者:yanzi1225627



  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved