Android通過(guò)bin二進(jìn)制程序調(diào)用jar原理
先來(lái)看看monkey二進(jìn)程程序的生成.
development\cmds\monkey\Android.mk LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_MODULE := monkeylib LOCAL_MODULE_STEM := monkey include $(BUILD_JAVA_LIBRARY) ################################################################ include $(CLEAR_VARS) LOCAL_MODULE := monkey LOCAL_MODULE_CLASS := EXECUTABLES LOCAL_SRC_FILES := monkey LOCAL_REQUIRED_MODULES := monkeylib include $(BUILD_PREBUILT)
Android.mk分了兩部分,第一部分是編譯生成monkey.jar,第二部分是把monkey這個(gè)文件編譯生成monkey的二進(jìn)制程序,看看monkey這個(gè)文件。
development\cmds\monkey\monkey base=/system export CLASSPATH=$base/framework/monkey.jar ......... exec app_process $base/bin com.android.commands.monkey.Monkey "$@"
monkey這是一個(gè)shell文件,先設(shè)置把monkey.jar添加環(huán)境變量中,然后執(zhí)行app_process這個(gè)二進(jìn)制程序,同時(shí)傳入monkey jar的路徑和類名。
app_process是在frameworks\base\cmds\路徑下,直接看它的main函數(shù)
frameworks\base\cmds\app_process\app_main.cpp
int main(int argc, char* const argv[])
{
.........
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));//創(chuàng)建AndroidRuntime
..............
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {//monkey測(cè)試時(shí),傳入的是monkey jar的路徑和包名,所以進(jìn)入這個(gè)分支
className.setTo(arg);//className包含com.android.commands.monkey.Monkey
break;
} else {
--i;
break;
}
}
Vector<String8> args;
if (!className.isEmpty()) {
...............
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);//com.android.commands.monkey.Monkey添加到AndroidRuntime中
.............
} else {
............
}
。。。。。。。。。。。。。
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {//className為com.android.commands.monkey.Monkey
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
}app_process.cpp的main方法先解析argv參數(shù),創(chuàng)建AndroidRuntime的實(shí)例,并傳入類名,最后調(diào)用AndroidRuntime.start
framework/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...........
//當(dāng)前環(huán)境是否在ANDROID_ROOT、ANDROID_RUNTIME_ROOT、ANDROID_TZDATA_ROOT
const char* rootDir = getenv("ANDROID_ROOT");
...............
const char* runtimeRootDir = getenv("ANDROID_RUNTIME_ROOT");
..................
const char* tzdataRootDir = getenv("ANDROID_TZDATA_ROOT");
.............
JniInvocation jni_invocation;
jni_invocation.Init(NULL);//jni初始化
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {//啟動(dòng)java虛擬機(jī)
return;
}
onVmCreated(env);//java虛擬機(jī)創(chuàng)建
if (startReg(env) < 0) {//注冊(cè)jni
ALOGE("Unable to register all android natives\n");
return;
}
.............................................................................
//jnv的環(huán)境設(shè)置和類型轉(zhuǎn)換
.............................................................................
char* slashClassName = toSlashClassName(className != NULL ? className : "");//className為com.android.internal.os.RuntimeInit
jclass startClass = env->FindClass(slashClassName);//得到j(luò)ava類,startClass為com.android.internal.os.RuntimeInit
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");//通過(guò)類名獲得類名里的main方法
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);//由C調(diào)用JAVA,反射調(diào)起com.android.internal.os.RuntimeInit的main方法,進(jìn)入到j(luò)ava世界
}
}
...............
}start方法里面首先判斷當(dāng)前環(huán)境是否在ANDROID_ROOT、ANDROID_RUNTIME_ROOT、ANDROID_TZDATA_ROOT,然后調(diào)用startVm,startVm主要是設(shè)置虛擬機(jī)的一些參數(shù),onVmCreated是通過(guò)jni的環(huán)境檢查類名是否存在,即檢查com.android.internal.os.RuntimeInit是否存在,最后通過(guò)反射調(diào)起java的main方法。
我們繼續(xù)看com.android.internal.os.RuntimeInit的main方法
frameworks\base\core\java\com\android\internal\os\RuntimeInit.java
public static final void main(String[] argv) {
.........
commonInit();//做些log的打印和異常的捕獲
nativeFinishInit();//又進(jìn)入C/C++世界
...............
}virtual void onStarted()
{
...............
AndroidRuntime* ar = AndroidRuntime::getRuntime();
ar->callMain(mClassName, mClass, mArgs);
.....................
}framework/base/core/jni/AndroidRuntime.cpp
status_t AndroidRuntime::callMain(const String8& className, jclass clazz,
const Vector<String8>& args)
{
................
methodId = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");//通過(guò)類名找到靜態(tài)方法名為main的id
if (methodId == NULL) {
ALOGE("ERROR: could not find method %s.main(String[])\n", className.string());
return UNKNOWN_ERROR;
}
//args類型轉(zhuǎn)換
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);//調(diào)起類名里的main靜態(tài)方法,即com.android.commands.monkey.Monkey的main方法
return NO_ERROR;
}總結(jié):通過(guò)命令執(zhí)行monkey時(shí),先設(shè)置monkey.jar的環(huán)境變量,然后執(zhí)行app_process的程序,并傳入monkey二進(jìn)制程序的路徑和monkey的類名,這時(shí)就進(jìn)入到了app_process程序。在app_process的main方法里,創(chuàng)建AndroidRuntime的實(shí)例,對(duì)參數(shù)進(jìn)行校驗(yàn),把com.android.internal.os.RuntimeInit包名傳給AndroidRuntime;在AndroidRuntime里做jni的初始化,設(shè)置虛擬機(jī)參數(shù),注冊(cè)jni,然后反射com.android.internal.os.RuntimeInit的main靜態(tài)方法,最后在AndroidRuntime里通過(guò)反射調(diào)起類名里的main方法。
app_process程序還是非常不錯(cuò)的,利用好它,我們可以仿照monkey程序,開(kāi)發(fā)出一些特殊的程序。
以上就是Android通過(guò)bin二進(jìn)制程序調(diào)用jar原理的詳細(xì)內(nèi)容,更多關(guān)于Android調(diào)用jar的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
android中知道圖片name時(shí)獲取圖片的簡(jiǎn)單方法
android中知道圖片name時(shí)獲取圖片的簡(jiǎn)單方法,需要的朋友可以參考一下2013-05-05
Android實(shí)現(xiàn)底部對(duì)話框BottomDialog彈出實(shí)例代碼
本篇文章主要介紹了Android實(shí)現(xiàn)底部對(duì)話框BottomDialog代碼。這里整理了詳細(xì)的代碼,有需要的小伙伴可以參考下。2017-03-03
android端使用openCV實(shí)現(xiàn)車牌檢測(cè)
這篇文章主要為大家詳細(xì)介紹了android端使用openCV實(shí)現(xiàn)車牌檢測(cè),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12
Android如何獲取系統(tǒng)通知的開(kāi)啟狀態(tài)詳解
這篇文章主要給大家介紹了關(guān)于Android如何獲取系統(tǒng)通知開(kāi)啟狀態(tài)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)各位Android開(kāi)發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編來(lái)一起看看吧啊。2017-08-08
android 上傳aar到私有maven服務(wù)器的示例
這篇文章主要介紹了android 上傳aar到私有maven服務(wù)器,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11
Android使用selector修改TextView中字體顏色和背景色的方法
這篇文章主要介紹了Android使用selector修改TextView中字體顏色和背景色的方法,實(shí)例分析了selector方法的相關(guān)使用技巧,需要的朋友可以參考下2016-01-01
android計(jì)算pad或手機(jī)的分辨率/像素/密度/屏幕尺寸/DPI值的方法
本文將介紹手機(jī)布局/界面設(shè)計(jì)/分辨率/密度相關(guān),接下來(lái)介紹android計(jì)算pad或手機(jī)的分辨率像素等等的方法,感興趣的朋友可以了解下,希望本文可以幫助你2013-01-01
Android Service啟動(dòng)過(guò)程完整分析
這篇文章主要為大家詳細(xì)分析了Android Service啟動(dòng)完整過(guò)程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10

