在Android上运行生成的ARM机器代码会对Java位图对象产生不支持的操作异常
我们()已经用Android NDK编译了我们的ARM重新编译器,它接受我们的内部字节码并生成ARM机器码。在执行重新编译的代码时,我们看到性能有了巨大的提高,只有一个小的例外,我们不能使用任何Java位图操作。 本机系统使用一个函数,负责重新编译代码调用的Java端的所有调用。在Java(Dalvik)方面,我们将绑定到Android功能。重新编译代码或执行机器代码时没有问题。同样的源代码在Symbian和WindowsMobile6.x上运行,因此重新编译程序似乎可以生成正确的ARM机器代码。 正如我所说,我们的问题是我们不能使用Java位图对象。我们已经验证了从Java代码发送的参数是正确的,并且我们已经尝试在Android自己的JNI系统中跟踪执行情况。问题是我们得到了一个“大小必须适合32位”的不支持操作异常。这个问题在安卓1.5到2.3上似乎是一致的。我们还没有在任何Android 3设备上尝试过重新编译 这是其他人遇到的bug吗?我想其他开发人员也做过类似的事情 我在以下文件中找到了此消息:在Android上运行生成的ARM机器代码会对Java位图对象产生不支持的操作异常,android,java-native-interface,android-ndk,arm,program-transformation,Android,Java Native Interface,Android Ndk,Arm,Program Transformation,我们()已经用Android NDK编译了我们的ARM重新编译器,它接受我们的内部字节码并生成ARM机器码。在执行重新编译的代码时,我们看到性能有了巨大的提高,只有一个小的例外,我们不能使用任何Java位图操作。 本机系统使用一个函数,负责重新编译代码调用的Java端的所有调用。在Java(Dalvik)方面,我们将绑定到Android功能。重新编译代码或执行机器代码时没有问题。同样的源代码在Symbian和WindowsMobile6.x上运行,因此重新编译程序似乎可以生成正确的ARM机器代码
我想说,您调用的代码似乎试图分配太大的大小。如果显示失败的实际Java调用以及传递给它的所有参数的值,可能更容易找到原因。我设法找到了解决方法。当我在Activity.runOnUiThread()中包装所有的Bitmap.createBitmap调用时,它会工作。谢谢Igor!即使我做了
Bitmap.createBitmap(10,10,Bitmap.Config.ARGB_8888)代码>我会解决这个问题。如果我在Java中直接调用createBitmap,这没有问题,但是当我从生成的ARM机器代码调用相同的东西时,这个问题总是发生。所有其他操作都很好,我们可以启动网络呼叫、蓝牙、播放声音,并使用new
在Java内部分配内存。在我们尝试过的所有东西中,只有位图对象会断裂。我尝试过的最简单的例子使用的内存少于2MB,因此在创建小位图时不应该出现内存问题。如何从ARM代码调用它?使用JNI的CallXXX函数?能否显示为该调用生成的汇编代码?我怀疑有符号/无符号整数可能有问题。嗨,伊戈尔!我已经检查了所有生成的代码,签名是正确的。我首先检查JNI侧的参数可绘制宽度:50高度:50
,然后检查Java/Dalvik侧的参数可绘制宽度:50高度:50
,这些参数都是正确的。发送到Bitmap.createBitmap的值是正确的,但我仍然得到一个java.lang.UnsupportedOperationException:大小必须适合32位
。最奇怪的是,当我运行更大的示例(如ok)时,只要不调用createBitmap,一切都正常。
/*
* public native boolean trackExternalAllocation(long size)
*
* Asks the VM if <size> bytes can be allocated in an external heap.
* This information may be used to limit the amount of memory available
* to Dalvik threads. Returns false if the VM would rather that the caller
* did not allocate that much memory. If the call returns false, the VM
* will not update its internal counts.
*/
static void Dalvik_dalvik_system_VMRuntime_trackExternalAllocation(
const u4* args, JValue* pResult)
{
s8 longSize = GET_ARG_LONG(args, 1);
/* Fit in 32 bits. */
if (longSize < 0) {
dvmThrowException("Ljava/lang/IllegalArgumentException;",
"size must be positive");
RETURN_VOID();
} else if (longSize > INT_MAX) {
dvmThrowException("Ljava/lang/UnsupportedOperationException;",
"size must fit in 32 bits");
RETURN_VOID();
}
RETURN_BOOLEAN(dvmTrackExternalAllocation((size_t)longSize));
}
size_t size = size64.get32();
jlong jsize = size; // the VM wants longs for the size
if (reportSizeToVM) {
// SkDebugf("-------------- inform VM we've allocated %d bytes\n", size);
bool r = env->CallBooleanMethod(gVMRuntime_singleton,
gVMRuntime_trackExternalAllocationMethodID,
jsize);