JVM类加载器的分类
BootStrap ClassLoader(启动类加载器/引导类加载器)
- 启动类加载器使用 C/C++ 语言实现,嵌套在 JVM 内部;
- 它用来加载 Java 的核心库(JAVA_HOME/jre/lib/rt.jar、resources.jar、sun.boot.class.path 路径下的内容),用于提供 JVM 自身需要的类;
- 并不集成 java.lang.ClassLoader,没有父类加载器;
- 加载扩展类和应用程序类加载器,并指定为他们的父类加载器;
- 出于安全考虑,启动类加载器只加载包名为 java、javax、sun 等开头的类。
Extension ClassLoader(扩展类加载器)
- 扩展类加载器使用 Java 语言编写,由 sun.misc.Launcher$ExtClassLoader 实现;
- 派生于 ClassLoader 类;
- 父类加载器为启动类加载器;
- 从 java.ext.dirs 系统属性所指定的目录中加载类库,或从 JDK 的 /jre/lib/ext 子目录(扩展目录)下加载类库。如果用户创建的 JAR 放在此目录下,也会自动由扩展类加载器加载。
Application ClassLoader(应用程序类加载器/系统类加载器)
- 应用程序展类加载器使用 Java 语言编写,由 sun.misc.Launcher$AppClassLoader 实现;
- 派生于 ClassLoader 类;
- 父类加载器为扩展类加载器;
- 它负责加载环境变量 classpath 或系统属性 java.class.path 指定路径下的类库;
- 通过 ClassLoader#getSystemClassLoader() 方法可以获取到该类加载器;
Custom ClassLoader(用户自定义类加载器)
- 是 java.lang.ClassLoader 的子类;
- 在程序运行期间,通过 java.lang.ClassLoader 的子类动态加载 class 文件,体现 Java 动态实时类装入特性;
- 用户自定义类加载器的作用:隔离加载类、修改类加载的方式、拓展加载源、防止源码泄漏。
双亲委派机制
Java 虚拟机对 class 文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的 class 文件加载到内存生成 calss 对象。而且加载某个类的 class 文件时,Java 虚拟机采用的是双亲委派机制,即把请求交由父类处理,它是一种任务委派机制。
工作原理
1)如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行;
2)如果父类加载器还存在父类加载器,则进一步向上委托,依次递归请求最终达到顶层的启动类加载器;
3)如果父类加载器可以完成加载任务就返回成功,若不能完成加载任务,子类才会尝试自己去加载。
优势
- 避免类的重复加载
- 保护程序安全,防止核心 API 被随意篡改,例如:自定义类 java.lang.String
沙箱安全机制
沙箱机制就是将 Java 代码限定在虚拟机(JVM)特定的运行范围中,并且严格限制代码对本地系统资源访问,通过这样的措施来保证代码的有效隔离,防止对本地系统造成破坏。沙箱机制主要限制系统资源访问,包括:CPU、内存、文件系统、网络。所有的 Java 程序运行都可以指定沙箱,可以定制安全策略,不同级别的沙箱对这些资源访问的限制也可以不一样。