浏览 4560 次
锁定老帖子 主题:class文件的动态加载
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-08-07
要实现这个功能我们就需要了解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 测试类的动态加载! 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |