0 虚拟机:
a) 概念: 通过软件模拟具有完整硬件系统功能,并运行在一个完整隔离环境中的完整计算机系统
b) 有哪些虚拟机:
vmware,visual box: 此两者都是使用软件模拟物理CPU的指令集(即模拟的东西都是现实存在的,
eg: cpu. 硬盘 )
jvm: 特点是使用软件模拟java字节码的指令集
jvm: 主要定义了 二进制class文件 和 JVM指令集,仅仅是一个规范 一份文档,任何组织都可以根据这份规范做自己的实现。
java语言和jvm关系:两者相互独立的关系
1 JVM启动流程
2 JVM基本结构
2.1 PC寄存器(program counter,即程序计数器)
a) 每个线程拥有一个PC寄存器
b) 在每个线程创建时 创建对应的PC寄存器
c) PC寄存器的内容指向下一条指令的地址
d) 执行本地方法时,PC的值为undefined
2.2 方法区
a) 保存装载的类的信息( 1类的常量池 2字段,方法信息 3方法字节码)
2.3 堆
a) 和程序开发密切相关
b) 应用系统对象都保存在java堆中
c) 所有线程共享java堆
2.3 栈
a) 线程私有
b) 栈由一系列帧组成(java栈也叫做帧栈)
c) 帧保存一个方法的局部变量,操作数栈,常量池指针,操作数栈,返回地址等
d) 每一次方法调用创建一个帧,并压栈
看下图,理解下静态方法和非静态方法下栈内数据:
看下面递归调用下栈流程:
备注:
每一次方法调用,就会创建一个帧,添加到栈中,一直加到方法执行完毕或者帧栈满了(出现溢出)
如果方法调用结束,那么此方法对应的帧在栈中移除掉。
java没有寄存器这个概念,那么在参数传递的时候,依靠的是栈,也只能依靠栈。
下面看操作数依靠栈下操作流程:
public static int add(int a, int b) { int c = 0; c = a + b; return c; }
看如下堆和栈的案例:
/** * 测试小对象创建下 jvm默认使用策略 * 1 运行时,使用参数 * -server -Xmx10m -Xms10m -XX:+DoEscapeAnalysis -XX:+PrintGC 直接打印出耗时 * 2 运势时,使用参数 * -server -Xmx10m -Xms10m -XX:-DoEscapeAnalysis -XX:+PrintGC 打印结果如下: [GC 3424K->160K(10176K), 0.0001908 secs] gc回收耗时 0.0001908 secs [GC 3424K->160K(10176K), 0.0001868 secs] 原来3424K大小缩减成160K,目前对内存为10176K [GC 3424K->160K(10176K), 0.0001891 secs] .... 参数表示 在小对象并有逃逸情况下,jvm会把对象创建(byte[] b = new byte[2];)放在堆上,并且因为内存不够造成不断 使用GC来回收历史操作消耗的内存 测试结论: a) 小对象,(一般几十bytes),创建时,在没有逃逸情况下,直接分配到栈上,随时用,用完在栈中随时回收,提高效率 b) 大对象或者逃逸对象则无法在栈上创建 * */ public class test2 { public static void main(String[] args) { long begin = System.currentTimeMillis(); for(int i=0; i<100000000; i++){ alloc(); } long end = System.currentTimeMillis(); System.out.println(end - begin); } public static void alloc(){ byte[] b = new byte[2]; b[0] = 1; } }
2.5 栈,堆,方法区交互:
public class appMain{ public static void main(String[] args) { Sample test1 = new Sample("测试1"); test1.printName(); } } class Sample{ private String name; public Sample(String name){ this.name = name; } public void printName(){ System.out.println(name); } }
JVM 参数中,栈 堆 方法区, 相互之间关系:
栈对象指向堆中产生的内存区域,对象的方法则放在方法区中,由堆来引用
3 线程内存模型
a) 每一个线程都有自己的工作内存和主存。
b) 工作内存中存放主存中变量值的拷贝
c) 线程中更新的值是不能马上反应在其他线程中的,他们操作的都是各自的工作内存,然后在将各自的工作内存更新到主存中(这个更新会耗时造成时差,如果想让线程的更新立刻通知到别的线程知道,使用volatile)
4 线程可见性:
基于3中线程从工作内存同步数据变化到主内存(共享内存) 会有延迟,为了规避这种延迟,使用如下方式保证
线程之间数据变化的可见性(线程修改了变量,别的线程立马就知道)
a) volatile
b) synchronized(unlock之前,写变量值回主存)
c) final(一旦初始化完成,其他线程就可见)
5 线程有序性:
a) 本线程内,操作都是有序
b) 线程外观察,操作都是无序
4 编译和解释运行的概念
解释运行
解释执行以解释方式运行字节码
解释执行的意思是:读一句执行一句
编译运行(JIT)
将字节码编译成机器码
直接执行机器码
运行时编译
编译后性能有数量级的提升(保守估计会比解释运行效率高10辈)
5 脑图: