`
ygsilence
  • 浏览: 336839 次
  • 性别: 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动态生成代码并编译载入.pdf

    综上所述,动态生成代码并编译载入是Java应用中一个非常强大但又复杂的功能,它涉及到了Java编程、编译原理、类加载机制以及反射API等多个方面。这个技术虽然提高了程序的灵活性,但也引入了安全性和性能上的考虑。...

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

    在Java编程语言中,`package`和`import`机制是构建大型、模块化代码库的关键要素,它们有助于组织和管理类以及确保代码的可重用性。本篇将深入探讨这两个概念,以及如何通过Visual Studio .NET来操控Java虚拟机(JVM...

    java 载入dll之后无法切换输入法测试工程(My Eclipse)

    这是一个复杂的问题,涉及到多个技术层面,包括Java虚拟机(JVM)、动态链接库(DLL)、操作系统API以及输入法系统。下面我们将深入探讨这个问题。 1. **Java本地方法接口(JNI)**: Java通过JNI允许Java代码调用...

    Java类加载器:静态变量初始化.docx

    在 Java 中,类加载器是通过委派机制来实现的,即一个类加载器可以委派另一个类加载器来加载类。这篇文章将深入探讨 Java 类加载器中的静态变量初始化机制,了解其背后的工作原理和载入过程。 静态变量初始化机制 -...

    Java虚拟机模拟实现

    1. **字节码与类加载机制**:Java源代码被编译成.class文件,这些文件包含字节码,这是JVM能够理解和执行的二进制指令。类加载器是JVM的一部分,负责查找和加载类文件,确保程序运行时正确地引用到所需的类。 2. **...

    java-servlet-api.doc

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

    Java虚拟机工作原理详解

    * Verifying:检查载入的类文件是否符合 Java 规范和虚拟机规范。 * Preparing:为类变量分配内存,并设置默认值。 * Resolving:将符号引用替换为直接引用。 * Initializing:执行类的初始化方法,如静态变量赋值和...

    JAVA五子棋简单实现

    【JAVA五子棋简单实现】是一个适合初学者的项目,旨在通过编程实现一个基本的五子棋游戏,以此巩固和加深对Java基础知识的理解。在这个项目中,开发者将学习到如何运用SWF(Simple Widget Framework)框架来构建用户...

    InsideJava(Java深度历险)

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

    实现java自定义注解拦截器.docx

    ### 实现Java自定义注解拦截器 #### 概述 本文主要介绍如何在Spring Boot项目中使用自定义注解来实现对特定方法的拦截功能。具体场景为:当访问项目中的控制器方法时,需要进行“token验证”,但登录等特殊方法...

    java classloader

    它是Java平台的独特特性,因为它允许动态加载类,增强了软件的可扩展性和灵活性。这篇博文(虽然链接不可用)可能深入探讨了ClassLoader的工作原理及其在Java应用程序中的应用。 ClassLoader分为三个主要层次:...

    c++详细用例 Java

    Java具有自动垃圾回收机制,降低了内存管理的复杂性。它的安全性、稳定性和跨平台能力使其在企业级应用、Web开发、移动应用(尤其是Android)等领域非常流行。 现在,让我们深入探讨这两种语言的知识点: 1. **C++...

    java深度历险(繁体)

    《Java深度历险》是一本全面探讨Java技术的书籍,主要涵盖了Java 2 SDK的深入解析,类别载入器的工作原理,Java与Microsoft Office的集成,如何利用Visual Studio .NET来操控Java虚拟机(JVM),以及Java的package与...

    在可执行jar中载入第三方jar的几个解决方法

    Java虚拟机(JVM)的类加载机制是导致此问题的关键。自JDK 1.2以来,JVM采用委托模式加载类,先由引导类加载器(Bootstrap ClassLoader)加载核心类,接着是由扩展类加载器(Extension ClassLoader)加载扩展类,...

    Java深度历险.rar

    深入类别载入器.pdf** - 这一部分深入讨论了Java的类加载机制。Java的类加载器负责查找和加载类,它是JVM(Java虚拟机)的重要组成部分。这部分内容可能会涵盖类加载器的工作原理,双亲委派模型,以及如何自定义类...

    java深度历险2

    书中可能详细讲解了自定义类加载器的创建、类加载的生命周期、以及如何利用类加载机制实现动态加载和热部署。 接下来,“CH_03.Java与MS Office.pdf”这部分可能会探讨Java与Microsoft Office系统的集成。Java提供...

Global site tag (gtag.js) - Google Analytics