java编程进行动态编译加载代码分享

简述

该类使用javax.tools.ToolProvider自带的JavaCompiler进行编译,使用IO的File及NIO的Files进行对应的路径创建、读取及拷贝,使用正则表达式进行包名与目录的转换,我只是将这些东西做了个容错整合,没什么技术含量,就为个方便吧。

模块API

class DynamicReactor://空参构造
public Class<?> dynamicCompile(String srcPath);//输入一个指定的源文件路径,若编译、拷贝成功则返回该类对应的Class类实例
private String changePacketToDic(String packageName);//将一个合法的包名转换为对应JavaClassPath中的路径(我是用的是eclipse 所以需要对应地增加bin这一目录,若使用其他不同编译器,请参考对应的运行上下文设置进行适当修改)
private String getPackage(String srcPath);//由一个合法的java文件路径尝试获得其包名 

源代码

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
/**
 * DynamicReactor 一个动态编译模块,负责编译源文件,复制到对应包下及加载类等过程(JDK 1.7)
 * @author 三向板砖
 * */
public class DynamicReactor {
	JavaCompiler compiler;
	Pattern packagePattern;
	static final String regEx = "(?<=package\\s).*(?=;)";
	public DynamicReactor()
	  {
		compiler = ToolProvider.getSystemJavaCompiler();
		packagePattern = Pattern.compile(regEx);
	}
	/**
   * 动态编译给定源文件
   * @param srcPath 源文件路径
   * @return Class
   *   <br>若成功返回对应类的Class实例
   *   <br>若失败返回null
   * */
	public Class<?> dynamicCompile(String srcPath)
	  {
		Class<?> result = null;
		//获得给定路径源文件的
		String packName = getPackage(srcPath);
		if(packName == null)
		    {
			System.out.println("DynamicRector:Load packageName Error!");
			return null;
		}
		//调用compiler编译指定源文件
		int res = compiler.run(null, null, null,srcPath);
		if(res != 0)
		    {
			System.out.println("DynamicRector:Compile Java Source Error!");
			return null;
		}
		//获得包名对应的路径,若路径不存在则创建,若指定class文件存在则覆盖
		String packageDst = changePacketToDic(packName);
		File dstDir = new File(packageDst);
		if(!dstDir.exists())
		    {
			dstDir.mkdirs();
		}
		Path pathFrom = Paths.get(srcPath.split("\\.java")[0] + ".class");
		Path pathTo = Paths.get(packageDst,pathFrom.getFileName().toString());
		try {
			Files.move(pathFrom, pathTo, StandardCopyOption.REPLACE_EXISTING);
		}
		catch (IOException e) {
			System.out.println("DynamicRector:Move File Fail!");
			e.printStackTrace();
		}
		try {
			result = Class.forName(packName+"."+pathFrom.getFileName().toString().split("\\.class")[0]);
		}
		catch (ClassNotFoundException e) {
			System.out.println("DynamicRector:Class Not found in Final!");
		}
		return result;
	}
	//该方法将一个合法包名转化为对应路径
	private String changePacketToDic(String packageName)
	  {
		String[] dirs = packageName.split("\\.");
		String res = ".\\bin";
		for (int i = 0;i < dirs.length;i++)
		    {
			res += "\\"+dirs[i];
		}
		return res;
	}
	//该方法从给定的路径源文件中获得包名
	private String getPackage(String srcPath)
	  {
		String result = null;
		BufferedReader br;
		try {
			br = new BufferedReader(new FileReader(srcPath));
			String data = br.readLine();
			while(data != null)
			      {
				if(data.indexOf("package") != -1)
				        {
					Matcher m = packagePattern.matcher(data);
					if(m.find())
					          {
						result = m.group();
					}
					break;
				}
				data = br.readLine();
			}
			br.close();
		}
		catch (IOException e) {
			System.out.println("DynamicRector:Error in open file "+srcPath);
		}
		return result;
	}
}

总结

以上就是本文关于java编程进行动态编译加载代码分享的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

(0)

相关推荐

  • 从源码编译Android系统的Java类库和JNI动态库的方法

    利用源码编译Android系统Java类库 1.编写Java项目和Android.mk文件 ├── Android.mk └── src └── com └── lhw └── framework └── led └── Led.java Led.java文件 package com.lhw.framework.led; /** * LED操作库 * @author Micky Liu */ public class Led { public boolean turnOn() { return

  • Java中的动态和静态编译实例详解

    Java中的动态和静态编译实例详解 首先,我们来说说动态和静态编译的问题. Q: java和javascript有什么区别?    总结了一下:有以下几点吧: 1.首先从运行环境来说java代码是在JVM上编译成class文件,而javascript则直接在浏览器上加载运行. 2.由第一点可看出,java代码需要编译,而javascript不需要编译. 3.从语言性质来说,java是一种高级编程语言,对变量检查要求严格,javascript只是一个简单的解释性的脚本语言,对变量检查及要求很弱.

  • 老生常谈Java动态编译(必看篇)

    一.动态编译简介 new创建对象是静态加载类,在编译时刻就需要加载所有可能使用到的类. 一百个类,有一个类错了,都无法编译. 通过动态加载类可以解决该问题 二.代码实例 2.1 OfficeBetter.java main接口 里面通过对Class类的动态编译 然后调用实例,完成动态编译 public class OfficeBetter { public static void main(String[] args) throws InstantiationException, Illegal

  • java编程进行动态编译加载代码分享

    简述 该类使用javax.tools.ToolProvider自带的JavaCompiler进行编译,使用IO的File及NIO的Files进行对应的路径创建.读取及拷贝,使用正则表达式进行包名与目录的转换,我只是将这些东西做了个容错整合,没什么技术含量,就为个方便吧. 模块API class DynamicReactor://空参构造 public Class<?> dynamicCompile(String srcPath);//输入一个指定的源文件路径,若编译.拷贝成功则返回该类对应的C

  • java编程基础之模仿用户登录代码分享

    上一篇文章我们了解了Java背包问题求解实例代码,接下来我们看看Java中模仿用户登录的相关代码,下面是具体内容. 基于用户从控制台输入模拟的简陋用户登录验证Demo原理: 利用 Scanner 类中 nextLine() 提取用户从控制台输入的字符串信息 利用 String 类的 equals 方法进行用户输入验证 import java.util.Scanner; public class Login { public static void main(String[] args) { //

  • java编程实现求质数与因式分解代码分享

    1.求解质数 1.1说明 首先,我们来了解这样一个概念,那就是什么叫做质数?质数:一个数如果只能被1和它自己整除,这样的数被称为质数,与之对应的,称为和数.基于这样的一个概念,我们可以很快想到一个方法,就是从1开始,不断试探,看从1到它自己,是否有数字能够被他整除. 这样看来,其实求质数很简单,我们有没有更加便捷的方式呢?在这里介绍一个著名的Eratosthenes求质数方法. 1.2解法 首先知道这个问题可以使用回圈来求解,将一个指定的数除以所有小于它的数,若可以整除就不是质数,然而如何减少回

  • Java编程接口调用的作用及代码分享

    很多JAVA初级程序员对于接口存在的意义很疑惑.不知道接口到底是有什么作用,为什么要定义接口. 好像定义接口是提前做了个多余的工作.下面我给大家总结了4点关于JAVA中接口存在的意义: 1.重要性:在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制.正是由于这两种机制的存在,才赋予了Java强大的 面向对象能力. 2.简单.规范性:如果一个项目比较庞大,那么就需要一个能理清所有业务的架构师来定义一些主要的接口,这些接口不仅告诉开发人员你需要实现那些

  • 通过实例解析Java class文件编译加载过程

    一.Java从编码到执行 首先我们来看一下Java是如何从编码到执行的呢? 我们有一个x.java文件通过执行javac命令可以变成x.class文件,当我们调用Java命令的时候class文件会被装载到内存中,这个过程叫做classloader.一般情况下我们自己写代码的时候会用到Java的类库,所以在加载的时候也会把Java类库相关的类也加载到内存中.装载完成之后会调用字节码解释器和JIT即时编译器来进行解释和编译,编译完之后由执行引擎开始执行,执行引擎下面对应的就是操作系统硬件了.下图是大

  • java selenium智能等待页面加载完成示例代码

    java selenium  智能等待页面加载完成 我们经常会碰到用selenium操作页面上某个元素的时候, 需要等待页面加载完成后, 才能操作.  否则页面上的元素不存在,会抛出异常. 或者碰到AJAX异步加载,我们需要等待元素加载完成后, 才能操作 selenium 中提供了非常简单,智能的方法,来判断元素是否存在. 阅读目录 实例要求 隐式等待 显式等待 实例要求 实例:set_timeout.html 下面的html 代码,  点击click 按钮5秒后, 页面上会出现一个红色的div

  • Canvas 制作动态进度加载水球详解及实例代码

    Canvas 动态进度加载水球 前言 之前看到一些球型的动态加载的效果,一直想自己动手做一个,正好这段时间重温了一个Canvas,所以就尝试了一下. 实现思路 关于水波的实现,使用了sin()函数,通过每一帧不断的移动sin()函数曲线,实现水波动态效果.然后,通过绘制圆形路径,进行clip(),实现球型效果. sin()函数相关 这里说一下sin()函数的相关基础,对于绘制水波的影响. 看一下图,回顾一下中学sin()函数的基础. 从图中可以看出,当函数为sin(x)时,值域为[-1, 1],

  • Java编程常见内存溢出异常与代码示例

    Java 堆是用来存储对象实例的, 因此如果我们不断地创建对象, 并且保证 GC Root 和创建的对象之间有可达路径以免对象被垃圾回收, 那么当创建的对象过多时, 会导致 heap 内存不足, 进而引发 OutOfMemoryError 异常. /** * @author xiongyongshun * VM Args: java -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError */ public class OutOfMemoryErrorTe

  • Android编程学习之异步加载图片的方法

    本文实例讲述了Android编程学习之异步加载图片的方法.分享给大家供大家参考,具体如下: 最近在android开发中碰到比较棘手的问题,就是加载图片内存溢出.我开发的是一个新闻应用,应用中用到大量的图片,一个界面中可能会有上百张图片.开发android应用的朋友可能或多或少碰到加载图片内存溢出问题,一般情况下,加载一张大图就会导致内存溢出,同样,加载多张图片内存溢出的概率也很高. 列一下网络上查到的一般做法: 1.使用BitmapFactory.Options对图片进行压缩 2.优化加载图片的

  • Java编程GUI中的事件绑定代码示例

    程序绑定的概念: 绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来.对java来说,绑定分为静态绑定和动态绑定:或者叫做前期绑定和后期绑定 静态绑定: 在程序执行前方法已经被绑定,此时由编译器或其它连接程序实现.例如:C. 针对java简单的可以理解为程序编译期的绑定:这里特别说明一点,java当中的方法只有final,static,private和构造方法是前期绑定 动态绑定 后期绑定:在运行时根据具体对象的类型进行绑定. 若一种语言实现了后期绑定,同时必须提供一些机制,可在运行期间

随机推荐