Why am I getting a ClassCastException
when the class is clearly of the right type?
Q: I am getting an exception when I run my module, such as
java.lang.ClassCastException: Implementation cannot be cast to Interface
at Factory.newInstance (Factory.java:123)
But Implementation
implements Interface
, so why is this a CCE?
A: Usually this is because the Interface
that Implementation
actually implements was loaded from a different class loader than what Factory
sees.
That is very likely the immediate cause of the CCE. The root cause is not always obvious, but it is likely to be that some code uses Thread.currentThread().getContextClassLoader()
to load a class by name. In NB by default the context class loader just looks around in loaded modules (lacking any better information), so it is possible for the following situation to arise:
module A: Interface, Factory
module B > A: Implementation implements Interface
module C: Interface, Factory
module D > A: Implementation implements Interface
where Factory
does something like:
Interface i = (Interface) Class.forName("Implementation", true,
Thread.currentThread().getContextClassLoader()).newInstance();
(This is a common design pattern for XML parsers, etc.)
Now if A’s Factory
happens to get D’s Implementation
(or C’s gets B’s) then you get a CCE at runtime.
An especially silly variant of this problem, known to occur at least in Xerces (), is that Implementation
actually resides in the same JAR as Interface
and Factory
, and is the standard impl almost everyone uses unless overridden somehow - yet Factory
loads it by name from the CCL rather than simply loading it directly using e.g. new Implementation()
.
The usual workaround is to wrap the problematic call(s) in a dynamic block:
ClassLoader orig = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(SomeReferenceClass.class.getClassLoader());
try {
Factory.load(...);
} finally {
Thread.currentThread().setContextClassLoader(orig);
}
Note: NetBeans forbids ambiguous delegations. ()
If a class could be loaded from two (or more) places, it will not be loaded at all.
This does not solve your problem but it at least ensures it gets reported more reliably
and with a descriptive message rather than an odd ClassCastException
.
Applies to: NetBeans 6.5 and later