第一章
JVM 架构
栈架构的优点:跨平台性、指令集小、指令多;执行性能比寄存器差。
JVM的生命周期
虚拟机的启动
Java虚拟机的启动是通过引导类加载器(bootstrap class loader)创建的一个初始类(initial class)来完成的,这个类是由虚拟机的具体实现指定的。
虚拟机的执行
程序开始执行时它才运行,程序结束时它便停止。
执行一个所谓的JAVA程序的时候,真真正正的执行的是一个叫做JAVA虚拟机的进程。
虚拟机的退出
- 程序正常执行结束
- 程序在执行中遇到异常或错误而终止
- 某线程调用Runtime类或System类的exit方法,或Runtime类的halt方法,并且Java安全管理器也允许这次exit或halt操作。
JVM的发展历程
HotSpot
- 不管是现在仍在广泛使用的JDK6,还是使用比例较多的JDK8中,默认的虚拟机都是HotSpot。
- Sun/Oracle JDK 和 OpenJDK 的默认虚拟机。
- 从服务器、桌面到移动端、嵌入式都有应用。
- HotSpot指的是它的热点代码探测技术。
- 通过计数器找到最具编译价值代码,触发即时编译或栈上替换。
- 通过编译器与解释器协同工作,在最优化的程序响应时间与最佳执行性能中取得平衡。
JRockit
- 专注于服务端。
- 内部不包含解析器。
- JRockit JVM是世界上最快的JVM。
J9
- 是IBM公司的。
- 与HotSpot接近。
Azul VM
- 与特定硬件平台绑定、软硬配合的专有虚拟机。
- 高性能java虚拟机中的战斗机。
Dalvik VM
- 只能称作虚拟机,而不能称作“java虚拟机”。
- 不能直接执行 java 的 class 文件。
- 基于寄存器架构,不是jvm的栈架构。
- 执行的是编译后的dex文件。
- Graal VM
- 在HotSpot VM基础上增强而成的跨语言全栈虚拟机,可以作为“任何语言”的运行平台使用。
第二章
内存结构概述
类加载器与类的加载过程
类加载器子系统的作用
- 类加载器子系统负责从文件系统或网络中加载Class文件,class文件在文件开头有特定的文件标识。
- ClassLoader只负责class文件的加载,至于它是否可以运行,则由Execution Engine决定。
- 加载的类信息存放于一块称为方法区的内存空间。除了类的信息外,方法区中还会存放运行时常量池信息,可能还包括字符串字面量和数字常量。(这部分常量信息是Class文件中常量池部分的内存映射)
流程 : 加载 -> 连接 -> 初始化
类加载的过程
加载阶段:
- 通过一个类的全限定名获取定义此类的二进制字节流。
- 将这个字节流所代表的的静态存储结构转化为方法区的运行时数据结构。
- 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
链接阶段:
验证
|
|
准备 |
|
解析 |
|
初始化:
初始化阶段就是执行类构造器方法<clinit>()的过程。
此方法不需定义,是javac编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并而来。
构造方法中指令按语句在原文件中出现的顺序执行。
构造方法中指令按语句在原文件中出现的顺序执行。
<clinit>() 不同于类的构造器。 (关联:构造器是虚拟机视角下的<init>())
若该类具有父类,JVM会保证子类的<clinit>()执行前,父类的<clinit>()已经执行完毕。
虚拟机必须保证一个类的<clinit>()方法在多线程下被同步加锁。(即一个类在多线程情况下只加载一次)