在OSGi Bundle中使用JavaCompiler

时间:2011-06-23 16:31:44

标签: java classpath osgi classloader

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

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

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

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

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

1 个答案:

答案 0 :(得分:3)

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

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

需要考虑的事项:

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

我应该提到Technology Excruciation,他的榜样帮助了我。