类装载器实现Java虚拟机安全(三)

来源:互联网 发布:大津算法 opencv 编辑:程序博客网 时间:2024/06/06 05:37

前言

今天继续聊类装载器是如何实现安全的,这些细节一定是你以前没有注意到的,深入底层的知识往往是我们最容易逃避的,小疯子写在头条里,希望你停下来娱乐的时候也能花个3分钟看看,对你是否有所启发?喜欢的一定点收藏,关注哦,每天都会在更新。

基本看完的人都收藏起来了。

类装载器实现Java虚拟机安全(三),看完100%的人都收藏了

正文

  1. 类装载器

类装载器体系结构守护了被信任类库的边界,因为类加载器的类型不同,装载以后分别放入不同的包里,包与包之间一般情况下是不能访问的。

在版本1.2开始,除了启动类装载器以外的每一个类装载器,都有一个“双亲”类装载器,在某个特定的类装载器试图以常用方式装载类型以前,它都会以默认的方式,把这个类委托给它的双亲来处理——请求双亲来装载这个类型。这个双亲再依次请求它自己的双亲类来处理,依次类推,直到到达启动类装载器,因为启动类装载器是没有双亲的,处于最顶层了。在这个传递过程中,如果有一个双亲类装载器有能力装载这个类型,则这个类型的类装载器返回这个类型,否则,这个类装载器试图自己来装载这个类型。

下面我们就接着分析一下启动类加载器、标准扩展类加载器和系统类加载器三者之间的关系。可能大家已经从各种资料上面看到了如下类似的一幅图片:

类装载器实现Java虚拟机安全(三),看完100%的人都收藏了

启动类装载器只负责加载那些核心的Java API的class文件,因为核心Java API的class文件是用于“启动”Java虚拟机的class文件,所以,启动类装载器的名字也因此而得。

用户自定义的类装载器来负责其他class文件的装载,在应用程序启动以前,它至少创建一个用户自定义类装载器,也可能创建多个,所有这些类装载器被连接在一个双亲-孩子的关系链中,在这条链的顶端是启动类装载器,末端是系统类装载器,它是由Java应用程序创建的,新的用户定义类装载器的默认委派双亲。

这里就简要叙述一下一般用户自定义类加载器的工作流程吧:

1、首先检查请求的类型是否已经被这个类装载器装载到命名空间中了,如果已经装载,直接返回;否则转入步骤2;

2、委派类加载请求给父类加载器(更准确的说应该是双亲类加载器,真实虚拟机中各种类加载器最终会呈现树状结构),如果父类加载器能够完成,则返回父类加载器加载的Class实例;否则转入步骤3;

3、调用本类加载器的findClass(…)方法,试图获取对应的字节码,如果获取的到,则调用defineClass(…)导入类型到方法区;如果获取不到对应的字节码或者其他原因失败,返回异常给loadClass(…), loadClass(…)转而抛异常,终止加载过程(注意:这里的异常种类不止一种)。

这里就不在细说了,一般熟悉类加载器这部分知识应该都比较熟悉,我们来继续将,类加载器怎么实现安全的!

类装载器实现Java虚拟机安全(三),看完100%的人都收藏了

类装载器的体系结构是通过剔除装作被信任的不可靠的类,来保护那些可信任类库的边界,如果某个恶意的类可以成功的欺骗Java虚拟机,使得Java虚拟机相信它是一个来自可靠源的可信类,那么,这个恶意类就可能突破沙箱的阻隔,为了防止这样的情况,类装载器体系结构阻塞了危机Java虚拟机运行时安全的潜在途径。

在双亲委派的情况下,启动类装载器会在最可信的类库-核心Java API-中检查每个被装载的类型,然后,才依次到标准扩展,类路径上的本地类文件中检查,所以,如果网络类装载器装载的某个代码执行时,想要从网络上下载一个和Java API中某个类型同名的类,例如Java.lang.Integer,它将不能成功,如果Java.lang.Integer的class文件已经存在,将不会再装载,它只能使用由它的双亲委派返回的类,这个类是由启动类装载器装载的,用这种方法,类装载器的体系结构就可以防止不可靠的代码用自己的版本来替代可信任的类。

还有一种可能,就是,我不是去替代你这个被信任的类,我是要在你被信任的类库里插入一个全新的类型,会怎么样?

比如我们下载了一个类Java.lang.virus,这个请求一路向上委派给启动装载器,但它无法找到这个成员,同时在已扩展以及本地类路径中也找不到,你的类装载器将试图从网络上下载这个类。

Java允许同一个包里面的类拥有相同的权限,而包外面的类则没有这个权限,你的类加载进Java.lang 包,那么也就拥有这个包的所有权限,它就可以其中被信任的类,这样的一个不可靠的类的存在太可怕了!

Java虚拟机是这样布置的,不同的类加载器加载的类放在不同的包里,于是,这个从网络上下载的类所属于的包跟启动类装载的类并不是在一个包里面,这样,它就得不到其他可信任类的信息。而两个包之间要允许可见,必须满足同一个类装载器装载,这样就可以避免不可靠类的侵犯。

下一节我们会将class文件检查器!喜欢一定要关注收藏哦!

阅读全文
0 0