@whosea
2017-12-18T06:12:28.000000Z
字数 1238
阅读 1462
Android热修复
java虚拟机内存
原文链接:https://www.zybuluo.com/whosea/note/931644
该章节只是对上一篇文章遗留下的问题(Andfix在替换方法时内存是什么一种情况)做稍微深入一下的分析,好让看官有个图形在脑海里。
java虚拟机内存分配参考了这两篇文章《Java内存分配》《浅析JVM内存区域》(最后有链接,想更详细的了解可以先看看这两篇文章),这里只是大致说下各个区域的作用,然后再结合上一篇的demo做分析。
以下图片是取自《浅析JVM内存区域》
JVM初始运行的时候都会分配好Method Area(方法区)和Heap(堆),也是给线程共享的。
而JVM 每遇到一个线程,就为其分配一个Program Counter Register(程序计数器), VM Stack(虚拟机栈)和Native Method Stack (本地方法栈),这三块区域是线程私有的,
当线程终止时,三者(虚拟机栈,本地方法栈和程序计数器)所占用的内存空间也会被释放掉。
方法区与堆这两块区域的内存清理通过垃圾收集器来回收。
接下来开始探索一下Andfix替换方法时内存的情况,正所谓不深不浅,恰是新知,哈哈。
为了更清晰的了解内存情况,我用一段代码来分析:
public static void main(String[] args) {
Cat mCat = new Cat();
mCat.call();
}
代码很简单,但内涵丰富哟。
该图显示运行main后的内存场景:
1.在运行main方法之前,JVM会加载方法所属的Class文件,把Class文件的数据(每个方法的局部变量、操作数栈)放进方法区。
2.运行main方法,根据方法区main Class中的局部变量区和操作数栈的大小来分配一个新的栈帧的内存大小,并压入栈。
3.代码解析到Cat mCat
时,首先加载Cat class字节码到方法区中,然后在本地变量表会存在一个Cat的指针类型的数据。
4.接着new Cat()
会在堆中存在一个Cat的实例数据,并且被栈中的mCat变量引用。
5.堆里的Cat对象的类又会保存指向方法区中Cat类的指针。
6和7.mCat.call()
调用call时,会根据方法区中Cat类的数据分配一个新的栈帧内存大小,并且压入栈中。至此该代码在内存里大致的情况已描述完。
该图是替换方法后的场景:
1.点击修复时候,会在方法表里面把新Cat类方法表里面的call ArtMethod对象里面的数据都赋值给错误Cat类方法表里面的call ArtMethod对象。
2.那么下次在重新运行main方法时,执行情景跟上面的一样,但是走到第6和7步时候,调用call时,会去Cat类的方法表里面获取call的数据,并且分配一个新的栈帧内存大小,因为前面做了替换操作,从而去加载新Cat方法表里面的call方法。
3.至此就完成了热修复的操作