PowerJob icon indicating copy to clipboard operation
PowerJob copied to clipboard

powerjob在openj9等无jfr环境下运行存在异常

Open 123shang60 opened this issue 2 years ago • 0 comments

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 image image

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相关功能,从而引起启动异常

123shang60 avatar Mar 23 '22 07:03 123shang60