精华内容
下载资源
问答
  • java动态编译以及动态生成jar文件

    千次阅读 2019-06-07 01:10:37
    本文主要为将指定java文件编译并生成jar,供其他程序依赖,直接上代码 动态编译java文件 /** * @author zhangchengping * @PackageName:com.demo.wms.tasks * @ClassName:CompilerUtils * @Description: 动态...

    java动态编译以及动态生成jar文件

    本文主要为将指定java文件编译并生成jar,供其他程序依赖,直接上代码

    动态编译java文件

    /**
     * @author zhangchengping
     * @PackageName:com.demo.wms.tasks
     * @ClassName:CompilerUtils
     * @Description: 动态编译java文件
     * @date 2019-06-06 10:37
     * @Version 1.0
     */
    
    import org.apache.commons.lang.StringUtils;
    
    import java.io.*;
    import java.util.Arrays;
    import java.util.List;
    
    import javax.tools.*;
    
    public class CompilerUtils {
        private static JavaCompiler javaCompiler;
        private static String encoding = "UTF-8";
    
        private CompilerUtils() {
        };
    
        private static JavaCompiler getJavaCompiler() {
            if (javaCompiler == null) {
                synchronized (CompilerUtils.class) {
                    if (javaCompiler == null) {
                        //根据JavaCompiler 的获取方式来看,应该是采用了单例模式的,但是这里为了顺便复习一下单例模式,以及确保一下单例吧
                        javaCompiler = ToolProvider.getSystemJavaCompiler();
                    }
                }
            }
    
            return javaCompiler;
        }
    
        /**
         * @Description: 编译java文件
         * @param encoding 编译编码
         * @param jarPath 需要加载的jar的路径
         * @param filePath 文件或者目录(若为目录,自动递归编译)
         * @param sourceDir java源文件存放目录
         * @param targetDir 编译后class类文件存放目录
         * @return boolean
         * @Author zhangchengping
         * @Date 2019-06-06 19:50
         */
        public static void compiler( String filePath, String targetDir, String sourceDir,String encoding, String jarPath)
                throws Exception {
    
            // 得到filePath目录下的所有java源文件
            List<File> sourceFileList = File4ComplierUtils.getSourceFiles(filePath);
    
            if (sourceFileList.size() == 0) {
                // 没有java文件,直接返回
                System.out.println(filePath + "目录下查找不到任何java文件");
                return;
            }
            //获取所有jar
            String jars = File4ComplierUtils.getJarFiles(jarPath);
            if(StringUtils.isBlank(jars)){
                jars="";
            }
            File targetFile = new File(targetDir);
            if(!targetFile.exists())targetFile.mkdirs();
            // 建立DiagnosticCollector对象
            DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
            //该文件管理器实例的作用就是将我们需要动态编译的java源文件转换为getTask需要的编译单元
            StandardJavaFileManager fileManager = getJavaCompiler().getStandardFileManager(diagnostics, null, null);
            // 获取要编译的编译单元
            Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(sourceFileList);
            /**
             * 编译选项,在编译java文件时,编译程序会自动的去寻找java文件引用的其他的java源文件或者class。 -sourcepath选项就是定义java源文件的查找目录, -classpath选项就是定义class文件的查找目录,-d就是编译文件的输出目录。
             */
            //Iterable<String> options =Arrays.asList("-encoding",encoding,"-classpath",jars,"-d", targetDir, "-sourcepath", sourceDir);
            Iterable<String> options =Arrays.asList("-encoding",encoding,"-classpath",jars,"-d", targetDir, "-sourcepath", sourceDir);
            /**
             * 第一个参数为文件输出,这里我们可以不指定,我们采用javac命令的-d参数来指定class文件的生成目录
             * 第二个参数为文件管理器实例  fileManager
             * 第三个参数DiagnosticCollector<JavaFileObject> diagnostics是在编译出错时,存放编译错误信息
             * 第四个参数为编译命令选项,就是javac命令的可选项,这里我们主要使用了-d和-sourcepath这两个选项
             * 第五个参数为类名称
             * 第六个参数为上面提到的编译单元,就是我们需要编译的java源文件
             */
            JavaCompiler.CompilationTask task = getJavaCompiler().getTask(
                    null,
                    fileManager,
                    diagnostics,
                    options,
                    null,
                    compilationUnits);
                // 运行编译任务
            // 编译源程式
            boolean success = task.call();
            for (Diagnostic diagnostic : diagnostics.getDiagnostics())
                System.out.printf(
                        "Code: %s%n" +
                                "Kind: %s%n" +
                                "Position: %s%n" +
                                "Start Position: %s%n" +
                                "End Position: %s%n" +
                                "Source: %s%n" +
                                "Message: %s%n",
                        diagnostic.getCode(), diagnostic.getKind(),
                        diagnostic.getPosition(), diagnostic.getStartPosition(),
                        diagnostic.getEndPosition(), diagnostic.getSource(),
                        diagnostic.getMessage(null));
            fileManager.close();
            System.out.println((success)?"编译成功":"编译失败");
        }
    }
    /**
     * @author zhangchengping
     * @PackageName:com.demo.wms.tasks.web.listener
     * @ClassName:s
     * @Description: 文件处理类
     * @date 2019-06-06 19:07
     * @Version 1.0
     */
    public class File4ComplierUtils {
    
        /**
         * @Description:  获取目录下所有源文件
         * @param sourceFilePath
         * @return java.util.List<java.io.File>
         * @Author zhangchengping
         * @Date 2019-06-06 19:47
         */
        public static List<File> getSourceFiles(String sourceFilePath){
    
            List<File> sourceFileList = new ArrayList<>();
            try {
                getSourceFiles(new File(sourceFilePath),sourceFileList);
            } catch (Exception e) {
                e.printStackTrace();
                sourceFileList = null;
            }
            return sourceFileList;
        }
    
        /**
         * @Description:  获取目录下所有的jar
         * @param sourceFilePath
         * @return java.lang.String
         * @Author zhangchengping
         * @Date 2019-06-06 19:46
         */
        public static String getJarFiles(String sourceFilePath){
    
            String jars = "";
            try {
                getJarFiles(new File(sourceFilePath),jars);
            } catch (Exception e) {
                e.printStackTrace();
                jars = "";
            }
            return jars;
        }
        /**
         * 查找该目录下的所有的java文件
         *
         * @param sourceFile
         * @param sourceFileList
         * @throws Exception
         */
        private static void getSourceFiles(File sourceFile, List<File> sourceFileList) throws Exception {
            if (!sourceFile.exists()) {
                // 文件或者目录必须存在
                throw new IOException(String.format("%s目录不存在",sourceFile.getPath()));
            }
            if (null == sourceFileList) {
                // 若file对象为目录
                throw new NullPointerException("参数异常");
            }
            if (sourceFile.isDirectory()) {// 若file对象为目录
                File[] childrenDirectoryFiles = sourceFile.listFiles(new FileFilter() {
                    @Override
                    public boolean accept(File pathname) {
                        return pathname.isDirectory();
                    }
                });
                for (File file : sourceFile.listFiles()) {
                    if(file.isDirectory()){
                        getSourceFiles(file,sourceFileList);
                    } else {
                        sourceFileList.add(file);
                    }
                }
            }else{
                sourceFileList.add(sourceFile);
            }
        }
    
        /**
         * 查找该目录下的所有的jar文件
         *
         * @param sourceFile
         * @throws Exception
         */
        private static String getJarFiles(File sourceFile,String jars) throws Exception {
            if (!sourceFile.exists()) {
                // 文件或者目录必须存在
                throw new IOException("jar目录不存在");
            }
            if (!sourceFile.isDirectory()) {
                // 若file对象为目录
                throw new IOException("jar路径不为目录");
            }
            if(sourceFile.isDirectory()){
                for (File file : sourceFile.listFiles()) {
                    if(file.isDirectory()){
                        getJarFiles(file,jars);
                    }else {
                        jars = jars + file.getPath() + ";";
                    }
                }
            }else{
                jars = jars + sourceFile.getPath() + ";";
            }
            return jars;
        }
    }

    将编译后的class生成jar文件

    **
     * @author zhangchengping
     * @PackageName:com.demo.wms.tasks.web.listener
     * @ClassName:PackageUtil
     * @Description: 生成jar文件
     * @date 2019-06-06 22:59
     * @Version 1.0
     */
    
    import com.sun.javafx.beans.annotations.NonNull;
    import org.apache.commons.io.FileUtils;
    import org.apache.commons.lang.StringUtils;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.lang.annotation.Target;
    import java.util.jar.JarEntry;
    import java.util.jar.JarOutputStream;
    import java.util.jar.Manifest;
    
    public class CreateJarUtils {
    
        /**
         * @param rootPath    class文件根目录
         * @param targetPath  需要将jar存放的路径
         * @param jarFileName jar文件的名称
         * @Description: 根据class生成jar文件
         * @Author zhangchengping
         * @Date 2019-06-06 23:56
         */
        public static void createTempJar(String rootPath, String targetPath, String jarFileName) throws IOException {
            if (!new File(rootPath).exists()) {
                throw new IOException(String.format("%s路径不存在", rootPath));
            }
            if (StringUtils.isBlank(jarFileName)) {
                throw new NullPointerException("jarFileName为空");
            }
            //生成META-INF文件
            Manifest manifest = new Manifest();
            manifest.getMainAttributes().putValue("Manifest-Version", "1.0");
            //manifest.getMainAttributes().putValue("Main-Class", "Show");//指定Main Class
            //创建临时jar
            File jarFile = File.createTempFile("edwin-", ".jar", new File(System.getProperty("java.io.tmpdir")));
            JarOutputStream out = new JarOutputStream(new FileOutputStream(jarFile), manifest);
            createTempJarInner(out, new File(rootPath), "");
            out.flush();
            out.close();
            //程序结束后,通过以下代码删除生成的jar文件
           /* Runtime.getRuntime().addShutdownHook(new Thread() {
                public void run() {
                    jarFile.delete();
                }
            });*/
            //生成目标路径
            File targetFile = new File(targetPath);
            if (!targetFile.exists()) targetFile.mkdirs();
            File targetJarFile = new File(targetPath + File.separator + jarFileName + ".jar");
            if(targetJarFile.exists() && targetJarFile.isFile())targetJarFile.delete();
            FileUtils.moveFile(jarFile, targetJarFile);
            //jarFile.renameTo(new File(""));
        }
    
        /**
         * @Description: 生成jar文件
         * @param out 文件输出流
         * @param f 文件临时File
         * @param base 文件基础包名
         * @return void
         * @Author zhangchengping
         * @Date 2019-06-07 00:02
         */
        private static void createTempJarInner(JarOutputStream out, File f,
                                               String base) throws IOException {
    
            if (f.isDirectory()) {
                File[] fl = f.listFiles();
                if (base.length() > 0) {
                    base = base + "/";
                }
                for (int i = 0; i < fl.length; i++) {
                    createTempJarInner(out, fl[i], base + fl[i].getName());
                }
            } else {
                out.putNextEntry(new JarEntry(base));
                FileInputStream in = new FileInputStream(f);
                byte[] buffer = new byte[1024];
                int n = in.read(buffer);
                while (n != -1) {
                    out.write(buffer, 0, n);
                    n = in.read(buffer);
                }
                in.close();
            }
        }
    }

    程序调用

    import java.io.File;
    import java.io.FileFilter;
    import java.io.IOException;
    
    import com.demo.wms.tasks.utils.CompilerUtils;
    import com.demo.wms.tasks.utils.CreateJarUtils;
    import org.apache.commons.io.FileUtils;
    
    public class BuildRmi {
        //资源文件根路径
        static String basePath = "E:\\WorkSpace\\demo\\WMS_TASK_NC";
        //生成jar文件路径
        static String jarFilePath = "E:\\WorkSpace\\demo\\rmi-client";
        //需要编译的源文件路径
        static String[] srcFiles = {
                "/src/com/demo/wms/tasks/vo/",
                "/rmi/com/demo/wms/tasks/rmi/",
                "/rmi/com/demo/wms/tasks/rmi/po/",
                "/rmi/com/demo/wms/tasks/rmi/client/"
        };
        static String jarReyOnPath = "E:\\WorkSpace\\demo\\WMS_TASK_NC\\WebRoot\\WEB-INF\\lib";
        static String jarFileName = "rim";
        static String encoding = "utf-8";
    
        public static void main(String[] args) {
            String sourcePath = "";
            String classPath = "";
            try {
                // 将RMI需要使用的JAVA文件拷贝到制定目录中
                System.out.println("分隔符:" + File.separator);
                System.out.println("资源拷贝......");
                sourcePath = jarFilePath + File.separator + "source";
                copySource(sourcePath);//拷贝资源
                System.out.println("资源拷贝结束");
                System.out.println("编译资源......");
                //编译java文件
                classPath = jarFilePath + File.separator + "class";
                try {
                    CompilerUtils.compiler(sourcePath, classPath, basePath, encoding, jarReyOnPath);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println("编译资源结束");
                System.out.println("生成jar......");
                //生成jar文件
                CreateJarUtils.createTempJar(classPath, jarFilePath, jarFileName);
                System.out.println("生成jar完成");
                //删除临时文件
                ExeSuccess(sourcePath, classPath);
            } catch (IOException e) {
                e.printStackTrace();
                deleteTempFile(sourcePath, classPath);
    
            } finally {
            }
    
        }
    
        private static void ExeSuccess(String sourcePath, String classPath) {
            final String sourcedir = sourcePath;
            final String classdir = classPath;
            //程序结束后,通过以下代码删除生成的文件
            Runtime.getRuntime().addShutdownHook(new Thread() {
                public void run() {
                    deleteTempFile(sourcedir, classdir);
                    System.out.println("***************执行完毕**********************");
                }
            });
        }
    
        private static void deleteTempFile(String sourcePath, String classPath) {
            //程序结束后,通过以下代码删除生成的class 和java文件
            try {
                File sourceFile = new File(sourcePath);
                if (sourceFile.exists()) {
                    FileUtils.deleteDirectory(sourceFile);
                }
                File classFile = new File(classPath);
                if (classFile.exists()) {
                    FileUtils.deleteDirectory(classFile);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
    
    
        }
    
        private static void copySource(String sourcePath) throws IOException {
            for (String f : srcFiles) {
                String path = f.replace("/", File.separator);
                System.out.println(path);
                File srcFile = new File(basePath + path);
                File targetFile = new File(sourcePath + path);
                FileUtils.copyDirectory(srcFile, targetFile, new FileFilter() {
                    @Override
                    public boolean accept(File pathname) {
                        System.out.println(pathname);
                        return pathname.getName().endsWith(".java");
                    }
                });
            }
        }
    }

     

     

    展开全文
  • 动态编译的应用场景 Java 6.0之后要引入了动态编译动态编译可以实现:让用户提交一段Java代码,上传到服务器,运行,实现在线评测...动态编译生成一个class文件 编译前: 编译后: 代码示例 下列代码返回值为...

    动态编译的应用场景

    Java 6.0之后要引入了动态编译。

    动态编译可以实现:让用户提交一段Java代码,上传到服务器,运行,实现在线评测系统。

    Java 6.0之前,可以使用这种方式,达到动态编译的效果:
    在这里插入图片描述
    Java 6.0之后,使用如下方式,也就是本文要讲的:

    • 使用JavaCompiler动态编译

    在这里插入图片描述

    官方API

    https://docs.oracle.com/en/java/javase/11/docs/api/java.compiler/javax/tools/Tool.html#run(java.io.InputStream,java.io.OutputStream,java.io.OutputStream,java.lang.String...)
    

    在这里插入图片描述

    run

    int run​(InputStream in, OutputStream out, OutputStream err, String... arguments)
    !!这里注意一下String... arguments,可以传进一个String数组,里面好像是所有需要编译的文件路径吧?
    Run the tool with the given I/O channels and arguments. By convention a tool returns 0 for success and nonzero for errors. Any diagnostics generated will be written to either out or err in some unspecified format.
    Parameters:
    in - "standard" input; use System.in if null
    out - "standard" output; use System.out if null
    err - "standard" error; use System.err if null
    arguments - arguments to pass to the tool
    Returns:
    0 for success; nonzero otherwise
    Throws:
    NullPointerException - if the array of arguments contains any null elements.

    动态编译

    动态编译生成一个class文件

    编译前:
    在这里插入图片描述
    编译后:
    在这里插入图片描述代码示例

    下列代码返回值为0,表示编译成功

    package cn.hanquan.dynamic;
    
    import javax.tools.JavaCompiler;
    import javax.tools.ToolProvider;
    
    public class DynamicCompile {
    	public static void main(String[] args) {
    		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    		int result = compiler.run(null, null, null, "c:/picture/Hello.java");
    		System.out.println("result=" + result);
    	}
    }
    
    

    输出

    result=0
    

    提问:如果由于某种原因(如拼接…),需要编译的不是一个文件,而是一个字符串,那么应该如何编译呢?

    • 可以通过IO流操作,将字符串存储成临时文件,然后调用动态编译方法

    动态运行编译好的类

    在这里插入图片描述
    代码示例

    (1)通过Runtime执行

    package cn.hanquan.dynamic;
    
    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    
    import javax.tools.JavaCompiler;
    import javax.tools.ToolProvider;
    
    public class DynamicCompile {
    	public static void main(String[] args) throws Exception {
    		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    		int result = compiler.run(null, null, null, "c:/picture/Hello.java");// 编译
    
    		if (result == 0) {
    			Runtime run = Runtime.getRuntime();// 运行
    			Process process = run.exec("java -cp c:/picture Hello");
    
    			InputStream is = process.getInputStream();// 获取运行后输出结果
    			BufferedReader br = new BufferedReader(new InputStreamReader(is));
    			String info = "";
    			while ((info = br.readLine()) != null) {
    				System.out.println(info);
    			}
    		}
    	}
    }
    

    输出结果

    Hello,World~~
    

    (2)通过反射加载相关类,调用相关方法
    在这里插入图片描述
    注意42行,main方法没有参数,可以不写参数。传String数组的时候,一定要加Object进行转型。
    在这里插入图片描述

    展开全文
  • Java文件动态编译并执行方法

    千次阅读 2018-07-16 10:25:41
    package ... import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.lang.reflect.Method; import java.net.URI; import java.net.URISyntaxExceptio...
    package com.example.demo.dimension;
    
    import java.io.File;
    import java.io.FileFilter;
    import java.io.IOException;
    import java.lang.reflect.Method;
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.net.URL;
    import java.net.URLClassLoader;
    import java.util.Arrays;
    import java.util.Stack;
    
    import javax.tools.JavaCompiler;
    import javax.tools.JavaCompiler.CompilationTask;
    import javax.tools.JavaFileObject;
    import javax.tools.SimpleJavaFileObject;
    import javax.tools.StandardJavaFileManager;
    import javax.tools.ToolProvider;
    
    /**
     * @ClassName: CompilerTest
     * @Description: JAVA源文件动态编译
     * @date: 2018年7月16日 上午9:45:32
     * 
     */
    public class CompilerTest {
    	public static void main(String[] args) throws Exception {
    		String classPath = "G:/deleted/apktool/dynamicClass" ;
    		System.out.println( calculate("1.0+1.0",classPath));
    	}
    	
    	/**
    	 * @Title: testHello   
    	 * @Description: 测试动态编译java文件
    	 * @param: @param classPath      
    	 * @return: void      
    	 * @throws
    	 */
    	public static void testHello(String classPath){
    		String className = "Main" ;
    		String source = "public class "+className+" { public static void main(String[] args) {System.out.println(\"Hello World!\");} }";
    		boolean isSuccess = complie(source,className,classPath) ;
    		System.out.println( "Complie successfully:"+isSuccess );
    	}
    	
    
    	/**
    	 * @Title: calculate   
    	 * @Description: 测试动态编译并且加载类并执行对应方法
    	 * @param: @param expr
    	 * @param: @param classPath
    	 * @param: @return
    	 * @param: @throws Exception      
    	 * @return: double      
    	 * @throws
    	 */
    	private static double calculate(String expr,String classPath) throws  Exception {
    		String className = "Main";
    		String methodName = "calculate";
    		String source = "public class " + className + " { public static double " + methodName + "() { return " + expr
    				+ "; } }";
    		// 省略动态编译Java源代码的相关代码,参见上一节
    		boolean result = complie(source,className, classPath);
    		if (result) {
    			loadClass( new File(classPath) );
    			ClassLoader loader = CompilerTest.class.getClassLoader();
    			try {
    				Class<?> clazz = loader.loadClass(className);
    				Method method = clazz.getMethod(methodName, new Class<?>[] {});
    				Object value = method.invoke(null, new Object[] {});
    				return (Double) value;
    			} catch (Exception e) {
    				throw new  Exception("内部错误。",e);
    			}
    		} else {
    			throw new  Exception("错误的表达式。");
    		}
    	}
    	
    	/**
    	 * @Title: complie   
    	 * @Description: 动态编译java类成成class文件放入指定目录
    	 * @param: @param expr
    	 * @param: @param classPath
    	 * @param: @return
    	 * @param: @throws Exception      
    	 * @throws
    	 */
    	public static boolean complie(String source,String className,String classPath){
    		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    		StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
    		StringSourceJavaObject sourceObject = null;
    		try {
    			Iterable<String> options = Arrays.asList("-d", classPath);
    			sourceObject = new CompilerTest.StringSourceJavaObject(className, source);
    			Iterable<? extends JavaFileObject> fileObjects = Arrays.asList(sourceObject);
    			CompilationTask task = compiler.getTask(null, fileManager, null, options, null, fileObjects);
    			boolean result = task.call();
    			return result ;
    		} catch (URISyntaxException e) {
    			e.printStackTrace();
    		}
    		return false ;
    	} 
    
    	private static class StringSourceJavaObject extends SimpleJavaFileObject {
    
    		private String content = null;
    
    		public StringSourceJavaObject(String name, String content) throws URISyntaxException {
    			super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
    			this.content = content;
    		}
    
    		public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
    			return content;
    		}
    	}
    	
    	/**
    	 * @Title: loadClass   
    	 * @Description: 动态加载class文件
    	 * @param: @param clazzPath
    	 * @param: @throws Exception      
    	 * @return: void      
    	 * @throws
    	 */
    	public static void loadClass(File clazzPath) throws Exception{
    		// 设置class文件所在根路径
    		// 例如/usr/java/classes下有一个test.App类,则/usr/java/classes即这个类的根路径,而.class文件的实际位置是/usr/java/classes/test/App.class
    //		File clazzPath = new File(class文件所在根路径);
    		 
    		// 记录加载.class文件的数量
    		int clazzCount = 0;
    		//only handle the folder
    		if( clazzPath.isFile() ){
    			clazzPath = clazzPath.getParentFile() ;
    		}
    		
    		if (clazzPath.exists() && clazzPath.isDirectory()) {
    			// 获取路径长度
    			int clazzPathLen = clazzPath.getAbsolutePath().length() + 1;
    		 
    			Stack<File> stack = new Stack<>();
    			stack.push(clazzPath);
    		 
    			// 遍历类路径
    			while (stack.isEmpty() == false) {
    				File path = stack.pop();
    				File[] classFiles = path.listFiles(new FileFilter() {
    					public boolean accept(File pathname) {
    						return pathname.isDirectory() || pathname.getName().endsWith(".class");
    					}
    				});
    				for (File subFile : classFiles) {
    					if (subFile.isDirectory()) {
    						stack.push(subFile);
    					} else {
    						if (clazzCount++ == 0) {
    							Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
    							boolean accessible = method.isAccessible();
    							try {
    								if (accessible == false) {
    									method.setAccessible(true);
    								}
    								// 设置类加载器
    								URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    								// 将当前类路径加入到类加载器中
    								method.invoke(classLoader, clazzPath.toURI().toURL());
    							} finally {
    								method.setAccessible(accessible);
    							}
    						}
    						// 文件名称
    						String className = subFile.getAbsolutePath();
    						className = className.substring(clazzPathLen, className.length() - 6);
    						className = className.replace(File.separatorChar, '.');
    						// 加载Class类
    						Class.forName(className);
    						System.out.println( String.format( "读取应用程序类文件[class=%s]", className) );
    					}
    				}
    			}
    		}
    	}
    }


    参考:

    动态加载jar和class文件    https://blog.csdn.net/mousebaby808/article/details/31788325

    JAVA源文件动态编译       https://blog.csdn.net/m1993619/article/details/78734682


    展开全文
  • 在D盘test目录下有两个java文件:AlTest1.java、AlTest2.java,现需要通过java代码实现java文件到class文件的编译操作: import java.io.BufferedReader; import java.io.InputStream; import java.io.Input...

    所谓动态编译,就是在程序运行时产生java类,并编译成class文件。

    在D盘test目录下有两个java文件:AlTest1.java、AlTest2.java,现需要通过java代码实现java文件到class文件的编译操作:

     
    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
     
    import javax.tools.JavaCompiler;
    import javax.tools.ToolProvider;
     
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
     
    import com.piao.main.ApplicationAdmin;
     
     
    @RunWith(SpringJUnit4ClassRunner.class)
    @ComponentScan("com.piao")
    @SpringBootTest(classes = ApplicationAdmin.class)
    public class Compiler {
    	
    	@Test
    	public void compiler1(){
    		String javaAbsolutePath = "D:/test/AlTest1.java";
    		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    	int status = compiler.run(null, null, null, "-encoding", "UTF-8", "-classpath", javaAbsolutePath.toString(), javaAbsolutePath);
            if(status!=0){
    		 System.out.println("没有编译成功!");
    	 }
    		
    	}
    	@Test
    	public void compiler2(){
    		String javaAbsolutePath = "D:/test/AlTest2.java";
    		
    		try {
    			Process process = Runtime.getRuntime().exec("javac -classpath D:/test/ " + javaAbsolutePath);
    			InputStream errorStream = process.getErrorStream();
    			InputStreamReader inputStreamReader = new InputStreamReader(errorStream);
    			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
    			String line = null;
    			while ((line=bufferedReader.readLine()) != null){
    				System.out.println(line);
    			}
    			int exitVal = process.waitFor();
    			System.out.println("Process exitValue: " + exitVal);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}	
    	}
    	
    	 
    }

    运行后, D:\test 目录会生成两个class文件

     

    其中方法compiler1是使用jdk自带的rt.jar中的javax.tools包提供的编译器

    方法compiler2是使用Runtime执行javac命令

     

    参考:

     https://blog.csdn.net/zhoufanyang_china/article/details/82767406

    展开全文
  • java实现动态编译动态加载

    万次阅读 2018-09-19 09:40:55
    在D盘test目录下有个java文件:AlTest.java public class AlTest { public String sayHello(){ System.out.println("AlTest类 sayHello()方法正在执行...."); return "hello word"; }...
  • 什么情况下会需要用java程序动态编译java源文件,动态的加载java文件呢?如果很少遇到这样的需求的兄弟们可能不会清楚动态编译动态的加载用在一个什么样的场景。下面我将我遇到的场景描述下。 Sdl说明: ...
  • java实现动态编译的几种方法

    万次阅读 2018-09-19 09:05:00
     在D盘test目录下有两个java文件:AlTest1.java、AlTest2.java,现需要通过java代码实现java文件到class文件的编译操作: import java.io.BufferedReader; import java.io.InputStream; import java.io.In...
  • JAVA多个.java文件编译

    千次阅读 2017-09-27 21:31:48
    例如某程序有A.java B.java两个.java文件此时,若在A中调用了不在A.java中的类B,在编译A时会寻找B.class文件,若未找到,会接着寻找B.java文件,找到后对B.java文件进行编译。所以,手动编译源文件时,可以只执行一...
  • 提取Tomcat6.0动态编译java文件核心代码,修整而成。为以后的学习工作带来便利。编译部分由JDT负责由URLClassLoader动态加载.class文件后通过java反射机制运行类main.javapackage com.dynamic;import java.io.File;...
  • 动态编译和运行外部java文件

    千次阅读 2016-08-08 17:40:39
    笔者在最近的项目中对一个用户任意指定的Java项目或Java文件进行测试,这就涉及到编译和运行这些Java文件,折腾一段时间后实现了这个功能,在这记录下使用到的技术点。编译Java文件对于一个给定的java文件进行编译,...
  • JAVA动态编译

    千次阅读 2011-11-19 17:59:53
    JAVA 6.0引入了动态编译机制,也就是说,你利用java的io流把完整的程序代码写入.java后缀的文件...下面假设在D盘根目录下有一个hello.java文件(实际上此文件多数时候应该由java创建): 编译步骤: 1、调用 ToolPro
  • 开心一笑【年底是各种案件的高发期,我们去ATM取钱的时候,一定要注意遮挡,不要被陌生人看到你的余额,要不然啊,就,,,非常容易被人嘲笑。... 】提出问题java中的动态编译和静态编译如何理解???解
  • Java_java动态编译整个项目

    千次阅读 2017-01-11 22:24:29
    动态java文件编译为class文件解决方案: 将temp\sdl\src目录中的java源文件编译成class文件,并存放到temp\sdl\classes目录中 java中早就提供了用java方式去动态编译java源文件的接口,有关java动态编译的API...
  • Java动态编译

    千次阅读 2011-05-10 20:05:00
    简介: Java语言是一种具有动态性的解释型编程语言,当指定程序运行时,java虚拟机就将编译生成的.class文件按照需求和一定的规则加载进内 存,并组织成一个完整的java应用程序。Java语言把单独的一个类...
  • Java动态编译

    千次阅读 2015-11-13 16:14:02
    程序产生过程下图展示了从源代码到可运行程序的过程,正常情况下先编译(明文源码到字节码)...这就是我们下面的主题,动态编译。 相关类介绍JavaCompiler: 负责读取源代码,编译诊断,输出class JavaFileObject: 文
  • PS:2018-03-08 10:11更新 修改编译的路径 原路径为WebRoot,修改为WebRoot/classes,否则会出现include会找不到jsp等问题 1.出现这个问题先检查一下输出路径 idea的class输出路径与eclipse是不一样的,idea...
  • Java动态编译执行

    万次阅读 2017-01-05 16:18:02
    在某些情况下,我们可能需要动态生成java代码,通过动态编译,然后执行代码。JAVA API提供了相应的工具(JavaCompiler)来实现动态编译。下面我们通过一个简单的例子介绍,如何通过JavaCompiler实现java代码动态编译...
  • 怎么把java文件编译为class文件

    万次阅读 2019-04-11 11:05:36
    java文件轻松编译为class文件 1.需要有配置好的java的环境变量 2.在你的jdk目录下的bin目录下打开cmd 2.然后找到你要编译java文件的路径,例如我要编译java文件在:E:\IntelliJ IDEA\Workplace\SpringJdbcTest\...
  • 在上篇文章中了解到了Java前端编译 JIT编译 AOT编译各有什么优点和缺点,下面详细了解Java前端编译Java源代码编译成Class文件的过程;我们从官方JDK提供的前端编译器javac入手,用javac编译一些测试程序,调试跟踪...
  • 主要是动态编译这点比较有趣, 1 定义一个接口,只有一个方法,sell (为什么要定义这个接口,就不多说了..面向接口编程可以说是必须的) package com.cjb.proxy; /**  * 类说明  * 表示商店  * @creator  ...
  • 解决 .java 文件编译问题

    千次阅读 2018-05-09 12:00:47
    项目编译时没报错,启动tomcat报错如下:org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [spring-mybatis.xml]: ...
  • Java 如何编译 Java 文件

    千次阅读 2016-12-10 10:18:28
    本文我们演示如何编译 HelloWorld.java 文件,其中 Java 代码如下:public class HelloWorld { public static void main(String []args) { System.out.println(“Hello World”); }} 接下来我们使用 javac 命令...
  • 遇到java 文件编译问题

    千次阅读 2018-02-04 10:18:36
    1.今天在开发中遇到我的classpath下的properties文件编译问题,因此进行了手动编译,将我们文件拷贝到classes路径下,其实便宜一个文件对我们来说so easy,但是这个编译文件是一个servlet文件,直接编译会不成功,...
  • //编译器类只有jdk6里面才有 public class CompilerTest { //window下面的换行是\r\t 回车换行 public static void main(String[] args) throws IOException, ... //得到系统当前的路径,即是java工程的路径(E:\works
  • 其项目很多java文件因为特殊框架原因,不能像正常一样通过编译。但是,我需要写一个main方法来测试自己的方法,即只需要保证该类编译正常,忽略其他类的编译错误。 (1)如下图,找到java Complier设置,Use ...
  • Java动态编译动态加载详解

    千次阅读 2018-10-15 13:58:43
    一.动态编译 在某些情况下,我们需要动态生成java代码,通过动态编译,然后执行代码。JAVA API提供了相应的工具(JavaCompiler)来实现动态编译。...//获取java文件管理类 StandardJavaFileManage...
  • java在线反编译class文件

    万次阅读 多人点赞 2018-10-27 14:44:31
    编译网址:http://javare.cn 对你有帮助的话,右上角给个赞呗~
  • JAVA动态编译(JavaCompiler)

    千次阅读 2013-11-14 15:19:20
    在java中javax报下提供了JavaCompiler类,此类可以允许开发人员编译java文件为class文件。 下面示例中是利用JavaCompiler编译文件,并利用URLClassLoader加载编译好的class文件执行其中的方法。 二、示例代码 ...
  • 最近一直在研究Java8 的动态编译, 并且也被ZipFileIndex$Entry 内存泄漏所困扰,在无意中,看到一个第三方插件的动态编译。并且编译速度是原来的2-3倍。原本打算直接用这个插件,但是发现插件的编译源码存在我之前...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 880,612
精华内容 352,244
关键字:

java文件的动态编译

java 订阅