2013-12-11 42 views
1

我在JRuby中爲Java庫編寫簡單的DSL。一些在JRuby中創建的對象被傳遞給Java代碼,處理並返回給JRuby。我正在使用JRuby 1.7.8。使用Java代碼序列化JRuby對象

在某些點在處理JRuby中創建的對象需要被串行化,並通過Java庫反序列化(執行深度克隆)。這是問題發生的地方。來自String和一個普通對象的Appart似乎無法在JRuby中創建的Java對象中進行序列化。

例如,當序列化到一個空的Hash對象,我得到:

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 

[ "asd" ]我得到:

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 

我發現一些職位,它(如herehere),但他們都很古老,並沒有解釋未來計劃的任何內容。在考慮Ruby和Java的集成時,我認爲這是一個重要的限制。

現在我在序列化Ruby端我的對象,JSON和JSON從反序列化他們返回時,他們。它可以工作,但這會帶來顯着的效率損失。

所以問題是:

  1. 是否有可能以某種方式使紅寶石的Java對象序列化?如果不是,將來有可能嗎?
  2. 有沒有人現在更好(更快)的解決方法,然後我上面描述的JSON解決方案?

編輯:

This規範JRuby中回購表明,有一些事情有關序列化。但是,它仍然2歲,並沒有解釋其他對象的系列化政策。

+1

Ouch,使用序列化克隆聽起來很痛苦。我對Ruby一無所知,但也許只是自己編碼吧?比如,用反射遞歸地返回所有數據的克隆(仍然很痛苦)?仍然應該快得多。 – tilpner

+0

克隆是在Java中,而不是在Ruby中。這是一個完全不同的討論,但序列化是如何完成的。序列化解決方案推薦使用很長時間。參見第45頁本書(舊參考):https://github.com/FelixRovinVincent/reference/blob/master/Design%20Patterns/The%20Design%20Patterns%20Java%20Companion.pdf或如這個問題:http://stackoverflow.com/questions/64036/how-do-you-make-a-deep-copy-of-an-object-in-java – wrzasa

+1

可能被一些人推薦,但它仍然在我的程序/應用程序中,即使考慮(對不起,這只是奇怪)而感到噁心。你可能不想看看[這個項目](http://code.google.com/p/cloning/)。 – tilpner

回答

1

深克隆的JRuby對象的問題是,它們包括遞歸引用所有到Ruby解釋器的方式。所以如果你試圖遞歸地克隆一個對象,那麼你最終會克隆整個Ruby世界,而這必然會成爲一場災難......至少在2013年是如此。

正如@tilpner所建議的,我放棄了克隆通過序列化並開始使用這個:https://github.com/kostaskougios/cloning。第一個優點是效率 - 它比序列化快得多。其次,更重要的是,你對被克隆的內容以及被省略的內容擁有更多的控制權。因此,通過試驗和錯誤,我得到了以下配置,可以正確克隆Ruby對象。我現在不記得所有的細節,所以我還包括了今天在此代碼中發現的所有評論。希望它會有所幫助。

 // 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"));    
     */ 

正如你看到的那樣,這是近一年前的情況。後來我把所有的實現都移到了Ruby上,並且能夠更快地實現它,所以我忘記了這個問題。

+0

非常感謝您的幫助和花時間。當我開始工作時,我會好好看看 –