Java内存模型,是指多线程并发时,将内存分为主内存和工作内存,每条线程运行时拥有自己的内存区域。
Java内存模型主要从三个特性进行解释。
一是原子性,线程工作时,一共八个原子操作,保证了原子性。工作时会从主内存中载入(复制)数据,执行的原子操作为read,load,将数据调入CPU运算,执行的原子操作为use,运算完毕从CPU返回工作内存,执行的原子操作为assign,然后从工作内存写回主内存,执行原子操作为store,write。其中read,load和store,write操作具有不可分割性,即每两个之间具有连续性。
剩下两个为Lock,和unLock原子操作,用于实现线程安全的访问,这两个操作是synchronized关键词的“底层实现”。
二是可见性,具体实现为volatile关键字.(并不保证原子性)
三是有序性,具体实现为先行发生原则
JVM类加载机制
概述:JVM要想执行class文件,首先会将文件载入虚拟机的方法区内,根据类文件的格式相应的存放数据。在需要产生对象时,从方法区中获取对应的类信息,在堆中建立对象。
1. 类文件格式:
魔数:一般为cafebabe,用于判断该文件是否能被JVM执行
版本号:包括主次版本号,说明能兼容的JDK版本号。
常量池:包含各种类型的常量,常见的有constant-utf8(String,int,float…)等等。每种常量又有其各自的数据结构(格式)。
访问标志:说明类的修饰符,如是否是public,final的。是否是注解,枚举类等等。
类索引,父类索引及接口索引:存放着this,super,及实现接口的索引。
字段表:包含字段的类型,如为static,final等修饰,其后往往跟着一个属性表
方法表:包含返回值类型,参数类型,其后也往往跟着属性表,其中的Code属性里存着方法里的代码。
属性表:往往用于修饰字段表和方法表。
2. 类加载过程:
载入:不一定从class文件中加载,如也可以从jar包里加载
校验:验证类文件格式是否正确,如魔数值,版本号是否匹配当前执行的虚拟机
准备:对于静态修饰的字段在此进行第一步初始化,如static a=1;
会先将a初始化为0;
解析:这一步不一定在初始化之前执行
初始化:对字段进行初始化,如前面的a,在此阶段会被赋值为1