2010-11-12 39 views
1

也許我正在嘗試做一些我不該做的事情。操縱256x256位圖崩潰android-ndk的JNI

我在模擬器中運行一段代碼。它看起來(或多或少) 是這樣的:http://pastie.org/1291380

這是構建一個動態壁紙背景。我傳入位圖, 調色板和平鋪陣列。我的位圖大小爲256 x 256. getRedPal/getGreenPal/getBluePal本質上會調用 Color.red()/ Color.green()/ Color。藍()以獲得調色板對象的顏色組件。

循環突然出現;在模擬器崩潰和燒燬之前,我得到一直到drawInC的j值 命中32的點:

11-11 15:34:44.032:INFO/distort_bmp(598):DrawInC:i:0 Y:32

11-11 15:34:44.032:INFO/distort_bmp(598):DrawTiles:I:0 Y:0

11-11 15:34:44.032:INFO/distort_bmp(598) :DrawTiles:I:0 Y:1

11-11 15:34:44.032:INFO/distort_bmp(598):DrawTiles:I:0 Y:2

11-11 15:34:44.032:INFO/distort_bmp(598):DrawTiles:i:0 j:3

11-11 15:34:44.032:INFO/distort_bmp(598):DrawTiles:i:0 j:4

之後我得到一個轉儲文件發送到/ data/tombstones。這裏是 轉儲(但我真心不覺得它什麼值得任何價值,只是 一堆內存地址):http://pastie.org/1291394

我添加機器人:vmSafeMode =「true」以我的標籤 閱讀後別處那可以解決問題。這是2.2, 使用bitmap.h。

個人而言,我半信半疑那

jbyte* buffer = 
(*env)->GetByteArrayElements(env, arr, &isCopy) 

通話;我從網上撥了那個 的代碼,因爲我完全無法從我的字節數組「arr」獲取值 。

任何想法?

編輯 操縱我的循環迭代之後(我縮短了循環的數量),我現在得到的信息的錯誤:

「ReferenceTable溢出(最大值= 512)」

JNI local reference table summary (512 entries): 
    509 of Ljava/lang/Class; 164B (3 unique) 
2 of Ljava/lang/String; 28B (2 unique) 
    1 of [Ljava/lang/String; 28B 
Memory held directly by tracked refs is 576 bytes 
Failed adding to JNI local ref table (has 512 entries) 

那「java.lang.class的509」看起來不太適合我......我如何在這裏優化我的代碼?

+0

我沒有花時間閱讀所有的代碼,但一些谷歌搜索顯示,你得到的錯誤可能是由於沒有釋放變量造成的...... http://代碼.google.com/p/android/issues/detail?id = 8676#c5不知道是否有任何幫助(是的,這是關於blutooth,但它不是一個BT問題) – Basic 2010-11-12 22:09:33

回答

2

從該錯誤消息看來,一些本地代碼調用了返回Class對象的函數,並且已經完成了509次。這些電話中的507個返回了一個特定的類。

JNI本地引用讓GC知道本機代碼正在查看某個對象,因此即使其他地方沒有引用該對象也無法收集該對象。當本地代碼返回到VM時,這些本地引用將被釋放。如果本機代碼沒有返回就做了很多工作,那麼可能會溢出本地ref表。

您可能只需要在某處添加DeleteLocalRef。我的猜測是你需要在DrawTile的末尾添加一個,因爲GetObjectClass調用。更好的是,將這些GetMethodID調用移動到一次性設置功能。 (他們進行字符串搜索以找到方法,使其不太快。)

欲瞭解更多信息,請登錄JNI Tips

+0

嗯,我掏出GetMethodID調用,而是直接將jmethodId傳遞給DrawTiles。我也改變了我的數組分配給GetByteArrayRegion - 但我仍然收到崩潰。嗯,嗯。 – GJTorikian 2010-11-13 00:12:55

+0

你是否得到了ReferenceTable溢出崩潰,或者只是一個本地崩潰(在logcat中有一個調試器堆棧轉儲)?我只是在處理ref表溢出(我將其描述爲「VM中止」而不是崩潰)。 – fadden 2010-11-19 00:43:45

0

我認爲這可能是一個記憶問題。你釋放數組嗎?

,如果你得到陣列,

(*env)->GetByteArrayElements(env, arr, &isCopy) 

必須釋放在C端它的陣列中的每個過程之後,或者你將填補你的記憶,直到你得到超過限制(限制大小取決於Android版本和/或製造商,但每個應用程序我所知最大48MB)

(*env)->ReleaseByteArrayElements(env, arr, &isCopy, 0); 

在這裏看到:http://www.iam.ubc.ca/guides/javatut99/native1.1/implementing/array.html

順便說一句,這種方法並複製陣列從java到c中的新內存塊,你在那裏工作,並在最後複製回java(這個內存可能已經被移動到另一個位置)。爲了提高性能,你可以看看https://groups.google.com/forum/?fromgroups#!msg/android-ndk/phDP5zqiYY4/BFMw4zTme8IJ