在Android上运行生成的ARM机器代码会为Java Bitmap对象提供UnsupportedOperationException

时间:2011-08-29 09:58:53

标签: android java-native-interface android-ndk arm program-transformation

我们(http://www.mosync.com)已经使用Android NDK编译了我们的ARM重新编译器,它采用我们的内部字节代码并生成ARM机器代码。执行重新编译的代码时,我们看到性能大幅提升,但有一个小例外,我们不能使用任何Java Bitmap操作。 本机系统使用一个函数来处理重新编译的代码正在调用的Java端的所有调用。在Java(Dalvik)方面,我们将绑定到Android功能。重新编译代码或执行机器代码时没有问题。完全相同的源代码适用于Symbian和Windows Mobile 6.x,因此重新编译器似乎生成正确的ARM机器代码。 就像我说的,我们遇到的问题是我们不能使用Java Bitmap对象。我们已经验证了从Java代码发送的参数是正确的,我们已经尝试在Android自己的JNI系统中执行。问题是我们得到一个UnsupportedOperationException,“大小必须适合32位。”。这个问题在Android 1.5到2.3上似乎是一致的。我们还没有在任何Android 3设备上尝试过重新编译器。

这是其他人遇到的错误,我猜其他开发人员也做过类似的事情。

2 个答案:

答案 0 :(得分:0)

我在dalvik_system_VMRuntime.c中找到了该消息:

/*
 * 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));
}

例如,从GraphicsJNI :: setJavaPixelRef:

调用此方法
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);

我会说你正在调用的代码似乎试图分配太大的代码。如果显示失败的实际Java调用以及传递给它的所有参数的值,则可能更容易找到原因。

答案 1 :(得分:0)

我设法找到了解决办法。当我将所有Bitmap.createBitmap调用包装在Activity.runOnUiThread()中时,它可以工作。