类的加载器
大家有没有仔细想过一个问题,java应用程序在类加载的时候,JVM做了什么?今天就让博主跟大家简单地聊一聊基于
反射机制的类的加载器。当程序运行的时候,JVM 将会将类调进内存并启动类的加载器。JVM会将类进行加载(将class放进
方法区),在内存的堆里创建了一个可以进入class文件的对象,该class文件有些教科书也叫字节码对象,这样的叫法没有异
议,这是因为class文件编译后产生字节码。当我们运行一个类时,加载器自动帮我们创建了一个class文件对象,该对象在程
序运行的瞬间被创建。并且这个对象只有这一份没有。下面先用一个简单的内存草图来说明class文件的内存环境。
在类被加载器放进方法区的时候需要检查类的内部结构,并和其他类协调一致。这一步称为连接验证。做完这一步后就
进入了下一个准备阶段,该阶段对所有成员进行初始化,就拿静态成员变量来说,为静态成员变量分配一块区别与其他成员
的内存地址,它被置于方法区的数据共享区里,并为该静态变量标明所属的类。包括静态变量在内,所有类的成员都会被初
始化。完成以上两步后接下来就为程序数据进行解析,将类的二进制数据中的符号引用替换为直接引用。我们方法中会有很
多运算符号,但是在内存中为了提高运算效率,将会去掉我们写程序的中间结果,比如我们定义了很多用于存储计算结果的
变量,但是在内存参与运算时,这些变量就会被消除。这与面向过程化的编程到面向函数式的编程的一个转化过程非常类似。
当一个程序完成了加载和连接后,接下去的工作是程序使用我们自己创建的对象,只有我们new一个对象后,内存堆里
才会创建一块内存空间。这个过程称为对象的初始化过程。当我们运行一个程序的时候,类什么时候会被放进内存呢?在平
时,我们用一个测试类的main方法调用另一个类的静态成员或静态方法时,该类会被加载进来。在继承结构里,当我们去new
一个子类的时候,父类会先被加载进内存。从某种角度上来说,在我们运行任何一个类的时候,先进内存的一定是Object类。
那下面就对类的初始化时机进行总结:
1.创建类的实例
2.类的静态变量或者为静态变量赋值
3.类的静态方法
4.使用反射机制来强制创建某个类或接口对应的java.lang.Class对象
5.初始化某个类的子类
6.直接使用java.exe命令
我们谈了这么久类的加载器,都已经知道它是干什么用的,但类的加载器又有哪几类呢?类的加载器也就三种,他们分别
是Extension ClassLoader、Extension ClassLoader和Extension ClassLoader,那下面我们就分析这三中加载器。
1. Extension ClassLoader(扩展类加载器) :
用于加载核心类,在我们运行程序的时候,Bootstrap ClassLoader会先将系统的核心类库加进内存。
比如System、String等。java核心类在JRE的lib目录下rt.jar文件中;
2. Extension ClassLoader(扩展类加载器):
负责JRE的扩展目录中jar包的加载,在JRE的lib目录下的ext文件目录中;
3.System ClassLoader(系统类加载器):
负责在JVM启动时加载来自java命令的class文件,换句话说就是程序员定义的类,以及加载classpath
环境变量指定的jar包和类的路径。
类的加载器