-
加载(Loading):
-
当程序引用一个类时,如果该类还没有被加载到JVM中,类加载器就会被调用来加载该类。
-
类加载器首先检查这个类是否已经被加载。如果没有,它将按照指定的搜索路径寻找对应的.class文件。
-
对于Bootstrap类加载器,它主要负责加载$JAVA_HOME/jre/lib目录下或者由-Xbootclasspath参数指定的路径中的核心类库。
-
Extension类加载器加载$JAVA_HOME/jre/lib/ext目录下或由系统属性java.ext.dirs指定位置的类库。
-
System/Application类加载器加载环境变量CLASSPATH或系统属性java.class.path指定的路径、类路径参数(-cp/-classpath)以及应用程序的类路径下的类。
-
链接(Linking):
-
验证(Verification): 确保加载的类符合JVM规范,不会危害到运行时环境。
-
准备(Preparation): JVM为类变量分配内存,并设置默认初始值。
-
解析(Resolution): 将类中的符号引用转换成直接引用。
-
初始化(Initialization):
-
在类被第一次使用时,比如创建实例、调用类的静态方法、使用类或接口的静态字段时(不包括定义常量的那种静态字段),JVM负责初始化类。
-
初始化涉及执行类初始化器,即运行类中的静态初始化块和静态字段的赋值操作。
双亲委派模型(Parent Delegation Model):
-
当一个类加载器尝试加载某个类时,它首先会代理给其父类加载器进行加载。
-
如果父类加载器无法完成这个任务(它并没有找到对应的类),子类加载器才会尝试自己加载这个类。
-
这个过程从Bootstrap类加载器开始,然后是Extension类加载器,最后是System/Application类加载器。
例子:
假设我们有一个名为 com.example.MyClass 的类,并且它不是 Java 标准库的一部分,而是用户定义的,并打包在 myclasses.jar 文件中。
当你的应用程序运行并第一次引用 MyClass 时,以下是会发生的事情:
-
系统类加载器会收到一个请求来加载 MyClass。
-
遵循委派模型,系统类加载器首先会委派给扩展类加载器,扩展类加载器又会委派给启动类加载器。
-
启动类加载器会搜索 JVM 核心库,但不会找到 MyClass,因为它不是核心库的一部分,于是返回并告诉扩展类加载器未找到该类。
-
扩展类加载器也不能在其搜索范围内找到 MyClass,同样返回并告知系统类加载器。
-
系统类加载器最后会在用户的类路径(假设 myclasses.jar 已经添加到了类路径中)查找 MyClass.class 文件。
-
系统类加载器找到并加载 MyClass,然后进行链接和初始化。
-
MyClass 现在可用于应用程序。
本篇文章来源于微信公众号: 互联网面试小帮手
微信扫描下方的二维码阅读本文

Comments NOTHING