用纯java分割包
OSGi 存在拆分包的问题,即相同的包但托管在多个包中。
是否存在任何边缘情况,拆分包可能会在纯 java(没有 OSGi)中造成问题?
只是好奇。
OSGi has a problem with split packages, i.e. same package but hosted in multiple bundles.
Are there any edge cases that split packages might pose problems in plain java (without OSGi) ?
Just curious.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
。
当使用清单头
Require-Bundle
时(我相信,在 Eclipse 的清单中),就会出现分割包(在 OSGi 中)的分割包Require-Bundle
命名用于搜索类的其他包(如果包未Import
ed)。 搜索发生在搜索包自己的类路径之前。 这允许从多个包(可能是不同的 jar)的导出中加载单个包的类。OSGi 规范 (4.1) 第 3.13 节描述了
Require-Bundle
,并列出了一长串使用此标头的(意外)后果(应该弃用此标头吗?),其中一节专门介绍 < em>拆分包。 其中一些后果很奇怪(而且是特定于 OSGi 的),但如果您了解一件事,大多数后果都是可以避免的:如果包片段是不相交的,那么一切都应该很好,除了您可能不会在任何地方都有类可见,并且如果从拆分的“错误”部分查看,包可见性成员可能看起来是私有的包裹。
——可以安装多个版本的包——但是从应用程序的角度来看,在任何时候包中的所有类都应该来自单个模块。]
[当然,这太简单了 “标准 Java”
在标准 Java 中,没有花哨的类加载器,您有一个类路径,并且搜索要加载的类的 jar(和目录)的顺序是固定且定义良好的:您得到的就是您得到的。 (但是,我们放弃了可管理的模块化。)
当然,您可以拥有拆分包——事实上这很常见——这表明模块化程度很差。 症状可能是模糊的编译/构建时错误,但在多个类实现的情况下(一个类实现覆盖单个类路径中的其余部分),由于语义的细微不同,它最常产生模糊的运行时行为。
如果您幸运,您最终会看到错误的代码 - 却没有意识到 - 并问自己“但这怎么可能那样 ?”
如果您不走运,您会查看正确的代码并询问完全相同的问题 - 因为其他东西会产生意想不到的答案。
这与旧的数据库格言并不完全不同:“如果您在两个地方记录同一条信息,很快它就不再相同了”。 我们的问题是“很快”通常还不够快。
Where split packages come from
Split packages (in OSGi) occur when the manifest header
Require-Bundle
is used (as it is, I believe, in Eclipse's manifests).Require-Bundle
names other bundles which are used to search for classes (if the package isn'tImport
ed). The search happens before the bundles own classpath is searched. This allows the classes for a single package to be loaded from the exports of multiple bundles (probably distinct jars).The OSGi spec (4.1) section 3.13 describes
Require-Bundle
and has a long list of (unexpected) consequences of using this header (ought this header be deprecated?), one section of which is devoted to split packages. Some of these consequences are bizarre (and rather OSGi-specific) but most are avoided if you understand one thing:If the package pieces are disjoint, then all should be well, except that you might not have the classes visible everywhere and package visibility members might appear to be private if viewed from a "wrong" part of a split package.
[Of course that's too simple—multiple versions of packages can be installed—but from the application's point of view at any one time all classes from a package should be sourced from a single module.]
What happens in 'standard Java'
In standard Java, without fancy class-loaders, you have a classpath, and the order of searching of jars (and directories) for classes to load is fixed and well-defined: what you get is what you get. (But then, we give up manageable modularity.)
Sure, you can have split packages—it's quite common in fact—and it is an indication of poor modularity. The symptoms can be obscure compile/build-time errors, but in the case of multiple class implementations (one over-rides the rest in a single class-path) it most often produces obscure run-time behaviour, owing to subtly-different semantics.
If you are lucky you end up looking at the wrong code—without realising it—and asking yourself "but how can that possibly be doing that?"
If you are unlucky you are looking at the right code and asking exactly the same thing—because something else was producing unexpected answers.
This is not entirely unlike the old database adage: "if you record the same piece of information in two places, pretty soon it won't be the same anymore". Our problem is that 'pretty soon' isn't normally soon enough.
对于不同捆绑包中的 OSGi 包来说,无论其名称如何,都是不同的,因为每个捆绑包都使用自己的类加载器。 确保捆绑包的封装不是一个问题,而是一个功能。
因此,在普通 Java 中,这通常不是问题,直到您开始使用某些使用类加载器的框架。 加载组件时通常会出现这种情况。
For OSGi packages in different bundles are different, regardless of their name, because each bundle uses its own class loader. It is not a problem but a feature, to ensure encapsulation of bundles.
So in plain Java this is normally not a problem, until you start using some framework that uses class loaders. That is typically the case when components are loaded.
将包拆分到 jar 中可能不是一个好主意。 我建议将 jar 内的所有包密封(将
"Sealed: true"
放在清单的主要部分)。 密封包装不能在罐子之间分开。对于 OSGi,具有相同包名称但不同类加载器的类将被视为位于不同的包中。
Splitting packages across jars probably isn't a great idea. I suggest making all packages within jars sealed (put
"Sealed: true"
in the main section of the manifest). Sealed packages can't be split between jars.In the case of OSGi, classes with the same package name but a different class loader are treated as if they are in different packages.
如果同一个包中有一些类,并且有些类位于已签名的 JAR 中,而其他类则不在签名的 JAR 中,那么您将收到严重的运行时错误。
You'll get a nasty runtime error if you have classes in the same package and some are in a signed JAR while others are not.
您问这个问题是因为有问题的软件包是您的,而不是第三方代码吗?
一个简单的例子是一个 Web 应用程序,其服务层和持久层作为单独的 OSGi 捆绑包。 持久性接口必须由两个包共享。
如果我正确地解释了你的问题,解决方案是创建一个包含共享接口的密封 JAR 并将其作为两个包的一部分吗?
我并不是想尝试劫持线程。 我请求那些迄今为止在 OSGi 方面所做的工作比我更多的人提供澄清和更好的见解。
Are you asking because the package in question is yours, not third party code?
An easy example would be a web app with service and persistence layers as separate OSGi bundles. The persistence interfaces would have to be shared by both bundles.
If I've interpreted your question correctly, would the solution be to create a sealed JAR containing the shared interfaces and make it part of both bundles?
I don't mean to try and hijack the thread. I'm asking for clarification and some better insight from those who might have done more with OSGi to date than I have.