java用什么编译器_Java用Java编译「建议收藏」

java用什么编译器_Java用Java编译「建议收藏」java用什么编译器在上一篇文章中,我写了关于如何在运行时生成代理的内容,我们已经了解到生成Java源代码的程度。但是,要使用该类,必须对其进行编译,并将生成的字节码加载到内存中。那是“编译”时间。幸运的是,从Java1.6开始,我们可以在运行时访问Java编译器,因此可以将编译时与运行时混淆。尽管在这种非常特殊的情况下,这可能会导致过多的麻烦事情,通常导致无法维护的自我修改代码,…

大家好,又见面了,我是你们的朋友全栈君。

java用什么编译器

在上一篇文章中,我写了关于如何在运行时生成代理的内容,我们已经了解到生成Java源代码的程度。 但是,要使用该类,必须对其进行编译,并将生成的字节码加载到内存中。 那是“编译”时间。 幸运的是,从Java 1.6开始,我们可以在运行时访问Java编译器,因此可以将编译时与运行时混淆。 尽管在这种非常特殊的情况下,这可能会导致过多的麻烦事情,通常导致无法维护的自我修改代码,但它可能还是有用的:我们可以编译运行时生成的代理。

Java编译器API

Java编译器读取源文件并生成类文件。 (将它们组装到JAR,WAR,EAR和其他软件包中是另一种工具的责任。)源文件和类文件不一定是驻留在磁盘,SSD或内存驱动器中的真实操作系统文件。 毕竟,当涉及到运行时API时,Java通常对于抽象是很好的,现在就是这种情况。 这些文件是一些“抽象”文件,您必须通过API提供访问这些文件,这些文件可以是磁盘文件,但同时几乎可以是任何其他文件。 将源代码保存到磁盘上只是为了让编译器在同一进程中运行以将其读回并在类文件准备好后对其进行相同操作,通常会浪费资源。

Java编译器作为运行时可用的API,要求您提供一些简单的API(或您喜欢的SPI)来访问源代码并发送生成的字节码。 如果我们在内存中有代码,则可以有以下代码( 来自此文件 ):

public Class<?> compile(String sourceCode, String canonicalClassName)
			throws Exception {
		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
		List<JavaSourceFromString> sources = new LinkedList<>();
		String className = calculateSimpleClassName(canonicalClassName);
		sources.add(new JavaSourceFromString(className, sourceCode));

		StringWriter sw = new StringWriter();
		MemoryJavaFileManager fm = new MemoryJavaFileManager(
				compiler.getStandardFileManager(null, null, null));
		JavaCompiler.CompilationTask task = compiler.getTask(sw, fm, null,
				null, null, sources);

		Boolean compilationWasSuccessful = task.call();
		if (compilationWasSuccessful) {
			ByteClassLoader byteClassLoader = new ByteClassLoader(new URL[0],
					classLoader, classesByteArraysMap(fm));

			Class<?> klass = byteClassLoader.loadClass(canonicalClassName);
			byteClassLoader.close();
			return klass;
		} else {
			compilerErrorOutput = sw.toString();
			return null;
		}
	}

编译器实例可通过ToolProvider并且要创建编译任务,我们必须调用getTask() 。 该代码通过字符串编写器将错误写入字符串。 文件管理器( fm )是在同一程序包中实现的,它只是将文件作为字节数组存储在映射中,其中的键是“文件名”。 这是类加载器稍后在加载类时将获取字节的位置。 该代码未提供任何可诊断的侦听器(请参见RT中Java编译器的文档),编译器选项或注释处理器要处理的类。 这些都是空值。 最后一个参数是要编译的源代码列表。 我们仅在此工具中编译一个类,但是由于编译器API是通用的并且需要可迭代的源,因此我们提供了一个列表。 由于存在另一个抽象级别,因此此列表包含JavaSourceFromString

要开始编译,必须“调用”创建的任务,如果编译成功,则从生成的一个或多个字节数组中加载类。 请注意,如果在我们编译的顶级类中有嵌套类或内部类,则编译器将创建几个类。 这就是为什么即使只编译一个源类,我们也必须维护类的整个映射,而不是单个字节数组。 如果编译不成功,则错误输出将存储在一个字段中并可以查询。

该类的使用非常简单,您可以在单元测试中找到示例:

private String loadJavaSource(String name) throws IOException {
		InputStream is = this.getClass().getResourceAsStream(name);
		byte[] buf = new byte[3000];
		int len = is.read(buf);
		is.close();
		return new String(buf, 0, len, "utf-8");
	}
...
	@Test
	public void given_PerfectSourceCodeWithSubClasses_when_CallingCompiler_then_ProperClassIsReturned()
			throws Exception {
		final String source = loadJavaSource("Test3.java");
		Compiler compiler = new Compiler();
		Class<?> newClass = compiler.compile(source, "com.javax0.jscc.Test3");
		Object object = newClass.newInstance();
		Method f = newClass.getMethod("method");
		int i = (int) f.invoke(object, null);
		Assert.assertEquals(1, i);
	}

请注意,以这种方式创建的类仅在运行时可用于代码。 例如,您可以创建对象的不可变版本。 如果要在编译时使用可用的类,则应使用scriapt之类的注释处理器。

翻译自: https://www.javacodegeeks.com/2016/03/java-compile-java.html

java用什么编译器

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/138982.html原文链接:https://javaforall.net

(0)
上一篇 2022年5月6日 下午11:00
下一篇 2022年5月6日 下午11:20


相关推荐

  • 卷积神经网络(CNN)与深度卷积神经网络(DCNN)

    卷积神经网络(CNN)与深度卷积神经网络(DCNN)作为小白,看到DCNN,一直想知道与CNN的区别,也没找到明确的说法,以下是自己的一点想法,欢迎指正!目录一、CNN与DCNN二、基于pytorch的实现1.LeNet-52.AlexNet一、CNN与DCNN卷积神经网络,如:LeNet深度卷积神经网络,如:AlexNetAlexNet与LeNet结构类似,但使用了更多的卷积层和更大的参数空间来拟合大规模数据集ImageNet。卷积神经网络就是含卷积层的网络。AlexNet是浅层神经网络和深度神经网络的分界..

    2022年5月3日
    228
  • TFS工作项模板自定义指南

    TFS工作项模板自定义指南概述 TFS 内置有 CMMI 模板 敏捷模板等过程模板 但是为了方便团队管理 TFS 提供自定义过程模板的功能 每个团队可以根据需要自定义模板界面 字段 流程等内容 本文档将会介绍如何自定义过程模板 以及制定的要求 环境准备获取修改权限过程模板修订完成后 需要导入到对应的团队项目中 此时要求执行导入的账号需要具有该项目的管理员权限 权限由服务器管理员开通 安装工具 VS 工具 与 TFS 服务器版本对应的 VS 工具 例如 172 16 10 116 服务器是 2010 版本的 TFS 服务器 则修改模板时需要通过 2

    2026年3月16日
    2
  • 解压war包和重新压缩war包[通俗易懂]

    解压war包和重新压缩war包[通俗易懂]publicclassWarUtils{ /** *解压war包 *@paramunWarPathwar解压的路径 *@paramwarFile解压的war包文件 */ publicstaticvoidunWar(StringunWarPath,FilewarFile){ try{ //读取文件流 Buffered

    2026年4月16日
    4
  • Lab4AI上线一键部署OpenClaw,附2分钟云养虾指南

    Lab4AI上线一键部署OpenClaw,附2分钟云养虾指南

    2026年3月14日
    2
  • 关于SQL2008AdventureWorks2008数据库的安装!

    关于SQL2008AdventureWorks2008数据库的安装!

    2025年10月26日
    5
  • JS获取当前时间(年月日时分秒)「建议收藏」

    JS获取当前时间(年月日时分秒)「建议收藏」JS获取当前时间(年月日时分秒)JS获取当前时间(年月日时分秒)代码直接撸:**拿走直接用`//获取当前时间getNowTime(){vardate=newDate();//年getFullYear():四位数字返回年份varyear=date.getFullYear();//getFullYear()代替getYear()//月getMonth():0~11varmonth=date.getMonth()+1;//日getDate():(1

    2026年2月21日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号