自定义编译类加载器

package com.company.bean;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;

public class ComplieClassLoader extends ClassLoader
{
    // 读取一个文件的内容
    private byte[] getBytes(String filename)
            throws IOException
    {
        File file = new File(filename);
        long len = file.length();
        byte[] raw = new byte[(int)len];
        try(
                FileInputStream fin = new FileInputStream(file))
        {
            // 一次读取Class文件的全部二进制数据
            int r = fin.read(raw);
            if(r != len)
                throw new IOException("无法读取全部文件:"
                        + r + " != " + len);
            return raw;
        }
    }
    // 定义编译指定Java文件的方法
    private boolean compile(String javaFile)
            throws IOException
    {
        System.out.println("CompileClassLoader:正在编译 "
                + javaFile + "...");
        // 调用系统的javac命令
        Process p = Runtime.getRuntime().exec("javac " + javaFile);
        try
        {
            // 其他线程都等待这个线程完成
            p.waitFor();
        }
        catch(InterruptedException ie)
        {
            System.out.println(ie);
        }
        // 获取javac线程的退出值
        int ret = p.exitValue();
        // 返回编译是否成功
        return ret == 0;
    }
    // 重写ClassLoader的findClass方法
    protected Class<?> findClass(String name)
            throws ClassNotFoundException
    {
        Class clazz = null;
        // 将包路径中的点(.)替换成斜线(/)
        String fileStub = name.replace("." , "/");
        String javaFilename = fileStub + ".java";
        String classFilename = fileStub + ".class";
        File javaFile = new File(javaFilename);
        File classFile = new File(classFilename);
        // 当指定Java源文件存在,且Class文件不存在,或者Java源文件
        // 的修改时间比Class文件的修改时间更晚时,重新编译
        if(javaFile.exists() && (!classFile.exists()
                || javaFile.lastModified() > classFile.lastModified()))
        {
            try
            {
                // 如果编译失败,或者该Class文件不存在
                if(!compile(javaFilename) || !classFile.exists())
                {
                    throw new ClassNotFoundException(
                            "ClassNotFoundExcetpion:" + javaFilename);
                }
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
            }
        }
        // 如果Class文件存在,系统负责将该文件转换成Class对象
        if (classFile.exists())
        {
            try
            {
                // 将Class文件的二进制数据读入数组
                byte[] raw = getBytes(classFilename);
                // 调用ClassLoader的defineClass方法将二进制数据转换成Class对象
                clazz = defineClass(name,raw,0,raw.length);
            }
            catch(IOException ie)
            {
                ie.printStackTrace();
            }
        }
        // 如果clazz为null,表明加载失败,则抛出异常
        if(clazz == null)
        {
            throw new ClassNotFoundException(name);
        }
        return clazz;
    }
    // 定义一个主方法
    public static void main(String[] args) throws Exception
    {
        // 如果运行该程序时没有参数,即没有目标类
        if (args.length < 1)
        {
            System.out.println("缺少目标类,请按如下格式运行Java源文件:");
            System.out.println("java CompileClassLoader ClassName");
        }
        // 第一个参数是需要运行的类
        String progClass = args[0];
        // 剩下的参数将作为运行目标类时的参数
        // 将这些参数复制到一个新数组中
        String[] progArgs = new String[args.length-1];
        System.arraycopy(args , 1 , progArgs
                , 0 , progArgs.length);
        ComplieClassLoader ccl = new ComplieClassLoader();
        // 加载需要运行的类
        Class<?> clazz = ccl.loadClass(progClass);
        // 获取需要运行的类的主方法
        Method main = clazz.getMethod("main" , (new String[0]).getClass());
        Object argsArray[] = {progArgs};
        main.invoke(null,argsArray);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_40596572/article/details/110557250