Java类加载器

作用

顾名思义,类加载器是加载 Java 类的东西。更准确地说,类加载器读取类文件的内容,然后使用读取的字节数组创建java.lang.Class的实例。

1:类加载器子系统负责从文件系统或者网络中加载class文件。
2:classLoader只负责class文件的加载,至于它是否可以运行,则由ExecutionEngine决定。
3:加载的类信息存放于一块称为方法区的内存空间。除了类的信息外,方法区中还会存放运行时常量池信息,可能还包括字符串字面量和数字常量。

过程

1:通过一个类的全限定名获取定义此类的二进制字节流
2:将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
3:在内存中生成一个代表这个类的java.lang.class对象,作为方法区这个类的各种数据的访问入口

加载字节码文件的方式

1:从本地系统中直接加载
2:通过网络获取,典型场景: web Applet
3:从zip压缩包中读取,成为日后jar、war格式的基础运行时计算生成,使用最多的是:动态代理技术由其他文件生成,典型场景:JSP应用
4:从专有数据库中提取.class文件,比较少见
5:从加密文件中获取,典型的防class文件被反编译的保护措施

类加载器的分类

有三种默认类型的类加载器:

Bootstrap ClassLoader

启动类加载器、引导类加载器,是类加载器的根,它负责加载Java的核心库,这个类由C/C++实现,嵌套在jvm内部。对引导类加载器加载的类调用getClassLoader()将返回 null。

Extension ClassLoader

扩展类加载器,派生于ClassLoader类,调用时,它首先将类加载委托给其父类。如果父级无法解析该类,Extension 会尝试自行完成。它将在与 java.ext.dirs 系统属性(例如:jre7/lib/ext)关联的目录(或目录)中查找所需的类。

AppClassLoader

系统类加载器,派生于ClassLoader类,负责加载 JAR 中的类路径参数 (-cp)、CLASSPATH 环境变量或 Manifest 文件的 Class-Path 属性中指定的类。是程序中默认的类加载器,一般来说,Java应用的类都是由它来完成加载。

自定义类加载器

我们可以自定义类加载器,定制类的加载方式。原因:
1:隔离加载类
2:修改类加载的方式
3:扩展加载源
4:防止源码泄漏
步骤:实现 java.lang.ClassLoader 接口,将自定义的类加载逻辑写在findClass()方法中,如果没有太复杂的需求,可以直接继承UrlClassLoader类。

获取ClassLoader的方式

//1:获取当前类的ClassLoader
clz.getClassLoader();
ClassLoader classLoader = Class.forName("java.lang.Error").getClassLoader();
//2:获取当前线程上下文的ClassLoader
Thread.currentThread().getContextClassLoader();
//3:获取系统的ClassLoader
ClassLoader.getSystemClassLoader();

双亲委派机制

Java虚拟机对class文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的class文件加载到内存生成class对象。而且加载某个类的class文件时,Java虚拟机采用的是双亲委派模式,即把请求交由父类处理,它是一种任务委派模式。即以下三个点

委托

假如现在程序开始加载Person.class,加载请求来到系统类加载器,系统类加载器委托给拓展类加载器,拓展类加载器委托给引导类加载器。如果 引导类加载器 找到了这个类,它就会返回它。如果没有,则轮到 Extension 尝试加载类。如果找到,则返回该类。否则,最后一次尝试在 Application 类加载器中进行。此操作也称为链接。

可见性

类加载器可以有父级,作为扩展,父级是 Bootstrap。子类加载器可以看到父类加载的类。但其他类型不行。

唯一性

由父级加载的类不应由子级再次加载

优势

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

沙箱安全机制

为了确保Java技术不会被邪恶目的所利用,SUN公司在设计Java的时候,设计了一套精密的安全模型;即安全管理器(Security Manager)将检查有权使用的所有系统资源。在默认的情况下,只允许那些无害的操作,要想允许执行其他操作,代码需得到数字签名,用户必须得到数字认证。
在所有的平台上,远程代码可以做什么呢?它可以显示图像、播放音乐、获得用户的键盘输入和鼠标点击,以及将用户的输入送回加载代码所在的主机。这些功能足以能够显示信息和图片,或者获得用户为订单所输入的信息。这种受限制的执行环境称为沙箱(sandbox)。
沙箱机制就是将 Java 代码限定在虚拟机(JVM)特定的运行范围中,并且严格限制代码对本地系统资源访问,通过这样的措施来保证对代码的有效隔离,防止对本地系统造成破坏。

类加载器的引用

JVM必须知道一个类型是由启动加载器加载的还是由用户类加载器加载的。如果一个类型是由用户类加载器加载的,那么JVM会将这个类加载器的一个引用作为类型信息的一部分保存在方法区中。当解析一个类型到另一个类型的引用的时候,JVM需要保证这两个类型的类加载器是相同的。

类的主动使用和被动使用

  1. 创建类的实例
  2. 访问某个类或接口的静态变量,或者对该静态变量赋值调用类的静态方法
  3. 调用类的静态方法
  4. 反射
  5. 初始化一个类的子类
  6. Java虚拟机启动时被标明为启动类的类
  7. JDK 7开始提供的动态语言支持:java . lang.invoke.MethodHandle实例的解析结果REF_getstatic、REF_putstatic、REF_invokestatic句柄对应的类没有初始化,则初始化
    除此之外使用Java类的方式都是对类的被动使用,不会导致类的初始化
posted @ 2021-12-07 20:16  翻蹄亮掌一皮鞋  阅读(122)  评论(0)    收藏  举报