Home » Eclipse Projects » Equinox » bundle class loaders caching issues?
bundle class loaders caching issues? [message #79909] |
Wed, 27 December 2006 14:41 |
Eclipse User |
|
|
|
Originally posted by: david.eauee.gmail.com
Hi,
I have a weird situation here were multiple calls to the "JAXBContext.newInstance(...)" causes an avalanche of "java.lang.LinkageError: duplicate class definition:..." error being spit out. I have copied a sample stack trace at the end of this mail
This call is made indirectly by one of the lib my plug-in is using.
The lib itself is hosted by a separate binary plug-in that also contains all the other dependant jars that i require.
Just to make sure I checked that the offending classes were not present more than once in the build path.
The weird thing is that the 1st call to the method returns happily but each one after that will fail. Dont the bundle class loaders have a caching mechanism to prevent them from trying to load the same class multiple times?
Has anybody come across this before?
Thanks,
David.
stack trace:
java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor5.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.sun.xml.bind.v2.runtime.reflect.opt.Injector.inject(Inje ctor.java:125)
at com.sun.xml.bind.v2.runtime.reflect.opt.Injector.inject(Inje ctor.java:48)
at com.sun.xml.bind.v2.runtime.reflect.opt.AccessorInjector.pre pare(AccessorInjector.java:51)
at com.sun.xml.bind.v2.runtime.reflect.opt.OptimizedAccessorFac tory.get(OptimizedAccessorFactory.java:128)
at com.sun.xml.bind.v2.runtime.reflect.Accessor$FieldReflection .optimize(Accessor.java:198)
at com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor$Compo siteTransducedAccessorImpl. <init>(TransducedAccessor.java:193)
at com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor.get(T ransducedAccessor.java:135)
at com.sun.xml.bind.v2.runtime.property.AttributeProperty.<init >(AttributeProperty.java:53)
at com.sun.xml.bind.v2.runtime.property.PropertyFactory.create( PropertyFactory.java:68)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:135)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXB ContextImpl.java:404)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:122)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXB ContextImpl.java:404)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:122)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXB ContextImpl.java:404)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:246)
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFact ory.java:76)
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFact ory.java:55)
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFact ory.java:124)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java: 132)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:286)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:372)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:337)
...
Caused by: java.lang.LinkageError: duplicate class definition: ...
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
... 72 more
|
|
|
Re: bundle class loaders caching issues? [message #79941 is a reply to message #79909] |
Thu, 28 December 2006 17:47 |
Eclipse User |
|
|
|
Originally posted by: alex_blewitt.yahoo.com
It looks like what's happening is that it's trying to redefine a class by reusing a classloader. Although the names should be unique, chances are whenever it tries to get a new call it's using the same name as before, and that somehow due to class loader linkagaes, that causes problems in the OSGi framework.
That's just a guess, based on what little I know of how such XML binding libraries work. You might get better results by embedding the JAXB libraries into the same plug-in that you're using; that way, the classes should be in the same classloader rather than cross-classloaders (which may be where a conflict occurs).
These are all just guesses; it may be something else all together.
Alex.
|
|
|
Re: bundle class loaders caching issues? [message #80003 is a reply to message #79941] |
Tue, 02 January 2007 11:15 |
Eclipse User |
|
|
|
Originally posted by: david.eauee.gmail.com
thanks for the answer,
i am not sure of what you mean in the 1st paragraph. but it's true that the same class is used for various extensions and and should be instanciated several times.
What bugs me is that, to the extend of my knowledge, structure of the OSGI classloading should only be an issues when various dependant libs gets spread across several bundles. In my case, everything i need is in that single lib plugin.
i actually tried to host the libs in the plugin that uses them (not that it's an option in the long run though) but got the same problem.
thnks,
d.
|
|
|
Re: bundle class loaders caching issues? [message #80017 is a reply to message #80003] |
Tue, 02 January 2007 12:10 |
Eclipse User |
|
|
|
Originally posted by: alex_blewitt.yahoo.com
You need to be careful with terminology. It's not that the same class is being instantiated multiple times, but rather that (through JaxB) the class is being *defined* multiple times:
Caused by: java.lang.LinkageError: duplicate class definition: ...
at java.lang.ClassLoader.defineClass1(Native Method)
What I'd imagine is happening is that there's some weirdness going on that doesn't expose itself when being used in a simple classloader scenario, but fails in the OSGi nested classloader case. One example might be that the class that's being defined is somehow leaking to the parent classloader, and that that's preventing the class from being redefined when it's next called.
If it doesn't work even when everything is being packaged up in a single plugin, and you're just using the JaxB stuff yourself (i.e. you're not trying to call defineClass multiple times) then I'd say it's a bug in JaxB that's exposed when running under OSGi. Perhaps using a different API (JibX, for example) might be the only way forward.
It's probably worth raising it as a bug at https://bugs.eclipse.org if you can provide a simple testcase, so that others know of the issue and/or someone might find out what it is.
Alex.
|
|
|
Re: bundle class loaders caching issues? [message #80410 is a reply to message #80017] |
Mon, 08 January 2007 15:57 |
Eclipse User |
|
|
|
Originally posted by: alex_blewitt.yahoo.com
By the way, for anyone else reading this and/or having this problem, I found the following on java.net:
http://forums.java.net/jive/thread.jspa?messageID=191633& ;tstart=0#191633
<blockquote>Due to classloader constraints when loading JAXB generated code into
an OSGi bundle, we've had to set this magic property ( com.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize) to true, preventing
the reference impl from force-feeding a class (via defineClass) into a
classloader that already has the class defined.
Thing is, we don't know what the side-effects may be. I think it might
just cause things to slow down ever so slightly, but is there more to it?
</blockquote>
The answer was no, it's just an optimisation feature. But this property might help out people -- try running your app with -Dcom.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize=true (or put it in the .ini) to see if that has any effect.
Alex.
|
|
| |
Re: bundle class loaders caching issues? [message #80522 is a reply to message #80438] |
Tue, 09 January 2007 08:47 |
Eclipse User |
|
|
|
Originally posted by: alex_blewitt.yahoo.com
It did seem to be by the original report/stack trace:
... multiple calls to the "JAXBContext.newInstance(...)" causes an avalanche of "java.lang.LinkageError: duplicate class definition:. ...
stack trace:
java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor5.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.sun.xml.bind.v2.runtime.reflect.opt.Injector.inject(Inje ctor.java:125)
at com.sun.xml.bind.v2.runtime.reflect.opt.Injector.inject(Inje ctor.java:48)
:
Caused by: java.lang.LinkageError: duplicate class definition: ...
at java.lang.ClassLoader.defineClass1(Native Method)
It looks like the JAXB is doing a dynamic method call to build up the bytecode, which in turn is then invoking the defineClass when it's already defined. I suspect that if you put together a quick ClassLoader and overrode the defineClass() method to print out diagnostics, you'd see the same thing. Alternatively, putting a breakpoint in the defineClass and using a JAXB sample would do the trick :-)
David, would you be able to open a bug at https://bugs.eclipse.org and attach a snippet that exhibits this problem? At least that way we could verify whether it's a JAXB issue or not.
Alex.
|
|
|
Re: bundle class loaders caching issues? [message #80674 is a reply to message #80522] |
Thu, 11 January 2007 09:34 |
David Beaurpere Messages: 15 Registered: July 2009 |
Junior Member |
|
|
sorry for not replying for the past few days (was sick)
You are correct Alex, The "injector" class from the JAXB impl really
goes out of it way to "force define" classes: it retrieves the Method
handle from Classloader.class, reset its accessibility settings and call
invoke on it directly (see the snippets from the injector class at the end)
Now, I have no idea why in the 1st place JAXB seems to believe that it
needs to go to such extremes to load classes (generated on the fly) that
the class loader knows about already.
That said, as a colleague of mine mentioned on java.net (the thread you
referenced earlier) we came across a work around: setting the env var
"com.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize" will cause JAXB to
avoid that code completely. For now we are content enough with that
resolution.
i will open a bug...
Regarding replicating the issue, I think the simplest would be to import
a recent apache cxf distrib (which includes and uses JAXB) in a plugin,
attach the srcs to the jar and call some of their their wsdl related
APIs. Would that be ok?
thanks,
d.
#############################
.....
private static final Method defineClass;
private static final Method resolveClass; ....
defineClass =
ClassLoader.class.getDeclaredMethod("defineClass",String.class,byte[].cl
ass,Integer.TYPE,Integer.TYPE);
resolveClass =
ClassLoader.class.getDeclaredMethod("resolveClass",Class.class);
.....
// TODO: check security implication
// do these setAccessible allow anyone to call these methods freely?s
defineClass.setAccessible(true);
resolveClass.setAccessible(true);
....
(Class)defineClass.invoke(parent,className.replace('/','.'), image,0,imag
e.length);
resolveClass.invoke(parent,c);
.....
#############################
Alex Blewitt wrote:
> It did seem to be by the original report/stack trace:
>
> .. multiple calls to the "JAXBContext.newInstance(...)" causes an avalanche of "java.lang.LinkageError: duplicate class definition:. ...
>
> stack trace:
>
> java.lang.reflect.InvocationTargetException
> at sun.reflect.GeneratedMethodAccessor5.invoke(Unknown Source)
> at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
> at java.lang.reflect.Method.invoke(Unknown Source)
> at com.sun.xml.bind.v2.runtime.reflect.opt.Injector.inject(Inje ctor.java:125)
> at com.sun.xml.bind.v2.runtime.reflect.opt.Injector.inject(Inje ctor.java:48)
> :
> Caused by: java.lang.LinkageError: duplicate class definition: ...
> at java.lang.ClassLoader.defineClass1(Native Method)
>
> It looks like the JAXB is doing a dynamic method call to build up the bytecode, which in turn is then invoking the defineClass when it's already defined. I suspect that if you put together a quick ClassLoader and overrode the defineClass() method to print out diagnostics, you'd see the same thing. Alternatively, putting a breakpoint in the defineClass and using a JAXB sample would do the trick :-)
>
> David, would you be able to open a bug at https://bugs.eclipse.org and attach a snippet that exhibits this problem? At least that way we could verify whether it's a JAXB issue or not.
>
> Alex.
|
|
|
Re: bundle class loaders caching issues? [message #80695 is a reply to message #80674] |
Thu, 11 January 2007 14:24 |
Eclipse User |
|
|
|
Originally posted by: alex_blewitt.yahoo.com
> You are correct Alex, The "injector" class from the JAXB impl
> really goes out of it way to "force define" classes: it retrieves
> the Method handle from Classloader.class, reset its accessibility
> settings and call invoke on it directly.
Cool, glad we found that error.
> Now, I have no idea why in the 1st place JAXB seems to believe
> that it needs to go to such extremes to load classes ...
A cynic might point out that JAXB is written by Sun, and that they don't like Eclipse or any of that nasty little OSGi stuff that it runs on when there's a perfectly good JSR277 around the corner :-)
> Regarding replicating the issue, I think the simplest would be
> to import a recent apache cxf distrib (which includes and uses
> JAXB) in a plugin, attach the srcs to the jar and call some of
> their their wsdl related APIs. Would that be ok?
The easier it is for the Eclipse guys to reproduce it, the easier that they can see what to do about it. A few lines that invoke (say) the WS code, and a 'download the Jar from http://...' would probably do.
That being said, I suspect it might be that the JAXB code is behaving badly, and that it turns out that it's not an issue that Equinox can work around anyway. So I wouldn't spend *too* long on it :-)
Alex.
PS I'm not an Eclipse committer; if you raise a bug, they may have different opions about reproducibility :-)
|
|
|
Goto Forum:
Current Time: Mon Sep 23 04:52:51 GMT 2024
Powered by FUDForum. Page generated in 0.26910 seconds
|