一、Java初始化过程:
- 初始化父类种的静态成员变量和静态代码块,顺序执行
- 初始化子类种的静态成员变量和静态代码块,顺序执行
- 初始化父类的普通成员变量和代码块,再执行父类的构造函数
- 初始化子类的成员变量和代码块,在执行子类的构造函数
在Java中,如果父类既有无参构造函数又有有参构造函数,并且子类没有显式调用父类的构造函数,则执行父类的无参构造函数。这是因为子类的构造函数会式地调用父类的无参构函数作为第步操作,以确保父类的初始化完成。只有在类的构造函数中显式调用了父类的有参构造函数时,会执行指定的父类构造函数。
二、类加载过程
类从加载到虚拟机内存开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载。其中加载、验证和解析三个部分统称为连接。
加载、验证、准备、初始化和卸载这5个部分是确定的,类的加载过程必须按照这个顺序执行,而解析不一定,解析可以在初始化阶段之后再开始,这是为了支持Java语言的运行时绑定(也称之为动态绑定或者晚期绑定)
-
加载阶段:
- 通过一个类的全限定名(包名在内的类的整名称)来获取此类的二进制字节流
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
- 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类各种数据的访问入口
加载阶段和连接阶段(Linking)的部分内容(如一部分字节码文件格式验证动作)是交叉进行的,加载阶段尚未完成,连接阶段可能已经开始,但这些夹在加载阶段之中进行的动作,仍然属于连接阶段的内容,这两个阶段的开始时间仍然保持着固定的先后顺序。
-
验证阶段:
- 验证是连接阶段的第一步,这一阶段的目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全
- 验证阶段大致会完成4个阶段的检验动作:
- 文件格式验证:验证字节流是否符合Class文件格式的规范
- 元数据验证:对字节码描述的信息进行语义分析,以保证其描述的信息符合Java语言规范的要求
- 字节码验证:通过数据流和控制流分析,确定程序语义是合法的,符合逻辑的
- 符号引用验证:确保解析动作能正确执行
- 验证阶段非常重要但不是必须的
-
准备阶段:
- 准备阶段是正式为类变量分配内存并设置类初始值阶段,这些变量所使用的内存都将在方法区中进行分配。这时候进行内存分配的仅包括类变量(static修饰的),不包括实例变量,实例变量在对象实例化时随着对象一起分配在堆中。
-
解析阶段:
- 解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。解析动作主要针对类或者接口、字段、类方法、方法类型、方法句柄和调用点限定符等
-
初始化阶段:类初始化阶段是类加载过程的最后一步,到了初始化阶段,才真正开始执行类中定义的java程序代码。看上述
三、只有左移<<、有符号右移>>、无符号右移>>>
四、类加载:
类的加载由类加载器完成,类加载器包括:根加载器BootStrap、扩展加载器Extension、系统加载器System、自定义类加载器java.lang.ClassLoader
- 根加载器BootStrap:一般用本地代码实现、负责加载JVM、基础核心类库
- 扩展加载器Extension:系统属性所指定的目录中加载类库,父加载器是根加载器
- 系统加载器System:应用类加载器,父类是扩展加载器Extension,它从环境变量classpath或者系统属性java.class.path所指定的目录中加载类,使用户自定义加载器默认夫加载器
- 自定义类加载器:java.lang.ClassLoader的子类,父类委托机制可以修改,有些服务器就是自定义类加载器优先的
Java的类加载器采用双亲委派模型,先检查是否已经被加载,若无,调用父类加载器的loadClass方法,若父类加载器为空,默认使用启动类加载器作为父类加载器,若父类加载器加载失败,抛出ClassNotFoundException异常
五、单例的5种实现模式:
- 懒汉式(线程不安全)
- 饿汉式(线程安全)
- 双重检查锁实现(线程安全)
- 静态内部类实现(线程安全)
- 枚举类实现(线程安全)