Skip to content

GraalVM Native Image Requires Config for lazy vals #13985

Closed
@jamesward

Description

@jamesward

Compiler version

3.1.0

Background

GraalVM Native Image Ahead-of-Time compiles JVM apps into native executables. To do the AOT compilation, reflection points must be specified.

Issue 1

Scala's scala.runtime.LazyVals uses reflection so it must be declared. This could be done in the Scala stdlib so that others don't need to do it themselves. But this approach is a bit brittle. Any chance of removing the use of sun.misc.Unsafe there? If not, then I can send a PR to include the GraalVM reflection config:

  {
    "name":"sun.misc.Unsafe",
    "allDeclaredFields":true
  }

Issue 2

Code generated by the compiler for lazy vals also uses reflection and must be declared, like:

  {
    "name":"App$package$",
    "fields":[{"name":"0bitmap$1"}]
  }

Also, ideally reflection is not required. But I haven't looked into what the reflection is doing. If someone uses a Scala library that uses lazy vals, and does NOT provide their reflection config for GraalVM, then the user must specify the config for the library on their own. Ideally the library authors nor the users need to specify this info.

Steps to Reproduce

  1. Clone https://github.com/jamesward/scala3-graalvm-tester.git
  2. Switch to the lazy-reflect-broke branch
  3. Run ./sbt nativeImage nativeImageRun

You will see a runtime error showing Issue 1:

Exception in thread "main" scala.runtime.LazyVals$$anon$1
	at scala.runtime.LazyVals$.$init$$$anonfun$3(LazyVals.scala:18)
	at scala.Option.getOrElse(Option.scala:201)
	at scala.runtime.LazyVals$.<clinit>(LazyVals.scala:19)
	at App$package$.<clinit>(App.scala:2)
	at run.main(App.scala:4)

(Note: It should be possible to fail the build in this case instead of producing a runtime error but there seems to be a bug: oracle/graal#4010)

If you switch to the lazy-reflect-works branch and re-run ./sbt nativeImage nativeImageRun you will see that it works given the requisite config for the app in that repo that has one lazy val.

One Approach (If Reflection Must Stay)

The Spring team has developed a set of annotations which provide the reflection info, like:
https://docs.spring.io/spring-native/docs/0.9.1-SNAPSHOT/api/org/springframework/nativex/hint/TypeHint.html

There has been talk that this work will merge in some way into GraalVM itself. In that case, the Scala compiler could generate the necessary TypeHint annotations for places it generates code that uses reflection.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions