我在一次漫长的牦牛剃须过程中将应用程序迁移到 Boot 2.4.1 和 Hazelcast 4.0.3 时发现了这一点。
当您从 jar 运行它时会失败:
@SpringBootApplication
public class IssueApplication {
public static void main(String[] args) {
SpringApplication.run(IssueApplication.class, args);
}
@Bean
CommandLineRunner runner(HazelcastInstance hazelcast) {
IMap<String, Foo> sessions = hazelcast.getMap("foos");
return args -> {
sessions.set("foo", new Foo("foo"));
System.err.println(sessions.get("foo"));
sessions.getAsync("foo").whenComplete((u, t) -> System.err.println(u)).toCompletableFuture().get();
};
}
}
class Foo implements Serializable {
private String value;
public Foo() {
}
public Foo(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return "Foo [value=" + this.value + "]";
}
}
当您在 IDE 中运行或使用java -classpath ...
.问题是 HazelcastThread.crrentThread().getContextClassLoader()
默认使用 ,而在异步后台线程中,这JarLauncher
不是AppClassLoader
.
我用这个解决了这个问题
@Bean
Config hazelcastConfig() {
Config config = new Config();
config.setClassLoader(SpringApplication.class.getClassLoader());
...
return config;
}
但这个问题实际上更通用——可能任何使用 JDK fork-join 实用程序的库最终都会得到相同的类加载器。