Java Reference
In-Depth Information
package b;
public class B extends a.A {}
package a;
public class A {}
No Import-Package
bundleB.loadClass("a.A")
a.A
ClassNotFoundException
a.A
bundleB.loadClass("b.B")
b.B
NoClassDefFoundError
Figure 8.11
Differences between
ClassNotFoundException
and
NoClassDefFoundError
cause of the exception. When you know the real cause, you can use the same problem-
solving approach used in
ClassNotFoundException
to fix the issue.
Figure 8.11 summarizes the difference between the two missing-class exception
types; together, they make up many of the class-loading issues you'll encounter when
using
OSG
i. Just remember:
ClassNotFoundException
means a class is missing,
whereas
NoClassDefFoundError
means one of its dependencies is missing.
Unfortunately, these two exceptions don't have a monopoly on confusing
OSG
i
developers. A classic puzzle for people new to class loading goes something like this:
you're given an object that says its type is
org.foo.Item
, but when you try to cast it to
org.foo.Item
you get a
ClassCastException
! What's going on?
8.2.2
Casting problems
How many of you would expect a
ClassCastException
from the following code?
ServiceTracker itemTracker =
new ServiceTracker(bundleContext, "org.foo.Item", null);
itemTracker.open(true);
Item item = (Item) itemTracker.getService();
At first glance, it looks correct: you configure a service tracker to track services of
type
org.foo.Item
and cast the discovered service, if any, to the same type. But
notice how you open the tracker. Instead of calling the no-argument
open()
method
as usual, you pass in a Boolean:
true
. This tells the service tracker to track
all
services
whose type name matches the
org.foo.Item
string, not just the ones that are class-
loader compatible with your bundle (we discussed a similar situation back in sec-
tion 4.5.1). If another bundle provides an
Item
service and happens to get the
org.foo
package from a different class space than you did, you'll see a
ClassCast-
Exception
at the last line.
How can this be? Recall from chapter 2 that class loaders form part of a type's iden-
tity at execution time, so the exact same class byte code loaded by two different class
loaders is considered to be two distinct types. This makes all the difference, because
OSG
i uses a class loader per bundle to support class-space isolation in the same Java
runtime. It also means you can get
ClassCastException
s when casting between types
that look identical on paper.