oracle / graal

GraalVM compiles Java applications into native executables that start instantly, scale fast, and use fewer compute resources 🚀
https://www.graalvm.org
Other
20.38k stars 1.64k forks source link

[GR-47365, GR-48191] Ability to Express all JVM Types in Reachability Metadata #7476

Open vjovanov opened 1 year ago

vjovanov commented 1 year ago

TL;DR

Expressing reflection over lambda-proxy and Java-proxy types in JSON-based reachability metadata is currently impossible. To compile programs that require those features, users currently have to rewrite the code to avoid reflection on proxies and lambdas.

We intend to modify the syntax of reflect-config.json to support all possible types on the JVM. The syntax for regular types would become:

{
    "type": "sun.misc.Unsafe",
    "forName": true
}

for lambda proxies:

{
    "type": {
        "lambda": {
            "capturingClass": "pkg.App",
            "capturingMethod": {"name": "main", "parameterTypes": ["java.lang.String[]"]}, 
            "interfaces": ["java.lang.Runnable"]
        }
    },
    "queryAllDeclaredMethods": true
}

and for Java proxies:

{
    "type": {
         "proxy": {
              "interfaces": ["sun.misc.SignalHandler"]
         }
    },
    "queryAllDeclaredMethods": true
}

Goals

  1. Allow all types to be described in reachability metadata files.
  2. Disentangle the type entry from the ability to do Class.forName for that type.
  3. (Outcome) Remove the need for proxy-config.json.
  4. (Outcome) Simplify serialization-config.json.

Non-Goals

  1. Make reachability metadata writing harder.
  2. Make reachability metadata backward incompatible.
  3. Change the way conditional configuration works.

Interactions with the Rest of the System

Native Image Agent Support

The native image agent will output only the new format of reachability metadata. Upon encountering lambda proxies or Java proxy classes, the agent will read the inherited interfaces and output the new format. In the case of lambdas, the agent will not output the capturingMethod as it is not possible to determine that value at runtime. The agent will have to track the forName calls and output that as a separate entry in the types which will be represented by `"forName": true" in JSON.

Removing the need for proxy-config.json

The current proxy-config.json file only specifies the ordered list of interfaces that define the proxy class. This can be subsumed by a simple entry in reflect-config.json:

{
    "type": {
         "proxy": {
              "interfaces": ["sun.misc.SignalHandler"]
         }
    }
}

Since proxy classes fall under the reflection API, the migration of this feature to reflect-config.json is natural.

Adopting the new Format in serialization-config.json

The serialization configuration has special sections for lambda proxies (lambdaCapturingTypes) and Java-proxy types (proxies). These sections can now be expressed in the section types with the same syntax as in reflect-config.json.

Backwards Compatibility

The value of "name" in reflect-config.json will continue to have the implicit meaning that the class can be fetched with Class.forName.

The new syntax will be produced by the agent and described in all documentation. The reachability metadata will be migrated to the new format on the next LTS release (GraalVM for Java 25).

The current format for "name" will be supported until the majority of the ecosystem adopts the new format.

vjovanov commented 1 month ago

Proxy types are now supported in GraalVM for JDK 23.