`
laotu5i0
  • 浏览: 140773 次
  • 性别: 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的安全,运行时包增加了对包可见成员的保护

分享到:
评论

相关推荐

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

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

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

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

    Python基于深度学习的矿车装载状态计数系统(源码+项目说明).zip

    因此,基于深度学习的矿车装载状态计数系统可以实现对矿车装载状态的自动检测和计数,提高检测和计数的准确性和速度。 Python作为一种简单易学、功能强大的编程语言,被广泛应用于深度学习领域。Python提供了许多...

    程序集动态装载与卸载

    学习网上的相关介绍,写成的完整类,可以直接使用,用于动态装载并执行程序集中的方法 也可以使用插件管理域进行动态装载\执行方法\卸载程序域 但日常工作中还是习惯对所有项目引用一个公共的项目(主要是设计接口\...

    TMS320C54XDSP指令系统学习资料.rar

    装载存储传送类指令的作用是把源操作数从源存储器(寄存器)中送到目的操作数指定的寄存器(存储器)里,用于完成数据的读入、保存或传送。   c54x的数据传送指令包括装载指令、存储指令(含条件存储指令...

    spring学习笔记(有代码有注解解释)

    通过运行时类获取 bean;通过有参构造创建 bean;给 bean 注入集合;scope 作用域;Spring 的继承;Spring 的依赖;Spring 的 p 命名空间;Spring 的工厂方法;IoC 自动装载(Autowire);AOP以及如何使用; 适用...

    ruby学习资料大全,很全很丰富

    Ruby是"一种用于迅速和简便的面向对象编程的解释性脚本语言";这意味着什么?...类,继承,方法,等等 单态方法 模块糅合 迭代器和闭包(closures) 以及: 多精度整数 异常处理模式 动态装载 线程

    Java类加载器加载类顺序

    sun提供了各个平台的JVM实现–也是说jvm不是跨平台的,编译好的字节码文件被放在不同的操作系统平台上的jvm所解释执行,这个章节主要解释一下JVM装载类的机制  1.ClassLoader是什么?  一个类如果要被JVM所调度...

    单片机类相关论文资料51 msp430 PIC 单片机设计学习资料200个合集.rar

    单片机类相关论文资料51 msp430 PIC 单片机设计学习资料200个合集: 基于at89c2051+单片机的防盗自动报警电子密码锁系统的设计.pdf 基于at89c2051单片机应用设计.pdf 基于AT89C2051单片机的电子称设计.pdf 基于AT89C...

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

    hasConstructor.java 拥有构造器的类 hasFinalFun.java 拥有最终方法的类 hasRecall.java 可以完成回调功能的类 HasStatic.java 一个简单的拥有静态成员的类 hideMember_1.java 成员隐藏示例1 hideMember_2....

    实例解读51单片机完全学习与应用

    如何系统学习单片机?单片机系统设计的流程是怎样的,需要掌握哪些辅助软件?本篇将针对这些问题一一阐述,为读者掀开单片机完全学习与应用的华丽序幕。 第1章 单片机在哪里 1.1 ■寻找单片机 1.1.1 电磁炉与单片机...

    Adriod学习笔记1

    Adriod学习笔记,Adriod入门示例。 总结Android开发的特点 1.布局文件是通过XML实现。 2.文件分类清晰。 3.代码和UI分开,在国际化和程序维护方面有着巨大的作用。如果你的Android程序需要自适应国际化,比如说多国...

    深入学习JVM(Java虚拟机)内核教程

    2.JVM运行机制.mp4 3.常用JVM配置参数.mp4 4.GC算法与种类.mp4 5.GC参数.mp4 6.类装载器.mp4 7.性能监控工具,mp4 8.Java堆分析.mp4 9.锁.mp4 10.Class文件结构.mp4 11.字节码执行.mp4

    c#学习笔记.txt

    virtual在派生类中声明其实现可由重写成员更改的方法或访问器。 volatile指示字段可由操作系统、硬件或并发执行的线程等在程序中进行修改。 9,语句 语句是程序指令。除非特别说明,语句都按顺序执行。C# 具有下列...

    javascript学习笔记.docx

    其实,它是Location类的一个实例,它还有一个reload()方法可以装载信的URL(用Back按钮不能回退到原页面)。 12) history属性可看成是代表历史URL的一个特殊数组,它的可读length属性表明数组的长度。支持三种方法...

    asp.net学习积累的代码段

    对于长时间装载的ASP.NET页面如何在客户端浏览器中显示进度?).txt 根据不同的dropdownlist选择值选择数据.txt 购物车代码.txt 关于TextBox和Label控件显示数据的问题.在线等.txt 广告代码.txt 获取键盘上任意按键的...

    java面试题宝典

    面试题集共分为以下十部分: 一、Core Java: 1 — 95 题1 — 24 页 基础及语法: 1 — 61 题1 — 13 页 异常: 62 — 69 题13 — 15 页 集合: 70 — 80 题15 — 18 页 线程: 81 — 90 题18 — 21 页 ...

    Python测试模块学习笔记

    TestSuite类:该类是一个测试集,即把相关的TestCase类集合到一起形成一个TestSuiteTestLoader类:该类负责搜索和装载TestCase到TestSuite中。TextTestRunner类:该类负责运行测试用例。TextTestResult类:该类负责存

    虚拟机实验报告.docx

    1、在计算机上学习安装虚拟机 2、在虚拟机上安装操作系统(win98或win2000) 3、实现虚拟机与主机通讯(比如在主机和虚拟机之间实现QQ聊天) 4、在虚拟机上运行软件实验(比如安装VideoPack5软件) 实验原理:所有的...

    webgl-obj-loader:一个简单的OBJ模型加载器,可帮助促进WebGL的学习

    我最初是为CS Graphics类编写此脚本的,因此我们不必仅拥有用于模型的多维数据集和球体即可学习WebGL。 当时,WebGL唯一的模型加载器是 。 为了使用装载程序,您必须使用整个框架(或进行一些非常认真的修改和录音...

Global site tag (gtag.js) - Google Analytics