00-JAVA基础-动态编译

动态编译

JAVA 6 引入了动态编译机制。Java 动态编译是指在运行时将Java源代码编译成可执行的字节码。这通常使用Java的内置编译器API javax.tools.JavaCompiler 来实现。

动态编译的应用场景

  • 可以做一个浏览器编写java代码,上传服务器编译和运行的在线测评系统
  • 服务器动态加载某些类文件进行编译

动态编译的两种实现方式

  • JAVA6之前,可以通过Runtime调用javac,启动新的进程去操作

    Runtime run = Runtime.getRuntime();
    Process process = run.exec("javac D:/myjava/demo/HelloWorld.java");
    
  • JAVA6之后,可以使用JavaCompiler实现

      public static in compileFile(String sourceFile){JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();int result = compiler.run(null,null,null,sourceFile);System.out.println(result == 0 ? "编译通过" : "编译失败")return result;}
    

compiler.run(null,null,null,sourceFile)参数说明:

第一个参数:为java编译器提供参数
第二个参数:得到Java编译器的输出信息
第三个参数:接受编译器的错误信息
第四个参数:可变参数(是一个String[]数组)能传入一个或多个Java源文件
返回值:0 表示编译成 ,非0 表示编译失败

使用runtime.exec方法编译

package demo2;import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;/*** 使用Runtime编译,通过反射调用main方法** @author Anna.* @date 2024/4/4 11:13*/
public class DyanmaicDemo {public static void main(String[] args) throws Exception {String path = DyanmaicDemo.class.getResource("").getPath();String javaName = "Hello";// 创建文件File tempFile = createFile(path, javaName);// 使用Runtime 编译compilation(tempFile);// 反射执行文件extracted(path, javaName);}/*** 创建文件** @param path* @param javaName* @return java.io.File* @author Anna.* @date 2024/4/4 13:05*/private static File createFile(String path, String javaName) throws IOException {// 创建编译内容StringBuffer sb = new StringBuffer();sb.append("public class ").append(javaName).append("{").append("public static void main(String[] args){").append("System.out.println(\"hello world !!!\");").append("}").append("}");// 写入临时文件File tempFile = new File(path + javaName + ".java");FileWriter fileWriter = new FileWriter(tempFile);fileWriter.write(sb.toString());fileWriter.close();return tempFile;}/*** 编译** @param tempFile* @return void* @author Anna.* @date 2024/4/4 13:05*/private static void compilation(File tempFile) throws IOException, InterruptedException {String replace = tempFile.getAbsolutePath().replace(tempFile.getName(), "");replace = replace.substring(0, replace.length() - 1);String str = "javac " + tempFile.getAbsolutePath();Runtime runtime = Runtime.getRuntime();Process process = runtime.exec(str);// 读取命令的标准输出BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));String line;while ((line = reader.readLine()) != null) {System.out.println(line);}// 读取命令的错误输出BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));while ((line = errorReader.readLine()) != null) {System.err.println(line);}// 等待进程结束并获取退出值int exitValue = process.waitFor();if (exitValue == 0) {System.out.println("Compilation is successful");} else {System.out.println("Compilation Failed");}}/*** 反射执行main方法** @param path* @param javaName* @return void* @author Anna.* @date 2024/4/4 13:05*/private static void extracted(String path, String javaName) throws MalformedURLException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL("file:/" + path)});Class<?> clazz = urlClassLoader.loadClass(javaName);Method mainMethod = clazz.getMethod("main", String[].class);// 注意:由于可变参数是JDK5之后才有的,下面代码如果new String[]{"1","2"}强制在转换才Object,则会被编译成 mainMethod.invoke(null,"1","2"),从而导致找不到方法。// 因此,如果传参则徐亚加上(Object),避免这个问题mainMethod.invoke(null, (Object) new String[]{"1", "2"});}}

执行结果

在这里插入图片描述

使用JavaCompiler实现

package demo1;import javax.tools.*;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Collections;/*** 使用JavaCompiler编译,通过反射调用main方法** @author Anna.* @date 2024/4/4 10:55*/
public class DyanmicDemo1 {public static void main(String[] args) throws Exception {// 创建编译内容String javaName = "Hello";// 获取JavaFileObjectJavaFileObject source = getJavaFileObject(javaName);// 编译compiler(source);// 执行extracted(javaName);}/*** 获取JavaFileObject** @param javaName* @return javax.tools.JavaFileObject* @author Anna.* @date 2024/4/4 13:56*/private static JavaFileObject getJavaFileObject(String javaName) {StringBuffer sb = new StringBuffer();sb.append("public class ").append(javaName).append("{").append("public static void main(String[] args){").append("System.out.println(\"hello world !!!\");").append("}").append("}");// 创建一个Java源代码文件 string:///是一个特殊的URI协议,用于表示源代码内容直接来自一个字符串,而不是来自文件系统中的一个文件。 好处是,你可以完全在内存中处理源代码,无需涉及文件系统的I/O操作。JavaFileObject source = new SimpleJavaFileObject(URI.create("string:///" + javaName + ".java"), JavaFileObject.Kind.SOURCE) {@Overridepublic CharSequence getCharContent(boolean ignoreEncodingErrors) {return sb.toString();}};return source;}/*** 编译** @param source* @return void* @author Anna.* @date 2024/4/4 13:49*/private static void compiler(JavaFileObject source) {// 获取系统Java编译器JavaCompiler systemJavaCompiler = ToolProvider.getSystemJavaCompiler();// 创建诊断收集器DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();// 创建编译任务StandardJavaFileManager fileManager = systemJavaCompiler.getStandardFileManager(diagnostics, null, null);// 设置输出目录Iterable<? extends File> locations = fileManager.getLocation(StandardLocation.CLASS_OUTPUT);try {fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Collections.singleton(new File(DyanmicDemo1.class.getClassLoader().getResource("").getPath())));} catch (IOException e) {e.printStackTrace();return;}Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(source);JavaCompiler.CompilationTask task = systemJavaCompiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits);// 执行编译任务boolean success = task.call();// 关闭文件管理器try {fileManager.close();} catch (IOException e) {e.printStackTrace();}// 处理编译诊断信息for (Diagnostic<?> diagnostic : diagnostics.getDiagnostics()) {System.out.println(diagnostic);System.out.println(diagnostic.getKind() + ": " + diagnostic.getMessage(null));}System.out.println(success ? "编译通过" : "编译失败");}/*** 反射执行** @param javaName* @return void* @author Anna.* @date 2024/4/4 13:50*/private static void extracted(String javaName) throws MalformedURLException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL("file:/" + DyanmicDemo1.class.getClassLoader().getResource("").getPath())});Class<?> clazz = urlClassLoader.loadClass(javaName);Method mainMethod = clazz.getMethod("main", String[].class);// 注意:由于可变参数是JDK5之后才有的,下面代码如果new String[]{"1","2"}强制在转换才Object,则会被编译成 mainMethod.invoke(null,"1","2"),从而导致找不到方法。// 因此,如果传参则徐亚加上(Object),避免这个问题mainMethod.invoke(null, (Object) new String[]{"1", "2"});}}

执行结果

在这里插入图片描述

注意:

Runtime不仅仅是可以用于执行javac,当然可以用来执行其他命令,这里就不进一步说明了

CommandUtil调用系统命令工具类

import org.apache.commons.exec.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;/*** 调用系统命令工具类** @author Anna.* @date 2021/9/8 16:05*/
public class CommandUtil {private static Logger logger = LoggerFactory.getLogger(CommandUtil.class);private static final String DEFAULT_CHARSET = "UTF-8";private static final Long TIMEOUT = 10000L;/*** 执行指定命令** @param command 命令* @return 命令执行完成返回结果* @throws RuntimeException 失败时抛出异常,由调用者捕获处理*/public synchronized static String exeCommand(String command) throws RuntimeException {try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {int exitCode = exeCommand(command, out);if (exitCode == 0) {logger.info("命令运行成功:" + System.currentTimeMillis());} else {logger.info("命令运行失败:" + System.currentTimeMillis());}return out.toString(DEFAULT_CHARSET);} catch (Exception e) {logger.info(e.getMessage());throw new RuntimeException(e.getMessage());}}/*** 执行指定命令,输出结果到指定输出流中** @param command 命令* @param out     执行结果输出流* @return 执行结果状态码:执行成功返回0* @throws ExecuteException 失败时抛出异常,由调用者捕获处理* @throws IOException      失败时抛出异常,由调用者捕获处理*/public synchronized static int exeCommand(String command, OutputStream out) throws ExecuteException, IOException {CommandLine commandLine = CommandLine.parse(command);PumpStreamHandler pumpStreamHandler = null;if (null == out) {pumpStreamHandler = new PumpStreamHandler();} else {pumpStreamHandler = new PumpStreamHandler(out);}// 设置超时时间为10秒ExecuteWatchdog watchdog = new ExecuteWatchdog(TIMEOUT);DefaultExecutor executor = new DefaultExecutor();executor.setStreamHandler(pumpStreamHandler);executor.setWatchdog(watchdog);return executor.execute(commandLine);}public static void main(String[] args) {String out = null;try {
//            out = CommandUtil.exeCommand("ipconfig");out = CommandUtil.exeCommand("D:\\SoftWare\\ffmpeg\\bin\\ffmpeg.exe -y  -i D:/test/1631090617181_191979483992900.mp3  -acodec pcm_s16le -f s16le -ac 1 -ar 16000 D:/test/PCM1631090617181_191979483992900.mp3.pcm");} catch (Exception e) {e.printStackTrace();}System.out.println(out);//CommandUtil.executeCommand("kill -9 3104");}}

gitee源码

git clone https://gitee.com/dchh/JavaStudyWorkSpaces.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/792437.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

继承.Java

目录 1&#xff0c;概述 1.1继承的含义 1.2什么时候用继承 1.3继承的好处 1.4继承的特点 2&#xff0c;继承的格式 3&#xff0c;可以继承哪些内容 4&#xff0c;成员方法和成员变量的访问特点 5&#xff0c;构造方法的访问特点 6&#xff0c;this&#xff0c;super…

前端三剑客 —— CSS (第一节)

目录 CSS 什么是CSS CSS的几种写法&#xff1a; 行内样式 内嵌样式 外链样式 import 加载顺序 CSS选择器*** 基本选择器 ID选择器 标签选择器 类选择器 通用选择器 包含选择器 上节内容中提到了 前端三剑客 —— HTML 超文本标记语言&#xff0c;这节内容 跟大家…

大厂面试之【Redis持久化机制】 - RDB和AOF概述及应用配置

文章目录 Redis持久化1. RDB(Redis DataBase)1.1 概述1.2 配置应用 2. AOF(Append Only File)2.1 概述2.2 配置应用 Redis持久化 先上结论&#xff1a;Redis持久化操作分为rdb以及aof&#xff0c;但是前者已经够用 1. RDB(Redis DataBase) 1.1 概述 rdb保存的是dump.rdb文件在指…

WEB漏洞挖掘详细教程--用户输入合规性(sql注入测试)

前置教程&#xff1a;WEB漏洞挖掘&#xff08;SRC&#xff09;详细教程--信息收集篇-CSDN博客 WEB漏洞挖掘&#xff08;SRC&#xff09;详细教程--身份认证与业务一致性-CSDN博客 WEB漏洞挖掘&#xff08;SRC&#xff09;详细教程--业务数据篡改-CSDN博客 2.4 用户输入合规性…

MCRNet:用于乳腺超声成像语义分割的多级上下文细化网络

这里写目录标题 摘要引言方法 摘要 由于对比度差、目标边界模糊和大量阴影的不利影响&#xff0c;乳腺超声成像中的自动语义分割仍然是一项具有挑战性的任务。最近&#xff0c;具有U形的卷积神经网络&#xff08;CNN&#xff09;在医学图像分割中表现出相当好的性能。然而&…

【C++ STL迭代器】iterator

文章目录 【 1. 迭代器的属性 】【 2. 不同容器支持的迭代器 】【 3. 迭代器的定义方式 】【 4. 实例 】4.1 定义方式&#xff1a;正向迭代器和反向迭代器4.2 迭代器属性&#xff1a;前向迭代、双向迭代、随机迭代4.2 迭代器的遍历方法4.3 auto关键字 自动指定迭代器定义类型 背…

【Qt】:常用控件(四:显示类控件)

常用控件 一.Lable二.LCD Number 一.Lable QLabel 可以⽤来显⽰⽂本和图⽚. 代码⽰例:显⽰不同格式的⽂本 代码⽰例:显⽰图⽚ 此时,如果拖动窗⼝⼤⼩,可以看到图⽚并不会随着窗⼝⼤⼩的改变⽽同步变化 为了解决这个问题,可以在Widget中重写resizeEvent函数。当用户把窗口从A拖…

基于单片机双路压力监测报警系统

**单片机设计介绍&#xff0c;基于单片机双路压力监测报警系统 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机双路压力监测报警系统是一个专门设计用于实时监测和报警两路压力变化的系统。它结合了单片机控制技术和压…

图DP

目录 有向无环图DP 力扣 329. 矩阵中的最长递增路径 力扣 2192. 有向无环图中一个节点的所有祖先 有向有环图DP 力扣 1306. 跳跃游戏 III 有向无环图DP 力扣 329. 矩阵中的最长递增路径 给定一个 m x n 整数矩阵 matrix &#xff0c;找出其中 最长递增路径 的长度。 对…

【DA-CLIP】test.py解读,调用DA-CLIP和IRSDE模型复原计算复原图与GT图SSIM、PSNR、LPIPS

文件路径daclip-uir-main/universal-image-restoration/config/daclip-sde/test.py 代码有部分修改 导包 import argparse import logging import os.path import sys import time from collections import OrderedDict import torchvision.utils as tvutilsimport numpy as…

数学知识--(质数,约数)

本文用于个人算法竞赛学习&#xff0c;仅供参考 目录 一.质数的判定 二.分解质因数 三.质数筛 1.朴素筛法 2.埃氏筛法 3.线性筛法 四.约数 1.求一个数的所有约数 2.约数个数和约数之和 3.欧几里得算法&#xff08;辗转相除法&#xff09;-- 求最大公约数 一.质数的判定 …

新型智慧城市大数据解决方案(附下载)

随着云计算、大数据、移动互联网等技术的发展&#xff0c;由城市运行产生的交通、环境、市政、商业等各领域数据量巨大&#xff0c;这些数据经过合理的分析挖掘可产生大量传统数据不能反映的城市运行信息&#xff0c;已成为智慧城市的重要资产。 在大数据时代&#xff0c;数据信…

理解main方法的语法

由于JVM需要调用类的main()方法&#xff0c;所以该方法的访问权限必须是public&#xff0c;又因为JVM在执行main()方法时不必创建对象&#xff0c;所以该方法必须是static的&#xff0c;该方法接收一个String类型的数组参数&#xff0c;该数组中保存执行Java命令时传递给所运行…

问题解决:写CSDN博文时图片大小不适应,不清晰,没法排版

项目环境&#xff1a; Window10&#xff0c;Edge123.0.2420.65 问题描述&#xff1a; 当我在CSDN写博文的时候&#xff0c;会经常插入一些图片&#xff0c;但有时候我插入的图片太大了&#xff0c;影响了整体排版。 比如我加入了一张图片&#xff0c;就变成了下面这个样子&…

PEFT-LISA

LISA是LoRA的简化版&#xff0c;但其抓住了LoRA微调的核心&#xff0c;即LoRA侧重更新LLM的底层embedding和顶层head。 根据上述现象&#xff0c;LISA提出两点改进&#xff1a; 始终更新LLM的底层embedding和顶层head随机更新中间层的hidden state 实验结果 显存占用 毕竟模型…

openstack云计算(一)————openstack安装教程,创建空白虚拟机,虚拟机的环境准备

1、创建空白虚拟机 需要注意的步骤会截图一下&#xff0c;其它的基本都是下一步&#xff0c;默认的即可 ----------------------------------------------------------- 2、在所建的空白虚拟机上安装CentOS 7操作系统 &#xff08;1&#xff09;、在安装CentOS 7的启动界面中…

RuoYi-Vue若依框架-集成mybatis-plus报错Unknown column ‘search_value‘ in ‘field list‘

报错信息 ### Error querying database. Cause: java.sql.SQLSyntaxErrorException: Unknown column search_value in field list ### The error may exist in com/ruoyi/sales/mapper/ZcSpecificationsMapper.java (best guess) ### The error may involve defaultParameter…

【简单讲解下WebSocket】

&#x1f308;个人主页:程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

Python卷积网络车牌识别系统(V2.0)

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

基于单片机的无线红外报警系统

**单片机设计介绍&#xff0c;基于单片机的无线红外报警系统 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的无线红外报警系统是一种结合了单片机控制技术和无线红外传感技术的安防系统。该系统通过无线红外传感器实…