`
ygsilence
  • 浏览: 332340 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java技术----实现JAVA的动态类载入机制

    博客分类:
  • java
阅读更多
----作为充分利用Java的动态类载入机制的最好例子,带有Java扩展的Web浏览器根据请求从网络或本地文件系统中动态加载Javaapplet(遵循一定规则的Java小应用程序类),然后在本地系统中执行它,大大增强了主页的功能。

----其实,Java本身就是一种极具动态性的语言。类似Windows的动态链接库(DLL),Java应用程序总是被编译成若干个单独的class文件,程序执行时根据需要由Java虚拟机动态载入相应的类。这种机制使编写动态的分布式应用程序成为可能:我们可以在客户端编写自己的类载入器,而真正执行的程序却存放在本地、局域网或世界另一端的主机上。下面将介绍如何在自己的应用程序中实现Java的动态类载入机制。

与动态类载入有关的系统类
----为支持动态类载入机制,在系统类组java.lang中提供了两个类:Class类和ClassLoader类。

----1、类java.lang.Class。在Java虚拟机中,每一个类或接口都是由Class类来操纵的,它不能被显式的实例化,必须用其他方法来获取Class类的对象。动态类载入机制的关键一步在于如何获得指定类的Class类型的对象。相关方法主要有:


---- public static Class forName(String className)

----这是一个静态方法,它获取指定名字的类的Class类型对象,类名可以是象“sun.applet.Applet”这样的字符串,但不能带有路径或网络地址等信息。这是从本地系统中动态载入类的最方便的办法。

---- public Object newInstance()

----这是最重要的一个方法,它建立由Class类型对象描述的指定类的实例。

----下面是一个用forName()和newInstance()方法实现动态类载入的代码,share类包含一个接口,详细内容将在第三部分中解释。

try{
//根据类名建立Class类型的对象。
Class cc =Class.forName("类名"));
//建立被载入类类的实例并强制类型转换,
值赋给share类型的变量。
share oo=((share)cc).newInstance();
//调用该类的方法进行工作。
}
catch (Exception ex){
//如果发生例外,则进行相应处理。
};

----2、类java.lang.ClassLoader。这是一个抽象类,如果打算运用它,必须继承它并重写它的loadClass()方法。其主要方法有:

---- protected ClassLoader();

----这是一个建构元,可以用它建立一个ClassLoader类的实例。注意继承这个类的类必须重写这个方法,而不能使用缺省的建构元。

---- protected abstract Class loadClass(String name, boolean resolve)

----载入指定的类数据,建立Class类型的对象并根据需要解析它。这是一个抽象方法,大家必须在自己的子类中重写这个方法,重写的规则可以参考第三部分的例子。

---- protected final Class defineClass(byte data[], int offset, int length)

----将字节数组中的数据定义为Class类型的对象,字节数组的格式由虚拟机规定。

---- protected final Class findSystemClass(String name)

----根据指定的类名载入类,它会自动在当前目录和环境变量“CLASSPATH”指定的路径中寻找,如果找不到,则会抛出ClassNotFoundException例外。

---- protected final void resolveClass(Class c)

----通过载入与指定的类相关的所有类来解析这个类,这必须在类被使用之前完成。

扩充ClasslLader类以实现动态类载入
----理解动态类载入机制的最好办法是通过例子,下面这个完整的例子由四个类组成,分别解释如下:

----1、MyClassLoader类是ClassLoader类的子类,它重写了loadClass方法,实现了将网络上用URL地址指定的类动态载入,取得它的Class类型对象的功能。读者可根据自己载入类的具体方式改写下面的代码。

import java.io.*;
import java.util.*;
import java.net.*;

public class MyClassLoader extends ClassLoader {
//定义哈希表(Hashtable)类型的变量,
用于保存被载入的类数据。
Hashtable loadedClasses;

public MyClassLoader() {
loadedClasses = new Hashtable();
}

public synchronized Class loadClass(String className,
boolean resolve) throws ClassNotFoundException {
Class newClass;
byte[] classData;

//检查要载入的类数据是否已经被保存在哈希表中。
newClass = (Class) loadedClasses.get(className);
//如果类数据已经存在且resolve值为true,则解析它。
if (newClass != null){
if (resolve)
resolveClass(newClass);
return newClass;
}

----/*首先试图从本地系统类组中载入指定类。这是必须的,因为虚拟机将这个类载入后,在解析和执行它时所用到的任何其他类,如java.lang.System类等,均不再使用虚拟机的类载入器,而是调用我们自制的类载入器来加载。*/

try {
newClass = findSystemClass(className);
return newClass;
} catch (ClassNotFoundException e) {
System.out.println(className+" is not a system class!");
}

//如果不是系统类,
则试图从网络中指定的URL地址载入类。
try {
//用自定义方法载入类数据,
存放于字节数组classData中。
classData = getClassData(className);
//由字节数组所包含的数据建立一个class类型的对象。
newClass = defineClass(classData, 0, classData.length);
if (newClass == null)
throw new ClassNotFoundException(className);
} catch (Exception e) {
throw new ClassNotFoundException(className);
}

//如果类被正确载入,
则将类数据保存在哈希表中,以备再次使用。
loadedClasses.put(className, newClass);
//如果resolve值为true,则解析类数据。
if (resolve){
resolveClass(newClass);
}
return newClass;
}
//这个方法从网络中载入类数据。
protected byte[] getClassData(String className)
throws IOException {
byte[] data;
int length;
try {
//从网络中采用URL类的方法
载入指定URL地址的类的数据。
URL url = new URL(className.endsWith(".class") ?
className : className + ".class");
URLConnection connection = url.openConnection();
InputStream inputStream = connection.getInputStream();
length = connection.getContentLength();

data = new byte[length];
inputStream.read(data);
inputStream.close();
return data;
} catch(Exception e) {
throw new IOException(className);
}
}
}

----2、由于Java是强类型检查语言,通过网络载入后的类被实例化后只是一个Object类型的对象,虚拟机并不知道它包含那些方法,应从哪个方法开始执行。因此,可以被动态载入的类必须继承某一个抽象类或实现某一个接口,因为父类只能有一个,所以通常用实现特定接口的办法。下面的代码定义了一个接口类share和它的方法start()。

public interface share {
public void start(String[] option);
}

----3、TestClassLoader类通过使用MyClassLoader类的loadClass()方法,将指定URL地址的类载入并在本地系统执行它,实现了类的动态载入。注意在执行被载入类的方法前一定要将它进行强制数据类型转换。

public class TestClassLoader {
public static void main(String[] args){
MyClassLoader ll = new MyClassLoader();
Class cc;
Object oo;
String ss = "http://kyzser.ydxx/classLoader/Tested.class";

if (args.length != 0) ss = args[0];
try {
System.out.println("Loading class "+ss+"...");
//使用重写的方法loadClass()载入类数据。
cc = ll.loadClass(ss);
System.out.println("Creat instance...");
//创建Object类型的类实例。
oo = cc.newInstance();
System.out.println("Call start() method...");
//强制类型转换并执行被载入类中的方法。
((share) oo).start(args);
}catch (Exception e) {
System.out.println("Caught exception : "+e);
}
}
}

----4、Tested类很简单,可以将它放在任何WEB服务器上,但应注意能动态载入且被执行的类,一定要实现预先定义的接口中的方法。下面的例子实现了接口share的start方法。

public class Tested implements share{
public void start(String[] option){
//填写程序代码。
}
}

动态类载入机制的几点应用
----1、开发分布式应用。这对开发远程的客户端应用程序最有用,客户端仅需要安装一些基本的系统和一个能实现动态类载入机制的类,需要本地系统不存在的功能时,仅需要从网络动态载入并执行相应类即可获得特定功能。因为客户端所使用的总是软件的最新版本,所以不再存在软件的升级和维护问题,即实现了所谓的“零管理”模式。

----2、对.class文件加密。由于Java的字节码(bytecode)容易被反编译,大部分开发Java应用程序的公司均担心自己的成果被别人不劳而获。其实可以将类文件进行适当的加密处理,执行时使用自己的类载入器进行相应的解密,就可以解决这个问题。

----3、使第三方开发者易于扩展你的应用。从前面可知,所有可以被你的类载入器动态载入并被执行的类,必须继承你定义的类或实现你定义的接口,这样,你可以制订一些规则,使其他开发者不必了解你的应用程序也可以扩充功能。

----当然,有利必有弊,在网络中使用动态类载入的主要缺陷在于安全性,很难保证不载入不怀好意的代码,这个问题要靠Java的安全管理器和适当的加密算法来解决,已超出本文的讨论范围。




分享到:
评论

相关推荐

    java-servlet-api.doc

    Servlet引擎利用Java类载入工具载入一个Servlet,Servlet引擎可以从一个本地的文件系统、一个远程的文件系统以及网络载入Servlet。 Servlet的初始化 Servlet引擎载入Servlet后,Servlet引擎必须对Servlet进行初始化...

    InsideJava(Java深度历险)

    讲解类别载入器的运作机制:类别载入器兼具Java程序的弹性与安全性两项重大任务,您不能不了解它;import与package机制的探讨:撰写Java程序的人,绝对会遇到import与package机制。只要明白这个机制的运作原理,你会...

    java深度历险 详细讲解了java的package机制等

    package与import机制 用Visual Studio.net来操控Java虚拟机 深入Java 2 SDK 深入类别载入器

    java的ClassLoader类加载器机制

    jvm运行的过程中,需要载入类,而类的加载需要类加载器,本文章提供了java的类加载器的工作原理。可以使读者更加理解jvm的运行机制。

    反射机制和类加载机制学习总结

    反射机制和类加载机制学习总结 Reflection 是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说“自审”,并能直接...这些工具通过 reflection 动态的载入并取得 Java 组件(类) 的属性。

    java环境搭建.docx

    JVM(java virtual machine java虚拟机):java程序会载入JVM,然后运行。 java核心类库:java程序在运行的过程中需要依赖一些库文件。 JDK(java development kit)  java开发工具。 JDK包含JRE,我们直接安装...

    Java核心技术II(第8版)

    11.2.3 一个示例:动态Java代码生成 11.3 使用注解 11.3.1 一个示例:注解事件处理器 11.4 注解语法 11.5 标准注解 11.5.1 用于编译的注解 11.5.2 用于管理资源的注解 11.5.3 元注解 11.6 源码级注解处理 11.7 字节...

    JVM技术,反射与动态代理

    Java程序的工作机制:Java对象都以单独的class文件存在,java虚拟机将其载入并执行其虚拟机指令。

    Java sdk深度历险

    讲解类别载入器的运作机制:类别载入器兼具Java程序的弹性与安全性两项重大任务,您不能不了解它;import与package机制的探讨:撰写Java程序的人,绝对会遇到import与package机制。只要明白这个机制的运作原理,你会...

    Java深度历险完整版

    Java深度历险 深入Java 2 SDK 深入类别载入器 Java与MS Office 用Visual Studio.net操控Java虚拟机 package与import机制 Ant 附录A.Java 2 SDK原版码概观

    99乘法表java源码-learn-lua:学习lua

    99乘法表java源码 ...能方便地利用表和动态元机制实现基于原型(prototype-based)的面向对象模型; 从5.1版开始提供了完善的模块机制,从而更好地支持开发大型的应用程序; Lua 基础数据类型 函数type

    apache-commons源码及jar文件

    Commons-launcher 消除了需要批处理或者Shell脚本来载入Java 类。.原始的 Java 类来自于Jakarta Tomcat 4.0 项目 Logging Commons-Logging 是一个各种 logging API实现的包裹类. Math Math 是一个轻量的,自包含...

    Java基础加强之类加载器

    学习概述:本模块深入讲解了Java类加载方面的知识,Java类加载器和类加载机制以及类加载原理  学习目标:掌握类加载机制和原理,能够独立开发自己的类加载器。  1.类的加载  什么是类加载? 类加载是指将类的...

    JAVA深度历险

    讲解类别载入器的运作机制:类别载入器兼具Java程序的弹性与安全性两项重大任务,您不能不了解它;import与package机制的探讨:撰写Java程序的人,绝对会遇到import与package机制。只要明白这个机制的运作原理,你会...

    Spring技术内幕:深入解析Spring架构与设计原理(第2部分)

     Spring ACEGI安全框架在用户验证和授权机制的实现上有何过人之处?  如何在Spring的基础上进行扩展开发?  你是否曾经也有过分析开源软件源代码的冲动?你想掌握分析源代码的最佳实践吗?  

    基于Java的XML解析与反射设计模式.doc

    java程序需要的类能够动态的被载入到运行环境,也可以通过网络来载入所需 要的类。安全性,java通常被用在网络环境宏,为此,java提供了一个安全机制加以防 恶意代码的攻击。除了java语言具有的许多安全特性以外,...

    java笔记.zip

    java笔记,包括以下几个部分,是我从我日常开发的实例中提取出来的东西,希望对大家有帮助!顺便赚点分! Annotion.doc ...javabean.doc java学习大纲.doc java语言的反射机制.doc ...类的动态载入.doc 时间与日期.doc

    面试必问之jvm与性能优化

    Java类的加载是动态的,它并不会一次性将所有类全部加载后再运行,而是保证程序运行的基础类(像是基类)完全加载到jvm中,至于其他类,则在需要的时候才加载。这当然就是为了节省内存开销。 Java的类加载器有三个,...

Global site tag (gtag.js) - Google Analytics