Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support GraalVM and native-image compilation #9402

Closed
gilles-degols opened this issue Jun 18, 2019 · 4 comments
Closed

Support GraalVM and native-image compilation #9402

gilles-degols opened this issue Jun 18, 2019 · 4 comments

Comments

@gilles-degols
Copy link

Are you looking for help?

Oracle has released "GraalVM", which allows, among other things, to build a native application out of any java/scala code. The drop in resource consumption (specifically the RAM) is extremely useful for a micro-service architecture.
An example of the performance improvement was done here.
And some efforts were done to use it with Akka: here, which worked fine, if you do a bit of extra-work.

Regarding Play!, an investigation was done ~1 year ago, but no significant update since then, at least, no easy-to-find documentation to make Play! compiles as a native image.

Play Version (2.5.x / etc)

Play 2.7.2 (also tested Play 2.8.0-M1, no difference)

API (Scala / Java / Neither / Both)

Scala

Operating System (Ubuntu 15.10 / MacOS 10.10 / Windows 10)

Centos 7.4

JDK (Oracle 1.8.0_72, OpenJDK 1.8.x, Azul Zing)

openjdk version "1.8.0_212"
OpenJDK Runtime Environment (build 1.8.0_212-20190420092731.buildslave.jdk8u-src-tar--b03)
OpenJDK GraalVM CE 19.0.0 (build 25.212-b03-jvmci-19-b01, mixed mode)

Library Dependencies

Native packager in the plugins.sbt:
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.22")

I also used the different dependencies described here.

Expected Behavior

sbt graalvm-native-image:packageBin
Should produce a valid native image, working the same way as "sbt run"

Actual Behavior

sbt graalvm-native-image:packageBin
produces the following output:

[info] Build on Server(pid: 11141, port: 36524)
[info] [toto:11141]    classlist:  21,260.28 ms
[info] [toto:11141]        (cap):   1,767.01 ms
[info] [toto:11141]        setup:   2,388.54 ms
[error] SLF4J: Class path contains multiple SLF4J bindings.
[error] SLF4J: Found binding in [jar:file:/root/.ivy2/cache/org.slf4j/slf4j-jdk14/jars/slf4j-jdk14-1.7.26.jar!/org/slf4j/impl/StaticLoggerBinder.class]
[error] SLF4J: Found binding in [jar:file:/root/.ivy2/cache/ch.qos.logback/logback-classic/jars/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
[error] SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
[error] SLF4J: Actual binding is of type [org.slf4j.impl.JDK14LoggerFactory]
[error] warning: unknown locality of class Lplay/api/ApplicationLoader$JavaApplicationLoaderAdapter$1;, assuming class is not local. To remove the warning report an issue to the library or language author. The issue is caused by Lplay/api/ApplicationLoader$JavaApplicationLoaderAdapter$1; which is not following the naming convention.
[info] [toto:11141]   (typeflow):  13,441.84 ms
[info] [toto:11141]    (objects):  17,188.40 ms
[info] [toto:11141]   (features):   1,067.56 ms
[info] [toto:11141]     analysis:  32,508.22 ms
[info] [toto:11141]     (clinit):   1,399.26 ms
[info] [toto:11141]     universe:   2,136.28 ms
[info] [toto:11141]      (parse):   1,952.24 ms
[info] [toto:11141]     (inline):   4,481.05 ms
[info] [toto:11141]    (compile):  20,128.95 ms
[info] [toto:11141]      compile:  27,921.33 ms
[info] [toto:11141]        image:   2,155.43 ms
[info] [toto:11141]        write:     496.31 ms
[info] [toto:11141]      [total]:  89,001.17 ms
[success] Total time: 127 s, completed Jun 18, 2019 3:54:19 PM

Even if the final output says "[success]", if you try to launch the generated application:

[root@localhost toto]# target/graalvm-native-image/toto
Oops, cannot start the server.
@7c8imkl6p: Cannot load play.application.loader[play.application.loader [play.api.inject.guice.GuiceApplicationLoader] was not loaded.]
        at play.utils.Reflect$.loadClass$1(Reflect.scala:132)
        at play.utils.Reflect$.configuredClass(Reflect.scala:145)
        at play.api.ApplicationLoader$.apply(ApplicationLoader.scala:166)
        at play.core.server.ProdServerStart$.start(ProdServerStart.scala:58)
        at play.core.server.ProdServerStart$.main(ProdServerStart.scala:31)
        at play.core.server.ProdServerStart.main(ProdServerStart.scala)
Caused by: java.lang.ClassNotFoundException: play.api.inject.guice.GuiceApplicationLoader
        at com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:51)
        at java.lang.ClassLoader.loadClass(Target_java_lang_ClassLoader.java:131)
        at play.utils.Reflect$.loadClass$1(Reflect.scala:126)
        ... 5 more

Reproducible Test Case

Project: https://github.com/gilles-degols/play-graal/
This is a very basic Play project generated automatically, from which I removed every service, controller and filter. The idea is first to compile it as simple as possible, then gradually try more advanced features of Play! with it.

@ignasi35
Copy link
Member

Hi @gilles-degols.
This is not in our short-term plan but is definitely an interesting investigation.

@schmitch
Copy link
Contributor

actually the problem here is that you use Guice @gilles-degols if you use play without guys it will work if you include everything necessary inside the image. with guice you basically need to add all classes to the image that will be included dynamically.

@gilles-degols
Copy link
Author

@schmitch you are right! By using a project here not relying on Guice, and meddling a bit with it I was able to compile & run the native-image.
I guess we can close this ticket, but it would be interesting for the future to update the initial post you wrote here, to give hope to the next people trying to use Play! as native-image. The error you had last time still appears for me, but I can run the compiled image just fine afterwards (and no problem for scala 2.12.8).

Thank you very much again for your initial blog post & this comment!

@SoerenSilkjaer
Copy link

@gilles-degols @schmitch
Guice 5 has come out, do you think that changes anything regarding running play with guice as native-image?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants