在 OSGi 包中使用 JavaCompiler

发布于 2024-11-17 00:31:00 字数 1344 浏览 2 评论 0原文

我正在重构 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. 为编译器提供包含上述代码的包所使用的类加载器,因为它知道所有必需的类。然而,从我读过的内容来看,这似乎不是一个可行的解决方案 这里此处
  2. 使用已安装包的物理位置构建类路径。我看过 org.osgi.framework.Bundle.getLocation() ,但我不确定这是否是一个可靠的解决方案。我返回的路径(至少在 Eclipse 中部署时)是相对的,我不确定它们是否可以在所有平台和情况下安全使用。

上述选项二似乎可行吗?有更好的解决方案吗?

I'm in the process of refactoring a Java application to use OSGi. One feature of the application is on-the-fly Java compilation using javax.tools.JavaCompiler. In the original application this process worked by feeding the compiler the existing classpath, like so.

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();

However, this won't work in an OSGi bundle since the classpath no longer contains the needed paths. In the refactored OSGi version of the application, the compiler needs access to classes that are within the same bundle as the above code, as well as classes from other bundles. How do I make the compiler aware of these classes?

I've thought of two possible solutions:

  1. Give the compiler the classloader used by the bundle containing the above code since it is aware of all the necessary classes. However, this doesn't seem like a viable solution from what I've read here and here.
  2. Build the classpath using the physical locations of the installed bundles. I've looked at org.osgi.framework.Bundle.getLocation() but I'm not sure if this would be a reliable solution. The paths I get back (at least when deploying within Eclipse) are relative and I'm not sure if they'd be safe to use across all platforms and situations.

Does option two above seem possible? Is there a better solution?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

喜你已久 2024-11-24 00:31:00

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

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

需要考虑的事项:

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

我应该提到 技术折磨,他的例子帮助了我非常地。

I've created a working example on GitHub.

It is not option 1 or 2, it creates a custom JavaFileManager which looks through all bundles and retrieves their resources.

Things to take into consideration:

  • It uses the JSR 199 compiler API, but it works only on the OpenJDK/Sun compiler, the Eclipse JDT compiler seems broken in this respect.
  • I've only tested on Equinox, I haven't used any equinox specific code, so it should work on other implementations.
  • It isn't optimized, so it might be slow and/or memory hungry.
  • It does register a bundle listener so it will flush its class cache when a bundle which offers a certain package resolves or unresolves
  • It is not very deterministic for split packages, I think.
  • It uses the BundleWiring API, which was introduced in OSGi 4.3, so it won't work on older OSGi implementations of OSGi (Karaf 2.x for example)

I should mention Technology Excruciation, his example helped me along tremendously.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文