-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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 newInstance() without reflection configuration when extracted to a method #2500
Comments
Any feedback on how hard it could be to support that? Could you please tag it with |
We currently have a research project that looks at method inlining before static analysis. We are starting with simpler cases that do not involve method calls, but then want to expand it to also cover cases like this. |
I have worked on this issue related to concrete Spring use cases, and would like to share a few interesting findings. We have 2 variants of
The good news is that we should be able to move forward short term with the second variant in order to experiment on removing the need for native-image reflection configuration via functional bean registration. At the same time, we still need this issue to be fixed because using I have created a functional bean registration repro project here to provide a realistic use case that we hope |
We have a prototype that could solve this but it is still early to merge it in. I am moving this issue for 20.3. |
This should be addressed by the following commit: Feel free to try this out by using |
The native-image option -H:+InlineBeforeAnalysis can be used (for now) without requiring reflection configuration for this example:
|
Thanks for those progresses that indeed now support use cases where the return value is a constant. As expected Spring use cases where that would be useful like reflection-static-analysis and reflection-static-analysis-functional are not yet supported because the return value is a new instance, not a constant. Could we reopen this issue (and removed the 21.0 target version) and start a discussion about how the use case below could be supported:
I guess the main question is what kind of general pattern could we use to make that use case recognized by |
For the more complex use cases like your I am currently thinking about a redesign of the native image generator that parses bytecodes only once. But that will be a few months before it can be finished. The main takeaway of the |
@christianwimmer Thanks for sharing more details, could you please remove the 21.0 target for that issue? Should this issue be reopened or do you prefer to create a new one related to the redesign you mentioned? |
@sdeleuze I merged an updated version of "inlining before analysis" last week. This is now the future-proof version that we want to enable by default. But for the upcoming 21.2 release it remains behind the I looked at what the new approach is doing with the
it is problematic that the When changing the method to
it can be inlined when the arguments are constants, because everything apart from the This is of course a change with a semantic difference: a Another barrier for inlining is class initialization. As it is written right now,
When Kotlin is really present, of course many lookups will not constant fold for the Kotlin part. I have not followed in detail where |
@christianwimmer Thanks for working on that.
|
@sdeleuze Sounds good, let me know if you need help when you experiment with it. Also we probably want some kind of tracing so that users like you know what gets folded and what not. Especially the latter is difficult, because we can certainly not just print all method invokes that are not folded. So there probably needs to be a filtering. |
@christianwimmer Should the milestone be updated to 21.2 instead 21.0? |
I changed the version to 21.3 since this will be the version where it is enabled by default. |
I was able to test it works as expected with spring-attic/spring-native@547d5dd, thanks. |
Turns out one cannot re-use builtins that are initialized in the static context because some state is not reset between tests. Trying to enforce that will also open a can of worms so we decided against that. However, while trying to instantiate builtins in the constructor we would no longer inling constructor calls, resulting in `NoSuchMethodException` once the native image was generated. This turned out to be a limitation related to oracle/graal#2500 so that we cannot make calls like `clazz.getContructor().newInstance()`. `clazz.getConstructor()` in the static initializer and creating new instances in Builtins constructor was however OK for the inliner and it was able to procede with constant folding.
Turns out one cannot re-use builtins that are initialized in the static context because some state is not reset between tests. Trying to enforce that will also open a can of worms so we decided against that. However, while trying to instantiate builtins in the constructor we would no longer inling constructor calls, resulting in `NoSuchMethodException` once the native image was generated. This turned out to be a limitation related to oracle/graal#2500 so that we cannot make calls like `clazz.getContructor().newInstance()`. `clazz.getConstructor()` in the static initializer and creating new instances in Builtins constructor was however OK for the inliner and it was able to procede with constant folding.
As a kind of follow-up of the idea I had when creating #905 (cc @cstancu) and of our recent discussions about how to improve GraalVM native static analysis to require less reflection configuration (important for Spring but not only), I think I have found an area where GraalVM native could be improved.
The repro is pretty simple, consider:
If I try to instantiate
FooImpl
viaFooImpl.class.getDeclaredConstructor().newInstance()
, the application compiles without reflection configuration needed:If I just extract the instantiation logic to a method (that's what we do with
org.springframework.beans.BeanUtils#instantiateClass(java.lang.Class<T>)
that is used everywhere in Spring) like that:Then running the native image fails with
java.lang.NoSuchMethodException: com.sample.FooImpl.<init>()
and requires reflection to work as expected. Same behavior if I useorg.springframework.beans.BeanUtils#instantiateClass(java.lang.Class<T>)
.Could you improve GraalVM native in order to support this kind of use case without requiring reflection configuration? I think that could allow us to support most function Spring application with almost no reflection configuration and would lead to smaller images that would consume less memory.
Repro project: https://github.com/sdeleuze/graal-issues/tree/master/reflection-static-analysis
Tested with GraalVM 20.1.0
Please tag this issue with
spring
label.The text was updated successfully, but these errors were encountered: