安卓开发必备JVM知识点
Java 跨平台
不同平台JVM 来实现跨平台。JVM 跟语言无关,比如随便定义一个XXX 满足JVM规范转编写,最后按XXX定义规范换为class就可以,按照oricle公司的文档去写,提交给Oracle 自己取的名字就是一个新的虚拟机。
常见虚拟机
常见 IBM(J9) Oracle(Hotspot) Zing(C4垃圾算法,垃圾回收时间停顿1ms, 收费的) TaobaoVM
运行时数据区
JVM在程序执行过程会把它管理的内存划分为若干个不同数据区域,注意这个分区划分是一个虚拟的区域。
线程共享区
1、方法区(hotspot的才叫永久代,元空间 实现了方法区,在JVM规范中其实是只有方法区)
2、堆
我们创建对象分配基本都在这个区间上
线程私有区
3、JVM栈
4、程序计数器
指向当前执行代码的行号,因为多线程,时间片轮转,可能会出现挂起,需要记录(唯一不会出现OOM 因为 它不用 记录全局的执行代码行数只管理栈顶的方法的执行而且记录的是行号)
5、 Native 栈
其实还有一块区域: 直接内存(上面的都是JVM虚拟化的) unsafe类
虚拟机栈
栈中存放的栈帧 一般的是1024KB ,取决平台比如常见的Linux 64位的 1024 32位的320KB, -Xss. (如何获取,如何OOM? stackoverflowererror)
思考: 我们常说的 创建一个线程大概要1M内存,就是因为每个线程单独具有单独的虚拟机栈,如果是64位的就是1M。比如500个线程,就是500M。如果厂商定制,可以使用 - Xss256K
栈帧结构
方法A:
int a = 1;
int b =2;
int c= a+b;
上面的.java文件经过javac编译后,我们 使用javap -c A.class反编译,可以看到如下代码
public class com.android.projects.mymvp.A {
public com.android.projects.mymvp.A();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static int add();
Code:
0: iconst_1
1: istore_0
2: iconst_2
3: istore_1
4: iload_0
5: iload_1
6: iadd
7: istore_2
8: iload_2
9: ireturn
}
首先寄存器记录的就是上面的行号。0-9 ,然后看
0: iconst_1
操作数栈定义一个常量 1
1: istore_0
把 1压入到局部变量表中索引为0的位置
4.iload_0
把局部变量表中下标为0的数压入到操作数栈
5.iload_1
把局部变量表中下标为1的数压入到操作数栈
6: iadd
再把操作数栈中的数相加
7: istore_2
把结果存储到局部变量表中索引为2的位置
8: iload_2
再把局部变量表中索引2的数加到操作数栈
9: ireturn
返回结果,返回的是操作数栈中的值,如果返回void,操作数栈中没东西,也就没有第8行代码
1.局部变量表
按上面的描述,局部变量表存的就是值
2.操作数栈
存储的是要计算的值
3.动态链接
与多态相关的,晚期绑定
4.完成出口
比如A方法第3行字节码执行调用B方法,那么B方法的栈帧的完成出口就记录了3 当B方法执行完,就回到A的3执行4
对象
划分内存的方式,根据内存是否规整,有两种方式
指针碰撞
空闲列表
对象头
Markword :hash 、GC分代年龄 、锁状态、线程持有的锁、偏向ID、偏向时间戳
类型指针: 表明自己是哪个类创建的
数组相关:如果是数组还要记录数组长度数据