gpt4 book ai didi

javac - 是否可以将 Java 编译器嵌入到应用程序中?

转载 作者:行者123 更新时间:2023-12-04 15:58:28 27 4
gpt4 key购买 nike

使用 Xtext 和 Xtend,我编写了一个 DSL 语法及其关联的代码生成器,该生成器创建了一组构成 Java 应用程序的 Java 源文件。我想为我的同事提供一个程序,让他们选择一个用我们的领域特定语言编写的文件,运行代码生成器以生成实际 Java 应用程序的 Java 源文件,编译这些文件并启动应用程序。这个过程在我的开发机器上运行良好,因为我已经安装了所有东西,包括 JDK。但是向我的同事提供此应用程序会迫使他们在使用该应用程序之前安装 JDK。所以我的问题是:是否可以将 Java 编译器嵌入到分发包中?如果没有,您是否看到其他方法可以继续?我正在使用 Gradle 和 javapackager + Inno Setup 来生成嵌入 JRE 的分发包。

更新 #1

 override public void afterGenerate(Resource input, IFileSystemAccess2 fsa, IGeneratorContext context)
{
// get the class loader
val URL[] classLoaderUrls = #{new URL("file:jfxrt.jar")}
val URLClassLoader cl = new URLClassLoader(classLoaderUrls)

// set Java compiler options
var CompilerOptions compilerOptions = new CompilerOptions
compilerOptions.sourceLevel = ClassFileConstants.JDK1_8
compilerOptions.complianceLevel = ClassFileConstants.JDK1_8
val Map<String, String> options = new HashMap
options.put(CompilerOptions.OPTION_ReportMissingSerialVersion, CompilerOptions.IGNORE)
options.put(CompilerOptions.OPTION_ReportUnusedParameter, CompilerOptions.IGNORE)
compilerOptions.set(options)

val InMemoryJavaCompiler compiler = new InMemoryJavaCompiler(cl, compilerOptions)

// compile all generated Java source files
val result = compiler.compile(new JavaSource("xxxx/Bit.java", bitGen.javaSource.toString),
new JavaSource("xxxx/BitNature.java", bitNatureGen.javaSource.toString),
new JavaSource("xxxx/ImageMaker.java", imgMakerGen.javaSource.toString),
new JavaSource("xxxx/MyApp.java", myAppGen.javaSource.toString))

val URLClassLoader runcl = new URLClassLoader(classLoaderUrls, result.classLoader)

val Class<?> mainClazz = runcl.loadClass("xxxx.MyApp")

val Method mainMethod = mainClazz.getMethod("main", typeof(String[]))
val String[] args = #["C:\\temp\\memory_a.yyy"]
try
{
mainMethod.invoke(null, #[args])
}
catch (InvocationTargetException e)
{
e.getCause().printStackTrace()
}
catch (Exception e)
{
// generic exception handling
e.printStackTrace();
}
}

更新#2

单步执行我的代码,我可以看到以下内容:

1 - 这个语句执行没有问题(mainClazz 似乎是一个有效的引用)

val Class<?> mainClazz = result.classLoader.loadClass("xxxx.MyApp")

2 - 当我执行时,mainMethod 似乎也是一个有效的引用

val Method mainMethod = mainClazz.getMethod("main", typeof(String[]))

3 - 当我执行时事情变坏了

mainMethod.invoke(null, #[args])

问题出现在 JavaFX Application 类中,在以下语句中启动方法 (ClassNotFoundException: xxxx.MyApp)

Class theClass = Class.forName(callingClassName, false,
Thread.currentThread().getContextClassLoader());

最佳答案

package org.xtext.example.mydsl2.tests

import java.lang.reflect.Method
import java.net.URLClassLoader
import org.eclipse.xtext.util.JavaVersion
import org.eclipse.xtext.xbase.testing.InMemoryJavaCompiler
import org.eclipse.xtext.xbase.testing.JavaSource

class SampleXXX {

def static void main(String[] args) {
val urls = #[]
val classLoader = new URLClassLoader(urls)
val compiler = new InMemoryJavaCompiler(classLoader, JavaVersion.JAVA8)
val result = compiler.compile(new JavaSource("demo/Demo.java", '''
package demo;
public class Demo {
public static void main(String[] args) throws Exception {
Class theClass = Class.forName("demo.Demo", false,
Thread.currentThread().getContextClassLoader());
}
}
'''))
val URLClassLoader runcl = new URLClassLoader(#[], result.classLoader)
(new Thread() {

override run() {
val Class<?> mainClazz = runcl.loadClass("demo.Demo")
val String[] args2 = #["C:\\temp\\memory_a.yyy"]
val Method mainMethod = mainClazz.getMethod("main", typeof(String[]))
mainMethod.invoke(null, #[args2])
}

}=>[
contextClassLoader = runcl
]).start
}

}

关于javac - 是否可以将 Java 编译器嵌入到应用程序中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51065909/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com