在前面的文章分析过/system/bin/app_process64可以打开指定的className,使用示例如下:
app_process -Djava.class.path=/data/local/tmp/Test.dex /data/test com.zygote.Test
- -Djava.class.p**:属于
[java-options],这些参数会传给虚拟机,并且参数必须以 - 开头,一旦遇到非 - 或者 --,表示[java-options]结束; - /data/test:属于 cmd-dir,程序的运行目录,随便指定即可,文件操作时会以此为当前路径,大多运行在 /system/bin 下;
- com.zygote.Test:属于 start-class-name,声明入口类的名称,有包名的话需要加上包名;
当指定className时会调用com.android.internal.os.RuntimeInit.main
@UnsupportedAppUsage
public static final void main(String[] argv) {
enableDdms();
if (argv.length == 2 && argv[1].equals("application")) {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application");
redirectLogStreams();
} else {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting tool");
}
commonInit();
/*
* Now that we're running in interpreted code, call back into native code
* to run the system.
*/
nativeFinishInit();
if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!");
}
commonInit用于执行一些通用配置的初始化:
- 设置 KillApplicationHandler 为默认的 UncaughtExceptionHandler;
- 设置时区;
- 设置 http.agent 属性,用于 HttpURLConnection;
- 重置 Android 的 Log 系统;
- 通过 NetworkManagementSocketTagger 设置 socket 的 tag,用于流量统计;
//frameworks/base/core/jni/AndroidRuntime.cpp
static void com_android_internal_os_RuntimeInit_nativeFinishInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onStarted();
}
gCurRuntime就是前面创建的AppRuntime实例,onStarted在AppRuntime进行了实现。
virtual void onStarted()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
AndroidRuntime* ar = AndroidRuntime::getRuntime();
ar->callMain(mClassName, mClass, mArgs);
IPCThreadState::self()->stopProcess();
hardware::IPCThreadState::self()->stopProcess();
}
- mClassName就是前面实例中的com.zygote.Test类
- mClass是mClassName的Class
status_t AndroidRuntime::callMain(const String8& className, jclass clazz,
const Vector<String8>& args)
{
JNIEnv* env;
jmethodID methodId;
ALOGD("Calling main entry %s", className.string());
env = getJNIEnv();
if (clazz == NULL || env == NULL) {
return UNKNOWN_ERROR;
}
methodId = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");
if (methodId == NULL) {
ALOGE("ERROR: could not find method %s.main(String[])\n", className.string());
return UNKNOWN_ERROR;
}
/*
* We want to call main() with a String array with our arguments in it.
* Create an array and populate it.
*/
jclass stringClass;
jobjectArray strArray;
const size_t numArgs = args.size();
stringClass = env->FindClass("java/lang/String");
strArray = env->NewObjectArray(numArgs, stringClass, NULL);
for (size_t i = 0; i < numArgs; i++) {
jstring argStr = env->NewStringUTF(args[i].string());
env->SetObjectArrayElement(strArray, i, argStr);
}
env->CallStaticVoidMethod(clazz, methodId, strArray);
return NO_ERROR;
}
callMain实际上就是通过反射调用com.zygote.Test.main方法。