安卓JVM加载so库流程

好久没有写点东西发了,工作中的事情有点杂,也找不到整块东西可以写的。

最近调查了一个问题,稍微追了一下流程,这里记录一下。

1. 问题背景

由于我们支持的设备相对比竞品,zygote进程多占用了好几倍的内存空间。通过dump meminfo后发现,我们的设备在so库,ttf,和unkonwn mmap的内存空间相比竞品一共大了20多M,其中so库多了15M左右。

通过查看zygote进程的smaps,确定了占用空间最大的几个so库确实是我们自己的。虽然确定了内存占用大的原因,还是得把这些so库是加载在zygote进程中的时机确定了才行。

我的第一反应就是在zygote启动时,加载sharedLibrary()时,把这些库加载了,于是去看了这部分源码,并没有。

通过反复调试以及追踪源码,最后发现是在JVM启动的过程中加载了这些so库,这些so库的配置在“system/etc/public.libraries.txt”下。

这个文件里配置的都是public的so库,能够被普通app访问的。类似的配置文件还有“vendor/etc/”下面的,还有一些其他的配置地方,我没有深入去看,想要看的盆友可以自己去看源码或者注释。

下面我就带大家一起看看虚拟机加载这些so库的流程。

2. JVM加载so库流程

调用栈:

frameworks/base/cmds/app_process/app_main.cpp

​ ---->runtime.start(“com.android.internal.os.ZygoteInit”, args, zygote);

frameworks/base/core/jni/AndroidRuntime.cpp

​ ---->AndroidRuntime::startVm

​ —>JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs)

art/runtime/jni/java_vm_ext.cc

​ —>android::InitializeNativeLoader();

system/core/libnativeloader/native_loader.cpp

​ ---->Initialize()

​ ---->ReadConfig(public_native_libraries_system_config, &sonames, always_true, &error_msg)

其中,public_native_libraries_system_config 为 system/etc/public.libraries.txt

这部分流程是在安卓设备开机过程中的,在执行ZygoteInit.main()之前会先启动java虚拟机的,这样fork其他java进程的时候,java环境就已经有了,不用再创建虚拟机了。

最后贴一下Initialize()函数:

void Initialize() {//一旦public命名空间被初始化,运行这个代码就没有意义了——它对当前的public库列表没有任何影响。if (initialized_) {return;}std::vector<std::string> sonames;const char* android_root_env = getenv("ANDROID_ROOT");std::string root_dir = android_root_env != nullptr ? android_root_env : "/system";std::string public_native_libraries_system_config =root_dir + kPublicNativeLibrariesSystemConfigPathFromRoot;std::string llndk_native_libraries_system_config =root_dir + kLlndkNativeLibrariesSystemConfigPathFromRoot;std::string vndksp_native_libraries_system_config =root_dir + kVndkspNativeLibrariesSystemConfigPathFromRoot;std::string product_public_native_libraries_dir = "/product/etc";std::string error_msg;LOG_ALWAYS_FATAL_IF(!ReadConfig(public_native_libraries_system_config, &sonames, always_true, &error_msg),"Error reading public native library list from \"%s\": %s",public_native_libraries_system_config.c_str(), error_msg.c_str());//对于可调试的平台构建,使用ANDROID_ADDITIONAL_PUBLIC_LIBRARIES环境变量将库添加到列表中。这仅用于平台测试。if (is_debuggable()) {const char* additional_libs = getenv("ANDROID_ADDITIONAL_PUBLIC_LIBRARIES");if (additional_libs != nullptr && additional_libs[0] != '\0') {std::vector<std::string> additional_libs_vector = base::Split(additional_libs, ":");std::copy(additional_libs_vector.begin(), additional_libs_vector.end(),std::back_inserter(sonames));}}//删除运行时命名空间中的公共库。这些库列在public.android.txt中,但我们不希望android的其余部分在默认命名空间中打开这些库。//例如,libicuuc。因此从运行时名称空间公开给类装入器名称空间。//不幸的是,它没有稳定的C符号,并且默认的命名空间应该只在libandroidicus .so中使用稳定的符号。http://b/120786417removePublicLibsIfExistsInRuntimeApex(sonames);// android_init_namespaces()期望加载所有的公共库,以便仅通过soname找到它们。// TODO(迪米特里·):这有点误导,因为我们不知道供应商公共库是否将从 /vendor/lib打开,我们可能最终会从/system/lib或/product/lib加载它们for (const auto& soname : sonames) {LOG_ALWAYS_FATAL_IF(dlopen(soname.c_str(), RTLD_NOW | RTLD_NODELETE) == nullptr,"Error preloading public library %s: %s", soname.c_str(), dlerror());}system_public_libraries_ = base::Join(sonames, ':');// read /system/etc/public.libraries-<companyname>.txt which contain partner defined// system libs that are exposed to apps. The libs in the txt files must be// named as lib<name>.<companyname>.so.sonames.clear();ReadExtensionLibraries(base::Dirname(public_native_libraries_system_config).c_str(), &sonames);oem_public_libraries_ = base::Join(sonames, ':');// read /product/etc/public.libraries-<companyname>.txt which contain partner defined// product libs that are exposed to apps.sonames.clear();ReadExtensionLibraries(product_public_native_libraries_dir.c_str(), &sonames);product_public_libraries_ = base::Join(sonames, ':');// Insert VNDK version to llndk and vndksp config file names.insert_vndk_version_str(&llndk_native_libraries_system_config);insert_vndk_version_str(&vndksp_native_libraries_system_config);sonames.clear();ReadConfig(llndk_native_libraries_system_config, &sonames, always_true);system_llndk_libraries_ = base::Join(sonames, ':');sonames.clear();ReadConfig(vndksp_native_libraries_system_config, &sonames, always_true);system_vndksp_libraries_ = base::Join(sonames, ':');sonames.clear();// This file is optional, quietly ignore if the file does not exist.ReadConfig(kPublicNativeLibrariesVendorConfig, &sonames, always_true, nullptr);vendor_public_libraries_ = base::Join(sonames, ':');}

【安卓开机启动】安卓JVM加载so库流程相关推荐

  1. 安装win7系统不能开机启动服务器,win7系统开机启动项不能加载的原因分析及解决...

    开机启动项是每台电脑都有的东西,就是多和少的问题的,很多人开机的时候喜欢加载很多的启动项,其实这也没什么不好的.现在的电脑为了受到更好的保护,往往在开机的时候就加载了一些启动项,如:杀毒软件,安全卫士 ...

  2. ReactOS 0.0.21从开机启动,到加载驱动的过程

    首先是在main.c中ExpInitializeExecutive函数.遍历所有加载的模块,其中有ntoskrnl.各个驱动.nls.注册表文件等.找出驱动程序,依次调用LdrInitializeBo ...

  3. php7.2 加载pgsql驱动,PHP启动:无法加载动态库PGSQL - php

    我正在尝试使用运行Symfony 3.x: Ubuntu 16.04 PHP 7.0 NGinx 我想与我创建的PGSQL数据库进行交互,但出现此错误: PHP警告:PHP启动:无法加载动态库 '/u ...

  4. clamav --reload 加载病毒库源码分析

    基本流程可以参考clamav中clamdscan --version 不生效 我们直接从解析command开始.parse_command函数返回COMMAND_RELOAD类型.然后进入execut ...

  5. J2EE JVM加载class文件的原理机制

    JVM加载class文件的原理机制 1.Java中的所有类,必须被装载到jvm中才能运行,这个装载工作是由jvm中的类装载器完成的,类装载器所做的工作实质是把类文件从硬盘读取到内存中 2.java中的 ...

  6. 常见Java面试题之JVM加载class文件的原理机制

    JVM加载class文件的原理机制 JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的 ...

  7. jvm加载class原理

    转载地址 : http://hxraid.iteye.com/blog/747625 当Java编译器编译好.class文件之后,我们需要使用JVM来运行这个class文件.那么最开始的工作就是要把字 ...

  8. 描述一下JVM加载class文件的原理机制

    Java中的所有类,都需要由类加载器装载到JVM中才能运行.类加载器本身也是一个类,而它的工作就是把class文件从硬盘读取到内存中.在写程序的时候,我们几乎不需要关心类的加载,因为这些都是隐式装载的 ...

  9. 阵列卡服务器启动不到pe桌面,制作启动u盘加载阵列卡驱动无法安装怎么办

    制作启动u盘加载阵列卡驱动无法安装怎么办?安装服务器时碰到没有阵列卡驱动无法安装的问题大家应该都碰到过.之前一次安装2003碰到没阵列卡驱动,解决的办法比较土,上网下了张别人做好的集成了raid驱动的 ...

最新文章

  1. html5 颜色弹窗 位置,HTML5之placeholder属性以及如何更改placeholder属性中文字颜色大小位置...
  2. R语言plotly可视化:plotly可视化多个直方图、通过bingroup参数设置多个直方图使用相同的bins设置(Share bins between histograms)
  3. 统治未来的离散式神经网络详解
  4. python协程池操作mysql_在python中使用aiomysql异步操作mysql
  5. vs opencv4 imread读不到图片问题的解决方法
  6. table control 光标定位控制
  7. Topless eclipse导入myeclipse的web项目没法识别问题解决
  8. boost::ratio_subtract相关的测试程序
  9. c语言本身有输入输出语句正确错误,C语言模拟选择题
  10. loadrunner直接压post请求loadrunner直接压post请求
  11. 人间值得!支付宝宣布平台上登记器官捐献人数:90后占比超一半
  12. 剧情介绍:“造雨人”
  13. win7/win10 密码忘了?没关系,利用5次shift,9步轻松破解密码
  14. 如何让测试RFC2544更便捷——RFC2544测试实操
  15. 16进制颜色透明度对照表
  16. 沙盒沙箱技术,移动沙盒等
  17. 数据分析学习总结笔记01:情感分析
  18. Transformer8
  19. 云阶月地,关锁千重(一.公平和非公平)
  20. hbase 常用命令行操作总结

热门文章

  1. 【autojs】Auto.js Pro陌陌点赞全脚本源代码
  2. #R语言# 生成随机数
  3. CPU,处理器插槽,逻辑处理器,处理器内核
  4. vip2-day22 MySQL 基础语句
  5. 根据关键词取商品列表API 返回值说明
  6. 剧白白 v3.1.1 修改版 (强大的最新影视在线平台)
  7. 关于Value ‘0000-00-00 00:00:00‘ can not be represented as java.sql.Timestamp错误
  8. ViewPager(六)让ViewPager用起来更顺滑——设置间距与添加转场动画
  9. 折腾黑苹果把win10的引导给弄没了 花了几小时找回
  10. python编码使用ascii编码_Python中的编码问题:ASCII码 Unicoden编码 UTF-8编码