类加载器和类加载过程,java加载类的三种方式
一、类与类加载器
类装入器:装入阶段的第一步是通过类的完全限定名将类的二进制字节流装入jvm。
类装入器:任何类的唯一性都是由其本身和装入它的类装入器决定的。两个类是否相等的前提是由同一个类装入器装入。
jvm中有两种类装入器:一种是Bootstrap类装入器,用C实现;另一个是所有其他用java实现的类装入器。
从java程序的角度来看:
1)启动类加载器:负责加载JAVA_HOME\lib目录或-Xbootclasspath参数指定的路径中的类。另外,文件名需要被虚拟机识别,不被jvm识别就不能加载。
2)扩展类加载器:负责加载JAVA_HOME\lib\exit目录或java.exit.dirs系统变量指定的路径下的所有类库。
3)应用类加载器(系统类加载器):是类加载器中getSystemClassloader()方法的返回值。负责加载用户类路径上指定的类库。如果应用程序中没有自定义的类加载器,这就是应用程序中的默认类加载器。
免费在线视频教学:java视频教程
二、双亲委派模型
如何解决写爬虫IP受阻的问题?立即使用。
除了顶级启动类装入器,所有其他类装入器都有自己的父类装入器。父子关系不是通过继承实现的,而是通过组合关系重用父类加载器。
工作过程:类加载器收到类加载请求——将请求委托给父类加载器(直到顶层类加载器启动)——父类尝试加载,加载失败反馈给子类加载器——子类加载器尝试加载。
父委托模型的好处:保证了java底层API的稳定性,避免了加载相同基本类名(对象)的自定义类造成java基本行为的混乱,导致多个不同类同名。
双亲委派模型源码:
该方法增加了同步锁来保证线程安全。首先,检查类是否已经被加载。如果还没有加载,调用父类加载器的loadClass()方法。如果父类装入器为空,则调用启动类装入器。
如果父类加载失败,会抛出ClassNotFoundException,调用自己的findClass()方法进行加载。
受保护阶层?loadClass(字符串名称,布尔解析)
引发ClassNotFoundException
{
//同步锁
synchronized(getClassLoadingLock(name)){
//首先检查这个类是否已经加载。
班级?c=findLoadedClass(name);
if (c==null) {
long t0=system . nano time();
尝试{
如果(家长!=null) {
//如果父类不为空,则调用父类加载器的loadClass方法
c=parent.loadClass(name,false);
}否则{
//如果没有父类,默认调用启动类加载器加载。
c=findBootstrapClassOrNull(name);
}
} catch(ClassNotFoundException e){
//如果父类加载器找不到该类,则抛出ClassNotFoundException
}
if (c==null) {
//当父类加载器失败时,调用自己的findClass方法进行加载。
long t1=system . nano time();
c=find class(name);
//记录
sun . misc . perf counter . getparentdelegationtime()。添加时间(t1-t0);
sun . misc . perf counter . getfindclasstime()。addElapsedTimeFrom(t1);
sun . misc . perf counter . getfindclass()。increment();
}
}
如果(解决){
resolve class(c);
}
返回c;
}
}三、破坏双亲委派模型
1.第一次破坏
JDK1.2之后出现了父委托模型,而类加载器和抽象类java.lang.ClassLoader已经存在。
因此,为了向前兼容,在JDK1.2之后,一个新的受保护的方法findClass被添加到ClassLoader中。用户在findClass方法中编写自己的类加载逻辑,而不是重写loadClass方法,以保证自定义的类加载符合父委托模型。
2.第二次破坏
模型本身是有缺陷的。父母委托可以保证每个类装入器的基础类的统一性,这在用户代码调用基础类时不适用,但是如果基础类回调用户代码。比如涉及SPI的场景,用来加载需要的SPI代码。
SPI机制介绍参考其他文章。
为了解决这个问题,引入了线程上下文类加载器。这个类加载器可以由java.lang.Thread类中的setContextClassLoader()方法设置。如果在创建线程时没有设置它,它将从父线程继承一个。如果全局没有,默认情况下它将是应用程序类加载器。使用这个加载器,父类加载器可以请求子类加载器加载。
3.第三次破坏
由于追求程序动态,比如热部署,热替换等。
例如,模块化标准OSGi R4.2将母公司委托的树形结构改变为更复杂的网络结构。
java文章教程推荐:java入门教程以上是对java加载器的详细了解。请多关注我们的其他相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。