论坛首页 Java企业应用论坛

class文件的动态加载

浏览 4532 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-08-07  
     在我们实际开发中经常会遇到一些问题,比如某些类我们需要动态的加载进java虚拟机的内存区域。
     要实现这个功能我们就需要了解java虚拟机的几个类加载器。
     Java 中的类加载器大致可以分成两类,一类是系统提供的,另外一类则是由 Java 应用开发人员编写的。系统提供的类加载器主要有下面三个:
     引导类加载器(bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader。
     扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
     系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader() 来获取它。
    除了系统提供的类加载器以外,开发人员可以通过继承 java.lang.ClassLoader 类的方式实现自己的类加载器,以满足一些特殊的需求。
    我们平时程序执行的时候在类加载器中寻找类的结构的顺序是:引导类加载器-》 扩展类加载器-》系统类加载器-》我们自定义的一些类加载器,每个类加载器都有自己的空间,同一个加载器里面的类的二进制名字必须是唯一的,当然同一个类也可以存在不同的加载器内存区域里面,不过我们寻找类的时候是按顺序找的,一但找的也就不会继续往下找了,最终也没找到就会报类不存在异常。
    我们如果想动态加载类的话就要仿照我们用的服务器如tomcat和weblogic之类的,他们的开发模式也就是把所有的类都加载到自身的类加载器中,当文件被替换的时候他们就重新加载新的class到内存里面去,从而实现了类的动态加载。
    以下是个人是实现一个动态加载类的小程序:
    Class A 是需要动态加载的一个小程序:

package jvm;

public class A {
public static void doSome(){
  System.out.println("测试类的动态加载!");
}
}

      我把A.class文件放到D盘,然后通过我自己写的类来动态加载他:

package jvm;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Method;

public class LoaderSomeClass {
public static void main(String[] args) throws Exception {
ClassLoaderSub classLoaderSub = new ClassLoaderSub();
Class clazz = classLoaderSub.getClassByFile("D:/A.class");
System.out.println("类的名字:"+clazz.getName());
System.out.println("类的加载器:"+clazz.getClassLoader());
classLoaderSub.loadClass(A.class.getName());
Object obj = clazz.newInstance();
Method method = clazz.getMethod("doSome");
method.invoke(obj, null);
}
}

class ClassLoaderSub extends ClassLoader{
public  Class defineClassByName(String name,byte[] b,int off,int len){
  //由于defineClass是protected,所以需要继承后来调用
  Class clazz = super.defineClass(name,b,off,len);
  return clazz;
}

public Class getClassByFile(String fileName) throws Exception{
  File classFile = new File(fileName);
  //一般的class文件通常都小于100k,如果现实情况超出这个范围可以放大长度
  byte bytes []= new byte[102400];
  FileInputStream fis = null;
  Class clazz = null;
  try {
   fis = new FileInputStream(classFile);
   int j = 0;
   while (true) {
    int i = fis.read(bytes);
    if (i == -1)
     break;
    j += i;
   }
   clazz = defineClassByName(null,bytes,0,j);
  } finally{
   fis.close();
   return clazz;
  }
}
}
输出结果为:
类的名字:jvm.A
类的加载器:jvm.ClassLoaderSub@1fb8ee3
测试类的动态加载!

论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics