操纵256x256位图崩溃android-ndk的JNI

时间:2010-11-12 16:43:00

标签: android bitmap java-native-interface android-ndk

也许我正在尝试做一些我不应该做的事情。

我在模拟器中运行了一段代码。看起来(或多或少) 像这样:http://pastie.org/1291380

这是构建一个动态壁纸背景。我传入一个位图, 调色板和平铺阵列。我的位图大小为256 x 256。 getRedPal / getGreenPal / getBluePal本质上是一个调用 Color.red()/ Color.green()/ Color.blue()以获得rgb 调色板对象的颜色组件。

循环突然出现;我一直到j值的地步 在模拟器崩溃并烧毁之前,drawInC命中32:

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

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

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

11-11 15:34:44.032:INFO / distort_bmp(598):DrawTiles:i:0 j: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

之后我将android:vmSafeMode =“true”添加到我的标签中 在别处读到可以解决问题的地方。这是在2.2, 使用bitmap.h。

我个人对此表示怀疑

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

调用;我采摘了那个 来自网络的代码,因为我完全无法获得价值 从我的字节数组“arr。”

有什么想法吗?

修改 在操作我的循环迭代器之后(我缩短了循环次数),我现在得到了一个信息错误:

“ReferenceTable overflow(max = 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”对我来说看起来不太合适......我怎样才能在这里优化我的代码?

2 个答案:

答案 0 :(得分:2)

从该错误消息中可以看出,某些本机代码调用了一个返回Class对象的函数,并且已经完成了509次。其中507个电话返回了一个特定班级。

JNI本地引用让GC知道本机代码正在查看对象,因此即使在其他地方没有引用该对象,也无法收集该对象。当本机代码返回VM时,将释放这些本地引用。如果本机代码在没有返回的情况下执行了大量工作,则可能会溢出本地ref表。

您可能只需要在某处添加DeleteLocalRef。我的猜测是你需要在DrawTile的末尾添加一个,因为GetObjectClass调用。更好的是,将这些GetMethodID调用移动到一次性设置功能。 (他们进行字符串搜索以找到方法,使它们不是特别快。)

有关详细信息,请参阅JNI Tips

答案 1 :(得分: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