2014-11-05 5 views
0

Я пытаюсь создать сериализуемую реализацию интерфейса динамически динамически, которая может быть отправлена ​​по проводу, где ее можно десериализовать и выполнить с помощью args. Я создал анонимную реализацию интерфейса с использованием карты, но это не сработает при сериализации.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 

Я не уверен, если заводной закрытие компилируется на имя случайного класса, которое сделало бы невозможным десериализации даже если он получает сериализации. Есть ли способ сделать это?

+2

В чем исключение? –

+0

Я использую https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/SerializationUtils.html и странно получаю java.io.NotSerializableException: X ie top level class :( – FUD

+0

На самом деле, если я делаю «X реализует Ser ..», то я могу сериализовать его, но при десериализации я получаю java.lang.ClassNotFoundException: X $ _closure1, что имеет смысл. Так что это может быть сделано некоторыми другой обман? – FUD

ответ

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, но вы думаете, что это сработает, когда i отправить сериализованный объект по проводу? С другой стороны, даже если у меня есть загрузчик классов, у него не будет таких классов (например, закрытие), определенных для сериализации. – FUD

+0

Не знаю, действительно. Вам нужно продолжить расследование. – Opal

0

Если вы используете groovy-io (https://github.com/jdereg/groovy-io), для их сериализации вам не потребуется реализовывать Serializable на ваших классах.

0

Согласно моему собственному ограниченному исследованию, я пришел к выводу, что в jvm нет стандартной/популярной библиотеки, которая могла бы пилить код, как в python, который был требованием, которым я был прежде всего после. Есть несколько способов сделать это через загрузчики классов URL и т. Д., Но с некоторыми сложностями. В итоге я просто отправил строку кода и перекомпилировал ее, когда это необходимо на нескольких машинах.

Смежные вопросы