运行机制"/>
第二课:jvm运行机制
1.启动流程
java + 类-->装载配置(config文件)-->根据配置找到java.dll(为java虚拟机的主要实现)-->初始化java虚拟机(比如JNIEnv接口,findclass等操作可以通过这个接口来实现)-->找到main方法
2.如图1所示:jvm的内部结构
几个重要的组成部分:
pc寄存器:1.每个线层又有一个pc寄存器2.在线程创建时 创建3.指向下一条指令的地址4.执行本地方法时,pc的值为undefined
方法区:保存类的原信息 (类型的常量池/字段、方法信息/方法字节码)在jdk6和7中,String等常量信息置于方法,jdk7时,已经移动到了堆通常和永久区(perm)关联在一起
java堆:所有通多new操作出来的对象,都是通过堆来操作的--和程序开发密切相关--应用系统对象都保存在java堆中--所有线程共享java堆--一般是对分代GC来说,堆也是分代的(不同的gc方法需要不同的堆)--GC的主要工作区间eden--s0--s1--tenured(复制算法)
java栈:-线程私有-栈由一系列的帧组成(因此Java栈也叫做帧栈)-帧保存一个方法的局部变量、操作数栈、常量池指针-每一次方法调用创建一个帧,并压栈
3.JVM栈很重要的一个局部变量表 基本结构 (包含参数和局部变量)
public class StackDemo{public static int runStatic(int i,long l,float f,Object O,byte b){return 0;}public int runInstance(char c,short s,boolean b){return 0;}}
想想成每一个都是32位的一个小格子一个槽位 long是64位占俩
静态方法如下:
0 int int i
1 long long l
2 *1
3 float float f
4 reference Object o
5 int byte b
实例方法如下:
0 reference this
1 int char c
2 int short s
3 int boolean b
4. java栈 操作数栈
-java没有寄存器 所有参数传递使用操作数栈
public static int add(int a,int b){int c = 0;c = a+b;return c;}
当执行上面程序帧栈的的操作工程
0 iconst_0 // 0压栈
1 istore_2 // 弹出int,存放于局部变量2
2 iload_0 // 把局部变量0压栈
3 iload_1 // 局部变量1压栈
4 iadd // 弹出两个变量,求和,结果压栈
5 istore_2 // 弹出结果,存放局部变量2
6 iload_2 // 局部变量2压栈
7 ireturn //返回
5. Java栈的分配(优化手段)
-小对象(几十个bytes),在没有逃逸的情况下,可以直接分配在栈上
-直接分配在栈上,可以自动回收,减少GC压力(是指,这个栈没有了,那我就没有必要再去进行垃圾回收了)
-大对象或者逃逸对象无法栈上分配
解释:一般来说一个栈最大几百kb,1M顶天了,所以大对象,是没有办法在栈上进行分配的。当有小对象时,当一个方法分配在栈上,执行完成之后,这些小对象随着方法的消亡而消亡,所以可以直接分派到栈上。
这里还有一个逃逸对象的概念,是指,我并不止一个线程中要用到这个对象,我在其他的线程中,也用到这个对象,所以这个对象是在栈尚无法进行分配的。
6.图2:堆、栈、方法去之间的交互
public class AddMain{// AddMain的所有信息都在方法区,包括main方法public static void main(String ){//new出来的sample对象在堆里面,test1和test2 都是sample的对象的引用,在栈里面Sample test1 = new Sample("测试1");Sample test2 = new Sample("测试2");test1.printName();test2.printName();}public class Sample{//Sample的所有信息都是在i方法区内private name;//name 的对象在堆里面,name的引用在栈里面public Sample(name){this.name = name;}//println方法也在方法区内部public class printName{System.Out.println(name);}
}
7.图三 :关于线程
-每一个线程都有一个工作内存和主存,主存是一个共享的内存区间(可以理解成堆空间,所有线程都共享,所有线程都可以在里面存储数据)
-工作内存存放主存中变量的值的拷贝
图三解释:当数据从主存复制到工作内存时,必须出现两个动作:第一由主存执行的read操作,第二,由工作内存执行的相应的load操作;当数据从工作内存拷贝到主存时,也出现两个操作,一个是由工作内存存储到主存的store操作,第二,由主存执行的相应的write操作每一个操作都是原子的,即执行期间不会被中断 但是read和load之间是可以被中断的对于普通变量,一个线程中更新的值,可能无法立即加载到主存中,也就无法被其他反应在其他变量中如果需要其他线程立即可见,需要使用volatile关键字
8.volatile关键字
public class VolatileStopThread extends Thread{private volatile boolean stop = false;public void stopMe(){stop = true ;}public void run(){int i = 0 ;while(!stop)i++}System.out..println("stop Thread");}public static void main(String args[]) throws InterruptException{VolatileStopThread t = new VolatileStopThread();t.start();Thread.sleep(1000);t.stopMe();Thread.sleep(1000);}}
volatile不能代替锁(线程不安全的)
一般认为volatile比锁的性能要好(不绝对)
选择使用volatile的条件是:
语义是否满足应用
如果这个里面没有volatile这个关键字的话,这个VolatileStopThread只在自己的工作内存当中查找这个stop的值,因此永远也不会停止
9.内存模型可见的概念
1.可见性
可见性是指在我修改了线程的值的时候,其他的线程能够立即知道(这里说的不是能够知道,是立即知道)能够实现可见性的几种方法1.volatile 2.synchronized(unlock之前,写变量值回主存)线程间的同步,这个词就是同步3.final(一旦初始化完成,其他线程就可见,常量)
2.有序性。(在一个线程当中,所有的指令,所有的操作都是有序执行的)
但是在另一个线程当中,去观察本线程,也许就是无序的(两种可能,第一种就是指令重排,第二种就是与主存存在同步延时)
指令重排:在编译器中,会自动重排一些语句,比如a=1,b=2。在编译器的理解下,它不考虑语句的语义,如果他认为这是可以重排的,那么就会发生指令重排。但是如果a=1,b=a 这个就不可以发生指令重排
指令重排的一个例子:
public class OrderExample{int a = 0 ;boolean flag = false ;
public void writer(){a = 1;flag = true ; }public void reader(){if (flag){int i = a + 1;...}
}
}
解释上述代码:
线程A首先执行write()方法线程B接着执行reader()方法线程B在 int i = a+1是不一定能看到a已经被赋值给1的,因为在write中,两句话的顺序可能会被打乱 (这个时候就体现了操作重排了)这个时候,两个方法都是同一个操作级别的,当你的flag = true时,这个时候reader就进来了,把flag取走了那么在执行的时候,最后的结果是多少呢 线程A: 线程B:flag = true flag = true(此时a = 0) a = 1 但是我想保证他的有序性,因为有时候是必要的,那我应该怎么做呢:我就可以在两个方法都加上synchronized关键字,加上suynchronized关键字之后,即使A线程出现了指令重排,但是线程B是进不来的,所以是要把一个线程运行完成之后,直到把线程锁释放,才能够运行下一个。不再是平行运行,而是属于一个串行了。
指令重排基本原则:
-程序顺序原则:一个程序内保证语义的串行性
-volatile规则:volatile变量的写,先发生于读
-锁规则:解锁(unlock)必然发生在所后的加锁(lock)前
-传递性:A先于B,B先于C,那么A必然先于C
-线程的 start方法先于它的每一个动作
-线程的所有操作电鱼线程的中介(Thread.join())
-线程的中断(interrupt())先于被中断线程的代码
-对象的构造函数执行结束先于finalize()方法
10.解释执行和编译执行的区别
解释执行:
-解释执行以解释的方式运行字节码-解释执行的意思是:读一句,执行一句
编译执行:
-将字节码编译成机器码
-直接执行机器码
-运行时编译
-编译后性能有数量级的提升(10倍以上)
更多推荐
第二课:jvm运行机制
发布评论