Reputation: 23
I am using apache felix osgi. When I am loading class using classLoader.loadClass(..)
it is giving ClassNotFoundException
but when I am using Class.forName()
to load a class it is working fine.
What difference it makes when we use classLoader.loadClass()
?. Why we need to use only Class.forName()
or how to use classLoader.loadClass()
properly?
Upvotes: 2
Views: 1680
Reputation: 1146
As an additional tip: since you got the exception, you probably got the class loader you refer to as classLoader
via a call to Thread.currentThread().getContextClassLoader()
. In an OSGi environment that is probably the worst class loader to get since it is absolutely undefined what it is set to. The loading may fail at one time and succeed at another time, resulting in hard-to-find problems.
Upvotes: 0
Reputation: 23948
In any modular environment, such as OSGi, it is not sufficient to load a class only by name, because many modules might have a class with that name. Therefore a class must be uniquely identified using the class name AND the module that should load it.
If you call Class.forName()
in its single-arg form then you are failing to provide the module information, so Java falls back to using the caller's class loader. This is no better than just taking a random guess. In your case it just happened to work (it found the class), but only through pure luck!
If you call ClassLoader.loadClass()
– note this is not a static method – then you are actually providing a class loader. This is much better! Unfortunately you provided the wrong loader, i.e., not the one that actually knows about the class. You didn't specify where you got this loader from so I can only speculate why it was wrong.
Better is to use OSGi's Bundle.loadClass()
method, which allows you to explicitly load a class from a bundle. Again you need to know which bundle the class is supposed to come from, but that's an inevitable consequence of working in a modular environment.
Finally, even better still is to forget about dynamic class loading completely and learn how to use Services. You should never have to use dynamic class loading in OSGi, except when dealing with 3rd party or legacy libraries that require it.
Upvotes: 10
Reputation: 20618
The method Class.forName(String) uses the caller's class loader. For example, if you are doing
class MyClass {
void someMethod() {
Class.forName("my.pkg.SomeClass");
}
}
then the class loader, which loaded the class MyClass, also loads the class "my.pkg.SomeClass". In standalone applications this is normally the so-called system class loader.
If you see a difference between using Class.forName and ClassLoader.loadClass, then you are using another class loader.
Class loading in OSGI is more difficult, as OSGI does a good job sepearting class loaders for all OSGI bundles to not get in conflict loading all their resources and classes.
Upvotes: 1
Reputation: 4534
ClassLoader.loadClass
or Class.forName
seem to be synonyms for the same basic operation: request a dynamic class load. Yet calling Class.forName
does additional "checking" which is not very useful (certainly in OSGi).
When doing a dynamic class load, the returned type has no implied type by the code. The code must use reflection to access static members or to create an instance. A created instance can either be reflected upon or cast to a type which must already implicitly know by the code. This cast will result in a runtime type check which will ensure type safety.
This is very different than an implicit class load done by the VM to resolve a class constant pool entry. Since it is the goal of these implicit class loads to avoid runtime type checks, the loader constraints are used to ensure type safety.
It does not seem necessary or reasonable to impose loader constraint checks on some dynamic class load requests. That is, code calling Class.forName
(or ClassLoader.loadClass
) and the VM resolving a class constant pool entry have different type safety needs. The former does not require loader constraint checks since that will be done at runtime by a type cast if needed. The latter does require loader constraint checks to avoid the need for runtime type checks.
So it does seem reasonable to have Class.forName
behavior altered to avoid loader constraint checks. Only internal VM
class load requests need to check loader constraints.
For more understanding Click here
Upvotes: 0