we're experiencing classloading issues with Hazelcast. A little bit of
background: We are using a managed environment which loads each
component with different classloaders (Apache Servicemix, service
assemblies are loaded with different classloaders). We are also
starting a custom JMX agent connector server which is started as a
java premain (-javaagent). When we want to access data structures
stored in Hazelcast distributed maps via JMX, we are getting
java.lang.ClassNotFoundException from AbstractSerializer because it
obviously tries to load the class with the current threads
contextclassloader, which is not working in our case.
Since we are packaging Hazelcast together with our own classes into
the service assembly which is loaded by Servicemix, for us it would be
good if the classes could be loaded by the classloader that loaded the
Hazelcast classes, not the current threads ones, but I saw this was
changed for a good reason a while back
(http://code.google.com/p/hazelcast/issues/detail?id=276).
Searching the web for a solution I found Config.setClassLoader, which
seems like could solve our problems, but unfortunately I do not find
any examples on how to use it. Could you please post a small example
on how to tell Hazelcast to use a different classloader than
Thread.currentThread().getContextClassLoader() ?
We are currently using Hazelcast very simple, just Hazelcast.getMap(),
we can certainly add code that sets the classloader in our code.
thanks and best regards,
christian!
from now on, hazelcast instance will use your classloader.
If you are using singleton Hazelcast class then you should call
Hazelcast.init(config) first.
> --
> You received this message because you are subscribed to the Google Groups "Hazelcast" group.
> To post to this group, send email to haze...@googlegroups.com.
> To unsubscribe from this group, send email to hazelcast+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/hazelcast?hl=en.
>
>
You are right. We really do need an OSGi expert to figure these all out.
-talip
Best Regards //Anders
@Andreas: Why is it an issue for you to use the TCCL inside OSGi?. Its something that works and without affecting the modularity of your applications. I agree that is some cases having the class loader being set in the configuration would help, but I don't see a problem with the TCCL inside OSGi.
Using the TCCL in OSGi is generally a bad idea. Here's some examples:
Basically (at least in our system) the TCCL is at best "undefined". The following scenario is typical:1. BundleA puts an entry in the hz-map: Hazelcast.getMap("foo").put("bar", reference)2. Later on, BundleA reads the entry back: Hazelcast.getMap("foo").get("bar") (on the same JVM or on another JVM)3. The TCCL in this case is undefined - most likely pointing to the AppClassLoader of the JVM (which does not see BundleA).You could setup the TCCL manually before calling map.get("..") but that adds un-necessary complexity - and will not work in all scenarios (it iterating over the values() in the map outside of the calling code, for example).
On Thu, Sep 22, 2011 at 6:07 PM, Ioannis Canellos <ioc...@gmail.com> wrote:
> If I follow the thread correctly, Christian who started the thread is using
> ServiceMix 3.x or ServiceMix 4.x but with JBI packaging rather than OSGi
> packaging. So according to my understanding this is not a pure OSGi related
> issue.
Yes, this is correct. We're using Servicemix 3.2.2 and as said the
problem arises because Hazelcast tries to load our custom classes with
the TCCL - which is in case of JMX access the "system classloader" and
this one does not know about our classes because our classes were
loaded together with Hazelcast by the Servicemix service
engine/assembly classloader.
For us the a simple solution like the one provided in the attached
patch (made from current trunk) would work, but I understood from your
discussion (which was btw. quite insightful; thanks for the links
Anders!) that this still would not work for all OSGI cases. However,
the patch makes the current situation a little bit better.
Thanks and best regards,
christian!
> It would be nice if it was possible to set the class loader inside hazelcast
> config and then have the AbstractSerializer reuse that class loader. Last
> time I checked the AbstractSerializer did not make use of that class loader.
> @Andreas: Why is it an issue for you to use the TCCL inside OSGi?. Its
> something that works and without affecting the modularity of your
> applications. I agree that is some cases having the class loader being set
> in the configuration would help, but I don't see a problem with the TCCL
> inside OSGi.
> --
> Ioannis Canellos
> FuseSource
>
> Blog: http://iocanel.blogspot.com
> Apache Karaf Committer & PMC
> Apache ServiceMix Committer
> Apache Gora Committer
>
>
>
>
>
private static final boolean USELOCALCLASSLOADER =
Boolean.valueOf(System.getProperty("hazelcast.serializer.use.local.classloader",
"false"));
...
if(!USELOCALCLASSLOADER)
theClassLoader = Thread.currentThread().getContextClassLoader();
Using the TCCL in OSGi is generally a bad idea. Here's some examples:
If you know what you are doing, using the TCCL is not a bad idea. [snip]
Fragments: Will require to be installed before the framework bundle or will require refresh, which might be unwanted.
Dynamic Imports: Can result in constraint violation and other issues such as unwanted refreshes etc.
Buddy Classloading: Only available to equinox, but still compromises modularity.
Custom Classloader: By custom classloaders, I mean classloader implementation that will try to delegate classloading to the correct bundle, either by registration (an extender possibly) or by a lookup (I think you mentioned package admin). This can only be a last resort, since they will only be able to trigger their lookups using the className but the classloader api doesn't have means to pass version information.
So the last solution is to somehow pick the right class loader from the framework or from the TCCL. If you see the source of most osgi ready frameworks, you will find out that most of them solve the problem this way.
Of course nobody can disagree that this needs to be hidden from the framework user and that the user should not put his fingers on the TCCL. This is something that needs to be done by the framework internally. So the question is how Hazelcast could hide that from the user.Basically (at least in our system) the TCCL is at best "undefined". The following scenario is typical:1. BundleA puts an entry in the hz-map: Hazelcast.getMap("foo").put("bar", reference)2. Later on, BundleA reads the entry back: Hazelcast.getMap("foo").get("bar") (on the same JVM or on another JVM)3. The TCCL in this case is undefined - most likely pointing to the AppClassLoader of the JVM (which does not see BundleA).You could setup the TCCL manually before calling map.get("..") but that adds un-necessary complexity - and will not work in all scenarios (it iterating over the values() in the map outside of the calling code, for example).Agree, this is what I mean that needs to be hidden from the framework user.