1

I am writing simple DSL in JRuby, for a Java library. Some object created in JRuby are passed to the Java code, processed and returned back to JRuby. I am using JRuby 1.7.8.

At some point while processing the objects created in JRuby need to be serialized and deserialized by the Java library (to perform deep cloning). Here is where the problem occurs. Appart from String and a plain Object it seems not possible to serialize in Java objects created in JRuby.

For example, while serializing to an empty Hash object I get:

IOError: org.jruby.RubyHash$RubyHashEntry
    load at org/jruby/RubyKernel.java:1103
         at /usr/local/rvm/gems/jruby-1.7.8/bin/pry:23
    eval at org/jruby/RubyKernel.java:1123
 (root) at /usr/local/rvm/gems/jruby-1.7.8/bin/jruby_executable_hooks:15

for [ "asd" ] i get:

IOError: org.jcodings.specific.UTF8Encoding
    load at org/jruby/RubyKernel.java:1103
         at /usr/local/rvm/gems/jruby-1.7.8/bin/pry:23
   eval at org/jruby/RubyKernel.java:1123
  (root) at /usr/local/rvm/gems/jruby-1.7.8/bin/jruby_executable_hooks:15

I found some posts about it (e.g. here and here), but they are all quite old and do not explain anything about future plans. It seems to me an important limitation when considering integration of Ruby and Java.

Now I'm serializing my objects to JSON on Ruby side, and deserializing them from JSON when they are returned. It works, but this comes with significant efficiency penalty.

So the questions are:

  1. Is it possible to somehow make Ruby objects Serializable in Java? If not, will it be possible in near future?
  2. Does anybody now a better (faster) workaround then the JSON solution I desribed above?

EDIT:

This spec in JRuby repo suggests that there is something going on concerning the serialization. However, its still 2 years old and does not explain serialization policy of other objects.

7
  • 1
    Ouch, cloning using serialization sounds painful. I know nothing about Ruby, but maybe just code it yourself? Like, recursively returning a clone of all data with reflection (still painful)? Still that should be a lot faster. Commented Dec 13, 2013 at 20:29
  • The cloning is in Java, not in Ruby. This is a completely different discussion, but the serialization is how it is done. The solution with serialization is recommended for a long time. See page 45 in this book (for old reference): github.com/FelixRovinVincent/reference/blob/master/… or e.g. this question: stackoverflow.com/questions/64036/… Commented Dec 13, 2013 at 21:34
  • 1
    It may be recommended by some people, but it still feels disgusting to even consider (excuse me, it's just weird) this in my program/app. You may wan't to have a look at this project. Commented Dec 13, 2013 at 21:37
  • Yes, I've just hit that and also this: matthicks.com/2008/05/fastest-deep-cloning.html -- very interesting too. Maybe it is a way to get out of the serialization problem while cloning. I must reconsider this. Thanks a lot, Your comment put me on a new track, I would certainly not consider myself. Commented Dec 13, 2013 at 21:45
  • Unfortunately, the cloner project: code.google.com/p/cloning mentioned in the comment above by @StackOverflowException seems incompatible with JRuby. If I try to deepClone a custom JRuby object in Java using this library JVM crashes. The same happens e.g. for most Hashes... anything that is not immutable... Commented Jan 3, 2014 at 21:39

1 Answer 1

1

The problem with deep cloning JRuby objects is that they include recursive references all the way up to the Ruby interpreter. So if you try to recursively clone an object you end up cloning the whole Ruby world and this must end up as a disaster... At least that's how it was in 2013.

As suggested by @tilpner I gave up cloning by serialization and started using this: https://github.com/kostaskougios/cloning. First advantage is efficiency -- it's much faster then serialization. Second and more important here is that you have much more control over what is being cloned and what is omitted. Thus, by trial and error I came to the following configuration that allowed for correct cloning of Ruby objects. I don't remember all details now, so I also include all my comments as found today in this code. Hope it will be helpful.

        // prevent from cloning whole JRuby mess
        cloner.dontClone(Class.forName("org.jruby.RubyClass"));
        cloner.registerImmutable(Class.forName("org.jruby.RubySymbol"));

        // WRz 2014-10-27
        // prevent cloning the whole mess with JRuby Proc object
        // FIXME: this does not copy bock's binding! That means that 
        // the cloned Procs share the same closure! Unfortunatelly
        // the struggling  to do it better (see below) gave no solution...
        // Deep cloning the Block pulls an awful lot of stuff! I cannot handle this
        // and this or the other way whole JRuby, java.reflection and more gets cloned...
        cloner.dontClone(Class.forName("org.jruby.runtime.Block"));
        // JRuby's active Enumerator caused cloning of whole mess without this:
        cloner.dontClone(Class.forName("org.jruby.Ruby"));

        /*
        cloner.dontClone(Class.forName("org.jruby.MetaClass")); // singleton!?
        cloner.dontClone(Class.forName("org.jruby.parser.LocalStaticScope"));
        cloner.dontClone(Class.forName("org.jruby.ast.executable.RuntimeCache"));
        cloner.dontClone(Class.forName("org.jruby.Ruby"));
        cloner.dontClone(Class.forName("java.lang.reflect.Constructor"));
        cloner.dontClone(Class.forName("org.jruby.javasupport.proxy.JavaProxyConstructor"));            
        */

As you see that's how it was almost a year ago. Later I moved all my implementation to Ruby and was able to make it much more faster, so I lost track of this problem.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot for your help and taking the time. I'll take a good look when I get to work

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.