- 浏览: 692365 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (239)
- 系统架构设计 (16)
- java collection framework (2)
- java分布式 (4)
- java多线程 (0)
- 故障处理及调优 (16)
- 软件开发过程及管理 (28)
- OS (5)
- 常用算法 (3)
- design pattern (8)
- transaction (7)
- java apps (48)
- corejava (7)
- java and DB (10)
- cache (0)
- webservice (14)
- web前端 (25)
- 报表 (4)
- 日志系统设计 (3)
- Oracle (4)
- mysql (11)
- xml (11)
- 数据源配置管理 (3)
- 企业数据存储 (4)
- php (2)
- 测试 (1)
最新评论
-
orangebook:
对于初学者来说,这样编写可能会误导,理解更烦锁。
观察者模式(发布-订阅) -
liudajiang:
呵呵 startThreads(rand ...
实践缩小Java synchronized 粒度 -
zengwenbo5566:
谢谢博主,学习了
解决getOutputStream() has already been called for this response -
u011335423:
大神厉害啊 可以了
解决getOutputStream() has already been called for this response -
xiang37:
...
解决getOutputStream() has already been called for this response
一、引言
Java虚拟机(JVM)的类装载就是指--将包含在类文件中的字节码装载到JVM中, 并使其成为JVM一部分的过程。JVM的类动态装载技术能够在运行时刻动态地加载或者替换系统的某些功能模块, 而不影响系统其他功能模块的正常运行。本文将分析JVM中的类装载系统,探讨JVM中类装载的原理、实现以及应用。
二、Java虚拟机的类装载实现与应用
2.1 装载过程简介
所谓装载,就是寻找一个类或是一个接口的二进制形式,并用该二进制形式来构造代表这个类或是这个接口的class对象的过程,其中类或接口的名称是给定了的。当然名称也可以通过计算得到,但是更常见的是通过搜索源代码经过编译器编译后所得到的二进制形式来构造。
在Java中,类装载器把一个类装入Java虚拟机中,要经过三个步骤来完成:装载、链接和初始化,其中链接又可以分成校验、准备和解析三步,除了解析外,其它步骤是严格按照顺序完成的,各个步骤的主要工作如下:
- 装载:查找和导入类或接口的二进制数据;
- 链接:执行下面的校验、准备和解析步骤,其中解析步骤是可以选择的;
- 校验:检查导入类或接口的二进制数据的正确性;
- 准备:给类的静态变量分配并初始化存储空间;
- 解析:将符号引用转成直接引用;
- 初始化:激活类的静态变量的初始化Java代码和静态Java代码块。
至于在类装载和虚拟机启动的过程中的具体细节和可能会抛出的错误,请参看《Java虚拟机规范》以及《深入Java虚拟机》,它们在网络上面的资源地址是: http://java.sun.com/docs/books/vmspec/2nd-edition/html/Preface.doc.html 和 http://www.artima.com/insidejvm/ed2/index.html。 由于本文的讨论重点不在此就不再多叙述。
2.2 装载的实现
JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个重要的Java运行时系统组件。它负责在运行时查找和装入类文件的类。
在Java中,ClassLoader是一个抽象类,它在包java.lang中,可以这样说,只要了解了在ClassLoader中的一些重要的方法,再结合上面所介绍的JVM中类装载的具体的过程,对动态装载类这项技术就有了一个比较大概的掌握,这些重要的方法包括以下几个:
①loadCass方法 loadClass(String name ,boolean resolve),其中name参数指定了JVM需要的类的名称,该名称以包表示法表示,如Java.lang.Object;resolve参数告诉方法是否需要解析类,在初始化类之前,应考虑类解析,并不是所有的类都需要解析,如果JVM只需要知道该类是否存在或找出该类的超类,那么就不需要解析。这个方法是ClassLoader 的入口点。
②defineClass方法 这个方法接受类文件的字节数组,并把它转换成Class对象。字节数组可以是从本地文件系统或网络装入的数据。它把字节码分析成运行时数据结构、校验有效性等等。
③findSystemClass方法 findSystemClass方法从本地文件系统装入文件。它在本地文件系统中寻找类文件,如果存在,就使用defineClass将字节数组转换成Class对象,以将该文件转换成类。当运行Java应用程序时,这是JVM 正常装入类的缺省机制。
④resolveClass方法 resolveClass(Class c)方法解析装入的类,如果该类已经被解析过那么将不做处理。当调用loadClass方法时,通过它的resolve 参数决定是否要进行解析。
⑤findLoadedClass方法 当调用loadClass方法装入类时,调用findLoadedClass 方法来查看ClassLoader是否已装入这个类,如果已装入,那么返回Class对象,否则返回NULL。如果强行装载已存在的类,将会抛出链接错误。
2.3 装载的应用
一般来说,我们使用虚拟机的类装载时需要继承抽象类java.lang.ClassLoader,其中必须实现的方法是loadClass(),对于这个方法需要实现如下操作:
(1) 确认类的名称;
(2) 检查请求要装载的类是否已经被装载;
(3) 检查请求加载的类是否是系统类;
(4) 尝试从类装载器的存储区获取所请求的类;
(5) 在虚拟机中定义所请求的类;
(6) 解析所请求的类;
(7) 返回所请求的类。
所有的Java 虚拟机都包括一个内置的类装载器,这个内置的类库装载器被称为根装载器(bootstrap ClassLoader)。根装载器的特殊之处是它只能够装载在设计时刻已知的类,因此虚拟机假定由根装载器所装载的类都是安全的、可信任的,可以不经过安全认证而直接运行。当应用程序需要加载并不是设计时就知道的类???时,必须使用用户自定义的装载器(user-defined ClassLoader)???。下面我们举例说明它的应用。
public abstract class MultiClassLoader extends ClassLoader{ ... public synchronized Class loadClass(String s, boolean flag) throws ClassNotFoundException { /* 检查类s是否已经在本地内存*/ Class class1 = (Class)classes.get(s); /* 类s已经在本地内存*/ if(class1 != null) return class1; try/*用默认的ClassLoader 装入类*/ { class1 = super.findSystemClass(s); return class1; } catch(ClassNotFoundException _ex) { System.out.println(">> Not a system class."); } /* 取得类s的字节数组*/ byte abyte0[] = loadClassBytes(s); if(abyte0 == null) throw new ClassNotFoundException(); /* 将类字节数组转换为类*/ class1 = defineClass(null, abyte0, 0, abyte0.length); if(class1 == null) throw new ClassFormatError(); if(flag) resolveClass(class1); /*解析类*/ /* 将新加载的类放入本地内存*/ classes.put(s, class1); System.out.println(">> Returning newly loaded class."); /* 返回已装载、解析的类*/ return class1; } ... }
三、Java虚拟机的类装载原理
前面我们已经知道,一个Java应用程序使用两种类型的类装载器:根装载器(bootstrap)和用户定义的装载器(user-defined)。根装载器是Java虚拟机实现的一部分,举个例子来说,如果一个Java虚拟机是在现在已经存在并且正在被使用的操作系统的顶部,用C程序来实现的,那么根装载器将是那些C程序的一部分。根装载器以某种默认的方式将类装入,包括那些Java API的类。在运行期间一个Java程序能安装用户自己定义的类装载器。根装载器是虚拟机固有的一部分,而用户定义的类装载器则不是,它是用Java语言写的,被编译成class文件之后然后再被装入到虚拟机,并像其它的任何对象一样可以被实例化。 Java类装载器的体系结构如下所示:
图1 Java的类装载的体系结构
Java的类装载模型是一种代理(delegation)模型。当JVM 要求类装载器CL(ClassLoader)装载一个类时,CL首先将这个类装载请求转发给他的父装载器。只有当父装载器没有装载并无法装载这个类时,CL才获得装载这个类的机会。这样, 所有类装载器的代理关系构成了一种树状的关系。树的根是类的根装载器(bootstrap ClassLoader) , 在JVM 中它以"null"表示。除根装载器以外的类装载器有且仅有一个父装载器。在创建一个装载器时, 如果没有显式地给出父装载器, 那么JVM将默认系统装载器为其父装载器。Java的基本类装载器代理结构如图2所示:
图2 Java类装载的代理结构
下面针对各种类装载器分别进行详细的说明。
根(Bootstrap) 装载器:该装载器没有父装载器,它是JVM实现的一部分,从sun.boot.class.path装载运行时库的核心代码。
扩展(Extension) 装载器:继承的父装载器为根装载器,不像根装载器可能与运行时的操作系统有关,这个类装载器是用纯Java代码实现的,它从java.ext.dirs (扩展目录)中装载代码。
系统(System or Application) 装载器:装载器为扩展装载器,我们都知道在安装JDK的时候要设置环境变量(CLASSPATH ),这个类装载器就是从java.class.path(CLASSPATH 环境变量)中装载代码的,它也是用纯Java代码实现的,同时还是用户自定义类装载器的缺省父装载器。
小应用程序(Applet) 装载器: 装载器为系统装载器,它从用户指定的网络上的特定目录装载小应用程序代码。
在设计一个类装载器的时候,应该满足以下两个条件:
- 对于相同的类名,类装载器所返回的对象应该是同一个类对象
- 如果类装载器CL1将装载类C的请求转给类装载器CL2,那么对于以下的类或接口,CL1和CL2应该返回同一个类对象:
b) S为C的直接超接口;
发表评论
-
Http状态码及实例
2018-03-24 15:06 0HTTP常用状态码列表: ... -
java同步机制及synchronized关键字的应用2
2013-03-25 22:03 1531类定义: public class Test{ ... -
实践缩小Java synchronized 粒度
2013-03-07 22:09 2074项目需求: 产品需要监视不同种类的多个数据库,例如:多个 ... -
java同步机制及synchronized关键字的应用1
2013-03-05 23:04 967Java对多线程的支持与同步机制深受大家的喜爱,通过JMM ... -
Thread_管理异步、定时及周期性任务
2012-09-24 14:43 1270项目中有很多异步、定时及周期性任务的需求,其实现有一定的特点, ... -
Thread_跨节点集合查询
2012-09-18 16:56 1644项目中数据库进行了水平切分,为了处理跨节点集合查询,采用了多线 ... -
Thread_大批量数据的分页处理(生产者-消费者)
2012-09-17 13:30 1376java应用中通常会有处理大批量数据的场景,这里介绍一种分 ... -
Thread_wait、notify、notifyAll的使用方法
2012-09-17 11:19 6859wait()、notify()、notifyAll()是三个定 ... -
计算java对象占用的内存
2011-12-13 11:38 1044Java有一个很好的地方就是java的垃圾收集机制,这个机制集 ... -
java调用shell执行数据压缩
2011-07-18 17:44 1463项目需求: 将迁移来的数据文件进行压缩。要求压缩过程耗时尽量 ... -
quartz应用之一:创建、关闭定时任务
2011-07-18 17:15 3426项目需求: 数据迁移进程开始执行后,启动定时任务每隔30秒计 ... -
xtree应用实例
2011-03-11 18:02 1352最近项目中用到了构造树形目录的功能,简单了解了下dtree和x ... -
JDBC方式访问数据库
2011-01-10 13:48 13991、 JDBC是什么JDBC是Java数据库连接(Java ... -
应用系统中配置文件的应用场景及简要分析
2010-11-12 16:13 1191使用配置文件的有点不外乎两点: 1.提高系统的灵活性。 2 ... -
解决getOutputStream() has already been called for this response
2010-08-26 14:57 158567getOutputStream() has already b ... -
实战防止重复提交(token)应用思路及过程
2010-06-11 16:39 1594我这里只考虑了直接使用struts API的情况,使用自定义的 ... -
Struts国际化完整解决方案-支持多国语言
2010-06-11 16:38 2038在网上有很多有关Struts的中文解决方案,但是很多都说得很零 ... -
jsp查询条件的保留
2010-06-11 16:23 2767本文适合java web开发初学者参考。 统计系统或者 ... -
java日期计算
2010-05-26 14:45 1315Calendar类:一个抽像类,不能直接new 得到。 Cal ... -
mvc应用实例
2010-04-04 19:58 971最近参与到一个行业数据处理的项目,我负责数据请求和订阅的功能, ...
相关推荐
Java虚拟机类装载:原理、实现与应用.doc
简单的介绍和描述Java虚拟机类装载:原理、实现与应用
现在很多JAVA程序员,都只是知道用JAVA,而不知道它的原理实现,深入Java虚拟机,有助于了解Java虚拟机类装载:原理、实现与应用
详细描述java虚拟机内部加载类机制和原理
本文从对嵌入式操作系统的讨论入手,结合Java虚拟机的原理和研究状况阐述了YJVM的设计和实现要点,体现了YJVM相比现有的嵌入式Java解决方案和Java操作系统的优势。本文的主要研究内容及成果包括: 1、作为一种...
Java 类的动态装载机制是Java 虚拟机的一项核心技术,可以在运行时刻...介绍了Java 虚拟机中类的动态装载机制的原理、实现 及应用,分析了类装载器的结构、用途,阐述了利用自定义类装载器装载并执行Java 类的过程。
Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java访问权限控制源代码 1个目标文件 摘要:Java源码,...
Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java访问权限控制源代码 1个目标文件 摘要:Java源码,...
JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个重要的Java运行时系统组件。它负责在运行时查找和装入类文件的类。 1说说JVM原理?内存泄露与溢出区别,何时产生内存泄露? 编译源代码为...
接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类,它...
JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个重要的Java运行时系统组件。它负责在运行时查找和装入类文件的类。 1说说JVM原理?内存泄露与溢出区别,何时产生内存泄露? 编译源代码为...
接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类,它...
学生提问:不是说JVM是运行Java程序的虚拟机吗?那JRE和JVM的关系是怎样的呢? 8 学生提问:为什么不安装公共JRE系统呢? 9 1.4.2 设置PATH环境变量 10 学生提问:为什么选择设置用户变量,用户变量和系统变量有...
类装载 class装载流程 ClassLoader模式 ClassLoader的使用实例分析 热替换例子 详细介绍ClassLoader的原理和应用。分析2个案例,说明ClassLoader的使用。 第七课 性能监控工具 线程死锁分析 OOM分析 介绍常用的JVM...