classLoader如何加载class【双亲委托模式】_双亲委托模式中的classload方法_咸粽的博客-程序员秘密

技术标签: javaSE  

ClassLoader【双亲委托模式进行类加载】

它是用来加载Class文件到JVM(Java Virtual Machine(Java虚拟机)的缩写)。
以供程序使用的。我们知道,Java程序可以动态加载类定义,而这个动态加载的机制就是
通过ClassLoader来实现的。
其中有一个ClassLoader不是用Java语言所编写的,而是JVM实现的一部分,这个
ClassLoader就是bootstrap classloader(启动类加载器),这个ClassLoader
在JVM运行的时候加载Java核心的API以满足Java程序最基本的需求,其中就包括用户自
定义的ClassLoader,这里所谓的用户自定义是指通过Java程序实现的ClassLoader,
一个是ExtClassLoader,这个ClassLoader是用来加载Java的扩展API的,也就是
/lib/ext中的类。另一个是AppClassLoader,这个ClassLoader是用来加载用户机器
上CLASSPATH设置目录中的class的,通常在没有指定ClassLoader的情况下,我们自
定义的类就由该ClassLoader进行加载。
当运行一个程序的时间,JVM启动,运行bootstrap classloader,该ClassLoader加
载Java核心API(ExtClassLoader和APPClassLoader也在此时被加载),然后调用
ExtClassLoader加载扩展API,最后APPClassLoader加载CLASSPATH目录下定义的
class,这就是一个程序最基本的加载流程。
每一个自定义ClassLoader都必须继承ClassLoader这个抽象类,而每个ClassLoader
都会有一个parent ClassLoader,我们可以看一下ClassLoader这个抽象类中有一个
getParent()方法,这个方法用来返回当前ClassLoader的parent,注意,这个parent
不是指定的被继承的类,而是在实例化该ClassLoader时指定的一个ClassLoader,如果
这个parent为null,那么就默认该ClassLoader的parent是bootstrap classloa-
der,这个parent有什么用呢?

我们可以考虑这样一种情况,假设我们自定义了一个ClientDefClassLoader,我们使用
这个自定义的ClassLoader加载java.lang.String,那么这里String是否会被这个
ClassLoader加载呢?事实上,java.lang.String这个类并不是被这个ClientDef-
ClassLoader加载,而是由bootstrap classloader进行加载,为什么会这样?实际
上这就是双亲委托模式的原因,因为在任何自定义ClassLoader加载一个类之前,它都会
先委托它的父亲ClassLoader进行加载,只有当父亲ClassLoader无法加载成功后,才会
由自己加载,在上面这个例子里,因为java.lang.String是属于Java核心API的一个类,
所以当使用ClientDefClassLoader加载它的时候,该ClassLoader会先委托他的父亲
ClassLoader进行加载,当ClassLoader的parent为null时,ClassLoader的parent
就是bootstrap classloader,所以在ClassLoader的最顶层就是bootstrap 
classloader,因此最终委托到bootstrap classloader的时候,bootstrap 
classloader就会返回String的Class。

下面我们看一下ClassLoader中的一段源码:

public class Snippet{
    
 
    protected synchronized Class loadClass(String name,boolean resolve) throws
        ClassNotFoundException{
    
        //首先检查该name指定的class是否被加载
        Class c = findLoadedClass(name);
        if(c==null){
    
            try{
    
                if(parent!=null){
    
                //如果parent不为null,则调用parent的loadClass进行加载
                c=parent.loadClass(name,false);
                }else{
    
                //如果parent为null,则调用BootstrapClassLoader进行加载
                c=findBootstrapClass0(name);
                }
       }catch(ClassNotFoundException e){
    
            //如果仍然无法加载成功,则调用自身的findClass进行加载
            c=findClass(name);
        }
  }
        if(resolve){
    resolveClass(c);}
        return c;
 }             
}

从上面的一段代码,我们可以看出一个类加载的大概过程,与我们刚开始所举的例子是一样的,而我们要实现一个自定义类的时间,只需要实现findClass方法即可。
为什么要使用这种双亲委托模式呢?
1:避免重复加载,当父亲已经加载过该类的时候,就没有必要再加载一次了
2:考虑到安全因素,试想一下,如果不使用这种模式,我们可以随时的用自定的String来动态替代java核心API中定义类型,这样存在非常大的安全隐患

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/g_l_xz/article/details/103331013

智能推荐

10分钟学会在Ubuntu 18.04 LTS上安装NFS服务器和客户端_weixin_33858485的博客-程序员秘密

https://www.linuxidc.com/Linux/2018-11/155331.htm转载于:https://www.cnblogs.com/clemente/p/10734265.html

iOS开发之通过cocoapods导入第三方类库_鹰击长空KO的博客-程序员秘密

在我们从终端安装了cocoapods之后,接下来学习从cocoapods上导入第三方类库。一、比如说我们要导入AFNetWorking,首先打开终端输入命令1. pod search afnetworking会出现下图所示的一些第三方类库二、选择我们要导入的3.0.4版本2.  pod 'AFNetworking', '~> 3.0.4'把这些命令复制一

ACL-设置权限,selinux,网络用户介绍,nfs客户端的使用_selinux需要开启那些,才可以访问nfs_/*守护她的笑容的博客-程序员秘密

文章目录ACL-设置权限用ACL为用户授权设置mask权限设置默认权限(只能对目录执行)selinuxselinux工作方式selinux的上下文selinux的几种模式selinux的布尔值(真或假)网络用户介绍nfs客户端的使用主服务器配置客户端配置ACL-设置权限用ACL为用户授权当我们需要对具体的某个用户/组,进行权限设置的时候,我们要考虑用ACL;setfacl -m u:用户名...

为在telnet自己TCP服务器程序的界面上实现shell一样的自动补齐和历史记录的功能。_ren911的博客-程序员秘密

1. 目的希望在telnet自己TCP服务器程序的界面上实现shell一样的自动补齐和历史记录的功能。2. 问题程序的远程登陆的telnet界面通常是通过一个TCP服务器来实现的,但是如果想在这个TCP服务器端实现客户端登陆界面的自动补齐和历史记录的功能会有如下的问题:(1)常见的telnet客户端是以行模式发送数据的,即输入一个字符串后再按一个回车,整个数据才会被发送到服务器端。(2)常见的telnet客户端是自动回显的,即你在键盘上输入一个字符后,客户端自己将这个字符显示在客户端界面上,而不是显示的从服

Django3.0.3自定义错误界面报错handler404,handler500&静态文件加载_yanyanforest的博客-程序员秘密

自定义404,500 报错错误如下所示The custom handler404 view 'standard.views.page_not_found_error' does not take the correct number of arguments (request, exception). ?: (urls.E007) The custom handler500 view 'st...

provider模式_weixin_30740295的博客-程序员秘密

最近看代码有所感想吧。当底层API,发生变化时,可以使用Provider模式。既然是模式就一定的股则。1.该模式对原有接口的封装。2.该模式实现对API的封装,不显示细节,从而取消依赖关系。3.provider可以将多个接口,合并在一起。转载于:https://www.cnblogs.com/wcLT/p/4592507.html...

随便推点

php接口加密_php secret_stand_forever的博客-程序员秘密

首先双方协商一个秘钥secret 然后按照统一的规则加密 md5/sha1等......请求接口需要携带 sign,timestamp参数中间件:接收传过来的参数 校验是否非法请求protected $secret = 'dwwww123';/**校验是否是合法请求 * @param $data * @throws CustomErrorMessageException */protected function checkSign($data){ if (!isset($d.

在思科模拟器上通过TFTP拷贝路由器的配置文件到本地_weixin_33775582的博客-程序员秘密

(1)服务器的配置: 首先设置服务器的IP地址为192.168.1.1,这里可以使用PC机,但在使用前,先要下载TFTP软件,并将其按装在C盘上,保持TFTP软件的打开。如图所示:(2)路由器的配置:Router>enableRouter#Router#configure terminalRouer(config)#interface f0/0Router(c...

DiskGenius安装教程_Roc-xb的博客-程序员秘密

DiskGenius是一款磁盘分区及数据恢复软件,支持对GPT磁盘(使用GUID分区表)的分区操作和VMware、Virtual PC、VirtualBox虚拟硬盘格式。DiskGenius除了具备基本的分区建立、删除、格式化等磁盘管理功能,还提供了强大的已丢失分区搜索功能、误删除文件恢复、误格式化及分区被破坏后的文件恢复等功能。...

使用hutool加密解密AES-程序员秘密

使用hutool加密解密AES

推荐文章

热门文章

相关标签