GraalVM conditional configuration is only documented for reflection but it also applies to serialization, proxy and resources configurations. Since this mechanism allows to leverage GraalVM static analysis to reduce the memory footprint and image size, and for consistency, it would make sense to not only expose this capability in ReflectionHints, but also in JavaSerializationHints, ProxyHints and ResourceHints.

Comment From: sdeleuze

After various discussion with GraalVM team and @bclozel, I think we need to make the reachableType mandatory in our API since: - It allows to keep track of the reason of the inclusion of a hint - It improves the footprint by leveraging GraalVM static analysis, not just basic classpath checks - This is consistent with the design decision on GraalVM native configuation side which as been renamed to jvm-reachability-metadata to emphasis the reachability is a central concern here - It will likely allow us to have the same maintenability issue that on Spring Native with @NativeHint

Since annotation are currently not supported yet as relevant trigger (see related GraalVM issue), we should implement a check to verify annotations are not used as reachableType.

Comment From: snicoll

we should implement a check to verify annotations are not used as reachableType.

You can't reliably do that I am afraid. TypeReference won't tell you that. We do have specific checks for methods that take a Class as a shortcut though.

Comment From: sdeleuze

You can't reliably do that I am afraid. TypeReference won't tell you that. We do have specific checks for methods that take a Class as a shortcut though.

That's not a hard requirement, we can at least document it and do the check when we have the class. We could also maybe perform this check via ASM-based utility methods (I think we already have that implemented) when generating the config files since this will happen AOT.

Comment From: sdeleuze

@snicoll About your remark on type = reachableType in Spring Native, that's the case in a lot of @NativeHint indeed because we have a lot of hints that are using a "Spring trigger" which has a special meaning and special processing (it does not translate to reachableType in this case).

What I would like to do in Framework 6 is removing this special processing for "Spring things" which is not clearly defined and can't be check in a reliable way, and always translate to regular reachableType.

Since that's sadly not properly documented yet on GraalVM side, see examples of such files from the jvm-reachability-metadata repository: proxy-config.json

[
  {
    "condition": {
      "typeReachable": "org.jline.utils.Signals"
    },
    "interfaces": [
      "sun.misc.SignalHandler"
    ]
  }
]

resource-config.json

{
  "bundles": [],
  "resources": {
    "includes": [
      {
        "condition": {
          "typeReachable": "org.jline.terminal.TerminalBuilder"
        },
        "pattern": "\\QMETA-INF/services/org.jline.terminal.spi.JansiSupport\\E"
      }
  ]
}

reflect-config.json

[
  {
    "condition": {
      "typeReachable": "org.jline.terminal.impl.jansi.JansiNativePty"
    },
    "name": "java.io.FileDescriptor",
    "queriedMethods": [
      {
        "name": "<init>",
        "parameterTypes": [
          "int"
        ]
      }
    ]
  }
]

Comment From: philwebb

We might be able to use com.oracle.svm.core.configure.ResourceConfigurationParser in the JUnit test to verify the JSON without needing a native image.

Comment From: sdeleuze

@snicoll Could you please have a look to this draft branch where: - I made reachable type mandatory by introducing condition since more could come later (see related commit) - I added reachable type to ResourceHints as well (see related commit)

If you test it with sample native application, notice GraalVM 22.1-dev is required since GraalVM 22.0 is broken for some kind of conditional configuration.

Comment From: snicoll

I had a look to the two commits and added some comments.

I don't think making the reachable type mandatory in the API is warranted when the commit does this at the same time. If we can't figure out a better reachable type in AutowiredAnnotationBeanPostProcessor, then I don't think we should be forced to write something like this.

I also think that making it mandatory in the method that creates the builder makes the API more fat. I'd welcome a different arrangement. Perhaps a validation that a condition is set when building the object? Still, I think it makes the API harder to use than it should and I am wondering if this is warranted.

Comment From: bclozel

If I understand correctly, the GraalVM agent will use as reachableType whatever type is right above in the call stack when performing a reflection/resource/etc call. That's a nice heuristic for many libraries, but I suspect that this approach won't be super efficient in Spring Framework.

In many cases, the call stack with start with a ResourceUtils, ClassUtils, etc. class that does not really help discarding useless hints. I think that two cases might happen in our case:

  • we will look higher in the call stack and select a type that's more representative of the use case, for example ResourceWebHandler for serving static resources
  • we will point instead to a configuration class that will not be in the call stack but still represents well the trigger for many features. For example, WebMvcConfigurationSupport.

I don't think making the reachable type mandatory in the API is warranted when the commit does this at the same time. If we can't figure out a better reachable type in AutowiredAnnotationBeanPostProcessor, then I don't think we should be forced to write something like this.

I agree with the comment above. On top of that, I believe some hints might not even have a valid reachableType. In the case of field injection, we would have to point to a class that's always reachable by the core context - or worse, point to an AOT-generated class. In both cases, this doesn't really help.

To summarize, I'd like to add this option to the API but not make it mandatory.

Comment From: sdeleuze

Ok thanks for your feedback, I think I will just make a new try with reachable types added to other hints than reflection one and let it optional.

Comment From: bclozel

To summarize our findings so far:

  • Hints conditions are important and we want to support them. So far typeReachable is the only existing one, and its main use case is about reflection metadata. But we've seen conditions used in other places like proxy-config or resource-config.
  • typeReachable and hints conditions should not be mandatory in our API
  • we can't necessarily automate the condition generation; typeReachable is about a particular type being reachable by the static analysis and doesn't necessarily means that it is part of the call stack

With this change, we can consider #28163 with a more general approach.