【问题标题】:Running Java 9 application with docker doesn't work - UnsupportedClassVersionError使用 docker 运行 Java 9 应用程序不起作用 - UnsupportedClassVersionError
【发布时间】:2018-04-11 15:39:45
【问题描述】:

我将应用程序从 Java 8 更改为 Java 9。 将 Windows 系统环境变量(路径)和 JAVA_HOME 更改为 Java 9 (jdk-9.0.1)。

在 IDE (IntelliJ) 中运行应用程序时,它运行良好。它也可以毫无问题地与 sbt 一起编译。仅使用 docker 运行应用程序是行不通的。

应用程序似乎使用 Java 9 成功编译,但 docker 尝试使用 Java 8 运行它(这是我从异常消息中读取的内容)。

命令:

sbt docker:publish

docker run --rm -p 9000:9000 eu.gcr.io/the-repository-name/the-image-name:1.0

我收到以下错误:

Exception in thread "main" java.lang.UnsupportedClassVersionError: 
    Module has been compiled by a more recent version of the 
    Java Runtime (class file version 53.0), this version of the 
    Java Runtime only recognizes class file versions up to 52.0
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at play.api.inject.Modules$.locate(Module.scala:119)
        at play.api.inject.guice.GuiceableModule$.loadModules(GuiceInjectorBuilder.scala:276)
        at play.api.inject.guice.GuiceApplicationBuilder$.$anonfun$$lessinit$greater$default$9$1(GuiceApplicationBuilder.scala:30)
        at play.api.inject.guice.GuiceApplicationBuilder.applicationModule(GuiceApplicationBuilder.scala:102)
        at play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:185)
        at play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:137)
        at play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)
        at play.core.server.ProdServerStart$.start(ProdServerStart.scala:51)
        at play.core.server.ProdServerStart$.main(ProdServerStart.scala:25)
        at play.core.server.ProdServerStart.main(ProdServerStart.scala)

Docker 使用 Java 9 我该怎么办?


java --version
java 9.0.1
Java(TM) SE Runtime Environment (build 9.0.1+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.1+11, mixed mode)

docker version
Client:
 Version:      17.10.0-ce
 API version:  1.33
 Go version:   go1.8.3
 Git commit:   f4ffd25
 Built:        Tue Oct 17 19:00:02 2017
 OS/Arch:      windows/amd64

Server:
 Version:      17.10.0-ce
 API version:  1.33 (minimum version 1.12)
 Go version:   go1.8.3
 Git commit:   f4ffd25
 Built:        Tue Oct 17 19:05:23 2017
 OS/Arch:      linux/amd64
 Experimental: true
  • 播放版本:2.6.7
  • Scala 版本 2.12.4
  • SBT 版本:1.0.2
  • sbt-native-packager: 1.3.1

【问题讨论】:

  • 您可能需要提及使用的库的版本。这里的主要问题是将 Java 9 代码编译为 Java 8 代码的核心库。相关Unable to process file module-info.class within a Java9 project results in ClassFormatException
  • @nullpointer 你能进一步解释一下吗?该应用程序在我的 IDE 中运行良好,它使用 Java 9(不是 Java 8)编译时没有问题。仅当我使用 docker 发布并运行它时,它才不起作用。该错误表明该项目是使用 java 9 编译的,但 docker 使用的是 java 8。
  • 我猜当你“发布”和“运行”时,你可能正在使用一些可传递的核心库,它可能试图访问类文件,就好像它们是 java 8 类一样,而它们已使用 Java 9 编译。为了进一步调试,您可能需要说明完整的日志,如问题中所述,在发布和运行期间遵循的详细步骤......最疯狂的猜测 ASM 一直是负责我在不同库中目睹的少数此类实例的库。跨度>

标签: docker sbt playframework-2.0 java-9 sbt-native-packager


【解决方案1】:

该错误表示您正尝试在旧版 Java(8 类版本 52.0)中运行使用较新版本 Java(9 类版本 53.0)编译的代码。所以,你的 docker 镜像可能已经安装了 Java 8。让我们做一些侦探工作。 :-)

如果我理解正确,您正在使用 sbt-native-packager 生成 Docker 映像。如果是这样,sbt-native-packager 使用openjdk:latest 图像作为基础图像,你可以在这里看到:

https://github.com/sbt/sbt-native-packager/blob/v1.3.1/src/main/scala/com/typesafe/sbt/packager/docker/DockerPlugin.scala#L69

1.3.1 版本是 Play 2.6.7 使用的版本,您也可以在此处看到:

https://github.com/playframework/playframework/blob/2.6.7/framework/project/plugins.sbt#L8

问题在于openjdk:latest 图像使用Java 8。您可以通过查看latest 代码linked at the image page 来确认。代码如下:

https://github.com/docker-library/openjdk/blob/a893fe3cd82757e7bccc0948c88bfee09bd916c3/8-jdk/Dockerfile#L38-L43

鉴于此,您可能希望更改 dockerBaseImage 以使用使用 Java 9 的基本映像,例如:

dockerBaseImage := "9-jdk"

您可以在此处查看映像版本的完整列表:https://hub.docker.com/_/openjdk/

【讨论】:

  • 这听起来和我想的一样。我不知道如何更改使用的 jdk 版本。星期一我会试一试的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-29
  • 2015-09-13
  • 1970-01-01
  • 2017-07-28
  • 2017-01-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多