看张龙的视频教程自己做的笔记, 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对象的引用的类加载器(包括定义类加载器)能被称为初始类加载器