看张龙的视频教程自己做的笔记, JVM学习笔记.txt (注意tab缩进,可以用notepad++查看缩进线)

JVM学习笔记 Java Virtual Machine (java虚拟机)
(1~2~3按顺序进行的)
1.加载
查找并加载类的二进制数据
把硬盘数据复制内存中
将.class文件中二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构
加载方式
从本地系统中直接加载
通过网络下载.class文件
从zip,jar等归档文件加载.class文件
从专有数据库中提取.class文件
将java源文件动态编译为.class文件
加载器的类型(2种)
java虚拟机自带的加载器
根类加载器(Bootstrap)
使用C++编写,程序员无法在java代码中获得该类
该加载器没有父加载器.他负责加载虚拟机的核心类库,如java.lang.*等..根类加载器从系统属性sun.boot.class.path所制定目录中加载类库.根类加载器的实线依赖于底层操作系统,属于虚拟机的实现的一部分,他并没有继承java.lang.ClassLoader类.
扩展类加载器(Extension)
使用java代码实现
他的父加载器为根类加载器.他从java.ext.dirs系统属性指定的目录中加载类库,如果把用户创建的jar文件放到这个目录下,也会自动由扩展类加载器加载.扩展类加载器是纯java类,是java.lang.ClassLoader类的子类.
系统类加载器(System)/应用加载器
使用java代码实现
也称为应用类加载器,他的父加载器为扩展类加载器,他从环境变量classpath或者系统属性java.class.path所指定的目录中加载类,他是用户自定义的类加载器的默认父加载器.系统类加载器是纯java类,是java.lang.ClassLoader类的子类
用户自定义类加载器
java.lang.ClassLoader的子类
用户可以定制类的加载方式
-----
(-------------------)
| 根类加载器 |
(-------------------)
^
|
(-------------------)
| 扩展类加载器 |
(-------------------)
^
|
(-------------------)
| 系统类加载器 |
(-------------------)
^
|
(-------------------)
|用户自定义类加载器 |
(-------------------)
JVM规范允许类加载器在预料某个类将要被使用时就预先加载它,如果在预先加载的过程遇到了.class文件缺失或存在错误,类加载器必须在程序首次主动使用该类时才报告错误(LinkageError)
如果这个类一直没有被程序主动使用(6种情况),那么类加载器就不会报告错误
2.连接
2.1验证
确保被加载的类的正确性
验证内容
类文件的结构检查
语义检查
字节码验证
二进制兼容性的验证
2.2准备
为类的静态变量分配内存,并将其初始化为默认值
在准备阶段,java虚拟机为类的静态变量分配内存,并设置默认的初始值.
例如
public class Sample{
private static int a=1;//在准备阶段为a分配4个字节的内存空间,并赋予默认值为0
public static long b;//在准备阶段为b分配8个字节的内存空间,并赋予默认值为0
static{
b=2;
}
}
2.3解释
把类中的符号引用转换为直接引用
3.初始化
为类的惊天变量赋予正确的初始值(用户的值)
如:
public class Test{
private static int a=3;
//在连接的准备阶段 a=0;
//到了初始化阶段才 a=3;
/*
他和这个过程是一样的
private static int a;
static{
a=3;
}
*/
}
--------
java对类的使用方式
主动使用
所有的java虚拟机实现必须在每个类或接口被java程序"首次主动使用"使才初始化他们
1.创建类的实例
2.访问某个类或接口的静态变量,或者对该静态变量赋值
3.调用类的静态方法
4.反射 Class.forName("com.memorycat.Person")
5.初始化一个类的子类
6.Java虚拟机启动时候被标明为启动类的类(Java Test)
被动使用
除了以上6种情况,,不会导致进入"初始化"阶段
---------
类加载的父委托机制
若有有一个类加载器能成功加载Sample类,那么这个累加载器称为定义累加载器,所有能成功发返回Class对象的引用的类加载器(包括定义类加载器)能被称为初始类加载器