设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间02 现在时间02 缓存数据 “秋是慢慢入的但冷是突然的” 就像失望是慢慢累积的 但不爱是突然的

“秋是慢慢入的但冷是突然的” 就像失望是慢慢累积的 但不爱是突然的 -- 拾忆

查看: 1608|回复: 3

Android通过bin二进制程序调用jar原理

[复制链接]

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
33
主题
27
精华
0
金钱
99
积分
64
注册时间
2023-9-30
最后登录
2025-5-31

发表于 2024-2-25 11:42:59 | 显示全部楼层 |阅读模式
先来看看monkey二进程程序的生成.
  1. development\cmds\monkey\Android.mk
  2. LOCAL_PATH:= $(call my-dir)
  3. include $(CLEAR_VARS)
  4. LOCAL_SRC_FILES := $(call all-subdir-java-files)
  5. LOCAL_MODULE := monkeylib
  6. LOCAL_MODULE_STEM := monkey
  7. include $(BUILD_JAVA_LIBRARY)
  8. ################################################################
  9. include $(CLEAR_VARS)
  10. LOCAL_MODULE := monkey
  11. LOCAL_MODULE_CLASS := EXECUTABLES
  12. LOCAL_SRC_FILES := monkey
  13. LOCAL_REQUIRED_MODULES := monkeylib
  14. include $(BUILD_PREBUILT)
复制代码
Android.mk分了两部分,第一部分是编译生成monkey.jar,第二部分是把monkey这个文件编译生成monkey的二进制程序,看看monkey这个文件。
  1. development\cmds\monkey\monkey
  2. base=/system
  3. export CLASSPATH=$base/framework/monkey.jar
  4. .........
  5. exec app_process $base/bin com.android.commands.monkey.Monkey "$@"
复制代码
monkey这是一个shell文件,先设置把monkey.jar添加环境变量中,然后执行app_process这个二进制程序,同时传入monkey jar的路径和类名。
app_process是在frameworks\base\cmds\路径下,直接看它的main函数
  1. frameworks\base\cmds\app_process\app_main.cpp
  2. int main(int argc, char* const argv[])
  3. {
  4.     .........
  5.     AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));//创建AndroidRuntime
  6.    ..............
  7.     while (i < argc) {
  8.         const char* arg = argv[i++];
  9.         if (strcmp(arg, "--zygote") == 0) {
  10.             zygote = true;
  11.             niceName = ZYGOTE_NICE_NAME;
  12.         } else if (strcmp(arg, "--start-system-server") == 0) {
  13.             startSystemServer = true;
  14.         } else if (strcmp(arg, "--application") == 0) {
  15.             application = true;
  16.         } else if (strncmp(arg, "--nice-name=", 12) == 0) {
  17.             niceName.setTo(arg + 12);
  18.         } else if (strncmp(arg, "--", 2) != 0) {//monkey测试时,传入的是monkey jar的路径和包名,所以进入这个分支
  19.             className.setTo(arg);//className包含com.android.commands.monkey.Monkey
  20.             break;
  21.         } else {
  22.             --i;
  23.             break;
  24.         }
  25.     }
  26.     Vector<String8> args;
  27.     if (!className.isEmpty()) {
  28.         ...............
  29.         args.add(application ? String8("application") : String8("tool"));
  30.         runtime.setClassNameAndArgs(className, argc - i, argv + i);//com.android.commands.monkey.Monkey添加到AndroidRuntime中
  31.         .............
  32.     } else {
  33.        ............
  34.     }
  35.     。。。。。。。。。。。。。
  36.     if (zygote) {
  37.         runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
  38.     } else if (className) {//className为com.android.commands.monkey.Monkey
  39.         runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
  40.     } else {
  41.         fprintf(stderr, "Error: no class name or --zygote supplied.\n");
  42.         app_usage();
  43.         LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
  44.     }
  45. }
复制代码
app_process.cpp的main方法先解析argv参数,创建AndroidRuntime的实例,并传入类名,最后调用AndroidRuntime.start
  1. framework/base/core/jni/AndroidRuntime.cpp
  2. void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
  3. {
  4.     ...........
  5.     //当前环境是否在ANDROID_ROOT、ANDROID_RUNTIME_ROOT、ANDROID_TZDATA_ROOT
  6.     const char* rootDir = getenv("ANDROID_ROOT");
  7.     ...............
  8.     const char* runtimeRootDir = getenv("ANDROID_RUNTIME_ROOT");
  9.     ..................
  10.     const char* tzdataRootDir = getenv("ANDROID_TZDATA_ROOT");
  11.     .............
  12.     JniInvocation jni_invocation;
  13.     jni_invocation.Init(NULL);//jni初始化
  14.     JNIEnv* env;
  15.     if (startVm(&mJavaVM, &env, zygote) != 0) {//启动java虚拟机
  16.         return;
  17.     }
  18.     onVmCreated(env);//java虚拟机创建
  19.     if (startReg(env) < 0) {//注册jni
  20.         ALOGE("Unable to register all android natives\n");
  21.         return;
  22.     }
  23.     .............................................................................
  24.     //jnv的环境设置和类型转换
  25.     .............................................................................
  26.     char* slashClassName = toSlashClassName(className != NULL ? className : "");//className为com.android.internal.os.RuntimeInit
  27.     jclass startClass = env->FindClass(slashClassName);//得到java类,startClass为com.android.internal.os.RuntimeInit
  28.     if (startClass == NULL) {
  29.         ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
  30.         /* keep going */
  31.     } else {
  32.         jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
  33.             "([Ljava/lang/String;)V");//通过类名获得类名里的main方法
  34.         if (startMeth == NULL) {
  35.             ALOGE("JavaVM unable to find main() in '%s'\n", className);
  36.             /* keep going */
  37.         } else {
  38.             env->CallStaticVoidMethod(startClass, startMeth, strArray);//由C调用JAVA,反射调起com.android.internal.os.RuntimeInit的main方法,进入到java世界
  39.         }
  40.     }
  41.     ...............
  42. }
复制代码
start方法里面首先判断当前环境是否在ANDROID_ROOT、ANDROID_RUNTIME_ROOT、ANDROID_TZDATA_ROOT,然后调用startVm,startVm主要是设置虚拟机的一些参数,onVmCreated是通过jni的环境检查类名是否存在,即检查com.android.internal.os.RuntimeInit是否存在,最后通过反射调起java的main方法。
我们继续看com.android.internal.os.RuntimeInit的main方法
  1. frameworks\base\core\java\com\android\internal\os\RuntimeInit.java
  2. public static final void main(String[] argv) {
  3.    .........
  4.     commonInit();//做些log的打印和异常的捕获
  5.     nativeFinishInit();//又进入C/C++世界
  6.     ...............
  7. }
复制代码
  1. virtual void onStarted()
  2.     {
  3.        ...............
  4.         AndroidRuntime* ar = AndroidRuntime::getRuntime();
  5.         ar->callMain(mClassName, mClass, mArgs);
  6.         .....................
  7.     }
复制代码
  1. framework/base/core/jni/AndroidRuntime.cpp
  2. status_t AndroidRuntime::callMain(const String8& className, jclass clazz,
  3.     const Vector<String8>& args)
  4. {
  5.     ................
  6.     methodId = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");//通过类名找到静态方法名为main的id
  7.     if (methodId == NULL) {
  8.         ALOGE("ERROR: could not find method %s.main(String[])\n", className.string());
  9.         return UNKNOWN_ERROR;
  10.     }
  11.      //args类型转换
  12.     const size_t numArgs = args.size();
  13.     stringClass = env->FindClass("java/lang/String");
  14.     strArray = env->NewObjectArray(numArgs, stringClass, NULL);
  15.     for (size_t i = 0; i < numArgs; i++) {
  16.         jstring argStr = env->NewStringUTF(args[i].string());
  17.         env->SetObjectArrayElement(strArray, i, argStr);
  18.     }
  19.     env->CallStaticVoidMethod(clazz, methodId, strArray);//调起类名里的main静态方法,即com.android.commands.monkey.Monkey的main方法
  20.     return NO_ERROR;
  21. }
复制代码
总结:通过命令执行monkey时,先设置monkey.jar的环境变量,然后执行app_process的程序,并传入monkey二进制程序的路径和monkey的类名,这时就进入到了app_process程序。在app_process的main方法里,创建AndroidRuntime的实例,对参数进行校验,把com.android.internal.os.RuntimeInit包名传给AndroidRuntime;在AndroidRuntime里做jni的初始化,设置虚拟机参数,注册jni,然后反射com.android.internal.os.RuntimeInit的main静态方法,最后在AndroidRuntime里通过反射调起类名里的main方法。
app_process程序还是非常不错的,利用好它,我们可以仿照monkey程序,开发出一些特殊的程序。
以上就是Android通过bin二进制程序调用jar原理的详细内容,更多关于Android调用jar的资料请关注晓枫资讯其它相关文章!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
26
积分
32
注册时间
2022-12-29
最后登录
2022-12-29

发表于 2024-12-22 10:54:27 | 显示全部楼层
感谢楼主,顶。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
21
积分
22
注册时间
2022-12-27
最后登录
2022-12-27

发表于 2025-1-21 11:36:21 | 显示全部楼层
顶顶更健康!!!
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
17
积分
14
注册时间
2022-12-24
最后登录
2022-12-24

发表于 昨天 20:42 | 显示全部楼层
感谢楼主分享。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼
3楼
4楼

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表