本帖最后由 黎志文 于 2013-7-23 02:09 编辑
好像不是这样的!请你去试试,自定义一个类,继承ClassLoader,然后只重写findClass方法,不重写loadClass方法,findClass方法里面,写简单些,不去整那些加密和解密,就直接去读取classpath中的一个class文件,然后写入到ByteArrayOutputStream这个字节数组流中,再将此数组流中的数据存储到一个byte数组里面,最后通过defineClass方法将这个byte数组中的数据转成字节码,将defineClass方法的返回值返回给findClass。
在一个主函数里面,用自定义的类加载器去加载classpath中的文件,试试最后加载这个文件的类加载器是自定义的那个,还是系统类加载器,我测试的结果是前者。
- <P>package cn.itcast.day3.classloader;
- import java.io.ByteArrayOutputStream;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.InputStream;
- //使用自定义的加载器加载classpath中的类,看看最后执行加载的类加载器是哪个?是自定义的,还是系统论加载器?
- public class TestClassLoader extends ClassLoader
- {
- @Override
- public Class findClass(String name) throws ClassNotFoundException
- {
- try
- {
- String classPath = "bin\\cn\\itcast\\day3\\classloader\\" + name+".class"; // 最前面那个路径,是我的eclipse的classpath
- InputStream ins = new FileInputStream(classPath); //读取classpath中的一个文件
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- int b = 0;
- while((b=ins.read())!=-1)
- {
- bos.write(b); //将读取到的文件信息写入到字节输出流
- }
- ins.close();
- byte[] bytes = bos.toByteArray(); //将字节输出流里面的数据存储到一个byte数组
- return defineClass(null,bytes,0,bytes.length); //最后将byte数组中的数据转成字节码对象。
- } catch (Exception e)
- {
- e.printStackTrace();
- }
- return super.findClass(name);
- }
- }
- class TestClassLoaderDemo
- {
- public static void main(String[] args) throws Exception
- {
- Class clazz = new TestClassLoader().loadClass("SourceFile"); //用自定义的类加载器去加载classpath中的SourceFile.class文件
- Object obj = clazz.newInstance(); //用加载好的字节码去创建一个实例对象
- System.out.println(obj.getClass().getClassLoader().getClass().getName()); //测试该实例对象的类是由哪个加载器加载的。结果是:我自定义的类加载器</P>
- <P>
- /*我自定义的类加载器去加载classpath中的数据,如果根据委托机制,自定义的类加载器会委托给父级类加载器,而自定义的类加载器的父级,系统类</P>
- <P> 加载器可以在classpath中找到这个SourceFile.class文件,那么不应该是由系统类加载器来加载它么?最后的返回结果应该是AppClassLoader才对?*/
- }
- }</P>
复制代码 |