`
andyliuxs
  • 浏览: 139425 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

JVM(类加载器)

阅读更多
从网上看到得这一系列的文章,感觉不错就转过来供自己深入了解java使用



     类加载器是沙箱的第一道防线,毕竟代码都是由它装入jvm中的,其中也包括有危险的代码。它的安全作用有三点:

一 保护善意代码不受恶意代码的干扰
二 保护已验证的类库
三 代码放入有不同的行为限制的各个保护域中



      类加载体系通过使用不同的类加载器把类放入不同的名字空间中从而保护善意代码不受恶意代码的干扰。

     JVM为每个类加载器维护一个名字空间。例如,如果jvm在某个名字空间中加载了一个称为volcano的类,就不能再在这个名字空间中加载另一个也称为volcano的类,除非你再创建另一个名字空间。也就是说,如果jvm有三个名字空间,你就可以加载三个叫做volcano的类,一个名字空间一个。

     在jvm中,同一个名字空间中的类是可以直接交互的,但在不同名字空间中的类就不行,除非提供另外的机制。这样,名字空间就起到了一个屏障的作用。

     在图3-1中(转载的地方就没图,也不知道网上相同的源头在哪里),显示了两个名字空间,各有一个类加载器,各加载了两个类型,两个名字空间都有一个叫做volcano的类型。左边颜色较深的类加载器加载了类型climber和volcano,右边颜色较浅的类加载器加载了类型bakingsoda和volcano。图中的箭头表示名字空间中的名字对在方法区(method area)中对应类型定义数据的引用。因为名字空间的屏障作用,当climber引用volcano时,是指的同一个名字空间中的volcano。尽管都在同一个jvm,它也无法知道另一个名字空间中的volcano。如果想知道如何达到名字空间的分隔的,可以看第八章“链接模式”(估计需要看哪本书吧,不过都没说出自哪本书,我倒是想看看)

     类加载器体系可以通过使用不同的类加载器加载可信包(trusted packages)和不可信包(untrusted packages)从而保护可信包的安全。尽管你可以对同一包中的类型制定访问控制,但这种控制只有在被同一个加载器加载的前提下才起作用。

     通常,一个用户定义的类加载器需要依赖其他类加载器来完成任务,至少需要一个在jvm启动时创建的类加载器,这个类加载器称为启动类加载器。在1.2版本以前,类加载器必须显示的调用其他类加载器,如调用其他用户定义的类加载器的loadClass方法,或者调用启动类加载器(bootstrap class loader)的静态函数findSystemClass()。
在1.2版本中,一个类加载器要求另一个类加载器加载某个类型的过程被规范化为代理模式(parent-delegation model 译者:就是Chain of Responsibility模式)

    在某个类加载器试图以自己的方式加载一个类时,它首先缺省把这个工作交给自己的父对象。而这个父对象又会首先把这个任务交给自己的父对象处理,这样这个任务会一直传到启动类加载器,因为启动类加载器通常是代理链的最后一个类。如果父类加载器能够加载这个类型,就会返回此类型,否则由子类加载器处理。
在1.2版本以前的多数jvm的实现中,内建类加载器负责加载本地可用的类文件,通常包括java应用的类文件和所有这个应用需要的库,尽管加载所需类文件的方式根据应用不同而不同,但许多应用都以class path定义的路径来搜寻所需类文件。

    在1.2版本中,加载本地可用类文件的任务被分解给了多个类加载器。以前称为原始类加载器(primordial class loader)的类加载器被改称为启动类加载器,用来表示它只用来加载核心java api的类文件,因为核心java api类文件是用来启动jvm的。

    而负责加载其他类文件的任务都给了用户定义的类加载器(译者:这里指广义用户,包括虚拟机的实现者),这些类文件包括应用的类文件,用来进行安装和下载的标准扩展类文件,用来在class path中查找库的类文件等等。
因此当1.2的JVM开始运行时,它会创建至少一个用户定义的类加载器,所有的这些类加载器串成一个链,在链的头部是启动类加载器,在链的尾部是系统类加载器(system class loader)。在1.2之前,有时称内建类加载器为系统类加载器,在1.2,这个名字被更正式的用于称呼java应用所创建的新的类加载器的父亲。

    这个缺省父代理通常来加载应用的初始类,但任何用户定义的类加载器都可能被java平台的设计者所改变。
例如,假如你写了一个应用,此应用需要安装一个类加载器,用来加载从网络上下载的类文件。这个应用运行在一个jvm上,而这个jvm有两个用户定义的类加载器,一个是安装扩展类加载器,另一个是类路径类加载器。它们和启动类加载器串成一个链,依次为:启动类加载器,安装扩展类加载器,类路径加载器。

    如图3-2,类路径加载器被设计成了系统类加载器,它将是java应用新的类加载器的父亲。当你的应用的网络类加载器被安装时,它将这个系统类加载器设为它的父亲。

    假如在java应用运行中需要加载一个称为volcano的类,你的类加载器会首先把这一任务交给它的父亲,类路径类加载器,去查找和加载这个类文件。而类路径类加载器同样首先交给自己的父亲,安装扩展类加载器,去完成任
务。这样,这个任务最后交给启动类加载器去首先尝试处理。

   假设类volcano不是java api的一部分,也不是安装扩展和类路径的一部分,所有对应的类加载器都没有返回这个类型,这样就轮到你自己的类加载器了。它将会从网络上下载此类文件,这样这个类就称为你应用中的一部分了。
   我们继续这个例子,假如以后某个时候第一次调用了类volcano的一个方法,这个方法中引用了java api中的类java.util.HashMap,而这个类是这个应用第一次引用,这样jvm就要求你的类加载器去加载这个类。象以前一样,这个请求最终到达了启动类加载器。

   但这次不同,启动类加载器能够加载java.util.Hashmap并把它返回给了你的类加载器。这样安装扩展类加载器和类路径类加载器只起到了一个传递的作用,而你的类加载器也不用从网络下载这个类文件了。从此,在类volcano中,所有对java.util.Hashmap的引用都会使用这个类。

   有了这个背景知识,我们就可以看看类加载器是如何被用来保护可信库(trusted libraries)的了。类加载器体系通过防止不可信类冒充可信类保护了可信类的边界,防止了对java runtime安全的潜在威胁。
   有了这个链状的代理关系,我们知道,要加载一个类,需要链上的类加载器按特定顺序逐次检查,这样自己定义的类加载器始终处于一个较低优先级的状态,如果你自己的类加载器想要从网络上下载一个叫做java.lang.Integer的类是不可能的。它只能使用从父类加载器传来的类型。通过这种方法,防止了用不可信代码替换可信代码的发生。

   但假如代码不准备去替换一个可信类型,而只想在可信包中插入一个新类型呢?假如在前面例子中,你的网络类加载器想加载一个叫做java.lang.Virus的类。象以前一样,加载类的要求在链内传递,直到启动类加载器,尽管启动类加载器负责加载核心java api的类,其中也包括一个叫java.lang的包名,但找不到Virus,我们假设这个类同样在安装扩展类加载器和类路径类加载器中也没有找到。这样你的网络类加载器就从网络上下载了这个类。
   假设你成功下载了类java.lang.Virus,Java对在同一个包中的类的相互访问有一定的特权。因此,因为你的类加载器加载了一个无耻的宣称自己是java api的一部分的类java.lang.Virus,你肯定希望能够享受到某种特权,从而干一些罪恶的勾当。但类加载机制制止了这种事情的发生,因为类加载机制限制这种特权只有在同一个类加载器加载的前提下。

因为java api的java.lang包中的可信类都由启动类加载器加载,而邪恶的java.lang.Virus由你的网络类加载器加载,他们并不属于同一个运行包(runtime package)。

   运行包这个术语首次在jvm第二版的规范中引入,指由同一个类加载器加载的同一个包中的所以类型。
在允许同一个包中的两个类型访问之前,jvm还有确信此两个类型是由同一个类加载器加载的。
    因此,jvm不允许java.lang.Virus去访问java api中java.lang 包中的其他类型,因为他们不是由同一个类加载器加载的。

    引入运行包的目的之一就是使用不同的类加载器加载不同类型的类文件。启动类加载器用来加载最值得信赖的核心java api。安装扩展类加载器用来加载安装扩展的任何类文件。虽然安装扩展也是可以信赖的,但还没有到可以向java api添加新类型的程度。同样,类路径类加载器加载的类也不能访问安装扩展和java api中的类型。

    类加载器也可以简单的禁止加载某些类型来保护可信代码。

    例如,你可能安装了某些包,其中有一些类你想由类路径类加载器来加载,而不是你的网络类加载器。
     假设你创建一个叫做absolutepower的包,并把它安装在了类路径类加载器的访问范围内。同时你希望由你的类加载器加载的类不能加载absolutepower包中任何类。这样在你的类加载器中的第一件事就是检查需要加载的类是不是把自己声明为absolutepower中的类,如果是,则抛出一个异常,并不是交给父类加载器来处理。
类加载器机制除了屏蔽不同名字空间,保护可信类库外,还把每个加载的类放到了一个保护域(protection domain)中,保护域对类的活动范围也有一个定义。
分享到:
评论

相关推荐

    JVM类加载器 test

    JVM类加载器 test

    JVM类加载器说明文档

    总结,Java 类加载器是JVM中的重要组成部分,它决定了类的加载过程和加载源,双亲委派机制保证了类加载的有序性和安全性。理解类加载器的工作原理有助于我们更好地进行程序设计和优化,特别是在开发插件系统、模块化...

    jvm类加载器基础解析

    JVM类加载器主要包括引导类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)和应用类加载器(Application ClassLoader)。 1. 引导类加载器(BootStrap):它是JVM内置的加载器,采用C++...

    JVM实战-JVM类加载机制案例分析

    2. **类加载器及类加载器的委托机制**:JVM中有三种内置的类加载器,分别是启动类加载器、扩展类加载器和应用类加载器。此外,还可以自定义类加载器。类加载器之间遵循委托机制,即下级类加载器先请求上级类加载器...

    JVM类加载机制详细讲解

    例如,当我们尝试加载 `java.lang.Object` 类时,首先会由启动类加载器加载,如果它找不到,会继续交给扩展类加载器,接着是系统类加载器,最后才会由用户自定义的类加载器尝试加载。 1.3 类加载双亲委派示例 为了...

    JVM、Tomcat、OSGI等类加载器整理文档

    在Java世界中,类加载器(ClassLoader)是关键组件,它们负责将类的字节码加载到Java虚拟机(JVM)中。JVM、OSGI(Open Service Gateway Initiative)和Tomcat等容器都涉及到了类加载器的概念,理解它们的工作原理对...

    深入Java虚拟机_002_深入详解JVM之类加载器深度剖析、根、扩展及系统类加载器

    本部分我们将深入探讨JVM中的类加载器,特别是根类加载器、扩展类加载器和系统类加载器。 首先,让我们了解类加载的基本过程。当JVM启动时,会触发类加载。这个过程分为三个阶段:加载、链接和初始化。加载阶段,类...

    JVM类加载过程.pptx

    Java代码执行流程是JVM的核心流程之一,它首先通过编译器把Java代码转换成字节码,然后通过类加载器加载到内存中,并将其放在运行时数据区的方法区内。最后,执行引擎将字节码翻译成底层系统指令,再交由CPU去执行。

    wanglijun93#AndroidNote#JVM类加载器1

    第一阶段要验证字节流是否符合Class文件格式的规范,并且能被当前版本的虚拟机处理 第二阶段是对字节码描述的信息进行语义分析,以保证其描述的信息符合Java语言

    JVM类加载分析

    类加载器是JVM实现动态加载的核心组件,它的主要任务是根据类名找到对应的.class文件,并将其转换为内存中的Class对象。Java中的类加载器主要有以下几种: 1. Bootstrap ClassLoader:引导类加载器,负责加载JRE...

    JVM类加载跟踪器

    JVM类加载跟踪器,用于排查jar包冲突、类冲突、类版本冲突、NoClassDefFoundError、ClassNotFoundException 等等类加载相关问题的辅助工具

    【JVM】类加载器与双亲委派模型

    Java虚拟机(JVM)的类加载器是Java运行时环境的重要组成部分,它负责将类的字节码(class文件)加载到JVM的方法区,从而使得程序能够执行。类加载器按照特定的规则工作,其中最核心的就是双亲委派模型。 类加载器...

    JVM:类加载器子系统.pdf

    Java虚拟机(JVM)的类加载器子系统是Java运行时环境的一个重要组成部分,它负责将.class文件加载到内存中,并生成对应的Java类对象。这一过程涵盖了从文件系统或网络获取.class文件、验证类文件的正确性、准备类...

    从JDK源码级别剖析JVM类加载机制

    JVM使用类加载器(ClassLoader)来完成这一任务。在Java中,每个类都由一个对应的ClassLoader实例负责加载。默认的类加载器包括Bootstrap ClassLoader(引导类加载器)、Extension ClassLoader(扩展类加载器)和...

    类加载器文件

    - **直接引用**: 当一个类直接引用另一个类时(例如,类A引用类B),JVM会使用加载类A的类加载器来加载类B。 - **反射调用**: 使用`Class.forName()`方法也会触发类的加载。 - **初始化**: 当类的静态块或静态成员被...

    java类加载器

    在Java中,类加载器(Class Loader)是一项核心机制,用于将字节码(.class文件)加载到JVM中,使其成为运行时的对象。类加载器不仅实现了类的加载功能,还确保了Java程序在多线程环境中的安全性和隔离性。类加载器...

    Java虚拟机JVM类加载初始化

    这些内置的类加载器加载的类在JVM生命周期中不会被卸载。而用户自定义的类加载器加载的类,当它们的`Class`对象不再被引用时,可能会被卸载,以节省内存资源。 了解类加载机制对于优化性能、理解和解决类加载相关...

Global site tag (gtag.js) - Google Analytics