首页 文章

在OSGi Bundle中使用JavaCompiler

提问于
浏览
6

我正在重构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版本的应用程序中,编译器需要访问与上述代码在同一个包中的类,以及其他包中的类 . 如何让编译器知道这些类?

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

  • 为编译器提供包含上述代码的bundle使用的类加载器,因为它知道所有必需的类 . 但是,这并没有herehere .

  • 使用已安装捆绑包的物理位置构建类路径 . 我看了 org.osgi.framework.Bundle.getLocation() 但是我不确定他们是否可以安全地在所有平台和情况下使用 .

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

1 回答

  • 3

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

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

    需要考虑的事项:

    • 它使用JSR 199编译器API,但它仅适用于OpenJDK / Sun编译器,Eclipse JDT编译器在这方面似乎已经破解 .

    • I 've only tested on Equinox, I haven' t使用了任何equinox特定代码,因此它应该适用于其他实现 .

    • 它未经过优化,因此可能很慢并且/或者内存很耗尽 .

    • 它确实注册了一个bundle监听器,所以它会在提供某个包解析或解析的bundle时刷新它的类缓存

    • 我觉得拆分包不是很确定 .

    • 它使用了OSGi 4.3中引入的BundleWiring API,因此它不适用于OSGi的旧OSGi实现(例如Karaf 2.x)

    我应该提一下Technology Excruciation,他的榜样帮助了我 .

相关问题