Need help understanding class loading rules used by JBoss Marshalling in Infinispan
sellhorn Apr 29, 2011 12:08 PMThis is related to using Infinispan in OSGi.
Basically, after some usage we sometimes see the JBoss Marshalling using the wrong class loaders in an OSGi environment. We have multiple bundles talking to a central bundle that holds all caches (the central bundle exposes itself as an OSGi service an does Dynamic-Import: *). Bundles have their own context and bundle class loaders and everything works fine. But when we run them all at the same time, after some time we start getting class loading exceptions and you can see jboss marshalling using the bundle context classloader from say bundle B, when it's trying to load say class A from bundle A.
It seems like the jboss marshaller keeps references to different classloaders and in a multithreaded environment can get messed up.
Here's an example stack trace of what I'm talking about;
Caused by: java.lang.ClassNotFoundException: com.ge.blah.A.SomeAClass not foundfrom bundle [com.ge.blah.B]
at org.springframework.osgi.util.BundleDelegatingClassLoader.findClass(BundleDelegatingClassLoader.java:103)
at org.springframework.osgi.util.BundleDelegatingClassLoader.loadClass(BundleDelegatingClassLoader.java:156)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)[:1.6.0_21]
at java.lang.Class.forName0(Native Method)[:1.6.0_21]
at java.lang.Class.forName(Class.java:247)[:1.6.0_21]
at org.jboss.marshalling.AbstractClassResolver.loadClass(AbstractClassResolver.java:135)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.jboss.marshalling.AbstractClassResolver.resolveClass(AbstractClassResolver.java:116)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.jboss.marshalling.river.RiverUnmarshaller.doResolveClass(RiverUnmarshaller.java:1148)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.jboss.marshalling.river.RiverUnmarshaller.doReadClassDescriptor(RiverUnmarshaller.java:862)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.jboss.marshalling.river.RiverUnmarshaller.doReadNewObject(RiverUnmarshaller.java:1183)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:270)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:207)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.jboss.marshalling.AbstractUnmarshaller.readObject(AbstractUnmarshaller.java:85)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.infinispan.marshall.exts.ReplicableCommandExternalizer.readObject(ReplicableCommandExternalizer.java:75)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.infinispan.marshall.jboss.ConstantObjectTable$ExternalizerAdapter.readObject(ConstantObjectTable.java:266)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.infinispan.marshall.jboss.ConstantObjectTable.readObject(ConstantObjectTable.java:253)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:357)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:207)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.jboss.marshalling.AbstractUnmarshaller.readObject(AbstractUnmarshaller.java:85)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.infinispan.marshall.exts.ReplicableCommandExternalizer.readObject(ReplicableCommandExternalizer.java:75)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.infinispan.marshall.jboss.ConstantObjectTable$ExternalizerAdapter.readObject(ConstantObjectTable.java:266)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.infinispan.marshall.jboss.ConstantObjectTable.readObject(ConstantObjectTable.java:253)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:357)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:207)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.jboss.marshalling.AbstractUnmarshaller.readObject(AbstractUnmarshaller.java:85)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.infinispan.marshall.jboss.GenericJBossMarshaller.objectFromObjectStream(GenericJBossMarshaller.java:162)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.infinispan.marshall.VersionAwareMarshaller.objectFromByteBuffer(VersionAwareMarshaller.java:111)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.infinispan.remoting.transport.jgroups.MarshallerAdapter.objectFromByteBuffer(MarshallerAdapter.java:26)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
at org.infinispan.remoting.transport.jgroups.CommandAwareRpcDispatcher.handle(CommandAwareRpcDispatcher.java:146)[198:com.ge.blah.someinfinispanwrapper:1.5.0.SNAPSHOT]
... 28 more
Caused by: java.lang.ClassNotFoundException: com.ge.blah.A.SomeAClass
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:506)[osgi-3.6.0.v20100517.jar:]
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:422)[osgi-3.6.0.v20100517.jar:]
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:410)[osgi-3.6.0.v20100517.jar:]
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)[osgi-3.6.0.v20100517.jar:]
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)[:1.6.0_21]
at org.eclipse.osgi.internal.loader.BundleLoader.loadClass(BundleLoader.java:338)[osgi-3.6.0.v20100517.jar:]
at org.eclipse.osgi.framework.internal.core.BundleHost.loadClass(BundleHost.java:232)[osgi-3.6.0.v20100517.jar:]
at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadClass(AbstractBundle.java:1197)[osgi-3.6.0.v20100517.jar:]
at org.springframework.osgi.util.BundleDelegatingClassLoader.findClass(BundleDelegatingClassLoader.java:99)
... 56 more
One work around we've found is that if you turn on lazy deserialization then this seems to fix the problem, but we're seeing degraded performance and issues with running out of memory.
My question is, how does JBoss Marshalling figure out what class loader to use, and how I can make it use the classloader of the bundle that interacts with the class it loads ... OR ... how can I tell it what classloader to use in a more direct way. For example, I believe that if it used the classloader I have with Dynamic-Import: * things would work.
Are these some settings I can try for JBoss marshalling to control what class loader it uses, interceptors I could use?
Thanks