关于在运行时动态生成 Java 字节码并将其加载到正在运行的 Dalvik VM 中,这个问题已被多次询问(并回答),但是有没有办法在运行时将 dex 文件/字节码加载到应用程序中?
谢谢
Dalvik 团队希望构建一流的运行时代码生成库。我们将功能请求作为Android 错误 6322进行跟踪。不幸的是,我们有一个很长的性能和正确性问题列表,所以我不能给你一个时间表,说明我们什么时候会花时间解决这个问题。
有一些替代方案,但它们都需要一些工作:
在标准 JVM 上运行您的应用程序并在那里执行所有运行时代码生成。将 .class 文件从内存转储到文件,然后对这些文件运行 dx。如果您相当老练,您可以将所有这些工作集成到您的构建中。
将开源 dx 工具作为项目库包含在内,并在您的应用程序中(可能在应用程序的类加载器中)以编程方式执行它。这将使您的应用程序的二进制文件膨胀。
有没有办法在运行时将 dex 文件/字节码加载到应用程序中?
我使用 ASM 和 BCEL 生成 Java 类,然后将它们转换为 Dex 文件。最后,我创建了 jar 文件以在设备上动态加载。
你可以看看我的代码:)
如果在任何 C 或 C++ 程序中,您想要加载并调用 DEX 类,您可以在 AndroidRuntime 中查看 Dalvik VM 是如何启动的 - 例如 frameworks/base/cmds/app_process/app_main.cpp:
status_t app_init(const char* className, int argc, const char* const argv[])
{
LOGV("Entered app_init()!\n");
AndroidRuntime* jr = AndroidRuntime::getRuntime();
jr->callMain(className, argc, argv);
LOGV("Exiting app_init()!\n");
return NO_ERROR;
}
由于“jr”AndroidRuntime 已经启动, callMain() 将被调用:
status_t AndroidRuntime::callMain(
const char* className, int argc, const char* const argv[])
{
JNIEnv* env;
jclass clazz;
jmethodID methodId;
LOGD("Calling main entry %s", className);
env = getJNIEnv();
if (env == NULL)
return UNKNOWN_ERROR;
clazz = findClass(env, className);
if (clazz == NULL) {
LOGE("ERROR: could not find class '%s'\n", className);
return UNKNOWN_ERROR;
}
methodId = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");
if (methodId == NULL) {
LOGE("ERROR: could not find method %s.main(String[])\n", className);
return UNKNOWN_ERROR;
}
<...>
env->CallStaticVoidMethod(clazz, methodId, strArray);
return NO_ERROR;
}
从上面,我们可以看到 DEX 类的代码是如何加载的,并且 CallStaticVoidMethod() 将开始解释 DEX 代码。