Dynamically Generating Dalvik Bytecode into a running Dalvik/Android application
This question has been asked(and answered) many times about dynamically generating and loading java bytecodes at runtime into a running Dalvik VM, but is there any way to load dex files/开发者_C百科bytecodes into an app at runtime?
Thanks
The Dalvik team would like to build a first-class runtime code generation library. We're tracking the feature request as Android bug 6322. Unfortunately, we have a very long list of performance and correctness issues, so I can't give you a timeline for when we'll spend time on this issue.
There are some alternatives, but they will all take some work:
Run your application on a standard JVM and exercise all runtime code generation there. Dump the .class files from memory to files, and then run dx on those files. If you're quite sophisticated, you could integrate all of this work into your build.
Include the open source dx tool as a project library, and execute it programatically from within your application, possibly in your application's classloader. This will bloat your application's binary.
is there any way to load dex files/bytecodes into an app at runtime?
Look at DexFile
and DexClassLoader
.
A related answer suggests Dexmaker for dynamic Dalvik bytecode generation.
I have used ASM and BCEL to generate Java classes and then I have converted them to Dex files. Finally I have created jar files to load dynamically on device.
You can check out my code :)
https://github.com/sciruela/android
If inside any C or C++ program, you want to load and call into the DEX classes, you can see how the Dalvik VM is started, inside the AndroidRuntime - for example 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;
}
As "jr" AndroidRuntime is already started, callMain() will be called:
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;
}
From above, we can see how the DEX classes' codes are loaded and CallStaticVoidMethod() will start interpreting the DEX codes.
精彩评论