Java Reference
In-Depth Information
To see this in practice, run the third example:
$ ./chapter08/classloading/PICK_EXAMPLE 3
You should see a ClassCastException involving the Spoke class. This is because your
spoke bundle contains its own private copy of org.foo.hub.spi , instead of importing
it from the hub bundle. The spoke and hub end up using different class loaders for the
same API class, which makes the spoke implementation incompatible with the hub:
java.lang.ClassCastException: org.foo.spoke.SpokeImpl
cannot be cast to org.foo.hub.spi.Spoke
The fastest way to investigate these impossible ClassCastException s is to compare
the class loaders for the expected and actual types. OSG i frameworks sometimes label
their class loaders with the bundle identifier, so calling getClassLoader().
toString() on both sides can tell you which bundles are involved. You can also use
the framework console to find out who's exporting the affected package and who
imports it from them. Use this to build a map of the different class spaces. The specific
commands to use depend on the framework; at the time of writing this topic, the OSG i
Alliance is still standardizing a command shell. On Felix, the inspect package com-
mand is the one to use. On Equinox you would use the packages or bundle com-
mands. Once you understand the different class spaces, you can adjust the bundle
metadata to make things consistent to avoid the ClassCastException . One approach
might be to add uses constraints, which we first introduced at the end of chapter 2.
8.2.3
Using uses constraints
Think back to chapter 2, specifically the discussion about consistent class spaces in
section 2.7.2. Bundles must have a consistent class space to avoid running into class-
related problems, such as visibility or casting issues. When you have two tightly cou-
pled packages, it's sometimes necessary to add uses constraints to make sure these
packages come from the same class space. Perhaps you don't think you need all these
uses constraints cluttering up your manifest—after all, what's the worst that can hap-
pen if you remove them?
Let's find out by running the fourth example in the class-loading series:
$ ./chapter08/classloading/PICK_EXAMPLE 4
Yet again you get a class-loading exception, except this time it happens inside the
spoke implementation. The Java runtime notices that you attempted to load two dif-
ferent versions of the Message class in the same class loader—in other words, your
class space is inconsistent:
java.lang.LinkageError: loader constraint violation: loader (instance of
org/apache/felix/framework/searchpolicy/ModuleImpl$ModuleClassLoader)
previously initiated loading for a different type with name
"org/foo/hub/Message"
How did this happen? Your new spoke bundle has an open version range for the hub
API , which means it can import any version after 1.0. It also provides a new 2.0 version
Search WWH ::




Custom Search