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

Introduce AOT generated class proxies #28115

Closed
sdeleuze opened this issue Feb 28, 2022 · 4 comments
Closed

Introduce AOT generated class proxies #28115

sdeleuze opened this issue Feb 28, 2022 · 4 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) theme: aot An issue related to Ahead-of-time processing type: enhancement A general enhancement
Milestone

Comments

@sdeleuze
Copy link
Contributor

sdeleuze commented Feb 28, 2022

GraalVM native-image only supports JDK dynamic proxies when configured explicitly on interfaces.

For proxies on classes, typically created at runtime with CGLIB on the JVM, there is a need to create such proxies Ahead-Of-Time. That's what @aclement did in Spring Native:

Spring Framework 6 should provide similar support for AOT generated class proxies, potentially by:

  • Leveraging ClassProxyHint to configure them
  • Deciding how the creation of the proxy should be implemented
  • Plug it into the AOT processing
  • Implement proper inferring if possible
  • Replace the substitution by proper handling in DefaultAopProxyFactory and/or other relevant classes
@sdeleuze sdeleuze added type: enhancement A general enhancement theme: aot An issue related to Ahead-of-time processing labels Feb 28, 2022
@sdeleuze sdeleuze added this to the 6.0.0-M4 milestone Feb 28, 2022
@aclement
Copy link
Contributor

Just a bit more context. I could have built my own proxy generation but it would have taken a while and I wasn't in a position to easily test it rigorously for all spring use cases. So I leveraged #1283 which replaced CGLIB with byte buddy because I knew that was passing the tests, and it would give me an easier route to pushing proxy generation to being something I could drive at build time rather than runtime. It had mechanisms for easily grabbing the bytecode for the proxy, and total control over the proxy naming (because when looking them up at runtime it had to exactly match what was created earlier).

Importantly it was also generating a more optimal proxy that was using less of the generated support classes for invoking some methods. For 'well known' interfaces that the proxy was implementing it was directly wiring up the invocations. Whereas CGLIB was using a general approach for all methods, leading to lots of new classes. (However, hand crafting could have also performed these optimizations, obviously).

The current version was definitely constructed as a building block. Ideally the necessary proxies could be more inferred rather than the user trying to work out what set of 'bits' they need to supply for proxy hints, or discovering it by trial and error when running the system is printing out the required hints.

@aclement
Copy link
Contributor

The commit encompassing all these changes in spring-native is spring-attic/spring-native@af0e804

@sdeleuze
Copy link
Contributor Author

sdeleuze commented Mar 2, 2022

Related topic : Spring Native we currently relies on Hibernate Build-time enhancement to perform Hibernate bytecode manipulation at build time. I mention that because:

  • It could be interesting to see how they implemented that.
  • This seems not super actively maintained (for example, no Gradle Kotlin DSL support if I remember correctly).
  • Using that imply painful additional build configuration, we may be interested by a more integrated approach.

Maybe a point to discuss with @mp911de, @schauder and @christophstrobl.

@jhoeller jhoeller added the in: core Issues in core modules (aop, beans, core, context, expression) label Mar 29, 2022
@jhoeller jhoeller modified the milestones: 6.0.0-M4, 6.0.0-M5 May 4, 2022
sdeleuze added a commit to sdeleuze/spring-framework that referenced this issue Jul 8, 2022
This commit introduces a TransactionBeanRegistrationAotProcessor
in charge of creating the required proxy and reflection hints
when @transactional is detected on beans.

It also refines DefaultAopProxyFactory to throw an exception
when a subclass-based proxy is created in native images
since that's unsupported for now (see spring-projectsgh-28115 related issue).

Closes spring-projectsgh-28717
sdeleuze added a commit to sdeleuze/spring-framework that referenced this issue Jul 8, 2022
This commit introduces a TransactionBeanRegistrationAotProcessor
in charge of creating the required proxy and reflection hints
when @transactional is detected on beans.

It also refines DefaultAopProxyFactory to throw an exception
when a subclass-based proxy is created in native images
since that's unsupported for now (see spring-projectsgh-28115 related issue).

Closes spring-projectsgh-28717
sdeleuze added a commit to sdeleuze/spring-framework that referenced this issue Jul 8, 2022
This commit introduces a TransactionBeanRegistrationAotProcessor
in charge of creating the required proxy and reflection hints
when @transactional is detected on beans.

It also refines DefaultAopProxyFactory to throw an exception
when a subclass-based proxy is created in native images
since that's unsupported for now (see spring-projectsgh-28115 related issue).

Closes spring-projectsgh-28717
@jhoeller jhoeller modified the milestones: 6.0.0-M5, 6.0.0-M6 Jul 8, 2022
@jhoeller
Copy link
Contributor

There is an initial commit coming to main now: This includes runtime storing of generated classes to a directory specified by the "cglib.generatedClasses" system property, to be picked up by the build process for further inclusion in a jar file (and ultimately in a native image). We also avoid lazy CGLIB fast-class generation now and replace the generated Enhancer and MethodWrapper key classes with equivalent record types. Last but not least, this introduces support for early type determination in InstantiationStrategy, AopProxy and SmartInstantiationAwareBeanPostProcessor - in order to trigger CGLIB class generation in refreshForAotProcessing (through early determineBeanType calls for bean definitions).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) theme: aot An issue related to Ahead-of-time processing type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

3 participants