Android 开发需要了解的虚拟机知识

Dalvik 和 ART

参看 快速理清 .dex、.odex、ART、AOT、OAT 逻辑关系

Java 内存结构和内存模型

参考 Java 内存基本知识

这里对 Java 内存模型做个简单的理解:

因为 CPU 存在多级缓存(详见 Java 锁机制详解(二)volatile 开头部分),导致多线程情况下存在内存可见性问题。

计算机内存可见性

Java 则据此在多线程环境下做了抽象:

Java内存可见性

并提供了 volatilesynchronizedfinal 等关键字,concurren 包、以及一系列规则等以解决此类问题。此外,指令重排等计算机内存的潜在隐患也同样做了抽象、处理。

所以,我们将此处 Java 抽象模型以及关键字等统一称为内存模型。即 Java 内存模型定义了 JVM 在计算机内存的工作方式。

垃圾回收策略

GC 主要针对 JVM 堆和方法区进行垃圾回收,因为这部分内存的动态分配和回收的。

垃圾识别策略

1、引用计数法

原理:给对象添加一个引用计数器,当计数器为 0 时说明没有引用,则对象可被回收。
缺点:无法解决循环引用。

2、可达性分析法

原理:从 GC Roots 创建一条到对象的引用链,当一个对象到 GC Roots 没有任何引用链时,视为对象可回收。

GC 会收集那些不是 GC Roots 且没有被 GC Roots 引用的对象。那么谁可作为 GC Roots 对象呢?总结来说就是:

当前肯定不会被回收的对象都可以作为 GC Roots。

如类的静态变量所引用的对象当前肯定不会被回收,那它即可作为它所引用对象的 GC Roots。

关于 GC Roots 的问题可以参考 知乎大神 的回答(或者直接看下边),很有启发。

问:为什么它们可以作为 GC roots?
答:因为这些东西被认为是在被使用。JVM 设计者命令 JVM 将他们作为 GC Roots 。

问:到底 GC Roots 是什么?
答:GC Roots 是一个统称,是所有可以用作"根集可达性算法"中的根。

问:它们存放在哪里?
答:GC Roots 本身是没有所谓的存储位置,他们都是字节码加载运行过程中加入 JVM 中的一些普通对象,只不过被认为是 GC Roots。

问:GC Roots 是引用还是对象?
答:引用就是对象,因为对于 Java 语言(非字节码)来说单独的引用(没有指向对象的引用)没有意义。

问:GC Roots 是放在堆里的还是方法栈还是哪个地方?
答:都有,只要他被认为是被使用的,但堆中开辟的对象都是在其他位置有一个引用的。

问:虚拟机会回收 GC Roots 吗?
答:不会但不保证绝对不会,因为 JVM 有几十种,无法保证以后会不会加入回收 GC Roots 的机制,但就 HotSpot 而言是不会的。

内存回收算法

1、标记清除算法

原理:在标记阶段给所有的活动对象打上标记,在回收阶段将没有标记的对象(即垃圾对象)回收。
缺点:内存碎片化严重,也正因为碎片化严重,导致内存再分配效率低。

2、复制算法

原理:将可用内存按容量划分为大小相等的两块,每次只使用其中一块。当一块的内存用完了,就将存活的对象复制到另一块上,然后再把已使用的内存一次清理掉。
优势:每次都对整个半区进行回收,解决碎片化问题,再分配效率高。
缺点:内存损失一半,代价太高。

3、分代回收算法

原理:将内存去分为新生代和老年代俩个区。新生代因为回收频繁,使用复制算法提高效率。老年代因为存活率高,使用标记清除算法节省内存。
优势:兼顾时间(效率)和空间(内存)的综合选择。

类的加载

加载过程

虚拟机把 Class 文件加载到内存,并完成链接和初始化,最终形成可被虚拟机直接使用的 Java 类型的过程叫做类的加载。

JVM 不是一开始就把所有的类都加载进内存中,只有第一次运行类时才会加载,且只加载一次。

题外话:Android 应用启动时有个 dexElements 数组,包含了所有 .dex 文件地址,ClassLoader 会遍历该数组查找要加载的类。也就是说可以通过修改 dexElements 数组以替换 JVM 加载的类文件,以实现热修复。

类的加载过程可以分为如下几步:

1、加载

通过类加载器(ClassLoader),将 Class 文件从各个来源加载到内存中。

ClassLoader

既然说到了 ClassLoader,那这里就简单解析下。

ClassLoader 类加载原理 -- 双亲委托

关于 Android 的双亲委托,可以参考 热修复原理与基础范例

简单来说,就是 ClassLoader 向上委托,向下查找,找到立即返回。

ClassLoader 实现类

Java 的 ClassLoader.

类名 用途
BootstrapClassLoader 顶层的加载类,主要加载核心类库,%JRE_HOME%\lib 下 的rt.jar、resources.jar、charsets.jar 和 class 等。
ExtentionClassLoader 扩展的类加载器,加载目录 %JRE_HOME%\lib\ext 目录下的 jar 包和 class 文件。还可以加载 -D java.ext.dirs 选项指定的目录。
AppclassLoader 加载当前应用的 classpath 的所有类。

Android 的 ClassLoader.

类名 用途
BootClassLoader 通常用来预加载一些 Java 常用的类;
PathClassLoader 通常用于加载系统类和应用程序的类(就是你的 apk,它可以从你的 apk 中解析出 class 对象),其中 optimizedDirectory 为null, 默认目录 /data/dalvik-cache/。
DexClassLoader 可以加载外部 dex 文件以及包含 dex 的压缩文件(apk 和 jar)。

ClassLoader 常用参数

参数名 用途
dexPath 包含目标类或资源的 apk/jar 列表,多个路径采用 : 分割
optimizedDirectory 优化后的 dex 文件输出的目录,可为 null
libraryPath native 库所在路径列表,多个路径采用 : 分割
classLoader 父类加载器

更多 ClassLoader 相关内容可参考此 链接

2、链接

链接又可以分为三个过程,分别是 验证、准备、解析。

2.1、验证

保证加载进来的字节流符合虚拟机规范,不会造成安全错误。

2.2、准备

给静态变量分配内存,并根据数据类型赋默认值。(如 int 类型则赋值 0.)

2.3、解析

把常量池内的符号引用替换为直接引用。

因为我们写代码时自定义的方法名、类名等虚拟机是无法识别的,所以会被虚拟机替换为对应的内存地址,也就是直接引用。

3、初始化

执行类的构造器进行初始化。

类的初始化顺序

既然说到了,就简单总结下类的初始化顺序。

父类--静态变量
父类--静态初始化块
子类--静态变量
子类--静态初始化块
父类--成员变量
父类--初始化块
父类--构造器
子类--成员变量
子类--初始化块
子类--构造器

总结

Android 开发需要了解的虚拟机知识就到这儿,后续有的话会继续补充。

[TOC]

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349