运行时数据区域
程序计数器:
1.为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储,我们称这一类存储区域为“线程私有”内存。
2.如果线程正在执行的是java方法,这个计数器记录的是正在执行的虚拟机季节吗指令的地址;如果正在执行的是Native方法,这个计数器值则为空。此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
虚拟机栈:
经常有人把Java内存区分为堆内存和栈内存。栈内存就是虚拟机栈,或者说是虚拟机栈中局部变量部分。
局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。
本地方法栈:
本地方法栈和虚拟机栈所发挥的作用是类似的,它们之间的区别不过是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则为虚拟机使用的Native方法服务。
Java堆:
Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。
方法区:
方法区与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。
运行时常量池:
运行时常量池是方法区的一部分。Class文件中除了有类的版本,字段,方法,接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用。
垃圾收集器:Serial收集器,ParNew收集器等。
类文件结构
整个Class文件本质上就是一张表

虚拟机类加载机制
在java语言里面,类型的加载,连接和初始化过程都是在程序运行期间完成的。
类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载,验证,准备,解析,初始化,使用和卸载7个阶段。其中验证,准备,解析3个部分统称为连接,这7个阶段的发生顺序
加载 - 验证 - 准备 - 解析 - 初始化 - 使用 - 卸载
通过其子类来引用父类中定义的静态字段,只会触发父类的初始化而不会触发子类的初始化。
加载:
1.通过一个类的全限定名来获取定义此类的二进制字节流
2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
3.在内存中生成一个代表这个类的java.lang.class对象,作为方法区这个类的各种数据的访问入口。
加载阶段与连接阶段的部分内容(如一部分字节码文件格式验证动作)是交叉进行的,但开始时间仍保持固定的先后顺序。
验证:
文件格式验证:保证输入的字节流能正确地解析并存储于方法区之内
元数据验证:继承关系的验证
字节码验证:相关语法验证
符号引用验证:对引用匹配性的验证
准备:
准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配。
首先,这时候进行内存分配的仅包括类变量(被static修饰的变量),而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在java堆中。
其次,这里所说的初始值“通常情况”下是数据类型的零值。
解析:
解析阶段是虚拟机将常量池内符号引用替换为直接引用的过程。
解析动作主要针对类或接口,字段,类方法,接口方法,方法类型,方法句柄和调用点限定符7类符号引用进行。
初始化:
到了初始化阶段,才真正开始执行类中定义的Java程序代码(或者说字节码)。
类加载器
虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到java虚拟机外部去实现,以便让应用程序自己决定如何获取所需要的类,实现这个动作的代码模块成为“类加载器”。
tomcat的类加载架构:
放置在 /common 目录中:类库可被 Tomcat 和所有的Web应用程序共同使用。
放置在 /server 目录中:类库可被 Tomcat使用,对所有的web应用程序不可见。
放置在 /shared 目录中:类库可被所有的web应用程序共同使用,但是对Tomcat自己不可见。
放置在 /webApp/WEB-INF 目录中:类库仅仅可以被此web应用程序使用,对Tomcat和其他的Web应用程序不可见。

OSGI:(open service gateway initiative)
在OSGI里面,是平级模块之间的依赖。一个模块里只有被Export过的Package才可能由外界访问,其他的Package 和Class将会隐藏起来。
基于OSGI的程序很可能可以实现模块级的热插拔功能,当程序升级更新或调试出错时,可以只停用,重新安装然后启用程序的其中一部分,这对企业级程序开发来说是一个非常有
诱惑力的特性。
主内存和工作内存
Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。此处的变量与Java编程中所说的变量有区别,它包括了实例字段,静态字段和构成数组对象的元素,但是不包括局部变量与方法参数,因为后者是线程私有的,不会被共享,自然就不会存在竞争的问题。
Java内存模型规定了所有的变量都存储在主内存中,但此处仅是虚拟机内存的一部分。

内存间交互操作:
lock(锁定): 作用于主内存变量
unlock(解锁): 作用于主内存变量
read(读取): 作用于主内存变量,从主内存传输到线程的工作内存中
load(载入): 作用于工作区内存变量,将从主内存中获得的变量值存入到工作内存中
use(使用): 作用于工作区内存变量,把工作内存中的变量的值传递给执行引擎
assign(赋值): 作用于工作区内存变量,执行引擎得到的值赋值到工作内存的变量
store(存储): 作用于工作区内存变量,将工作内存中的变量的值传递到主内存中
write(写入): 作用于主内存变量,将从工作内存中传过来的变量存放到主内存变量中