一、能干嘛
1.1、方法区
存放类的描述信息的地方。
1.2、JVM中的类装载器
1.3、类加载器详解
1.3.1、启动类加载器
概述:
Java的核心类库都是通过启动类加载器加载的,例如:String类。
启动类加载器(Bootstrap ClassLoader)
(1)这个类的加载器是使用C/C++语言实现的,嵌套在JVM内部;
(2)用来加载Java的核心库(%JAVA_HOME%/jre/lib/*.jar、或者sun.boot.class.path路径下的内容),用于提供JVM自身需要的类;
(3)没有父加载器,是顶级的加载器;
(4)加载扩展类和应用程序类加载器,并指定为它们的父加载器;
(5)出于安全考虑,Bootstrap启动类加载器只加载包名为java、javax、sun等开头的类;
1.3.2、扩展类加载器
扩展类加载器(Extension ClassLoader)
(1)Java语言编写,由 sun.misc.Launcher$ExtClassLoader实现
(2)派生于ClassLoader类;
(3)父加载器为启动类加载器;
(4)从java.ext.dirs系统属性所指定的目录中加载类库,或者从JDK的安装目录的%JAVA_HOME%/lib/ext子目录(扩展目录)加载类库。如果用户创建的jar放在此目录下,也会自动由扩展类加载器加载。
1.3.3、系统类加载器
系统类加载器(AppClassLoader)
(1)java语言编写,由sun.misc.Launcher$AppClassLoader实现;
(2)派生于ClassLoader类;
(3)父加载器为扩展类加载器;
(4)负责加载环境变量classPath或者系统属性java.class.path指定路径下的类库;
(5)该类加载器是程序中默认的类加载器,一般来说Java应用的类(自己写的类)都是由它来加载完成;
(6)通过ClassLoader#getSystemClassLoader()方法可以
1.3.4、自定义类加载器
在Java的日常应用程序开发中,类的加载几乎都是由上述三种类加载器相互配合执行的,在必要时,我们还可以自定义类加载器,来定制类的加载方式。
为什么要自动以类加载器?
(1)隔离类加载;
(2)修改类的加载方式;
(3)扩展加载源;
(4)防止源码泄露;
1.4、类加载过程
加载===>链接===>初始化
1.4.1、概览
1.4.2、加载
步骤:
第一步:通过一个类的全限定名来获取定义此类的二进制字节流;
第二步:将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;
第三步:在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口;
补充:加载.class文件的方式
(1)从本地系统中直接加载;
(2)通过网络获取,典型场景:Web Applet;
(3)从zip压缩包中读取,成为日后jar、war格式的基础;
(4)运行时计算生成,例如:动态代理技术;
(5)从其他文件生成,典型场景:jsp应用;
(6)从专有数据库中提取.class文件,比较少见;
(7)从加密文件中获取,典型的防Class文件被反编译的保护措施;
1.4.3、链接
1.4.4、初始化
1.5、获取ClassLoader的方式
/**
* @Author : 一叶浮萍归大海
* @Date: 2023/11/16 0:08
* @Description: 获取类的加载器的方式
*/
public class ClassLoaderMainApp {
public static void main(String[] args) throws ClassNotFoundException {
// 获取类加载器的第一种方式
Car car1 = new Car();
ClassLoader classLoader1 = car1.getClass().getClassLoader();
System.out.println("获取类加载器的第一种方式:" + classLoader1);
// 获取类加载器的第二种方式
ClassLoader classLoader2 = Class.forName("org.star.entity.Car").getClassLoader();
System.out.println("获取类加载器的第二种方式:" + classLoader2);
// 获取类加载器的第三种方式
ClassLoader classLoader3 = Car.class.getClassLoader();
System.out.println("获取类加载器的第三种方式:" + classLoader3);
System.out.println("*********************");
Object obj = new Object();
System.out.println("Object类的根加载器:" + obj.getClass().getClassLoader());
System.out.println("自定义类的加载器:" + Car.class.getClassLoader());
System.out.println("自定义类的加载器(父亲):" + Car.class.getClassLoader().getParent());
System.out.println("自定义类的加载器(爷爷):" + Car.class.getClassLoader().getParent().getParent());
}
}