1.所有线程共享的内存区域: 方法区 + java堆
a)方法区中 存放着: 类型信息, 类(静态)变量,字节码。
方法区大小不必固定,虚拟机可以根据应用的需要动态调整;也不必连续,可以在堆(甚至是JVM自己的堆)中自由分配
用户或者程序员 可以 设置 方法区的初始大小、最小/最大尺寸等!
方法区也可以被垃圾收集。
方法区中保存的信息,可以通过反射API访问。
类型信息:
i)基本类型信息:访问权限信息,全部 的 类型/接口 信息等。
1)这个类型的全限定名
2)直接超类全限定名(java.lang.Object除外)
3)这个类型是 类类型 还是 接口类型
4)类型的 访问修饰符 (public、abstract或final的某个子集)
5)任何直接超接口的全限定名的 有序列表。
ii)其他类型信息。
1)该类型的 常量池
2)字段信息
3)方法信息
4)类变量(除常量外---常量在编译时,被编译器处理替换,也称为 编译时常量)
5)一个到类ClassLoader引用
6)一个到Class类的引用
b)java堆:一个Java虚拟机实例只存在一个堆空间,因此所有线程将共享这个堆。同时,每个Java程序独占一个Java虚拟机实例。
2.线程私有的区域: Java栈 + PC程序计数器。
多线程访问同一个类的情况,如果该类还没有被装入虚拟机,那么,这时只应该有一个线程去装载它,而另一个线程则只能等待。
Java栈:
栈帧 由3部分组成:局部变量区,操作数栈 和 帧数据区
1)局部变量区 被组织为一个以字长为单位、从0开始计数的数组。
类型为 int、float、reference、returnAddress的值在数组中只占据一项。
而类型为byte、short和char的值在存入数组前都将被转换为int值,因而同样占据一项。
当这3种类型的数据被存回堆或方法区时,才会转换回原来的类型。
虚拟机并不直接支持boolean类型,因此java编译器总是用int来表示boolean.
2)操作数栈 问:在程序中的局部变量,声明并赋值时(int i = 0;) 变量i 是在哪里分配的空间呢?——答:
在该语句所在的方法的操作数栈中 分配空间存储的。??(存疑!)
3) 帧数据区 保存 支持常量池解析的数据、正常方法返回以及异常派发机制、用于调试的数据等。
3.类装载器子系统(class loader):主要作用有 动态化 和 类隔离。
1)启动类装载器(BootStrap Class Loader)
2)扩展类装载器(Extension Class Loader)
3)系统类装载器(System Class Loader/ AppClassLoader)
4)用户自定义类装载器(User-Defined Class Loader)
命名空间:每个类装载器都有自己的命名空间,其中维护着由它装载的类型。
4.常量池解析:把常量池中的符号引用(字符串) 替换为 直接引用(指针)。
5.
执行引擎: 指令集 定义执行引擎的行为
1)运行中的Java程序的每一个线程都是一个独立的虚拟机执行引擎的实例。
2)Java虚拟机指令集关注的中心是操作数栈。
3)指令集实际的工作方式就是把局部变量当作寄存器,用索引来访问。
4)指令集的设计遵循几个不同的目标:平台无关性、网络移动性以及安全性。
i.平台无关性 是影响指令集设计的最大因素。指令集的这种以栈为中心、而非以寄存器为中心的设计方法,使得在那些只有很少的寄存器,或者寄存器很没有规律的机器上实现Java更便利(Intel 80X86)。
ii.Java以栈为中心设计指令集的另一个动机是,编译器一般采用以栈为基础的结构向连接器或优化器传递编译的中间结果。
iii.指导指令集设计的另一个目标就是 进行字节码验证的能力,特别是使用数据流分析器进行的一次性验证。
6.本地方法: