动态生成的 Hazelcast 用户代码部署 类

Hazelcast User Code Deployment with dynamically generated classes

我有一个应用程序,它由一个使用大量运行时字节码生成 (asm) 的 hazelcast 节点网格组成。具体来说,我正在根据用户输入的过滤器表达式动态构建 predicate<> Java 函数。我想将谓词存储在映射中,以便它们在整个集群中可用而无需重新编译。谓词不是唯一的例子。我还有 ORM 样式映射 classes,它们是在运行时生成的,需要在集群中共享。这些 class 由名为 DynamiClassLoader 的自定义 classloader 加载。

起初我无法将自定义生成的 classes 存储在 Hazelcast IMaps 中,出现 ClassNotFoundexception。但是,我发现如果使用 Config.setClassLoader() 告诉 Hazelcast 使用我的自定义 DynamicClassLoader,那么它能够找到我的动态 classes 并在本地成员中使用它们,因此我在序列化和反序列化实例时没有问题我的自定义 classes 在同一成员的 IMaps 中。

但是,我仍然无法反序列化由其他成员插入到映射中的谓词实例。我已经启用了 UserCodeDeployment 并在我的调试器中逐步执行代码以确认如果它在本地找不到 class 那么它正在命中 UserCodeDeploymentClassLoader.java 并且在 classNotFoundException 上它正在继续检查其他classes 的成员,但找不到他们。我一直无法发现这是如何工作的。它似乎在内部地图中查找可以找到任何给定 class 的成员,但它没有在其中找到我的 classes。我相信它会向其他成员分派一个操作,然后寻找 class,但在这种情况下,我的自定义 classloader 似乎没有被使用,所以它无法找到我的自定义 [=25] =]es.

如何使动态生成的 classes 与 Hazelcast 上的 UserCodeDeployment 一起工作?有没有什么方法可以 'register' 我的动态 classes 与会员代码服务或类似的东西?

谢谢, 特洛伊

经过大量调试,我终于弄明白了。原来Hazelcast中对目标成员查找class的操作调用了ClassDataProvider.java中的loadBytecodeFromParent()。这会在 classloader:

上使用 getResourceAsStream 查找 .class 文件
String resource = className.replace('.', '/').concat(".class");

...

is = parent.getResourceAsStream(resource);

这基本上是在文件系统上查找 class 文件。由于我的动态 classes 完全在内存中,因此没有 .class 文件资源可供它查找。

我解决了这个问题,方法是在我的 DynamicClassLoader 中放置一个散列映射以保留生成的字节码,并在进一步查看之前将 getResourceAsStream 覆盖为 return 该字节码。现在可以使用了!