我是靠谱客的博主 大力小懒猪,最近开发中收集的这篇文章主要介绍java加载一个来自项目之外的java文件,执行其main方法的一种实现方式写在前面代码实现思路代码具体实现,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
目录
写在前面
代码实现思路
代码具体实现
写在前面
近期有一个小想法,就是我一个springboot项目,想做一个给用户可以编写java代码并且直接在页面运行的功能。
难点就在于,如何将java文本转变成class实例,然后运行其main方法,在此提供了一种思路,那就是自定义ClassLoader类加载器!
关于java类加载器等详细介绍,请移步该博文了解:
java类加载器、双亲委派、沙箱安全机制全都让你整明白(三万字,收藏慢慢啃)_秃了也弱了。的博客-CSDN博客
代码实现思路
1.从前端传过来java类的文本,保存在本地临时目录,生成对应的java文件。
2.编译java文件生成class类。
3.通过自定义的classloader加载class。
4.执行class的main方法。
代码具体实现
需要读取的java文件:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("HelloWorld");
}
}
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.*;
import java.lang.reflect.Method;
public class MyClassLoader3 extends ClassLoader {
private String rootDir;
public MyClassLoader3(String rootDir) {
this.rootDir = rootDir;
}
public MyClassLoader3(ClassLoader parent, String rootDir) {
super(parent);
this.rootDir = rootDir;
}
@Override
protected Class<?> findClass(String className) throws ClassNotFoundException {
BufferedInputStream bis = null;
ByteArrayOutputStream baos = null;
try {
// 获取字节码文件的完整路径
String fileName = getClassFile(className);
// 获取输入流
bis = new BufferedInputStream(new FileInputStream(fileName));
// 获取输出流
baos = new ByteArrayOutputStream();
// 具体读入数据、写出数据
int len;
byte[] data = new byte[1024];
while((len = bis.read(data)) != -1) {
baos.write(data, 0, len);
}
// 获取内存中完整的字节数组数据
byte[] byteCodes = baos.toByteArray();
// 调用defineClass,将字节数组数据转换为Class实例
return defineClass(null, byteCodes, 0, byteCodes.length);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(baos != null) {baos.close();}
if(bis != null) {bis.close();}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 类文件的完全路径
*/
private String getClassFile(String className) {
return rootDir + "\" + className.replace('.', '\') + ".class";
}
private void compiler1(String javaAbsolutePath) {
//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("没有编译成功!");
}
}
public void compiler2(String javaAbsolutePath){
//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();
}
}
public static void main(String[] args) throws Exception {
String path = "E:\mycode\";
String className = "HelloWorld";
MyClassLoader3 loader = new MyClassLoader3(path);
// 编译java文件,生成class字节码
loader.compiler2(path + className + ".java");
// 加载class文件
Class clazz = loader.findClass(className);
System.out.println("此class的类加载器为:" + clazz.getClassLoader());
System.out.println("此class的类加载器父类为:" + clazz.getClassLoader().getParent());
// 以下是执行main方法
Object o = clazz.newInstance();
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod.getName());
if("main".equals(declaredMethod.getName())){
System.out.println("执行main方法");
declaredMethod.invoke(o, new String[1]);
}
}
}
}
最后
以上就是大力小懒猪为你收集整理的java加载一个来自项目之外的java文件,执行其main方法的一种实现方式写在前面代码实现思路代码具体实现的全部内容,希望文章能够帮你解决java加载一个来自项目之外的java文件,执行其main方法的一种实现方式写在前面代码实现思路代码具体实现所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复