Java ASM是否可以使用远程执行客户端?

Java ASM是否可以使用远程执行客户端?,java,lambda,java-bytecode-asm,Java,Lambda,Java Bytecode Asm,我希望为我的应用程序创建自定义远程执行客户端。客户机可能看起来像这样: interface Client { <T> T computeRemotely(Function<List<MyBigObject>, T> consumer) } Client client = new Client(); Integer remoteResult = client.computeRemotely(list -> { Integer resul

我希望为我的应用程序创建自定义远程执行客户端。客户机可能看起来像这样:

interface Client {

    <T> T computeRemotely(Function<List<MyBigObject>, T> consumer)
}
Client client = new Client();
Integer remoteResult = client.computeRemotely(list -> {
    Integer result = -1;

    // do some computational work here.

    return result;
});
这意味着我需要以某种方式从客户端获取lambda,将其发送到服务器,运行函数(传入一个真正的
列表
)并将结果发送回

值得注意的是,对使用我的客户机库的一个限制是,您不能在该lambda中使用JDK之外的任何东西并期望它工作(因为类可能不在服务器上的类路径上)……但是我希望它们能够使用任何JDK类将自己的数据引入计算

现在,我不能仅仅序列化
函数
lambda,因为它就像lambda所在的任何类的内部客户端一样进行序列化,而lambda不在服务器的类路径上

因此,我一直在研究ASM,看看这是否可行。考虑到我以前从未做过字节码操作,我只想检查一下我所说的是否正确:

  • 我可以使用ASM转换来读取lambda所在的类
  • 使用方法访问者,获取方法字节,将它们发送到服务器
  • 使用ASM从字节创建实例并执行它
鉴于lambda类似于一个匿名的内部类,我猜我也必须在其中进行某种方法重命名


这大概是正确的,还是我的判断完全错了?

请注意,lambdas可以从上下文中访问所有不可变的值。因此,您需要禁止访问外部值(这将严重限制您的解决方案的有效性),或者标识它们并发送这些值的表示(这会遇到您提到的问题;它们的实现可能在服务器类路径之外)

因此,即使您发送方法表示(您甚至不需要ASM;您可以直接从类加载器获取资源),它也不适用于一般情况

编辑:根据你的评论,它可以工作。你需要将一个类与

  • 上下文属性作为最终字段
  • 具有所有字段参数的构造函数(在构造时将在此处传递反序列化的值)
  • lambda方法-请参阅

    • 分析运行时生成的lambda表达式类没有意义。它们有一个非常简单的结构,在序列化时会显示出来。在序列化过程中,它们将被一个实例替换,该实例包含您可能收集到的所有信息,尤其是:

      • 这将被调用
      关键是目标方法。对于lambda表达式(与方法引用不同),目标方法是驻留在包含lambda表达式的类中的合成方法。该方法是私有的,顺便说一下,这就是为什么试图复制调用该方法的类注定要失败的原因,需要特殊的JVM交互才能创建这样的类。但重要的一点是,您需要远程端的目标方法来执行它,特定于lambda的运行时类是不相关的。如果你有目标方法,你可以


      当然,您可以使用ASM分析目标方法的代码,将其(以及所有依赖项)传输到远程端,但请注意,这与传输任意
      函数
      实现没有什么不同;事实上,通过lambda表达式创建的运行时生成的类中有一层对您没有任何帮助。

      我计划做的是允许访问JDK中的任何不可变值(即列表、集合等),但不允许访问自定义类。我不熟悉lambda实现,因此,不确定是否需要重命名。但如果是这样的话,您需要在任何地方重命名—特别是在方法的字节码中—对重命名类的字段和方法的任何访问。也许没那么难,但记住这一点很好。有Remapper和org.objectweb.asm.commons.RemappingClassAdapter类,它们似乎能够处理重命名。