Java 序列化完全未来字节码

Java 序列化完全未来字节码,java,serialization,lambda,java-8,completable-future,Java,Serialization,Lambda,Java 8,Completable Future,我想创建一个CompletableFuture链,将其作为字节码/参数序列化到磁盘,并在将来的某个时候再次运行它。例如: CompletableFuture<String> chain = new CompletableFuture<String>(); CompletableFuture<String> pos = chain; for (int ii = 0; ii < 4; ++ii) { final int val = ii;

我想创建一个
CompletableFuture
链,将其作为字节码/参数序列化到磁盘,并在将来的某个时候再次运行它。例如:

CompletableFuture<String> chain = new CompletableFuture<String>();

CompletableFuture<String> pos = chain;
for (int ii = 0; ii < 4; ++ii) {
    final int val = ii;
    pos = pos.thenApply( (s)->{ return s+" plus"+val;} );
}
pos = pos.thenApply( (s)->{ return "The final answer is "+s;} );

saveDisk( "chaindata.dat", chain, pos );
/////
// at some time in the future, perhaps in another program
Pair<CompletableFuture<String>,CompletableFuture<String>> newChain = loadFrom( "chaindata.dat" );
newChain.getA().complete("Hello");
String result = newChain.getB().get(); // should get hello with all post processing
// result==The final answer is Hello plus0 plus1 plus2 plus3
CompletableFuture链=新的CompletableFuture();
可完成的未来位置=链;
对于(int ii=0;ii<4;++ii){
最终int val=ii;
pos=pos.thenApply((s)->{returns+“plus”+val;});
}
pos=pos.thenApply((s)->{return“最终答案是”+s;});
存储盘(“chaindata.dat”,chain,pos);
/////
//在将来的某个时候,也许在另一个项目中
Pair newChain=loadFrom(“chaindata.dat”);
newChain.getA().complete(“Hello”);
字符串结果=newChain.getB().get();//应该得到所有后期处理的问候
//结果==最终答案是Hello plus0 plus1 plus2 plus3
当然,这方面的棘手问题是,即使字节码存储在当前类文件中(可通过
class.getResource()
检索),我也需要保存在链中设置的最终变量。
(参见上面的for循环
final int var=ii;

我未来的目标实际上是在一个从进程上运行链,该从进程具有大多数相同的类文件(但不是创建链的类文件) 我将编写字节码/数据,在从属进程上重新加载,然后运行它

如前所述,我相信在实例化时在循环中创建的最终变量是这个过程中的棘手部分。即。
pos=pos.thenApply((s)->{返回s+”加上“++
;})

有人对如何实现这一点有什么建议吗?

首先是一个警告,来自:

如果lambda表达式的目标类型及其捕获的参数是可序列化的,则可以使用该表达式。但是,与之类似,强烈反对lambda表达式的序列化

(重点是我的)

这个要求的问题是,
CompletableFuture
不可
序列化
,扩展它需要从
CompletableFuture
复制大量代码,因为您需要重写许多方法(如
thenApply()
)以使它们返回新的可序列化类型

但是,可以做的是序列化要执行的操作链。由于它基本上是一个将
CompletableFuture
转换为另一个的函数,因此最简单的方法是定义
SerializableFunction
类型:

private interface SerializableFunction<T, R> extends Serializable {
    R apply(T t);

    default <V> SerializableFunction<T, V> andThen(SerializableFunction<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }
}
并根据需要对其进行序列化:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(createChain());
oos.close();

ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
SerializableFunction<CompletableFuture<String>, CompletableFuture<String>> chain =
        (SerializableFunction<CompletableFuture<String>, CompletableFuture<String>>) ois.readObject();

CompletableFuture<String> future = new CompletableFuture<>();
CompletableFuture<String> newChain = chain.apply(future);
newChain.thenAccept(System.out::println);
future.complete("Hello");
ByteArrayOutputStream=newbytearrayoutputstream();
ObjectOutputStream oos=新的ObjectOutputStream(BAS);
oos.writeObject(createChain());
oos.close();
ByteArrayInputStream bais=新的ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois=新ObjectInputStream(BAI);
可序列化函数链=
(SerializableFunction)ois.readObject();
CompletableFuture=新的CompletableFuture();
CompletableFuture newChain=chain.apply(未来);
newChain.thenapt(System.out::println);
future.complete(“你好”);
输出:

最后的答案是Hello plus0 plus1 plus2 plus3

请注意,要使其正常工作,捕获的变量确实是序列化的(这由处理),但未序列化的JVM仍然需要在兼容版本中具有lambda代码本身


考虑到这一点,最好在专用结构中表示您的操作链,并处理该结构以远程重建该链。

您没有太多。我认为你唯一缺少的就是对程序本身的合理推理。我在对话中迷失了方向,我只能看到你的对话,因为它很难阅读。for循环是一个用于描述目的的示例程序。最终的目标是将一个完整的未来链运送到一个从进程,并在那里进行处理。这将是远程处理库的一部分。顺便说一句,我已经让远程代理类加载器工作了。我一直致力于提供远程运行的CompletableFutures。我想,那么,你是在要求我们给你一些提示,让你在信息发布后再发布。在这种情况下,你应该听取自己的建议。你在这里可能听不到太多,但这次我想你已经有了答案。对原来的问题做了一些编辑,让它更清楚一点。pos=pos.thenApply((s)->{returns+“plus”+val;});我不认为val(0…3)存储在字节码中,我也不知道如何以任何其他方式将其取出。添加到链中的每个项目都有自己的val值。我仍然认为您做得很好。
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(createChain());
oos.close();

ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
SerializableFunction<CompletableFuture<String>, CompletableFuture<String>> chain =
        (SerializableFunction<CompletableFuture<String>, CompletableFuture<String>>) ois.readObject();

CompletableFuture<String> future = new CompletableFuture<>();
CompletableFuture<String> newChain = chain.apply(future);
newChain.thenAccept(System.out::println);
future.complete("Hello");