1.JVM组成部分
- 类装载器:加载字节码文件。
- 运行时数据区:存放数据。
- 执行引擎:负责把这些命令解释给操作系统。
- 本地方法接口:调用不同的语言接口给java用。
2.内存结构图
- 堆:
- 堆内存最大;线程共享;可垃圾回收;java堆处于物理上不连续的内存空间中,堆的内存是一块块凑起来的;当堆中没有内存完成实例分配,且堆空间无法扩展时会抛出OutOfMemoryError。
- 存放对象。
- GC采用分代收集法管理堆空间。
- 方法区:
- 线程共享,内存不连续,可扩展、可垃圾回收,可抛出OutOfMemoryError。
- 存储类信息、常量、静态变量、即时编译后的代码。
- GC主要针对常量回收、类信息卸载。
- java虚拟机栈:
- 线程私有;生命周期与线程相同;线程请求的栈深度大于虚拟机所允许的深度会抛出stackOverflowError。
- 用于支持虚拟机进行方法调用和方法执行的数据结构。
- 存储了方法局部变量表、操作数栈、动态连接、方法返回地址。
- 局部变量表:是一组变量存储空间,用于存放方法参数和方法内部局部变量。
- 操作数栈:从局部变量表或对象实例的字段中复制常量或变量写入到操作数栈中,再将计算结果返回给方法调用者或出栈到局部变量表
- 动态连接:每个栈帧都包含一个指向运行时常量池中该栈所属方法的符号应用;持有这个引用的目的是支持方法调用过程中的动态链接。
- 方法返回地址:无论方法是否正常完成,都需要返回到方法被调用的位置,程序才能继续执行。
- 本地方法栈:与java虚拟机栈作用相似,本地方法栈为虚拟机使用到的Native服务。
- 程序计数器:
- 占用空间小、线程私有、唯一没有OutOfMemoryError区域
- 它的作用是作为当前线程所执行的字节码的行号指示器,字节码解释器就是通过改变计数器的值来选取下一条指令。
- 没有程序计数器,java程序无法正确控制,多线程也无法正确轮换。
3.类加载过程
加载、验证、准备、解析、初始化;其中验证、准备、解析称为连接阶段。
- 加载
- 通过一个类的全限定名来获取定义此类的二进制字节流。
- 从二进制字节流中解析出类的信息存储到方法区中。
- 在堆内存中生成一个代表这个类的class对象,作为在方法区中这个类的访问入口。
- 验证:确保Class文件字节流信息符合java虚拟机全部约束要求。
- 格式检查:版本检查(能否被当前版本的虚拟机解析处理)。
- 元数据检查:是否继承final,抽象方法是否实现。
- 字节码验证:操作数的类型是否合理。
- 符号引用验证:看其引用的其他类或方法是否存在。
- 准备:为类中定义的静态变量分配方法区内存,并进行默认初始化。
- 解析:将符号引用转换直接引用;也就是得到类、字段、方法在内存中的指针或偏移量。(会加载尚未加载的应用,比如加载父类&