`
Arthur_Wen
  • 浏览: 29959 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java class loading 研究技术---整理后的代码

    博客分类:
  • 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);

    }

}

http://www.blogjava.net/realsmy/archive/2007/04/18/111582.html
分享到:
评论

相关推荐

    java基础学习笔记

    ### Java基础学习笔记知识点 #### 一、Java学习路线概览 ...以上是根据给定文件内容整理出的关键知识点,这些知识点不仅有助于初学者理解Java的基础概念和技术栈,也能为进阶学习提供方向和参考。

    The Java Virtual Machine Specification 3rd

    该书作为官方权威指南,不仅适用于软件开发者,也适合对Java技术栈有深入了解需求的技术人员和研究人员。 #### 二、JVM的核心概念 1. **字节码(Bytecode)** - 字节码是Java程序在编译后的中间表示形式,它是一种...

    找工作java知识总结

    根据给定的信息,我们可以整理出一份关于Java求职者所需掌握的核心知识点总结,主要涉及JVM的基础知识、垃圾回收机制以及线程池等关键概念。 ### 1. JVM基础 #### JVM架构与内存区域 JVM(Java虚拟机)是运行Java...

    高级Java经典面试题2019

    ### 并发编程 #### 多线程并发与并行 - **并发**:指一个系统内多个进程或线程交替执行的...通过深入理解这些概念和技术,可以帮助开发者更好地掌握Java核心技术,提高面试竞争力。希望本文能为读者提供有益的帮助。

    java架构师职位描述与岗位职责任职要求[001].docx

    4. **了解JVM,GC,Classloading** - 对Java虚拟机(JVM)及其相关机制的了解可以帮助架构师更好地优化程序的性能。 5. **娴熟使用过诸如Spring,MyBatis等Java生态圈主流框架** - 熟悉这些框架可以帮助架构师更高效...

    2021Java字节跳动面试题——面向字节_JVM(上).pdf

    - **标记-整理算法**:在标记阶段完成后,让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。 - **复制算法**:适用于新生代,将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块...

    JVM演讲PPT分享

    Hotspot的技术演进对于Java开发者而言也是学习和研究的重点。 通过以上内容的深入学习,可以对JVM有一个全面的认识,理解它在Java生态系统中的核心地位,以及如何通过学习JVM来提升Java程序的性能。

    hibernate整理1

    本篇主要针对Hibernate的一些核心概念和配置进行整理,尤其是对象关系映射(ORM)和数据类型映射。 1. **对象关系映射(ORM)**: - Hibernate通过ORM将Java对象与数据库表进行对应,使得对象的实例可以直接映射到...

    jvm.xmind.zip

    - **类加载器子系统(Class Loading Subsystem)**:负责加载字节码文件,验证、解析并初始化这些类。 - **运行时数据区(Runtime Data Areas)**:包括堆内存、方法区、虚拟机栈、本地方法栈和程序计数器。 - **...

    hibernate 增删改查的操作

    描述中的“hibernate 增删改查的操作做了以下整理,希望给大家带来帮助”提示我们,内容可能包含了对Hibernate CRUD操作的详细步骤、示例代码和实践技巧,旨在为学习者提供清晰的指导和帮助。 **标签解析:** ...

    JVM 真的很难学么?不、只是你“不敢学”而已

    了解这些基础知识后,Java程序员可以更深入地探讨JVM内存管理,包括堆内存、栈内存、方法区、本地方法栈等,以及垃圾收集器的工作原理,比如标记-清除、复制、标记-整理、分代收集等算法。此外,还有JVM调优、性能...

Global site tag (gtag.js) - Google Analytics