类加载器

定义:Java类加载器(Java Classloader)是Java运行时环境(Java Runtime
Environment)的一部分,负责动态加载Java类到Java虚拟机的内存空间中。

分类

类加载器的任务是根据一个类的全限定名来读取此类的二进制字节流到JVM中,然后转换为一个与目标类对应的java.lang.Class对象实例.

在虚拟机提供了3种类加载器:

  • 引导(Bootstrap)类加载器:Bootstrap ClassLoader
  • 扩展(Extension)类加载器:ExtClassLoader
  • 系统(System)类加载器(也称应用类加载器):AppClassLoader

Bootstrap ClassLoader

启动类加载器,或者称引导类加载器

  • 这个类加载使用C++语言实现的,是虚拟机自身的一部分
  • 它用来加载Java的核心类库:JAVA_HOME/jre/lib/rt.jar 、resources.jar、sun.boot.class.path路径下的内容,主要用于提供JVM自身需要的类
  • 出于安全考虑,Bootstrap启动类加载器只加载包名为java、javax、sun等开头的类
  • 并不继承自java.lang.ClassLoader,没有父加载器
  • 加载扩展类和应用程序加载器,并指定为他们的父类加载器

ExtClassLoader

扩展类加载器

  • 扩展类加载器是指Sun公司(已被Oracle收购)实现的sun.misc.Launcher$ExtClassLoader类,由Java语言实现的,是Launcher的静态内部类
  • 派生于ClassLoader类
  • 父类加载器为启动类加载器
  • 从java.ext.dirs系统属性所指定的目录中加载类库,或者从 JDK的安装目录的 jre/lib/ext子目录(扩展目录)下加载类库。如果用户创建的JAR放在此目录下,也会自动的由扩展类加载器加载

AppClassLoader

应用程序类加载器,也叫系统类加载器

  • Sun公司实现的sun.misc.Launcher$AppClassLoader。java语言编写
  • 派生于ClassLoader类
  • 父类加载器为扩展类加载器
  • 它负责加载系统属性java.class.path或环境变量classpath 指定路径下的类库
  • 一般情况下该类加载是程序中默认的类加载器,一般来说,java应用的类都是由他来加载
  • 通过ClassLoader#getSystemClassLoader()方法可以获取到该类加载器

用户自定义类加载器

在Java的日常应用程序开发中,类的加载几乎是由上述3种类加载器相互配合执行的,在必要时,我们还可以自定义类加载器。

为什么要自定义类加载器:

隔离加载类
修改类加载方式
扩展加载源
防止源码泄露

实现步骤:

  • 开发人员可以通过继承抽象类java.lang.ClassLoader类的方式,实现自己的类的加载器,满足一些特殊的需求
  • 在JDK1.2之前,在自定义类加载器时,总会去继承ClassLoader类并重写loadClass()方法,从而实现自定义类的类加载器。但是在JDK1.2之后已不再建议用户去覆盖loadClass()方法。而是建议把自定义类加载逻辑写在fingClass()方法中
  • 在编写自定义类加载器时,如果没有太过于复杂的需求,可以直接继承URLClassLoader类,这样就可以避免自己去编写findClass()方法及获取字节码流的方式,使自定义类加载器编写更加简洁

ClassLoader

classLoader类是一个抽象类,其后面所有的类加载器都继承自classLoader(不包括启动类加载器)

双亲委派机制

JVM在加载类时默认采用的是双亲委派机制。
通俗的讲,就是某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归 (本质上就是loadClass函数的递归调用),因此所有的加载请求最终都应该传送到顶层的启动类加载器中。
如果父类加载器可以完成这个类加载请求,就成功返回;只有当父类加载器无法完成此加载请求时,子加载器才会尝试自己去加载。

工作原理:
双亲委派模式要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器,请注意双亲委派模式中的父子关系并非通常所说的类继承关系,而是采用组合关系来复用父类加载器的相关代码,类加载器间的关系如下:

优势:

  • 避免类重复加载
  • 保护程序安全,防止核心API被随意篡改

在JVM中表示两个class对象是否为同一个类对象存在两个必要条件:

  • 类的完整类名必须一致,包括包名。
  • 加载这个类的ClassLoader(指ClassLoader实例对象)必须相同。

换句话说,在 JVM 中,即使这两个类对象(Class 对象)来源于同一个 Class 文件,被同一个虚拟机所加载,但是只要加载它们的 ClassLoader 实例对象不同,那么这两个类对象也是不相等的 。

沙箱安全机制(待续)

类的主动使用和被动使用

二者区别在于:是否导致类的初始化。

主动使用

主动使用又分为 7 种情况:

  • 创建类的实例
  • 访问某个类或接口的静态变量,或者对该静态变量赋值
  • 调用类的静态方法
  • 反射(比如:Class.forName(“top.gldwolf.Test”))
  • 初始化一个类的子类
  • Java 虚拟机启动时被标明为启动类的类
  • JDK 7 开始提供的动态语言支持:java.lang.invoke.MethodHandle 实例的解析结果
    REF_getStatic、REF_putStatic、REF_invokeStatic 句柄对应的类没有初始化,则初始化

被动使用

除了以上 7 种情况,其他使用 Java 类的方式都被看作是对类的被动使用,都不会导致类的初始化。

全部评论

相关推荐

10-05 23:02
东北大学 Java
我说句实话啊:那时候看三个月培训班视频,随便做个项目背点八股,都能说3 40w是侮辱价
点赞 评论 收藏
分享
评论
点赞
收藏
分享
正在热议
# 25届秋招总结 #
440279次浏览 4490人参与
# 春招别灰心,我们一人来一句鼓励 #
41427次浏览 524人参与
# 北方华创开奖 #
107274次浏览 599人参与
# 地方国企笔面经互助 #
7916次浏览 18人参与
# 虾皮求职进展汇总 #
113889次浏览 883人参与
# 实习,投递多份简历没人回复怎么办 #
2453837次浏览 34847人参与
# 阿里云管培生offer #
119737次浏览 2219人参与
# 实习必须要去大厂吗? #
55644次浏览 960人参与
# 同bg的你秋招战况如何? #
75364次浏览 551人参与
# 提前批简历挂麻了怎么办 #
149798次浏览 1977人参与
# 投递实习岗位前的准备 #
1195641次浏览 18546人参与
# 你投递的公司有几家约面了? #
33170次浏览 188人参与
# 双非本科求职如何逆袭 #
661833次浏览 7394人参与
# 机械人春招想让哪家公司来捞你? #
157595次浏览 2267人参与
# 如果公司给你放一天假,你会怎么度过? #
4719次浏览 54人参与
# 如果你有一天可以担任公司的CEO,你会做哪三件事? #
11300次浏览 267人参与
# 发工资后,你做的第一件事是什么 #
12384次浏览 61人参与
# 工作中,努力重要还是选择重要? #
35576次浏览 384人参与
# 参加完秋招的机械人,还参加春招吗? #
20079次浏览 240人参与
# 实习想申请秋招offer,能不能argue薪资 #
39220次浏览 314人参与
# 我的上岸简历长这样 #
451897次浏览 8088人参与
# 非技术岗是怎么找实习的 #
155837次浏览 2120人参与
牛客网
牛客企业服务