1.虚拟机字节码执行引擎
1)物理机和虚拟机的执行引擎区别
物理机:直接建立在处理器、硬件、指令集、操作系统层面上
虚拟机:执行引擎是自己实现的,可以自行制定指令集与执行引擎的结构体系,并且能够执行那些不被硬件直接支持的指令集格式

2)虚拟机字节码执行引擎的概念模型
概念模型的建立为了统一执行引擎的外观,都是:输入字节码文件=>字节码解析=>输出执行结果

3)运行时栈帧结构
用于支持虚拟机进行方法调用和方法返回的数据结构,它是虚拟机运行时数据区中的虚拟栈的栈元素。存储了方法的局部变量表、操作数栈、动态连接、方法返回地址和额外附加等信息。

技巧:使用恰当的变量作用域来控制变量回收才是最优雅的解决方法
技巧:不使用的对象手动赋值为null

2.虚拟机类加载机制
1)虚拟机如何将Class 加载到内存中的?
部分其他语言不同于Java语言,部分语言是在编译时进行连接的工作,而Java语言中,类的加载和初始化都在程序运行期间完成的。而且Java 天生的动态扩展语言特性,也是依赖于运行期间动态加载和动态连接的特点实现的。

加载步骤:7个阶段分别是加载、验证、准备、解析 、初始化、使用、卸载。

2)什么时候会立即进行类的初始化?
a)如果类没有进行初始化,遇到new、getstatic、putstatic、invokestatic 字节码指令会触发器初始化
b)使用java.lang.reflect包下的方法对类进行反射调用的时候
c)初始化一个类的时候,如果发现其父类还没有进行初始化,先触发其父类初始化
d)虚拟机启动时,用户指定一个要执行的主类(main类),会先初始化该主类
e)使用JDK 1.7 动态语言支持,如果遇到java.lang.invoke.MethodHandle 实例后解析结果REF_***的方法句柄,会先初始化这个句柄所对应的类

3)验证4个阶段的检查动作
文件格式验证、元数据验证、字节码验证、符合引用验证

4)准备阶段
准备阶段是正式给你类变量分配内存并设置类变量初始化的阶段 。这时候进行内存分配的仅包括类变量(被static修饰的变量),而并不包括实例变量,实例变量会在对象实例化是随着对象一起分配在Java 堆中。

5)初始化阶段
真正开始执行中定义的Java 程序代码(或称为字节码)

6)类与类加载器
a)判断二个类是否相等条件:二个类来源于同一个Class、同一类加载器;
b)启动类加载器(C++)是虚拟机的自身的一部分,其他的类加载器都是由Java语言实现的,独立于虚拟机外部;
c)分类:启动类加载器(JAVA_HOME\lib)、扩展类加载器(JAVA_HOME\lib\ext)、应用程序类加载器(ClassPath)、自定义类加载器;

7)JDK 每次升级新增功能分类
a)编译器层面的改进(自动装箱、拆箱)
b)Java API 代码增强(增加集合类Collections)
c)需要字节码中进行支持的改动(新增字节码指令)
d)虚拟机内部改动(内存模型、CMS收集器)

3.Java内存区域
1)内存区域划分
a)方法区、虚拟机栈、本地方法栈、堆、程序计数器、执行引擎、本地库接口、本地方法库
b)线程共享区域:方法区、堆;线程私有区域:虚拟机栈、本地方法区、程序计数器
c)程序计数器:每个线程都有一个独立的程序计数器,记录在多线程的切换执行下,保证字节码从上大下顺序执行并可以交替执行顺序
d)栈:一个方法为一个栈帧(局部变量表、操作数栈、动态链接、方法出口)
e)本地方法栈:Native 方法特有,功能和栈大同小异
f)堆:存放对象实例,包括新生代、老年代
g)方法区:类信息、常量、静态变量、运行时常量池等
h)直接内存:不是虚拟机运行时数据区的一部分

2)对象创建过程
new 指令=>去常量池检查指令参数的符号引用是否存在并检查这个符号引用代表的类是否加载、解析、初始化=>没有=>执行类加载过程=>为新生对象分配内存=>执行init 初始化=>对象创建成功

3)对象的内存布局
内存中的对象:对象头、实例数据(真正有效数据:程序代码中定义的各种类型的字段)、对齐填充。
主流访问方式为:句柄和直接指针