基本类型由jvm预先定义好的。
引用类型别分为四种类型:类、接口、数组类和泛型参数。泛型参数在编译过程中会被擦除,数组类由jvm直接生成,其他两种则有对应的字节流(需要先被虚拟机加载)。
字节流最常见的形式由Java编译器生成的class文件,除此之外还可以在程序中内部直接生成、从网络中获取字节流。
无论是数组类还是字节流,jvm都需要对其进行链接和初始化。
加载
加载是指查找字节流,除了数组类之外,java虚拟机需要借助类加载器来完成查找字节流的过程。
启动类加载器是Java类加载层次中最顶层的类加载器。其他类加载器都需要由启动类加载器加载至jvm中,才能执行类加载。
JVM中有个特别的模式,双亲委派模式。每一个类加载器在收到加载请求之后,都需要先将请求转发给父类加载器。在父类加载器没有找到请求类的情况下,该加载器才会尝试去加载。
在Java9之前,从顶至下分别为启动类加载器(Bootstrap ClassLoader)、扩展类加载器(Extention ClassLoader)和应用类加载器(Application ClassLoader)。
启动类加载器加载最为基础、最为重要的类,比如存放在JRE的lib目录下jar包中的类。扩展类加载器的父类是启动类加载器,负责加载相对次要、但又通用的类,比如存放在JRE的lib/ext目录下jar包中的类。应用类加载器的父类是扩展类加载器,它负责加载应用程序路径下的类。默认情况下,应用程序中包含的类便是由应用类加载器加载的。
Java9引入了模块系统,扩展类加载器被改名为平台类加载器。JAVASE中除了少数几个关键模块,比如java.base模块是由启动类加载器加载之外,其他模块均由平台类加载器所加载。
在JVM中,类的唯一性由类加载器实例和类的全名一同确定。即便是一串字节流,由不同的类加载器加载,会得到两个不同的类。
链接
指将创建成的类合并至JVM中,使之能够执行的过程。可分为验证、准备和解析三个阶段。
验证,为了确保被加载类能满足JVM的约束条件。
准备,为被加载类的静态字段分配内存。除了分配内存之外,还会在该阶段构造其他跟类层次相关的数据结构。
在class文件被加载至JVM之前,这个类无法知道其他类及其方法、字段所对应的具体地址,也不知道自己的方法、字段地址。如果需要引用这些成员时,编译器会生成一个符号引用,在运行阶段,这个符号引用一般都能够无歧义地定位到具体目标上。
解析阶段的目的,正是将这些符号引用解析成为实际引用。如果符号引用指向一个未被加载的类,那么解析将会触发这个类的加载(未必触发这个类的链接和初始化,思考下原因)。
初始化
如果直接赋值的静态字段被final所修饰,并且类型是基本类型或者字符串时,那么该字段便会被java编译器标记成常量值,其初始化直接由JVM完成。
普通的赋值操作以及静态代码块中的代码,则会被java编译器置于同一方法中,把它命名为