What does the private-package manifest header do?

2019-04-05 05:00发布

问题:

I am familiar with Import-Package and Export-Package, but this is a new one for me. What does it do?

回答1:

At runtime in the OSGi container it does nothing. In fact, it's not even mentioned in the OSGi specification (I checked R4).

However, it can be specified in a .bnd file for use by bnd at build time. If so, it can be used to determine what goes into the bundle. When bnd builds a bundle, it automatically determines which classes need to go into the bundle. All the classes in packages that are exported are included, and all the classes that they depend on (transitively) are included too. This means that if a class doesn't appear to be used, then it won't be included in the bundle. However, you can use the Private-Package instruction to tell bnd to include the contents of the package in the bundle, even if it appears to be unused. If the Private-Package instruction is not specified, then it will be automatically generated by bnd.

The documentation for Private-Package reads as follows:

Private Package

The method of inclusion is identical to the Export-Package header, the only difference is, is that these packages are not exported. This header will be copied to the manifest. If a package is selected by noth the export and private package headers, then the export takes precedence.

Private-Package= com.*



回答2:

If you know what static linking is then you understand Private-Package. Otherwise read on.

Private-Package is bnd's way of telling you the packages that must be inside the jar but that are not exported. It is not an OSGi header but a bnd 'instruction'.

The instruction defines the packages from the classpath (with wildcards) that must be included in the JAR. bnd is unique that it populates the JAR from a specification and not some directory like most build tools. The reason is that unless modules are 'designed' and their layout carefully considered they are rarely provide modular benefits.

In general Private-Package specifies the packages holding the classes that should not be shared with other bundles, i.e. the implementation classes. Though in general they come from the corresponding project that bnd is used in it is perfectly acceptable to get them from any other JAR on the classpath.

One use case is a library with utils. Turning a util library in a bundle is usually wreaking havoc with dependencies since utils tend to depend on lots of unrelated things; you use one tiny method and suddenly you drag in 30Mb of dependencies. bnd itself heavily uses this model with the aQute.lib* packages, packages from this library should never be exported. It is a trade of between bundle size and 'downloading the internet'. The difference is visible between the Eclipse's and Apache Felix's worlds. Apache Felix bundles are usually standalone and do not require all kinds of support and util bundles while Eclipse's bundles have a tendency to require lots of plumbing bundles. I think this difference is largely caused by Eclipse's PDE that makes it impossible to include packages from other projects unless you copy the source code which is of course a big no-no.

In the C world they have something called static linking. After a program is linked, any unresolveds are retrieved from a library and added to the target. To a certain extent Private-Package is the same idea. There is actually a header Conditional-Package that statically links the specified packages and anything they transitively depend on (as long as they fall in the pattern).

In the end bnd shows the expanded packages that are not exported in the Private-Package header in the manifest. After all, a manifest is supposed to describe the contents ...

If you're the author you can remove the header with -removeheaders: Private-Package (or in maven with <_removeheaders>Private-Package



回答3:

In fact Private-Package does more than just not exporting a package. If the packages specified in Private-Package are not defined inside you own project and are not imported in Import-Package then they are automatically inlined into your jar. So this is an easy way to include non OSGi dependencies. Be careful though that inlining can easily lead to classpath problems.



标签: java osgi bnd