1.JVM
1.1 什么是java虚拟机?
JVM全称为 java vartual machine,中文名称为java虚拟机
是java程序运行的底层平台
简单来说就是能够执行标准java字节码的虚拟计算机
分为系统虚拟机(VMvare)和程序虚拟机(java虚拟机)
1.2java虚拟机的作用?
负责将标准的字节码文件加载到运行时数据区
负责存储数据
负责将字节码文件翻译为机器码文件,执行
垃圾回收
1.3JVM的组成部分:
类加载器
(引导类加载器,扩展类加载器,应用程序类加载器)
运行时数据区
(包括堆,java虚拟栈,方法区,程序计数器,运行时本地方法栈)
执行引擎
(将字节码文件翻译为机器码并执行)
本地方法接口
(调用本地方法)
垃圾回收
2.JVM-结构-类加载
2.1类加载的过程
加载-链接(验证-准备-解析)-初始化
加载:通过类名将字节流所代表的静态存储结构转换为方法区的运行时结构
验证:检验被加载的类是否具有正确的内部结构
准备:负责为类的静态属性分配内存,并设置默认值,不包含final修饰静态变量,此类变量在编译时进行初始化
解析:将类中的符号引用(class文件中的逻辑符号)替换成直接引用
(直接引用指向方法区的某一个地址)
初始化:为类的静态变量赋予初始值,JVM负责对类进行初始化,主要初始化类的变量
2.2类在什么时候进行初始化?
主动使用:
通过new创建新的对象时
读取和更新类的静态变量时
访问类的静态方法时
初始化子类的时候会初始化父类
执行该类的main方法
在被动使用的情况下并不会加载类:
引用类中的静态常量时并不会加载类
构造某个类的数组时并不会加载类
2.3类的初始化顺序
包含多个静态变量和静态代码块时,遵循自上而下的原则
初始化类时,如果此类的父类未初始化,则优先初始化父类,再初始化子类
2.4类加载器的分类
站在JVM的角度,类加载器分为:
引导类加载器(启动类加载器)
其他所有类加载器(由java语言实现,独立存在于虚拟机外部,全部继承抽象类java.lang.ClassLoader)
站在java语言开发者的角度,类加载器应当细分为:
引导类加载器
由C++/C语言实现,镶嵌于JVM内部,用于加载java核心类库,并不继承于java.lang.ClassLoader,没有父加载器;负责加载扩展类加载器和应用程序类加载器,并为它们指定父加载器
扩展类加载器
java语言编写,派生于ClassLoader类,从 java.ext.dirs 系统属性所指定的目录中加载类库,或从 JDK 系统安装目录下加载类库
应用程序类加载器
java语言编写,派生于ClassLoader类,用于加载我们自己所定义的类,是程序中默认的类加载器;
2.5双亲委派机制
java虚拟机对class文件采用按需加载模式,加载某个类的class文件时,java虚拟机采用的是双亲委派机制,即就是把请求优先交给父类处理,这是一种任务委派模式
自定义加载器——应用程序类加载器——扩展类加载器——引导类加载器
工作原理:
如果一个类加载器接收到了类加载请求,则会向上委托,呈交给父类加载器,如果父类加载器还存在父类加载器,则依次向上委托,最终请求将到达引导类加载器,由引导类加载器加载,如果加载失败,再由子类加载器加载,如果所有类加载器均加载失败,就会抛ClassNotFoundException 异常,这就是双亲委派机制
优点:
避免自己所创建的类替换掉了java核心类库中的类
避免重复加载,父类已加载过的类不需要子类继续加载
如何打破:
在 ClassLoader 类中涉及类加载的方法有两个,loadClass(String name), findClass(String name),这两个方法并没有被 final 修饰,也就表示其他子类可以 重写
重写loadclass方法会破坏双亲委派机制的结构,不推荐使用;
重写findclass方法可以自定义类加载器从而打破双亲委派机制