`
hanzhicheng754
  • 浏览: 7732 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类

Java 类装载器详解

阅读更多
Java类装载器详解

一:标准JavaSE 类装载器
    1.标准JavaSE 类装载器概述
        本质上来说,类装载器是以某种方式,读取Java类的class文件到JVM中,并将class文件中的信息写入到内存中的一种机制。Java语言中的类装载器可以分为两种:一种是用Java语言编写的(Java程序员只需要关注这种类型的类装载器即可);一种不是用Java语言编写的,我们称之为启动类装载器,它是Java虚拟机实现的一部分。
    2.启动类装载器
        顾名思义,启动类装载器是用于装载JVM启动时需要的Java类。实际上,启动类装载器负责装载所有核心的Java类(例如 java.lang.*和 java.io.*)。启动类装载器以某种特定的方式从本地磁盘(Java虚拟机安装目录)中装载JVM运行所需的Java类。例如如果JVM是用C或者C++编写的,那么JVM的实现者可以调用C或者C++的API来装载Java class文件到JVM中。有些人知道了启动类装载器装载了核心的Java类,他们可能还想知道,启动类状态器具体在哪里找到这些类。JAR文件的查找方法因厂商的不同而变化。例如Sun的Java SE 5 JVM在<JDK>/jre/lib目录下查找JAR文件,尤其在<JDK>/jre/lib/rt.jar目录下查找启动类。对于Sun的JVM,可以使用 -Xbootclasspath 为JVM查找启动类的位置,一般而言,我们不需要这么做。
(启动类装载器在一个JVM实现中,只有一个。也有翻译成引导类装载器,原始类装载器的,但我觉得启动类装载器最为精确)
    3.扩展类装载器
        Java 1.2 引入了标准扩展机制。通常情况下,当我们想让JVM在某个特定的位置查找类文件时,我们会更改CLASSPATH环境变量,将类文件加入到CLASSPATH环境变量中。(或者使用 -classpath 选项)。Sun引入了标准扩展机制作为一个可选的方法,可以将JAR文件放入到标准扩展目录,JVM将自动找到他们。
       一般情况下,扩展类装载器是用Java语言编写的。标准扩展目录也会随着JVM厂商的不同而不同,Sun的JVM的标准扩展目录为<JDK>/jre/lib/ext。
    4.系统类装载器
        系统类装载器是Java 1.2引入的系统默认Java实现,当然,它是用Java编写的。系统类装载器在目录和CLASSPATH环境变量指定的JAR文件中查找自己的类,或者通过-classpath命令行选项传递的类。系统类装载器也用于装载应用程序的entry point类(即含有main()方法的类),对于那些其他任何没有上述的两类类装载器装载的类,都默认使用系统类装载器。
(系统类装载器有时被称为应用程序类装载器,虽然更为贴切,不过系统类装载器是Sun的约定)
二:委派模型
     
      如前所述,Java SE用于3种不同的类装载器。他们之间的关系可以用父子关系形容。启动类装载器是爷爷,系统类装载器是孙子,优先级最低。JDK1.2以后的JVM版本都会使用委派模型。当JVM受到装载类的请求时,只有在父类装载器未能装载该类的情况下,原始类(子类)才会尝试装载该类。举个例子来说,你定义了一个类名为A的类。当你请求装载该类时,系统类装载器会受到请求(为什么是系统类装载器会先收到请求?),他首先想到的不是自己去装载这个类,而是会想,难不成他在扩展类装载器那?于是乎他就找到扩展类装载器,问他类A在你那吗?扩展类装载器收到请求后第一件事情也不是做事,而是在想,难不成他在启动类装载器那?于是乎,他又找到了启动类装载器,问他了,喂看看类A在你那不?当然了,启动类装载器在接到请求后,第一件想到的事情也不是自己去装载类A啊,他也想问他老子啊,可他一看,他前面没人了啊 。于是乎,没办法,他就到自己的装载域中找找看有没有类A。找了半天,他没发现类A,他就告诉扩展类装载器,跟他说,我这没有啊 ,你自己找找看吧,扩展类装载器就去自己的装载域中找了,结果没发现,于是,他也只能不好意思的跟系统类装载器说,我这也没有啊 ,还是你自己来吧。于是,系统类装载器就自己去找了,他当然能找到啦,于是就把对象的引用返回了。(写了这么久的Java程序了,有没有弄清楚,JVM在什么时候装载一个类?)
三:Endorsed Standards Override 机制
    Java 1.4引入了称为 Endorsed Standards Override 机制的概念,在Java SE1.5中也可以使用该机制。随着时间的推移,核心的Java SE发布已经包括越来越多的Java扩展(曾经认为是可选的)。其中一个很好的例子就是J2SE 1.4包含XML处理的Java API(JAXP)。既包括JAXP的API类,也包括其实现。实现类包含在rt.jar中,启动类装载器将装载它们。因此,如果程序员将更新版本的JAXP实现与该JDK一起放到CLASSPATH中,新的版本将不能使用。
四:Java 类装载器在安全模型中扮演的角色
    在计算机的世界里,以说到安全问题,我们可就又回到了严肃而认真的问题上了。显然,类装载器体系位于Java安全模型的中心。(为什么?)是否还记得我们上述的三种类装载器,其中最重要的就是启动类装载器装载的类了,如果一个第三者的java.lang.String 插足到JVM中了,他成了你调用的String 类,结果他把你的硬盘给格了,你是否会崩溃?
   1.委派模型
    前述的委派模型通常被描述为一个安全特性。你看了之后是不是也觉得是那么回事呢?
启动类装载器装载了所有的JVM自带的核心Java API。任何装载核心的Java类的请求,都会在启动类装载器那获得它所保存的副本。
    但是,委派模型并不是JVM规范的一部分,所以委派模型在安全方面是存在缺陷的。(乖乖,又想到一个问题,为什么不把他加入到JVM规范中呢?那样Java岂不是更安全?)
   2.我们不是可以自定义类装载器吗?你要是不把请求委派给父类装载器,你怎么阻止别人装载java.lang.String呢?事实上任何用Java语言编写的类装载器,都不能装载核心的Java类。ClassLoader抽象类(所有类装载器必须继承的)禁止创建任何以java开始的类。你的类装载器还能装载核心的java类吗?不能吧?那还是让启动类装载器来干吧。
   4.第二条所述的只是在装载类的时候,限制了错误的核心类被装载,那么在运行时,怎么保证JVM的安全呢?Sun的策略有两种,第一就是独立的类装载器命名空间。
     JVM在运行时,会为每个类监视每个运行的类装载器,并为之分配一个唯一的命名空间。并且,当JVM在运行Java代码时,收到一个类发出装载另一个类的请求时,他会先找到装载发出请求的类的装载器,并用他来装载待装载的类。这样的话,不同的类装载器装载的类就会有不同的命名空间。同一个类装载器装载的类之间可以进行直接交换,不同的类装载器装载的类之间不可以进行直接交换,JVM会禁止这样的行为,除非你的程序显式的允许。大家都知道,在Java语言中,我们区分不同的类,是通过包名加类名(完全限定名),实际在JVM中,还会在你的类之前加上类装载器的命名空间。也就是说,两个不同的类装载器均装载了com.Test.java这个Java类,在JVM看来,会认为他们不是同一个类。这样的话,在运行状态下,恶意的代码就不能够破话善意的代码了。
   5.Security Manager
     如果真的想保证自定义类装载器不能破坏程序,可以在应用程序中完全阻止它。这可以通过Security Manager类完成。
    使用Security Manager和它的策略文件,可以在应用程序中阻止(或者不阻止)大量的任务。例如,可以阻止应用程序打开和某个网络主机的socket连接,或者打开某个本地文件。此外,还可以阻止应用程序装载类装载器。
    至于怎么使用Security Manager则又是另外一个话题了。
四:类装载器的其他行为
    1.延迟加载
    2.类缓存
   
五:为什么我们要学习类装载器
    这个问题问的真是好,我说了那么多废话,只是让我们学习了之后去写属于我们自己的类装载器吗?当然不是,很少情况下,我们需要写。
     那么,学习类装载器干什么?我们不知道他,还不是照样可以编程,照样做Java程序员,事实上,我也经常问自己这些问题
     由于本人Java的从业时间不长,知道的不多。
     目前来看,主要有:
     1.深入Java虚拟机的学习有帮助
     2.我在学习Tomcat时,也有很多帮助。比如Tomcat中不同的Context。
    
分享到:
评论
1 楼 medicine 2012-09-13  
l

相关推荐

    Java开发技术大全(500个源代码).

    HelloWorldApp.java 第一个用Java开发的应用程序。 firstApplet.java 第一个用Java开发的Applet小程序。 firstApplet.htm 用来装载Applet的网页文件 第2章 示例描述:本章介绍开发Java的基础语法知识。 ...

    java虚拟机详解.docx

    当虚拟机装载类文件的时候,它解析其中的二进制数据所包含的类信息,并把它们放到方法域中;当程序运行的时候,JVM把程序初始化的所有对象置于堆上;而每个线程创建的时候,都会拥有自己的程序计数器和 Java栈,其中...

    详解Java的Spring框架下bean的自动装载方式

    主要介绍了Java的Spring框架下bean的自动装载方式,Spring是Java的SSH三大web开发框架之一,需要的朋友可以参考下

    Java命令详解

    Java是通过java虚拟机来装载和执行编译文件(class文件)的,java虚拟机通过命令java option 来启动,-option为虚拟机参数,通过这些参数可对虚拟机的运行状态进行调整.  

    疯狂JAVA讲义

    学生提问:构造器是创建Java对象的途径,是不是说构造器完全负责创建Java对象? 141 5.5.2 构造器的重载 142 学生提问:为什么要用this来调用另一个重载的构造器?我把另一个构造器里的代码复制、粘贴到这个构造器...

    Java字节码(.class文件)格式详解((转载)

    NULL 博文链接:https://plkong.iteye.com/blog/1680902

    ClassLoader 详解.doc

    关于J2EE服务器的ClassLoader的原理,该文档清晰了揭示了jvm装载类的顺序,同时用户可以自定义修改classLoader的配置 通过该文档,可以加深对Java虚拟机的理解

    图文详解Java中class的初始化顺序

    网上有很多关于Java中class的初始化顺序文章,但是本文通过图文更加详细的介绍了Java中class的初始化顺序,并对class的装载顺序进行了讲解,下面一起来看看。

    集合小结 Collection

    java中各种集合详解! 集合(集合类的对象)是用来管理其他若干对象的。它类似于C++标准模板库中的容器,不过在JAVA的集合类的对象中可以用来存放多种类型的对象。 接口和类共同构成了一个集合框架,集合的概念,一...

    Spring.3.x企业应用开发实战(完整版).part2

    3.2.2 类装载器ClassLoader 3.2.3 Java反射机制 3.3 资源访问利器 3.3.1 资源抽象接口 3.3.2 资源加载 3.4 BeanFactory和ApplicationContext 3.4.1 BeanFactory介绍 3.4.2 ApplicationContext介绍 3.4.3 父子容器 ...

    Spring3.x企业应用开发实战(完整版) part1

    3.2.2 类装载器ClassLoader 3.2.3 Java反射机制 3.3 资源访问利器 3.3.1 资源抽象接口 3.3.2 资源加载 3.4 BeanFactory和ApplicationContext 3.4.1 BeanFactory介绍 3.4.2 ApplicationContext介绍 3.4.3 父子容器 ...

    Spring中文帮助文档

    2.3.4. 对AspectJ装载时织入(AspectJ load-time weaving)的支持 2.4. 中间层 2.4.1. 在XML里更为简单的声明性事务配置 2.4.2. 对Websphere 事务管理的完整支持 2.4.3. JPA 2.4.4. 异步的JMS 2.4.5. JDBC ...

    Spring API

    2.3.4. 对AspectJ装载时织入(AspectJ load-time weaving)的支持 2.4. 中间层 2.4.1. 在XML里更为简单的声明性事务配置 2.4.2. 对Websphere 事务管理的完整支持 2.4.3. JPA 2.4.4. 异步的JMS 2.4.5. JDBC ...

    iuhyiuhkjh908u0980

    PrettyFaces优雅的解决了这个问题,包括诸如功能:网页装载行动,无缝的跟faces的导航整合,动态视图的ID分配和管理参数分析,无需配置,兼容其他JSF框架。P ... by zly06 2009-09-09 回复 (0) 相关博客 ant模板 ...

    webx3框架指南PDF教程附学习Demo

    现在有很多Java的Web框架可供选择,并且它们也都是免费的。例如: • Struts • Webwork • Tapestry • Spring MVC 以上框架都是非常优秀的。说实话,如果阿里巴巴网站在2001年开始,就有这么多可选择的话,...

Global site tag (gtag.js) - Google Analytics