JAVA CLASS LOADING技术研究---整理后的代码

以下是整理后的代码部分,欢迎批评指正。

MyClassLoader.java
/**/ /*
 * @MyClassLoader.java    07/04/17
 *
 * Copyright Zhao Jiucheng. All rights reserved.
 
*/

package  com.neusoft.classloader;

import  java.io.File;
import  java.io.FileInputStream;
import  java.io.IOException;
import  java.util.Hashtable;
import  java.util.jar.JarEntry;
import  java.util.jar.JarInputStream;

/** */ /**
 * A class loader is an object that is responsible for loading classes. Given
 * the binary name of a class, a class loader should attempt to locate or
 * generate data that constitutes a definition for the class. A typical strategy
 * is to transform the name into a file name and then read a "class file" of
 * that name from a file system.
 * 
 * 
@version 1.0, 07/04/17
 * 
@author Zhao Jiucheng
 * 
 
*/

public   class  MyClassLoader  extends  ClassLoader  {

    
// a classpath for search
    private static String myClasspath = new String("");

    
// hashtable that memory the loaded classes
    private static Hashtable<String, Class<?>> loadClassHashTable = new Hashtable<String, Class<?>>();

    
// hashtable that memory the time of loading a class
    private static Hashtable<String, Long> loadClassTime = new Hashtable<String, Long>();

    
// the null constructor
    public MyClassLoader() {

    }


    
/** *//**
     * create a classloader and specify a classpath.
     * 
     * 
@param myClasspath
     *            the specified classpath name.
     
*/

    
public MyClassLoader(String myClasspath) {
        
if (!myClasspath.endsWith("\\")) {
            myClasspath 
= myClasspath + "\\";
        }

        MyClassLoader.myClasspath 
= myClasspath;
    }


    
/** *//**
     * set the classpath
     * 
     * 
@param myClasspath
     *            the specified classpath name
     
*/

    
public void SetmyClasspath(String myClasspath) {
        
if (!myClasspath.endsWith("\\")) {
            myClasspath 
= myClasspath + "\\";
        }

        MyClassLoader.myClasspath 
= myClasspath;
    }


    
/** *//**
     * Loads the class with the specified binary name. This method searches for
     * classes in the same manner as the loadClass(String, boolean) method.
     * Invoking this method is equivalent to invoking {loadClass(name,false)}.
     * 
     * 
@param className
     *            The binary name of the class.
     * 
     * 
@return The resulting <tt>Class</tt> object.
     * 
     * 
@throws ClassNotFoundException
     *             If the class was not found.
     
*/

    @SuppressWarnings(
"unchecked")
    
public Class loadClass(String className) throws ClassNotFoundException {
        
return loadClass(className, false);
    }


    
/** *//**
     * Loads the class with the specified binary name. The default
     * implementation of this method searches for classes in the following
     * order:
     * 
     * Invoke {findLoadedClass(String)} to check if the class has already been
     * loaded.
     * 
     * Invoke {findSystemClass(String)} to load the system class.
     * 
     * Invoke the {findClass(String)} method to find the class.
     * 
     * If the class was found using the above steps, and the resolve flag is
     * true, this method will then invoke the {resolveClass(Class)} method on
     * the resulting Class object.
     * 
     * 
@param name
     *            The binary name of the class.
     * 
     * 
@param resolve
     *            If true then resolve the class.
     * 
     * 
@return The resulting Class object.
     * 
     * 
@throws ClassNotFoundException
     *             If the class could not be found.
     
*/

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

        
try {
            Class foundClass 
= findLoadedClass(name);

            
// check if the class has already been loaded.
            if (foundClass != null{
                System.out.println(
"Complete to load the class: " + name);
                
return foundClass;
            }


            
// if the class is systemClass, load the system class by system
            if (name.startsWith("java.")) {
                foundClass 
= findSystemClass(name);
                loadClassHashTable.put(name, foundClass);
                System.out.println(
"System is loading the class: " + name);
                
return foundClass;
            }


            
// invoke the findClass() method to load the class
            try {
                foundClass 
= findClass(name);
            }
 catch (Exception fnfe) {
            }


            
if (resolve && (foundClass != null)) {
                resolveClass(foundClass);
            }

            
return foundClass;
        }
 catch (Exception e) {
            
throw new ClassNotFoundException(e.toString());
        }

    }


    
/** *//**
     * Finds the class with the specified binary name.The default implementation
     * throws a ClassNotFoundException.
     * 
     * 
@param className
     *            The binary name of the class.
     * 
     * 
@return The resulting Class object.
     * 
     * 
@throws ClassNotFoundException
     *             If the class could not be found.
     
*/

    @SuppressWarnings(
"unchecked")
    
public Class findClass(String className) {

        
byte[] classData = null;
        
try {
            classData 
= loadClassData(className);
        }
 catch (IOException e) {
            e.printStackTrace();
        }

        
if( classData == null){
            
return null;
        }


        System.out.println(
"MyClassLoader is loading : " + className + "");
        Class c 
= defineClass(className, classData, 0, classData.length);
        MyClassLoader.loadClassHashTable.put(className, c);
        System.out.println(
"Complete to load the class :" + className);
        
return c;
    }


    
/** *//**
     * Loads the classData with the specified binary name. This method searches
     * for classes in the specified classpath as
     * searchFile(myClasspath,className) method.
     * 
     * 
@param name
     *            The binary name of the class
     * 
     * 
@return The resulting the classData of the class object by byte[]
     * 
     * 
@throws IOException
     *             if have some failed or interrupted I/O operations.
     
*/

    
private byte[] loadClassData(String className) throws IOException {

        String filePath 
= searchFile(myClasspath, className + ".class");

        
if (!(filePath == null || filePath == "")) {

            System.out.println(
"It have found the file : " + className
                    
+ ".  Begin to read the data and load the class。");
            FileInputStream inFile 
= new FileInputStream(filePath);
            
byte[] classData = new byte[inFile.available()];
            inFile.read(classData);
            inFile.close();
            loadClassTime.put(className, 
new File(filePath).lastModified());
            
return classData;
        }
 else {

            filePath 
= searchFile(myClasspath, className + ".java");
            
if (!(filePath == null || filePath == "")) {
                System.out.println(
"It have found the file : " + filePath
                        
+ ".  Begin to translate");
                Runtime.getRuntime().exec(
"javac " + filePath);
                
try {
                    Thread.sleep(
1000);
                }
 catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(
"Translate it over : " + filePath);
                
return loadClassData(className);
            }
 else {
                System.out
                        .println(
"Haven't found the file, and fail to read the classData!");
                
return null;
            }

        }

    }


    
/** *//**
     * Loads the class with the specified binary name.The default implementation
     * throws a ClassNotFoundException.
     * 
     * 
@param classData
     *            The data of the class.
     * 
@param className
     *            The binary name of the class.
     * 
     * 
@return The resulting Class object.
     * 
     * 
@throws ClassNotFoundException
     *             If the class could not be found.
     
*/

    
public Class loadClass(byte[] classData, String className)
            
throws ClassNotFoundException {

        System.out.println(
"MyClassLoader is loading : " + className + "");
        Class c 
= defineClass(className, classData, 0, classData.length);
        loadClassHashTable.put(className, c);
        System.out.println(
"Complete to load the class :" + className);

        
return c;
    }


    
/** *//**
     * Loads the class with the specified binary name.The default implementation
     * throws a ClassNotFoundException.
     * 
     * 
@param className
     *            The binary name of the class.
     * 
@param jarName
     *            The binary name of the jar that search the class from it.
     * 
     * 
@return The resulting Class object.
     * 
     * 
@throws ClassNotFoundException
     *             If the class could not be found.
     
*/

    
protected Class loadClass(String className, String jarName)
            
throws ClassNotFoundException {

        String jarPath 
= searchFile(myClasspath, jarName + ".jar");
        JarInputStream in 
= null;

        
if (!(jarPath == null || jarPath == "")) {

            
try {
                in 
= new JarInputStream(new FileInputStream(jarPath));
                JarEntry entry;
                
while ((entry = in.getNextJarEntry()) != null{
                    String outFileName 
= entry.getName().substring(
                            entry.getName().lastIndexOf(
"/"+ 1,
                            entry.getName().length());
                    
if (outFileName.equals(className + ".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 loadClass(classData, className);
                    }

                }

                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;
    }


    
/** *//**
     * Reloads the class with the specified binary name. Needn't have to restart
     * JVM then reload the class.
     * 
     * 
@param className
     *            The binary name of the class need to reload .
     * 
     * 
@return The resulting Class object.
     * 
     * 
@throws ClassNotFoundException
     *             If the class was not found.
     
*/

    
public Class reload(String fileName) {

        String filePath 
= searchFile(myClasspath, fileName + ".class");
        Long a 
= new File(filePath).lastModified();

        
if (!a.equals(loadClassTime.get(fileName))) {
            loadClassHashTable.remove(fileName);
            loadClassTime.remove(fileName);
            
try {
                MyClassLoader mc2 
= new MyClassLoader(myClasspath);
                mc2.loadClass(fileName);
            }
 catch (ClassNotFoundException e) {
                e.printStackTrace();
            }

        }
 else {
            System.out
                    .println(
"The class is the newest version , needn't reloading.");
        }

        
return null;
    }


    
/** *//**
     * search the file with the specified binary name. Needn't have to restart
     * JVM then reload the class.
     * 
     * 
@param classpath
     *            the specified path where we search.
     * 
@param fileName
     *            The binary name of the file that want to search.
     * 
     * 
@return The resulting file path.
     
*/

    
public String searchFile(String classpath, String fileName) {

        String cut 
= fileName.substring(fileName.lastIndexOf('.'), fileName
                .length());
        String path 
= fileName.substring(0, fileName.lastIndexOf('.')).replace(
                
'.''/')
                
+ cut;

        File f 
= new File(classpath + path);
        
if (f.isFile()) {
            
return f.getPath();
        }
 else {
            String objects[] 
= new File(classpath).list();
            
for (int i = 0; i < objects.length; i++{
                
if (new File(classpath + File.separator + objects[i])
                        .isDirectory()) 
{
                    String s 
= searchFile(classpath + objects[i]
                            
+ File.separator, fileName);
                    
if (s == null || s == ""{
                        
continue;
                    }
 else {
                        
return s;
                    }

                }

            }

        }

        
return null;
    }
;

    
public static void main(String[] args) {
        MyClassLoader c1 
= new MyClassLoader(
                
"E:/javawork/teacher's classloader/bin");
        
//MyClassLoader c2 = new MyClassLoader(
        
//        "E:/javawork/teacher's classloader");
        try {
            
while (true{
                c1.loadClass(
"com.neusoft.test.A");
                
//c2.loadClass("com.neusoft.test.B");
                try {
                    Thread.sleep(
300000);
                }
 catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }

        }
 catch (Exception e) {
            e.printStackTrace();
        }

    }

}



MyThread.java
/**/ /*
 * @MyThread.java    2007/04/17
 *
 * Copyright Zhao Jiucheng. All rights reserved.
 * 
 
*/

package  com.neusoft.classloader;

import  java.io.File;


/** */ /**
 * Create a Thread to watch the specify directory,if new classes haved
 * appended,load them.
 * 
 * 
@author Zhao Jiucheng
 * 
@version 1.0, 2007/04/17
 
*/


public   class  MyThread  extends  Thread  {

    
// for get the classpath
    private String filePath;

    
// instantiation a ClassLoader
    private MyClassLoader mcl;

    
/** *//**
     * Constructs a new MyThread for the given path.
     * 
     * 
@param path
     * 
@return null
     
*/

    
public MyThread(String path) {
        
this.filePath = path;
        mcl 
= new MyClassLoader(path);
    }


    
/** *//**
     * Watch pecify directory to search for appended classes time after time.
     * 
     * 
@param filepath
     * 
     * 
@return null
     * 
@exception ClassNotFoundException
     *                if the class could not be found.
     
*/

    
public void search(String filePath) {
        File dir 
= new File(filePath);
        String[] fileList 
= dir.list();
        
for (int i = 0; i < fileList.length; i++{

            
if (new File(filePath + File.separator + fileList[i]).isDirectory()) {

                search(filePath 
+ fileList[i]);
            }
 else if (new File(filePath + File.separator + fileList[i])
                    .isFile()) 
{

                
if (fileList[i].endsWith(".class")) {
                    
try {

                        mcl.loadClass(fileList[i].substring(
0, fileList[i]
                                .length() 
- 6));
                    }
 catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }

                }

            }

        }

    }


    
/** *//**
     * If this thread was constructed using a separate runnable run object, then
     * that runnable object's run method is called;
     * 
     * 
@return null
     * 
@exception InterruptedException
     *                if the thread has been interrupted.
     
*/


    
public void run() {
        
int i = 1;
        
while (true{
            search(filePath);
            System.out.println(
"searching " + i++ + "s");
            
try {
                Thread.sleep(
1000);
            }
 catch (InterruptedException e) {
                e.printStackTrace();
            }

            
if (i == 20{
                System.out.println(
"search over!");
                
break;
            }

        }

    }


    
public static void main(String[] args) {
        MyThread t 
= new MyThread("D:\\soft\\aa");
        t.start();
    }

}


MyURLClassLoader.java
/**/ /*
 * @MyURLClassLoader.java    2007/04/17
 *
 * Copyright Zhao Jiucheng. All rights reserved.
 * 
 
*/

package  com.neusoft.classloader;

import  java.net. * ;


/** */ /**
 * This class loader is used to load classes and resources from a search path
 * 
 * 
@author Zhao Jiucheng
 * 
@version 1.0, 2007/04/17
 
*/

public   class  MyURLClassLoader  extends  URLClassLoader  {
    
/** *//**
     * Constructs a new URLClassLoader for the given URLs.
     * 
     * 
@param url
     
*/

    
public MyURLClassLoader(URL[] url) {
        
super(url);
    }


    
/** *//**
     * Finds the class with the specified binary name.
     * 
     * 
@param name
     *            The binary name of the class
     * 
@return The resulting Class object
     * 
     * 
@throws ClassNotFoundException
     *             If the class could not be found
     
*/

    @SuppressWarnings(
"unchecked")
    
public Class findClass(final String name) {
        
try {
            
return super.findClass(name);
        }
 catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        
return null;
    }


    
public static void main(String[] args) {
        URL url 
= null;
        
try {
            url 
= new URL("http://192.168.44.19:8088/Webtest/");
        }
 catch (MalformedURLException e) {
            e.printStackTrace();
        }

        MyURLClassLoader urlClassLoader1 
= new MyURLClassLoader(
                
new URL[] { url });
        Class c1 
= urlClassLoader1.findClass("Tree");
        System.out.println(c1);

    }


}




欢迎来访!^.^!
本BLOG仅用于个人学习交流!
目的在于记录个人成长.
所有文字均属于个人理解.
如有错误,望多多指教!不胜感激!

你可能感兴趣的:(JAVA CLASS LOADING技术研究---整理后的代码)