一、类加载的过程是怎么样的?
- 加载: 通过类的全限定名获取该类的二进制字节流,并在内存中为之创建一个java.lang.Class对象
- 连接
2.1. 验证:用于检验被加载的类是否有正确的内部结构,并和其他类协调一致,主要为了确保虚拟机自身安全。大致包括四种验证:文件格式验证,元数据验证,字节码验证,符号引用验证。
2.2. 准备:为类的静态变量分配内存,并设置默认初始值
2.3. 解析:将类的二进制数据中的符号引用替换成直接引用
-
初始化:执行类构造器<clinit>()方法的过程。为类的静态变量(即类变量)赋予正确的初始值。
二、两个不同的类加载器加载同一个类,如何进行区分和隔离?
双亲委派模型:如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器,如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载。
双亲委派机制可以避免类的重复加载、防止核心API库被随意篡改。
在Java虚拟机中,即便是同样的字节代码,被不同的类加载器加载之后所得到的类,也是不同的。
- 每个类装载器都有自己的类名称空间,其中维护着由它装载的类型。所以一个JAVA程序可以多次装载具有同一个全限定名的类型。这样一个类型的全限定名就不足以确定在一个JAVA虚拟机中的唯一性。因此,当多个类装载器都装载了同名的类型时,为了唯一表示该类型,还要在类型名称前加上装载该类型的类装载器来表示。
- 在同一个命名空间内的类可以直接进行交互,而不同的命名空间中的类甚至不能觉察彼此的存在,除非显示地提供了允许它们进行交互的机制,如获取Class对象的引用后使用反射来访问
在类加载器的灵活应用:web容器Tomcat、OSGI
网友评论