我有一个应用程序,该应用程序由使用大量运行时字节码生成(asm)的hazelcast节点网格组成。具体来说,我是根据用户输入的过滤器表达式动态构建谓词<> Java函数。我想将谓词存储在映射中,这样它们就可以在整个群集中使用,而不必重新编译。谓词不是唯一的实例。我还具有在运行时生成的ORM样式映射类,需要在整个集群之间共享。这些类由称为DynamiClassLoader的自定义类加载器加载。
起初,我无法将自己的自定义生成的类存储在Hazelcast IMaps中,从而得到ClassNotFoundexception。但是,我发现如果告诉Hazelcast通过Config.setClassLoader()使用我的自定义DynamicClassLoader,那么它能够找到我的动态类并在本地成员中使用它们,因此在IMaps中序列化和反序列化自定义类的实例时,我没有问题相同的成员。
但是,我仍然无法反序列化由其他成员插入到地图中的谓词实例。我已启用UserCodeDeployment并在调试器中逐步执行代码以确认是否无法在本地找到该类,然后单击UserCodeDeploymentClassLoader.java并在classNotFoundException上继续检查该类的其他成员,但找不到它们。我还无法发现它到底是如何工作的。它似乎在内部映射中查找可以找到任何给定类的成员,并且在其中找不到我的类。我相信它将分派一个操作给其他成员然后寻找该类,但是在这种情况下,它看起来好像没有使用我的自定义类加载器,因此无法找到我的自定义类。
如何使动态生成的类与Hazelcast上的UserCodeDeployment一起使用?是否可以通过成员的代码服务或类似的方式“注册”动态类?
谢谢, 特洛伊。
答案 0 :(得分:0)
经过广泛的调试,我终于弄明白了。事实证明,在Hazelcast上对目标成员进行查找类的操作在ClassDataProvider.java中调用loadBytecodeFromParent()。这会在类加载器上使用getResourceAsStream查找.class文件:
String resource = className.replace('.', '/').concat(".class");
...
is = parent.getResourceAsStream(resource);
基本上在文件系统上查找类文件。由于我的动态类完全在内存中,因此没有可供查找的.class文件资源。
我解决了这个问题,方法是在我的DynamicClassLoader中放置一个哈希图以保留生成的字节码,并覆盖getResourceAsStream以在该字节码可用时返回该字节码,然后再进行进一步查找。现在可以了!