zoukankan      html  css  js  c++  java
  • java 自制类加载器的简单实现

    package com.xiaomo.reflex;


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


    public class CompileClassLoader 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;
    }
    }

    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 e) {
    System.out.println(e);
    }
    //获取javac线程的退出值
    int ret = p.exitValue();
    return ret == 0;
    }

    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("ClassNotFoundException:"+javaFilename);
    }
    }catch (IOException e) {
    e.printStackTrace();
    }
    }
    //如果class文件存在,系统负责将该文件转换成class对象
    if(classFile.exists()){
    try{
    //将class文件的二进制数据读入数组
    byte[] raw = getBytes(classFilename);
    //调用classloader的defineclass方法将二进制数据转换成class对象
    clazz = defineClass(name, raw, 0, raw.length);
    }catch(IOException e){
    e.printStackTrace();
    }
    }
    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);
    CompileClassLoader cc1 = new CompileClassLoader();
    //加载需要运行的类
    Class<?> clazz = cc1.loadClass(progClass);
    //获取需要运行的类的主要方法
    Method main = clazz.getMethod("main",(new String[0]).getClass());
    Object argsArray[] = {progArgs};
    main.invoke(null, argsArray);
    }


    }

  • 相关阅读:
    11.29 两百字
    Django:基础知识
    deepdiff:对比文件
    openpyxl:二次封装
    openpyxl:openpyxl的随笔
    web:pykeyboard、pymouse得使用
    Jmeter:如何让线程顺序执行
    Jmeter:如何将上一个线程得变量使用到下一个线程中,将上一个线程变量设置为全局变量
    Jmeter:BeanShell中的vars.put(string,string)
    Jmeter:数据库查询当天的日期
  • 原文地址:https://www.cnblogs.com/riskyer/p/3343452.html
Copyright © 2011-2022 走看看