2014-11-05 112 views
0

我想在groovy中动态地创建一个可序列化的接口实现,它可以通过网络发送,它可以被反序列化并用args执行。我使用map创建了匿名接口实现,但在序列化时失败。没有类定义的Groovy序列化

gcloader = new ​GroovyClassLoade​r() 
script = "class X { public def x = [call: {y -> y+1}] as MyCallable }"​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​ 
gclass = gcloader.parseClass(script) 
x = gclass.newInstance().x​​ 
// serialzing x fails 

我不知道,如果一个Groovy闭包被编译为一个随机的类名,这将使它不可能,即使它被序列化反序列化。有没有办法做到这一点?

+2

什么是例外? – 2014-11-05 14:39:13

+0

我使用的是https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/SerializationUtils.html,奇怪的是我得到java.io.NotSerializableException:X ie顶级类:( – FUD 2014-11-05 14:42:56

+0

其实如果我做“X实现SER ..”然后我能够序列化它,但在反序列化我得到java.lang.ClassNotFoundException:X $ _closure1,这是有道理的。所以这可以通过一些其他的诡计? – FUD 2014-11-05 14:45:48

回答

0

下面是一段代码,可能会有所帮助:

import groovy.lang.GroovyClassLoader 

def gcLoader = new GroovyClassLoader() 
def script = """ 
class X implements Serializable { 
    public def x = [ 
     call: { y -> y + 1 } 
    ] 
}""" 
def cls = gcLoader.parseClass(script) 
def inst = cls.newInstance().x 

def baos = new ByteArrayOutputStream() 
def oos = new ObjectOutputStream(baos) 

oos.writeObject(inst) 

def serialized = baos.toByteArray() 

def bais = new ByteArrayInputStream(serialized) 
def ois = new CustomObjectInputStream(bais, gcLoader) 
inst = ois.readObject() 

assert 2 == inst.call(1) 

public class CustomObjectInputStream extends ObjectInputStream { 
    private ClassLoader classLoader 

    public CustomObjectInputStream(InputStream ins, ClassLoader classLoader) throws IOException { 
     super(ins) 
     this.classLoader = classLoader 
    } 

    protected Class<?> resolveClass(ObjectStreamClass desc) throws ClassNotFoundException { 
     return Class.forName(desc.getName(), false, classLoader) 
    } 
} 

基本上,你需要的ObjectInputStream实例定制ClassLoader

+0

谢谢@Opal,但你认为这会工作,当我通过线路发送序列化的对象?另一方面,即使我有一个类加载器,它也不会有为序列化定义的类(例如闭包) – FUD 2014-11-06 03:42:19

+0

不知道真的,你需要做进一步的调查。 – Opal 2014-11-06 03:54:29

0

根据我自己的有限研究,我得出的结论是,在jvm中没有标准/流行的库,它可以像python一样腌制代码,这是我主要以后的要求。有一些方法可以通过URL类加载器来完成,但有一些固有的复杂性。我最终只是简单地发送代码字符串并在需要时在多台机器上重新编译它。