android 动态编译java_页面上动态编译及执行java代码

最近看到同事在页面上编译和执行java代码,有点像Web IDE,感觉很酷就试着自己实现下。

预期要实现以下几个功能:

页面上使用textarea作为简单的代码编辑器,通过单击执行按钮向服务器发送请求

服务器端接收到java代码,进行简单的校验,若检验通过则进行编译

如果编译错误,返回异常信息

重定向代码中的system.out输出,将结果返回到客户端

相关实现

public class RuntimeCompiler {

private List options = null;

private JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

private DiagnosticCollector diagnostics = new DiagnosticCollector();

private StringBuffer traceMsg = new StringBuffer();

public RuntimeCompiler(String... options) {

// inital compile params

if (options != null && options.length > 0) {

this.options = Arrays.asList(options);

}

}

public boolean compile(String className, String code) {

JavaFileObject sourceFile = new StringJavaFileObject(className, code);

Iterable extends JavaFileObject> compilationUnits = Arrays.asList(sourceFile);

CompilationTask task = compiler.getTask(null, null, diagnostics, options, null, compilationUnits);

boolean result = task.call();

// Record compile error messages

for (Diagnostic> diagnostic : diagnostics.getDiagnostics()) {

traceMsg.append(diagnostic.getMessage(null)).append("\n");

traceMsg.append(String.format("Error on line %d in %s%n", diagnostic.getLineNumber(),

((FileObject) diagnostic.getSource()).toUri()));

}

return result;

}

public String getTraceMsg() {

return traceMsg.toString();

}

}

编译时需指定生成的.class文件的路径,由于是在tomcat作为服务器,存在到WEB-INF\classes下即可:

String realPath = request.getServletContext().getRealPath("/") + "WEB-INF\\classes";

RuntimeCompiler rc = new RuntimeCompiler("-d", realPath);

boolean success = rc.compile(className, code);

在使用反射执行该类时,需将System.out的输出重定向到ByteArrayOutputStream,最后将该结果返回到客户端

// Create a stream to hold the output

ByteArrayOutputStream baos = new ByteArrayOutputStream();

PrintStream printStream = new PrintStream(baos);

// Tell Java to use your special stream

System.setOut(printStream);

if (success) {

try {

Class.forName(fullClassName).getDeclaredMethod("main", new Class[] {

String[].class

}).invoke(null, new Object[] {

null

});

} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException

| InvocationTargetException e) {

result = "Load class error: " + e;

}

}

// flush output stream

System.out.flush();

out.print(baos.toString());

我在页面中是使用angularjs来实现交互,发现angularjs无法通过在 textarea 标签里边来设置默认值,只好用指令 ng-model 绑定变量,在controller中设置初始值。

目前存在的问题

当在页面上的修改同一个类时,连续点击run,会有10秒左右的延迟,这是由于它会编译成内容不同的.class文件,只有当 org.apache.catalina.core.StandardContext reload 才有效。

运行效果

4fe54a09dd0b1ec81c01516ce249bc0c.png

查看完整源代码:点击这里

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值