Android JVM你应该知道的一些知识。

JVM内存分配

JVM内存划分,首先从线程上划分两部分 

线程私有部分

程序计数器,虚拟机栈,本地方法栈

特点 :不需要垃圾回收,线程结束自动结束。

线程共享部分

方法区,堆区 

 特点 :需要进行GC回收,

GC算法(判断那些对象要被回收)

根搜索可达性算法,根据根去搜索,如果没有被根这条线上对象引用的对象,就代表可以回收。

GCRoot对象

静态属性引用的对象,常量引用的对象,虚拟机栈引用的对象,本地方法栈引用的对象

——————————————————————————————————————

线程私有的意思,每个线程对应一个程序计数器,虚拟机栈,本地方法栈。N多个线程对应N多个这些。

程序计数器

程序计数器的作用: 程序计数器指向的是下一条指令的地址,防止线程切换执行出错。

 public static  void  main(){
      1,  Person person =new Person();
      2, personProxy.say("吃饭啦");
    }

javaC把java文件转换成.class文件,每一行都会转换成对应的一条二进制指令(二进制命令我就不上了),程序计数器指的就是前边的1,当执行当前指令,程序计数器+1,下次程序计数器就变成了2,程序计数器也就是指示我们当前命令执行到那一步了。当前线程失去执行权利,在拿到执行权利的时候,就可以通过程序计数器来保证程序不会错乱。

 

虚拟机栈

栈的结构,先进后出,如果超过栈允许的最大深度,就会抛出异常StackOverflowError(一般递归会发生)

虚拟机栈的作用:执行Java方法,每一个java方法执行都会产生一个栈帧。

栈帧

局部变量表 :方法使用的局部变量,第一个存的是当前对象This。

操作数栈  

动态链接 :连接常量池的一些信息

返回地址 :  方法返回地址

详细的请观看此篇文章Java —— 运行时栈帧结构,非常细。

本地方法栈

本地方法栈和虚拟机栈差不多,不过执行的都是native方法。

————————————————————————————————

方法区

静态变量

静态常量

java类元信息 java.class文件 (就是这个类里边所有的方法和变量,常量信息)

堆区

存储实例对象。

堆分为 新生代(1/3),老年代(2/3),永久代(1.8以上是元空间,元空间可以直接使用物理内存地址,不在占用虚拟机内存)

新生代

分为Eden(8)S1(1)S2(1);

Eden 区

刚创建的对象一般都放在Eden区,除非特别大直接放入老年区。

s1区s2区

这两个比例是一比一,当GC首先从Eden区扫过 ,存活的对象就会放到S区

老年代

当S区的对象每经过一次GC的时候年龄就会+1,超过15就会进入老年代

GC回收算法

 

新生代 

主要是复制算法

老年代

标记清除和标记整理 结合

复制法

主要发生在新生代,s1对里面经过可达性算法,复制一份copy到S2区,然后回收s1的所有内存,这样就做到了垃圾回收,s1和s2这两个区就是用复制法回收内存的。

标记清除法

标记需要回收的内存,直接清除,这样有个弊端,会导致大量的内存碎片,比如说 1 ,2,3,4,5对象,回收了2 和4 

标记整理法 

标记清除之后,把内存整理出来,消除内存碎片。

你可能感兴趣的:(Android,高级)