[关闭]
@whosea 2017-12-18T06:12:28.000000Z 字数 1238 阅读 1462

Java虚拟机内存分配——Andfix热修复替换方法内存解析

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替换方法时内存的情况,正所谓不深不浅,恰是新知,哈哈。

为了更清晰的了解内存情况,我用一段代码来分析:

  1. public static void main(String[] args) {
  2. Cat mCat = new Cat();
  3. mCat.call();
  4. }

代码很简单,但内涵丰富哟。
该图显示运行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.至此就完成了热修复的操作

参考文章

Java内存分配
浅析JVM内存区域

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注