`
VerRan
  • 浏览: 458656 次
  • 性别: Icon_minigender_1
  • 来自: 陕西.西安
社区版块
存档分类
最新评论

类装载器学习

    博客分类:
  • JAVA
阅读更多

Java的类装载器(Class Loader)和命名空间(NameSpace)

 

1.摘要:

Java的类装载器是Java动态性的核心,本文将向大家简要介绍Java的类装载器,及相关的双亲委派模型,命名空间,运行时包等概念,同时讨论一些在学习中容易混淆的问题。

 

2.类装载器的功能及分类:

顾名思义,类装载器是用来把类(class)装载进JVM的。JVM规范定义了两种类型的类装载器:启动内装载器(bootstrap)和用户自定义装载器(user-defined class loader)。

 

bootstrap是JVM自带的类装载器,用来装载核心类库,如java.lang.*等。由例1可以看出,java.lang.Object是由bootstrap装载的。

 

Java提供了抽象类ClassLoader,所有用户自定义类装载器都实例化自ClassLoader的子类。

System Class Loader是一个特殊的用户自定义类装载器,由JVM的实现者提供,在编程者不特别指定装载器的情况下默认装载用户类。系统类装载器可以通过ClassLoader.getSystemClassLoader() 方法得到。

 

例1,测试你所使用的JVM的ClassLoader

/*LoaderSample1.java*/

public class LoaderSample1

{

       public static void main(String[] args)

       {

              Class c;

              ClassLoader cl;

             

              cl = ClassLoader.getSystemClassLoader();

              System.out.println(cl);

             

              while (cl != null)

              {

                     cl = cl.getParent();

                     System.out.println(cl);         

              }

 

              try

              {

                     c = Class.forName(“java.lang.Object”);

                     cl = c.getClassLoader();

                     System.out.println(“java.lang.Object’s loader is ” + cl);

 

                     c = Class.forName(“LoaderSample1”);

cl = c.getClassLoader();

                     System.out.println(“LoaderSample1’s loader is ” + cl);

              }

              catch (Exception e)

              {

                     e.printStackTrace();

}

       }

}

 

在我的机器上(Sun Java 1.4.2)的运行结果

sun.misc.Launcher$AppClassLoader@1a0c10f

sun.misc.Launcher$ExtClassLoader@e2eec8

null

java.lang.Object's loader is null

LoaderSample1's loader is sun.misc.Launcher$AppClassLoader@1a0c10f

 

第一行表示,系统类装载器实例化自类sun.misc.Launcher$AppClassLoader

第二行表示,系统类装载器的parent实例化自类sun.misc.Launcher$ExtClassLoader

第三行表示,系统类装载器parent的parent为bootstrap

第四行表示,核心类java.lang.Object是由bootstrap装载的

第五行表示,用户类LoaderSample1是由系统类装载器装载的

 

 

3.双亲委派模型:

从1.2版本开始,Java引入了双亲委托模型,从而更好的保证Java平台的安全。在此模型下,当一个装载器被请求装载某个类时,它首先委托自己的parent去装载,若parent能装载,则返回这个类所对应的Class对象,若parent不能装载,则由parent的请求者去装载。

 

如图1所示,loader2的parent为loader1,loader1的parent为system class loader。假设loader2被要求装载类MyClass,在双亲委派模型下,loader2首先请求loader1代为装载,loader1再请求系统类装载器去装载MyClass。若系统装载器能成功装载,则将MyClass所对应的Class对象的reference返回给loader1,loader1再将reference返回给loader2,从而成功将类MyClass装载进虚拟机。若系统类装载器不能装载MyClass,loader1会尝试装载MyClass,若loader1也不能成功装载,loader2会尝试装载。若所有的parent及loader2本身都不能装载,则装载失败。

 

若有一个能成功装载,实际装载的类装载器被称为定义类装载器,所有能成功返回Class对象的装载器(包括定义类装载器)被称为初始类装载器。如图1所示,假设loader1实际装载了MyClass,则loader1为MyClass的定义类装载器,loader2和loader1为MyClass的初始类装载器。

system class loader
 
loader1
 
   loader2
 
MyClass
 

           图1

 

需要指出的是,Class Loader是对象,它的父子关系和类的父子关系没有任何关系。一对父子loader可能实例化自同一个Class,也可能不是,甚至父loader实例化自子类,子loader实例化自父类。假设MyClassLoader继承自ParentClassLoader,我们可以有如下父子loader:

ClassLoader loader1 = new MyClassLoader();

ClassLoader loader2 = new ParentClassLoader(loader1); //参数 loader1为parent

 

那么双亲委托模型为什么更安全了?因为在此模型下用户自定义的类装载器不可能装载应该由父亲装载器装载的可靠类,从而防止不可靠甚至恶意的代码代替由父亲装载器装载的可靠代码。实际上,类装载器的编写者可以自由选择不用把请求委托给parent,但正如上所说,会带来安全的问题。

 

 

4.命名空间及其作用:

每个类装载器有自己的命名空间,命名空间由所有以此装载器为创始类装载器的类组成。

不同命名空间的两个类是不可见的,但只要得到类所对应的Class对象的reference,还是可以访问另一命名空间的类。

例2演示了一个命名空间的类如何使用另一命名空间的类。在例子中,LoaderSample2由系统类装载器装载,LoaderSample3由自定义的装载器loader负责装载,两个类不在同一命名空间,但LoaderSample2得到了LoaderSample3所对应的Class对象的reference,所以它可以访问LoaderSampl3中公共的成员(如age)。

 

例2不同命名空间的类的访问

/*LoaderSample2.java*/

import java.net.*;

import java.lang.reflect.*;

 

public class LoaderSample2

{

       public static void main(String[] args)

       {

              try

              {

                     String path = System.getProperty("user.dir");

                    

                     URL[] us = {new URL("file://" + path + "/sub/")};

                    

                     ClassLoader loader = new URLClassLoader(us);        

                    

                     Class c = loader.loadClass("LoaderSample3");

                     Object o = c.newInstance();

                    

                     Field f = c.getField("age");

             

                     int age = f.getInt(o);

                     System.out.println("age is " + age);

                                         

              }

              catch (Exception e)

              {

                     e.printStackTrace();     

              }           

       }

      

}

 

 

/*sub/Loadersample3.java*/

public class LoaderSample3

{

       static

       {

              System.out.println("LoaderSample3 loaded");     

       }

      

       public int age = 30;

}

 

编译:javac LoaderSample2.java; javac sub/LoaderSample3.java

运行:java LoaderSample2

LoaderSample3 loaded

age is 30

 

从运行结果中可以看出,在类LoaderSample2中可以创建处于另一命名空间的类LoaderSample3中的对象并可以访问其公共成员age。

 

5.运行时包(runtime package):

由同一类装载器定义装载的属于相同包的类组成了运行时包,决定两个类是不是属于同一个运行时包,不仅要看它们的包名是否相同,还要看的定义类装载器是否相同。只有属于同一运行时包的类才能互相访问包可见的类和成员。这样的限制避免了用户自己的代码冒充核心类库的类访问核心类库包可见成员的情况。假设用户自己定义了一个类java.lang.Yes,并用用户自定义的类装载器装载,由于java.lang.Yes和核心类库java.lang.*由不同的装载器装载,它们属于不同的运行时包,所以java.lang.Yes不能访问核心类库java.lang中类的包可见的成员。

 

 

6.总结:

在简单讨论了类装载器,双亲委派模型,命名空间,运行时包后,相信大家已经对它们的作用有了一定的了解。命名空间并没有完全禁止属于不同空间的类的互相访问,双亲委托模型加强了Java的安全,运行时包增加了对包可见成员的保护

分享到:
评论
2 楼 zxy861114 2010-10-29  
liuxuejin 写道
在第一个例子中我的eclipse报错了!在类中自己加载自己能行吗?? c = Class.forName(“LoaderSample1”);第一个例子

你报错的原因应该是,你加了包名。c = Class.forName(“LoaderSample1”);这一句得全限命名
1 楼 liuxuejin 2009-12-27  
在第一个例子中我的eclipse报错了!在类中自己加载自己能行吗?? c = Class.forName(“LoaderSample1”);第一个例子

相关推荐

    java类装载器学习一、类加载器的基本概念

    类装载器学习一、类加载器的基本概念 类装载器学习一、类加载器的基本概念 类装载器学习一、类加载器的基本概念

    Java的类装载器和命名空间

    在学习过程中,可能会遇到一些混淆的问题,比如类装载器的委托模型、类的加载顺序以及如何自定义类装载器以加载非标准路径的类。理解这些概念有助于解决实际开发中遇到的类加载问题,例如,当需要加载外部库或者...

    java之jvm学习笔记五(实践写自己的类装载器)

    这个“java之jvm学习笔记五(实践写自己的类装载器)”很可能是对这一主题的详细探讨。 类装载器在Java中的主要职责是动态加载类到JVM中。Java的类装载器分为三个基本层次:启动类装载器(Bootstrap ClassLoader)、...

    深入JVM内核—原理、诊断与优化视频教程-6. 类装载器

    1. **类装载器的层次结构**:Java的类装载器采用双亲委派模型,即当一个类装载器接到加载类的请求时,它首先会委托父类装载器去尝试加载,只有当父类装载器无法加载时,子类装载器才会尝试自己加载。这种模型保证了...

    JAVA虚拟机的类装载机制的原理分析与应用研究.pdf

    当一个类装载器收到加载类的请求时,它首先会委托给父类装载器,只有当父类装载器无法找到相应类时,才会尝试自己加载。 2. **类的二进制表示**: 类的二进制数据通常来自`.class`文件,包含类的结构信息,如方法...

    WAS+V7+理解类装入器-红皮书.pdf

    ### WAS V7 理解类装载器 #### Java类装载器介绍 Java类装载器在Java编程语言...通过以上内容的学习和实践,开发者可以更加熟练地掌握类装载器的配置技巧,从而有效地管理和解决实际应用中可能出现的各种类装载问题。

    行业分类-设备装置-装载机电器实验教学仪器.zip

    这类仪器模拟真实装载机的电气系统,让学生在实验室环境中进行操作练习,以加深理论知识的理解。例如,通过实验仪器,学生可以实际操作模拟开关,观察电流表的变化,理解不同工作模式下电气系统的运行状态;还可以...

    main_Celesteeverest_蔚蓝mod装载器_源码.zip

    "main_Celesteeverest_蔚蓝mod装载器_源码.zip" 文件包含了这个装载器的源代码,对于想要深入理解游戏MOD开发或者对编程感兴趣的玩家来说,这是一个宝贵的学习资源。 源码通常由一系列编程语言编写,如C++、Python...

    求解装载问题.rar

    总的来说,"求解装载问题.rar"文件为学习者提供了一个实践C语言编程和理解算法设计的好机会,特别是对于那些对优化问题和运筹学感兴趣的读者。通过深入研究并理解这个解决方案,不仅可以掌握装载问题的解决策略,还...

    jvm虚拟机学习资料.zip

    类装载器是JVM加载类的关键组件,包括启动类装载器、扩展类装载器和系统类装载器。理解类装载器的工作原理有助于理解类的加载、链接和初始化过程,以及自定义类装载器的应用。 3. **JVM配置参数** (3.常用JVM配置...

    Linux_c++_编程之链接与装载--基础篇

    在C++编程中,链接与装载还涉及到命名空间、类的继承、模板和异常处理等特性。例如,C++的多态性在链接阶段会进行虚函数表的构造;模板在编译时会产生多个实例化代码,这些实例在链接时会被合并;异常处理机制需要...

    山东临工装载机基础知识PPT学习教案.pptx

    【装载机基础知识详解】 装载机,作为一种广泛应用的工程机械,其高效能和多功能性在各种建设领域都有着不可或缺的地位。本篇将深入探讨装载机的基础知识,...理解装载机的基本知识对于选择和使用这类机械至关重要。

    装载机基础知识PPT学习教案.pptx

    总的来说,装载机的多样化设计满足了不同工况的需求,而对其基础知识的深入理解有助于更有效地选择和使用这类设备,提高工程作业的效率和安全性。了解装载机的分类、构造和型号编制规则,是工程管理和技术人员必备的...

    行业分类-设备装置-纸张装载装置.zip

    这个压缩包文件“行业分类-设备装置-纸张装载装置.zip”主要关注的是这类装置的设计、工作原理以及在实际应用中的重要性。 纸张装载装置,通常指的是打印机或多功能一体机中用于装载和处理纸张的组件。这些装置的...

    基于BP神经网络的复合储能式装载机工况识别及控制器匹配.pdf

    基于BP神经网络的复合储能式装载机工况识别及控制器匹配 本文研究了基于BP神经网络的复合储能式装载机工况识别及控制器匹配技术,以解决装载机的控制性能和经济性能问题。通过 BP 神经网络识别模块对工况进行识别,...

    Spring源码学习五:BeanDefinition装载1

    Spring 源码学习五:BeanDefinition 装载 1 在 Spring 框架中,BeanDefinition 是一个核心概念,它描述了一个 Bean 的定义,包括其依赖项、作用域、生命周期等信息。在本篇文章中,我们将深入探讨 Spring 的源码,...

    JAVA深度历险

    首先,我们要知道Java的类装载器分为 Bootstrap ClassLoader(引导类装载器)、Extension ClassLoader(扩展类装载器)和App ClassLoader(应用程序类装载器)这三层。Bootstrap ClassLoader主要负责加载JRE的核心库...

    java装载工具及方法指导

    本文将深入探讨Java的装载工具——类加载器(ClassLoader)以及相关的加载方法,旨在为开发者提供详尽的指导。 首先,类加载器在Java中扮演着关键角色。它的主要职责是将类的字节码文件(.class文件)从文件系统或...

    Python基于深度学习的矿车装载状态计数系统(部署教程和源码).zip

    在本项目中,"Python基于深度学习的矿车装载状态计数系统" 是一个利用人工智能技术,特别是深度学习,来实现矿车装载状态自动化计数的系统。这个系统旨在提高工业生产中的效率和准确性,减少人为错误,适用于监控...

Global site tag (gtag.js) - Google Analytics