jvm_0_JVM运行机制

 

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 脑图:



 


 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值