自定义类加载器 ( by quqi99 )

来源:互联网 发布:java api帮助文档 编辑:程序博客网 时间:2024/06/05 01:01

                                                        自定义类加载器( by quqi99 )


 

作者:张华 发表于:2010-03-12

版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明

 

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;


/**
 * 自定义类加载器
 * @version 0.10 2010-3-12
 * @author Zhang Hua
 */
public class LicClassLoader extends ClassLoader {
    public static boolean TRACE = true;
    private static boolean isDecrypt = true;  //是否加解密
    private String cp; 

    public static void main(String[] args){
        LicClassLoader mcl = new LicClassLoader("E://workspace//3.4//License//bin", LicClassLoader.class.getClassLoader());
        Thread.currentThread().setContextClassLoader(mcl);
        try { 
            Class c = mcl.loadClass("my.secret.code.License"); 
            Object LicenseObj = c.newInstance(); 
            //这样调用会出错,因为License是由系统类加载器加载的,而obj是由 LicClassLoader加载的,系统类加载器看不到LicClassLoader加载的LicenseObj,只能通过反射调用
//            License te = (License)LicenseObj;
            Method checkMethod = c.getMethod("validate", new Class[]{String.class});
            Object result = checkMethod.invoke(LicenseObj, new Object[]{"a"});
            System.out.println(result);
        } catch (Exception e) { 
            e.printStackTrace(); 
        }
    }
   
    public LicClassLoader(String cp, ClassLoader parent) {
        super(parent);
        this.cp = cp;
    }
   
    @SuppressWarnings("unchecked")
    public Class loadClass(String className) throws ClassNotFoundException {
        return loadClass(className, false);
    }

    @SuppressWarnings("unchecked")
    protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException {

        try {
            if (TRACE)
                System.out.println ("loadClass (" + name + ", " + resolve + ")");
            if(name.endsWith("Object")){
                System.out.println("");
            }
            //调用系统方法检查此类是否已经被本classloader实例加载过
            Class foundClass = findLoadedClass(name);
           
            //如果不是属性本classloader加载的范畴,请求父加载器加载
            if(foundClass == null){
                Class parentsVersion = null;
                try{
                    parentsVersion = getParent().loadClass(name);
                    if(parentsVersion.getClassLoader() != getParent())
                        foundClass = parentsVersion;
                }catch (Exception ignore){}
            }
           
            //从自定义的classloader加载
            if(foundClass == null){
                try{
//                    foundClass= findClass(name);             //从class文件找类
                    foundClass= findClassFromJar(name,"lic.jar");   //从JAR包中找类
                }catch(Exception ignore){}   
            }   
           
            //还不行,调用系统类加载器再试一次
          //  if(foundClass == null){
           //     foundClass = findSystemClass(name);
         //   }
           
            //根据情况决定是否加载关系类
            if (resolve && foundClass!=null) {
                resolveClass(foundClass);
            }
            return foundClass;
        } catch (Exception e) {
            throw new ClassNotFoundException(e.toString());
        }
    }

    //从class中找类
    public Class findClass(String className) throws ClassNotFoundException {
        if (TRACE)
            System.out.println("findClass (" + className + ")");
        final String filePath = className.replace('.', '/') + ".class";
        final URL classURL = getResource(filePath);
        if (classURL == null) {
            throw new ClassNotFoundException(className);
        } else {
            InputStream in = null;
            try {
                in = classURL.openStream();
                final byte[] classBytes = readFully(in);
                if(isDecrypt){
                    crypt(classBytes);   //加密
                    crypt(classBytes);   //解密
                    if (TRACE)
                        System.out.println("decrypted [" + className + "]");
                }
                return defineClass(className, classBytes, 0, classBytes.length);
            } catch (IOException ioe) {
                throw new ClassNotFoundException(className);
            } finally {
                if (in != null)
                    try {
                        in.close();
                    } catch (Exception ignore) {
                    }
            }
        }
    }

   

    //从jar中找类
    protected Class findClassFromJar(String className, String jarName) throws ClassNotFoundException {
        String jarPath = cp + File.separator + jarName;
        if(!jarPath.toLowerCase().endsWith(".jar") && !jarPath.toLowerCase().endsWith(".zip"))
            jarPath = jarPath + ".jar";
        JarInputStream in = null;
        if (!(jarPath == null || jarPath == "")) {
            try {
                in = new JarInputStream(new FileInputStream(jarPath));
                JarEntry entry;
                while ((entry = in.getNextJarEntry()) != null) {
                    if (entry.toString().equals(className.replace('.', '/') + ".class")) {
                        if (entry.getSize() == -1) {
                            System.err.println("error : can't read the file!");
                            return null;
                        }
                        byte[] classData = new byte[(int) entry.getSize()];
                        System.out.println("It have found the file : " + className + ".  Begin to read the data and load the class。");
                        in.read(classData);
                        return defineClass(className, classData, 0, classData.length);
                    }
                }
                System.out.println("Haven't found the file " + className + " in " + jarName + ".jar.");
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } else {
            System.out.println("Haven't found the jarFile: " + jarName + ".jar.");
            return null;
        }
        return null;
    }


    /**
     * De/encrypts binary data in a given byte array. Calling the method again
     * reverses the encryption.
     */
    private static void crypt(final byte[] data) {
        for (int i = 8; i < data.length; ++i)
            data[i] ^= 0x5A;
    }
   
     private static byte[] readFully(final InputStream in) throws IOException {
        final ByteArrayOutputStream buf1 = new ByteArrayOutputStream();
        final byte[] buf2 = new byte[8 * 1024];
        for (int read; (read = in.read(buf2)) > 0;) {
            buf1.write(buf2, 0, read);
        }
        return buf1.toByteArray();
    }
     
}