-
-
Notifications
You must be signed in to change notification settings - Fork 925
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unable to override classpath for ScriptingContainer #3461
Comments
@r6p the only thing you can set with the ScriptingContainter is the the classloader: `````` scriptingContainer.setClassLoader(somehting)``` and this classloader needs to contain the org.jruby:jruby dependencies (or jruby-complete). so you can always get the "jars" and setup a clean classloader hierarchy with only ONE jruby in it. if you use the you also can try to look at the jruby classloader before going to the parent but this one has problems with nokogiri gem (and maybe others). but there is a change to this solves your problem:
|
@mkristian Thanks. But, I actually already tried what you suggested i.e. IsolatedScriptingContainer#setClassLoader but had no luck with that. Adding scriptingContainer.setClassloaderDelegate#setClassloaderDelegate(false) doesn't seem to change the behavior the parent classloader is always at play. Here's what I tried, if I am doing something wrong or don't have the order correct let me know. Keep in mind that this did work when testing via rspec, but not at runtime in my target deployment environment.
|
but this will not work if jruby is the bootstrap classloader which for example bin/jruby from the binary distribution does for faster loading. |
@mkristian |
@r6p this sounds like this is wrong :( where is this jruby-complete.jar located ? which classloader ? ClassLoader.getSystemClassLoader() ? take this |
@mkristian, both our jar with 9K embedded and the conflicting older jruby-complete.jar are in the SystemClassLoader. That is why it seems that #getParent() should work as you describe. I've also tried the code below and within an 'rspec' context the resulting $CLASSPATH still contains jars that come from the SystemClassLoader that I had filtered out when creating the isolatedClassLoader. Let me try it in the true runtime context to see if anything is different there.
|
@r6p what is the output of this ? FYI $CLASSPATH are the urls from now I had the thought that the problem might be that per default those ScriptingContainer create singleton runtime, i.e. uses the global runtime which might be the reason things get shared between the two runtime (are there two runtimes ? it sounds like what you described so far). |
@r6p hey any luck with this ? I know it is tricky and remote debugging is difficult but actually I am sure there is a way of getting it to work (as I had similar cases in the past). |
@mkristian, I've tried a few things and none worked. The last major effort I made was to use an IsolatedScriptingContainer created via reflection, with setClassLoaderDelegate(false), and setClassLoader(customClassLoader) being called to then launch the Ruby code to kick's off our Map/Reduce jobs. Doing this produces a number of problems associated with code loading from multiple class loaders, i.e. the same types not being equivalent as they could have been loaded under multiple class loaders mostly as it is related to Hadoop dependencies (see Stacktrace below). I am going to try to generate a simple test case that reproduces the problem and post back. With regards to your thoughts own two runtimes, can you give me more information on how I can either ensure that there are two separate Runtimes or verify that a single runtime is being shared? Is there a JRuby test case that validate that each ScriptingContainer has a unique Runtime? If, so can you point me to that? Any help working through this would be appreciated, it is blocking our upgrade to JRuby 9030 at the moment.
|
@mkristian, so I was able to get something working using multiple classloaders (not ideal), but the key was to create a new classloader that doesn't include the conflicting jruby-complete jar in that classloader, then load the All this was required to avoid a YAML conflict when doing I "think" this bit of irb code illustrates the root issue that I was facing.
|
@headius @enebo, any chance I can get you guys to have a look at this as well. I basically have two colliding versions of jruby-complete on the classpath that I don't control. The primary version that I want to use is bundled into my own jar. But there is another older version of the jruby-complete jar on the classpath. I basically want all resources for 9000 from stdlib and site_ruby to load from my jar like |
@r6p when you talked about classpath and mean |
@mkristian this happens/is true whether it is |
@r6p what I said is around the java.class.path - let me try this. |
@r6p I just played around a bit with having both jruby-complete-17.19 and jruby-complete-9.0.4.0 on the java.class.path. this starts using org.jruby.gen.org$jruby$ext$psych$PsychParser$POPULATOR which does not exists on jruby-9k anymore, and this uses methods which only exists in jruby-1.7.x. yes, there is no way to run both jrubies in one classloader |
@mkristian, ok many thanks for "all" your help. Is it worthy of a technical feature request to be able to isolate the ScriptingContainer environments to a single version of JRuby? Or is this just too hard or impossible to do? And I mean doing so w/o having to create a custom ClassLoader. I.e. first version of the the JRuby jar on the classpath containing ScriptingContainer or IsolatedScriptingContainert wins and is used ignoring any other versions later on the classpath. |
@rp6 the problem here is really that you have two versions of the same library on classloader - in general this is source for all kind of classloader problems: NoSuchMethodError, ClassCastException. this is true for any library. having a classpath there is an order and you could make something here but putting the same jars into WEB-INF/lib directory there is no order - maybe the lexical or creation time. IMO there is no way to achieve this. |
@mkristian ok thanks again for all your help. |
@r6p closing issue since as far I understood the problem there nothing we can do on the JRuby side of things |
In one of my target deployment environments the Java classpath contains another older version of JRuby. Our application is making use of ScriptingContainer to execute Ruby code and when it goes to load YAML files it uncovers the classpath collision between the two versions of JRuby with an error related to Psych. To workaround this issue, I've attempted to make use of ScriptingContainer#setLoadPaths to control the classpath provided to the Ruby "environment" by excluding the older jruby-complete jar from the classpath , but it doesn't seem to take, it always inherits the classpath from the parent Java environment.
Maybe this isn't supposed to work in this way, but the documentation below led me to believe this would be possible. If this isn't a bug, is there another way to override the CLASSPATH or class loading behavior to exclude certain jars at runtime?
The text was updated successfully, but these errors were encountered: