【发布时间】:2018-09-21 08:49:29
【问题描述】:
我正在使用 Java 编译器 API 动态编译 Java 源代码。我生成的源文件继承自com.example.BaseClass,它只是一个普通的类,不是动态生成的。生成的 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
^
我尝试更改编译器的类加载器,以便编译器在 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() 返回
java.net.FactoryURLClassLoader@39a5ae48
因此,Compiler 实例不使用 CustomClassloader。如何让编译器使用我的 CustomClassloader?当然也欢迎更好的解决编译问题的解决方案:-)。
【问题讨论】:
-
在获得 JavaCompiler 实例之前,如果不是交换类加载器,而是 getClass().forName("com.example.BaseClass") 会发生什么
-
无变化;编译器仍然抱怨包不存在。
标签: java spring-boot dynamic classloader java-compiler-api