Java Reference
In-Depth Information
8.2.4
Staying clear of Class.forName()
Suppose you're writing a module that needs to look up a class at execution time based
on some incoming argument or configuration value. Skimming through the Java plat-
form API , you spot a method called Class.forName() . Give it a class name, and it returns
the loaded class. Perfect, right? Its ongoing popularity suggests many Java programmers
agree; but before you sprinkle it throughout your code, you should know it has a flaw:
it doesn't work well in modular applications. It assumes the caller's class loader can see
the named class, which you know isn't always true when you enforce modularity.
How does this affect you as an OSG i developer? Any class you attempt to load using
Class.forName() must either be contained, imported, or boot-delegated by the bun-
dle making the call. When you're loading from a selection of known classes, this isn't a
big deal; but if you're providing a general utility (such as an aspect-weaving service),
there's no way to know which classes you may need to load. And even if you happen to
know, you may decide to keep things flexible for the future. If you remember our dis-
cussion on discovering imports from section 6.1.3, you may think this sounds like a job
for dynamic imports:
DynamicImport-Package: *
But dynamic imports only work when the wanted packages are exported. In addition,
your bundle can get wired to many different packages in numerous client bundles. If
any one of these bundles is refreshed, your bundle will also end up refreshed, which in
turn may affect the other bundles. Finally, you can import only one version of a package
at any one time. If you want to work with non-exported classes or handle multiple ver-
sions of the same code concurrently, you need to find another way to access them.
Whenever you work with OSG i class loading, always remember that well-defined
rules govern visibility. It's not some arbitrary decision about who sees what. Every
loaded class must be visible to at least one class loader. Your bundle may not be able to
see the client class, but the client bundle certainly can. If you can somehow get hold
of the client class loader, you can use it to load the class instead of using your own class
loader. This job is much easier if the method arguments already include a type or
instance of a type that you know belongs to the client. Let's see how easy it can be with
the help of the sixth spoke implementation.
Listing 8.3 Audited spoke implementation
public class SpokeImpl implements Spoke {
String address;
public SpokeImpl(String address) {
this.address = address;
}
public boolean receive(Message message) {
if (address.matches(message.getAddress())) {
Assumes same
package
Class msgClazz = message.getClass();
String auditorName = msgClazz.getPackage().getName() + ".Auditor";
 
Search WWH ::




Custom Search