Using a separate classloader for a block

I am looking to see how plausible it is to execute a block within a
child Classloader. A list of Jars would be passed to the ClassLoader to
load for the execution of the block. The problem I have is telling the
JRuby runtime to use the new classloader instead of the default. What I
have now is a bit of a hack, it manually uses a custom class loader.
The call to create(string class) uses it for constructing an instance.

An example of what I am attempting now:

 email = LockJar::ClassLoader.new( 'tmp/IsolateJarfile.lock'

).isolate do
email = create( ‘org.apache.commons.mail.SimpleEmail’ )
email.setSubject( ‘test subject’ )
email
end

 email.getSubject().should eql 'test subject'

This works, the SimpleEmail is created in the child ClassLoader. The
default JRuby classpath is not changed. The call to create(
‘org.apache.commons.mail.SimpleEmail’ ) is ugly. Ideally
'org.apache.commons.mail.SimpleEmail.new could be called and the JRuby
runtime would pull from the custom class loader instead of the default
JRuby classloader. I tried changing
Thread.currentThread().setContextClassLoader during the block execution,
but that did not work. I snooped around the JRuby source some, but could
not figure out a good way to hook into the ClassLoader. Any help or
advice is appreciated.

The simple custom classloader:

Ruby to load jars in isolation:
https://github.com/mguymon/lock_jar/blob/class_loader/lib/lock_jar/class_loader.rb
The green spec:
https://github.com/mguymon/lock_jar/blob/class_loader/spec/lock_jar/class_loader_spec.rb

thanks,
Michael

Hi Michael,

On 25.09.2012 16:22, Michael Guymon wrote:

I am looking to see how plausible it is to execute a block within a
child Classloader.

I’ve also been playing around with a JRuby/Maven integration and found
it necessary to run some JRuby code in an alternate classloader.

My solution is rather inelegant: I instantiate a whole new JRuby
runtime
and then use it as a regular Java object using the JRuby embed API. I
pass Ruby objects into it by Marshal.dump’ing them them to Java strings
and then Marshal.load’ing them inside the sub-JRuby, if that makes
sense.

Example here:

See the #with_ruby_container and #resolve methods. The sub-JRuby loads
a
.rb file (mini_aether/resolver) which is then free to load JARs that
won’t
contaminate the original JRuby runtime.

Hope that helps.


Patrick M.