如何更改 getSystemJavaCompiler 的类加载器
How can I change classloader of getSystemJavaCompiler
我正在使用 Java 编译器 API 动态编译 Java 源代码。我生成的源文件继承自com.example.BaseClass,这只是一个普通的class,不是动态生成的。生成的 Java 来源如下所示:
public class Foo implements com.example.BaseClass
{
@Override
public Integer getAnswer(com.example.Context context) throws Exception
{
return ...;
}
}
运行在IDE时一切正常,但在打包成Springboot jar后,我的com.example.BaseClass被移动到BOOT-INF/classes/com.example.BaseClass。动态编译时我现在得到:
/Foo.java:1: error: package com.example does not exist
public class Foo implements com.example.BaseClass
^
我尝试更改编译器的 class 加载程序,以便编译器在 BOOT-INF/classes 中搜索。
ClassLoader before = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(new CustomClassloader(before));
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
Thread.currentThread().setContextClassLoader(before);
但是,调试显示我的 CustomClassloader.loadClass(String name) 方法从未被调用。更多调试显示 compiler.getClass().getClassloader() returns
java.net.FactoryURLClassLoader@39a5ae48
因此,CustomClassloader 未被 Compiler 实例使用。如何让编译器使用我的 CustomClassloader?当然也欢迎更好的解决编译问题的解决方案:-)。
java 标准编译器进行查找的方式有些奇怪,它并不总是正确解析出 运行 class 路径。无论如何,它使用 JavaFileManager.list 调用来完成该解决方案。
它会在尝试查找您的基地的过程中至少调用它 4 次 class。覆盖 ForwardingJavaFileManager and pass that into getTask 并让它查找资源并 return 它。
或者,您可以使用 Janino in-momeory compiler 库,它在内存文件系统中设置一个伪造的文件系统(不编译到磁盘)并且仍然使用平台编译器并整理出所有这些 classpath 废话给你。
我正在使用 Java 编译器 API 动态编译 Java 源代码。我生成的源文件继承自com.example.BaseClass,这只是一个普通的class,不是动态生成的。生成的 Java 来源如下所示:
public class Foo implements com.example.BaseClass
{
@Override
public Integer getAnswer(com.example.Context context) throws Exception
{
return ...;
}
}
运行在IDE时一切正常,但在打包成Springboot jar后,我的com.example.BaseClass被移动到BOOT-INF/classes/com.example.BaseClass。动态编译时我现在得到:
/Foo.java:1: error: package com.example does not exist
public class Foo implements com.example.BaseClass
^
我尝试更改编译器的 class 加载程序,以便编译器在 BOOT-INF/classes 中搜索。
ClassLoader before = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(new CustomClassloader(before));
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
Thread.currentThread().setContextClassLoader(before);
但是,调试显示我的 CustomClassloader.loadClass(String name) 方法从未被调用。更多调试显示 compiler.getClass().getClassloader() returns
java.net.FactoryURLClassLoader@39a5ae48
因此,CustomClassloader 未被 Compiler 实例使用。如何让编译器使用我的 CustomClassloader?当然也欢迎更好的解决编译问题的解决方案:-)。
java 标准编译器进行查找的方式有些奇怪,它并不总是正确解析出 运行 class 路径。无论如何,它使用 JavaFileManager.list 调用来完成该解决方案。
它会在尝试查找您的基地的过程中至少调用它 4 次 class。覆盖 ForwardingJavaFileManager and pass that into getTask 并让它查找资源并 return 它。
或者,您可以使用 Janino in-momeory compiler 库,它在内存文件系统中设置一个伪造的文件系统(不编译到磁盘)并且仍然使用平台编译器并整理出所有这些 classpath 废话给你。