PowerJob
PowerJob copied to clipboard
powerjob在openj9等无jfr环境下运行存在异常
Describe the bug
当我尝试在 jdk-11.0.14.1+1_openj9-0.30.1
环境下启动powerjob程序时,powerjob提示了如下的错误:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
Caused by: java.lang.NoClassDefFoundError: jdk.jfr.Event
at java.base/java.lang.ClassLoader.defineClassImpl(Native Method)
at java.base/java.lang.ClassLoader.defineClassInternal(ClassLoader.java:481)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:442)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:1110)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:898)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:806)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:764)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:1086)
at akka.remote.artery.jfr.JFRRemotingFlightRecorder.transportStarted(JFRRemotingFlightRecorder.scala:24)
at akka.remote.artery.ArteryTransport.start(ArteryTransport.scala:372)
at akka.remote.RemoteActorRefProvider.init(RemoteActorRefProvider.scala:261)
at akka.actor.ActorSystemImpl.liftedTree2$1(ActorSystem.scala:1026)
at akka.actor.ActorSystemImpl._start$lzycompute(ActorSystem.scala:1022)
at akka.actor.ActorSystemImpl._start(ActorSystem.scala:1022)
at akka.actor.ActorSystemImpl.start(ActorSystem.scala:1045)
at akka.actor.ActorSystem$.apply(ActorSystem.scala:272)
at akka.actor.ActorSystem$.apply(ActorSystem.scala:316)
at akka.actor.ActorSystem$.apply(ActorSystem.scala:290)
at akka.actor.ActorSystem$.create(ActorSystem.scala:213)
at akka.actor.ActorSystem.create(ActorSystem.scala)
at tech.powerjob.server.remote.transport.starter.AkkaStarter.init(AkkaStarter.java:65)
at tech.powerjob.server.PowerJobServerApplication.main(PowerJobServerApplication.java:36)
... 8 more
Caused by: java.lang.ClassNotFoundException: jdk.jfr.Event
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:766)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:1086)
... 32 more
powerjob 程序无法工作,同时,直接依赖于powerjob-worker-spring-boot-starter 组件的程序也因为同样的问题无法运行
To Reproduce
安装官方版本的 jdk-11.0.14.1+1_openj9-0.30.1
,启动powerjob即可稳定复现
Expected behavior 期望powerjob程序可以在openj9等环境下运行
Environment
- PowerJob Version: PowerJob-V4.0.1
- Java Version: jdk-11.0.14.1+1_openj9-0.30.1
- OS: ubuntu 20.04
Screenshots
Additional context 经过分析,powerjob无法启动的原因应该是因为akka组件引入了jfr,导致了openj9下的启动异常。分析akka源码,发现官方在引入jfr时的代码如下:
private[akka] object FlightRecorderLoader {
def load[T: ClassTag](casp: ClassicActorSystemProvider, fqcn: String, fallback: T): T = {
val system = casp.classicSystem.asInstanceOf[ExtendedActorSystem]
if (JavaVersion.majorVersion >= 11 && system.settings.config.getBoolean("akka.java-flight-recorder.enabled")) {
// Dynamic instantiation to not trigger class load on earlier JDKs
system.dynamicAccess.createInstanceFor[T](fqcn, Nil) match {
case Success(jfr) =>
jfr
case Failure(ex) =>
system.log.warning("Failed to load JFR flight recorder, falling back to noop. Exception: {}", ex.toString)
fallback
} // fallback if not possible to dynamically load for some reason
} else
// JFR not available on Java 8
fallback
}
}
观察powerjob-server在启动akka ActorSystem 时,代码如下:
// 启动 ActorSystem
Map<String, Object> overrideConfig = Maps.newHashMap();
String localIP = NetUtils.getLocalHost();
overrideConfig.put("akka.remote.artery.canonical.hostname", localIP);
overrideConfig.put("akka.remote.artery.canonical.port", port);
actorSystemAddress = localIP + ":" + port;
log.info("[PowerJob] akka-remote server address: {}", actorSystemAddress);
Config akkaBasicConfig = ConfigFactory.load(RemoteConstant.SERVER_AKKA_CONFIG_NAME);
Config akkaFinalConfig = ConfigFactory.parseMap(overrideConfig).withFallback(akkaBasicConfig);
actorSystem = ActorSystem.create(RemoteConstant.SERVER_ACTOR_SYSTEM_NAME, akkaFinalConfig);
actorSystem.actorOf(Props.create(FriendRequestHandler.class), RemoteConstant.SERVER_FRIEND_ACTOR_NAME);
log.info("[PowerJob] PowerJob's akka system started successfully, using time {}.", stopwatch);
overrideConfig
并没有为 akka 配置jfr是否可用的配置项,powerjob貌似也没有提供可以通过配置文件禁用akka jfr功能的能力。因此,在java11 + openj9的环境下,akka会按照默认配置加载jfr相关功能,从而引起启动异常