一、类装载子系统
类装载子系统加载.class文件,把加载后的类信息存放在方法区中,classloader只负责加载,运行需要通过执行引擎来执行
加载过程
加载——连接——初始化
加载
- 预加载:加载rt.jar,里面是一些常用的类lang包和io包
- 运行时加载
1、获取.class文件的二进制流
2、将类信息、静态变量、字节码、常量这些.class文件中的内容放入方法区中
3、在内存中生成一个代表这个.class文件的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。一般
这个Class是在堆里的,不过HotSpot虚拟机比较特殊,这个Class对象是放在方法区中的
连接
1、验证
为了确保.class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
2、准备
准备阶段是正式为类变量分配内存并设置其初始值的阶段,这些变量所使用的内存都将在方法区中分配
3、解析
解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。
- 直接引用可以是直接指向目标的指针、相对偏移量或是一个能间接定位到目标的句柄。如果有了直接引用,那引用的目标必定已经存在在内存中了。
初始化
静态变量和静态代码块的赋值。
初始化阶段就是执行类构造器<clinit>()方法的过程。<clinit>()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static{}块) 中的 语句合并产生的, 编译器收集的顺序是由语句在源文件中出现的顺序决定的, 静态语句块中只能访问 到定义在静态语句块之前的变量.。
Java虚拟机会保证在子类的<clinit>()方法执行前, 父类的()方法已经执行 完毕。
二、类加载器
- 作用:类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在创建一个java.lang.Class对象,用来封装类在方法区内的数据结构
- 分类
1.启动类加载器:加载rt.jar
2.扩展类加载器:加载/lib/ext目录下jar包
3.系统类加载器:默认的类加载器,应用程序中的类由它加载
三、双亲委派
- 如果一个类加载器收到类加载的请求,它不会自己去尝试加载这个类,而是把这个请求委派给父类加载器完成。每个类加载器都是如此,只有当父加载器在自己的搜索范围内找不到指定类时(即 ClassNotFoundException ),子加载器才会尝试自己去加载
网友评论