Requiring and using a Java library that ends up using a Thread Context classloader doesn't work.
I'm integrating some Java code into my JRuby project and adding the jars to JRuby's classpath using require.
The external Java code uses other libraries that use a Thread Context classloader. When the ThreadContext classloader tries to create a class that is defined in one of the jars I required from JRuby I get a ClassNotFoundException.
If I add the jars to the system CLASSPATH everything works.
This problem came up while trying to integrate our SAIL-OTrunk code however we've created a much simpler test to show the problem.
Setting up the test:
Running the tests:
Here's some of the investigation I did when I was originally looking into the classloading issues running OTrunk from JRuby.
The problem occurs when a Java class I call then calls XMLDecoder to instantiate another Java class – XMLDecoder is not using the JRuby classloader – instead it is using a thread context classloader and can't find the class it's trying to create because only the JRuby classloader has the new jars I've required
In JRuby the thread context classloader is the parent of the jruby classloader. See my experiments here:
When I contacted Charles Nutter on IRC he wrote that JRuby is not setting the threadcontext classloader when the JRuby thread is created to make it easier to create new JRuby thread instances.
the problem we would have setting the jruby loader as thread context classloader is...what happens if the thread calls through to another JRuby instance? since the jaxp libs are loaded by system classloader, in order for them to locate and instantiate classes from lower classloaders it looks at tc classloader – we don't set tc classloader to the jruby classloader because, well, we really can't if we want jruby instances to be able to migrate across threads
I don't know enough about the JRuby threading to know why using a ThreadContext classloader would hinder or prevent migrating JRuby instances across threads.
You can see more of the IRC conversation between me and Charles starting around 01:05:43 here:
Recent threads mentioning related issues:
"When I add the websphere jars to the classpath in the jruby executable, it works.
If I append the jars in the script, either through $CLASSPATH << or 'require
blah.jar', the script fails."
"..trying to use the Spring's ClassPathXmlApplicationContext, but it seems that
internally, Springkeeps trying to load stuff with the Thread's contextClassLoader"