在OSGi Bundle中使用JavaCompiler

我正在重构Java应用程序以使用OSGi。 该应用程序的一个function是使用javax.tools.JavaCompiler Java编译。 在原始应用程序中,此过程通过向编译器提供现有类路径来完成,就像这样。

 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); String[] options = {"-classpath", System.getProperty("java.class.path")}; DiagnosticListener listener = new DiagnosticListener() {...}; StandardJavaFileManager fileManager = compiler.getStandardFileManager(listener, null, null); Iterable fileObjects = fileManager.getFileObjects(sourceFile); CompilationTask task = compiler.getTask(null, fileManager, listener, Arrays.asList(options), null, fileObjects); task.call(); 

但是,这在OSGi包中不起作用,因为类路径不再包含所需的路径。 在重构的OSGi版本的应用程序中,编译器需要访问与上述代码在同一个包中的类,以及来自其他包的类。 如何让编译器知道这些类?

我想到了两种可能的解决方案:

  1. 为编译器提供包含上述代码的bundle使用的类加载器,因为它知道所有必需的类。 但是,从我在这里和这里读到的内容来看,这似乎不是一个可行的解决方案。
  2. 使用已安装捆绑包的物理位置构建类路径。 我查看了org.osgi.framework.Bundle.getLocation()但我不确定这是否是一个可靠的解决方案。 我得到的路径(至少在Eclipse中部署时)是相对的,我不确定它们是否可以安全地在所有平台和情况下使用。

上面的选项2似乎可能吗? 有更好的解决方案吗?

我在GitHub上创建了一个工作示例。

它不是选项1或2,它创建一个自定义JavaFileManager,查看所有包并检索其资源。

需要考虑的事项:

  • 它使用JSR 199编译器API,但它仅适用于OpenJDK / Sun编译器,Eclipse JDT编译器在这方面似乎已经破解。
  • 我只在Equinox上测试过,我没有使用任何equinox特定的代码,所以它应该适用于其他实现。
  • 它没有经过优化,因此它可能很慢并且/或者内存很耗尽。
  • 它确实注册了一个bundle监听器,因此当提供某个包的bundle解析或取消解析时,它会刷新它的类缓存
  • 我认为,拆分包装不是很确定。
  • 它使用了OSGi 4.3中引入的BundleWiring API,因此它不适用于OSGi的旧OSGi实现(例如Karaf 2.x)

我应该提到技术难以理解 ,他的榜样帮助了我。