java加载一个来自项目之外的java文件,执行其main方法的一种实现方式
生活随笔
收集整理的這篇文章主要介紹了
java加载一个来自项目之外的java文件,执行其main方法的一种实现方式
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
目錄
寫(xiě)在前面
代碼實(shí)現(xiàn)思路
代碼具體實(shí)現(xiàn)
寫(xiě)在前面
近期有一個(gè)小想法,就是我一個(gè)springboot項(xiàng)目,想做一個(gè)給用戶(hù)可以編寫(xiě)java代碼并且直接在頁(yè)面運(yùn)行的功能。
難點(diǎn)就在于,如何將java文本轉(zhuǎn)變成class實(shí)例,然后運(yùn)行其main方法,在此提供了一種思路,那就是自定義ClassLoader類(lèi)加載器!
關(guān)于java類(lèi)加載器等詳細(xì)介紹,請(qǐng)移步該博文了解:
java類(lèi)加載器、雙親委派、沙箱安全機(jī)制全都讓你整明白(三萬(wàn)字,收藏慢慢啃)_禿了也弱了。的博客-CSDN博客
代碼實(shí)現(xiàn)思路
1.從前端傳過(guò)來(lái)java類(lèi)的文本,保存在本地臨時(shí)目錄,生成對(duì)應(yīng)的java文件。
2.編譯java文件生成class類(lèi)。
3.通過(guò)自定義的classloader加載class。
4.執(zhí)行class的main方法。
代碼具體實(shí)現(xiàn)
需要讀取的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;}@Overrideprotected Class<?> findClass(String className) throws ClassNotFoundException {BufferedInputStream bis = null;ByteArrayOutputStream baos = null;try {// 獲取字節(jié)碼文件的完整路徑String fileName = getClassFile(className);// 獲取輸入流bis = new BufferedInputStream(new FileInputStream(fileName));// 獲取輸出流baos = new ByteArrayOutputStream();// 具體讀入數(shù)據(jù)、寫(xiě)出數(shù)據(jù)int len;byte[] data = new byte[1024];while((len = bis.read(data)) != -1) {baos.write(data, 0, len);}// 獲取內(nèi)存中完整的字節(jié)數(shù)組數(shù)據(jù)byte[] byteCodes = baos.toByteArray();// 調(diào)用defineClass,將字節(jié)數(shù)組數(shù)據(jù)轉(zhuǎn)換為Class實(shí)例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;}/*** 類(lèi)文件的完全路徑*/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("沒(méi)有編譯成功!");}}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字節(jié)碼loader.compiler2(path + className + ".java");// 加載class文件Class clazz = loader.findClass(className);System.out.println("此class的類(lèi)加載器為:" + clazz.getClassLoader());System.out.println("此class的類(lèi)加載器父類(lèi)為:" + clazz.getClassLoader().getParent());// 以下是執(zhí)行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("執(zhí)行main方法");declaredMethod.invoke(o, new String[1]);}}} }總結(jié)
以上是生活随笔為你收集整理的java加载一个来自项目之外的java文件,执行其main方法的一种实现方式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: spring MVC使用自定义的参数解析
- 下一篇: 数据结构-栈详解(类C语言版)