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

Support alias of super-class methods in substitutions #2458

Closed
sdeleuze opened this issue May 14, 2020 · 5 comments
Closed

Support alias of super-class methods in substitutions #2458

sdeleuze opened this issue May 14, 2020 · 5 comments
Assignees
Labels
feature spring spring related issue

Comments

@sdeleuze
Copy link
Collaborator

While working on Spring support for GraalVM native, I found a blocking limitation in substitutions. It seems currently not supported to create an alias for a method invoking a method originally defined in a super class.

It is annoying when the said method is long, and it is blocking when for example your want to access a private field via a public/protected/package private getter. Most of my use case are substitutions to remove some code in order to reduce the memory footprint (typically XML support).

If you consider following code:

public class Foo extends Bar {
	public Foo() {
		method1();
		method2();
	}
}

public class Bar {
	public void method1() {
		// ...
	}
	public void method2() {
		// ...
	}
}

@TargetClass(className = "Foo")
public final class Target_Foo {
	@Substitute
	public Target_Foo() {
		method2();
	}
	@Alias
	public void method2() {
	}
}

It currently fails (tested with 20.1 branch) with following error:

Error: could not find target method: public void Target_Foo.method2()
com.oracle.svm.core.util.UserError$UserException: could not find target method: public void Target_Foo.method2()
	at com.oracle.svm.core.util.UserError.abort(UserError.java:68)
	at com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor.findOriginalMethod(AnnotationSubstitutionProcessor.java:637)
	at com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor.handleMethodInAliasClass(AnnotationSubstitutionProcessor.java:330)
	at com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor.handleAliasClass(AnnotationSubstitutionProcessor.java:302)
	at com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor.handleClass(AnnotationSubstitutionProcessor.java:274)
	at com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor.init(AnnotationSubstitutionProcessor.java:230)
	at com.oracle.svm.hosted.NativeImageGenerator.createDeclarativeSubstitutionProcessor(NativeImageGenerator.java:908)

I would expect such substitution works as expected, like it does when all methods are defined in the same class.

Please tag this issue with the spring label.

@eginez
Copy link
Contributor

eginez commented May 14, 2020

@sdeleuze can you points us to a concrete use case of this new feature how you would use it in the context of spring?

@christianwimmer
Copy link

I don't understand entirely what you are trying to do. But on first glance, it seems like you want to make a @Alias to a method in Bar, which means you need a TargetClass for Bar.

You cannot model a class hierarchy of target classes. But you can freely cast between them. So when you have a Target_Foo and a Target_Bar, then you can cast a Target_Foo instance to a Target_Bar without the possibility for a ClassCastException at run time. In fact, these casts will be removed by the AOT compiler.

@christianwimmer
Copy link

And for all issues and requests like this I want to point out that you should use substitutions as little as possible, because they lead to code that is difficult to maintain.

sdeleuze added a commit to sdeleuze/spring-native that referenced this issue May 15, 2020
This commit introduces various optimizations that allow to significantly
reduce Spring Boot applications footprint when compiled as native images.

The first one is the capability to remove XML parsers (see related
oracle/graal#2327 GraalVM issue) including those configured habitually
by Spring. XML Parsers from Logback, Tomcat, Spring Boot, Spring Framework
Core/WebMvc/WebFlux can be disabled via -Dspring.graal.remove-xml-support=true
and is implemented via various substitutions.
Notice for now FormHttpMessageConverter is used instead of
AllEncompassingFormHttpMessageConverter due to oracle/graal#2458.

It is now also possible to remove SpEL via -Dspring.graal.remove-spel-support=true
and JMX via -Dspring.graal.remove-jmx-support=true.

BackgroundPreinitializer are now disabled since they do not make sense with
GraalVM native.

spring-graal-feature is now added as a regular Maven dependency in order to make
the new org.springframework.boot.NativePropertiesListener taken in account when
the agent is used.

Key samples and petclinic ones have been updated to take advantage of those
optimizations. Spring Fu samples now also takes advantages of
spring-projects-experimental/spring-fu#269 and those capabilities.

In the long run, these "not so easy to maintain substitutions" could maybe be
replaced by a new GraalVM capability that would monitor used classes by the
JVM via an agent and pass this list to native-image compiler to remove those
unused classes from the native image in order to load classes lazily like
the JVM does. It would also have the advantage to not require an explicit
option to enable those optimizations.

Closes spring-atticgh-109
dsyer pushed a commit to scratches/spring-graalvm-native that referenced this issue Sep 23, 2020
This commit introduces various optimizations that allow to significantly
reduce Spring Boot applications footprint when compiled as native images.

The first one is the capability to remove XML parsers (see related
oracle/graal#2327 GraalVM issue) including those configured habitually
by Spring. XML Parsers from Logback, Tomcat, Spring Boot, Spring Framework
Core/WebMvc/WebFlux can be disabled via -Dspring.graal.remove-xml-support=true
and is implemented via various substitutions.
Notice for now FormHttpMessageConverter is used instead of
AllEncompassingFormHttpMessageConverter due to oracle/graal#2458.

It is now also possible to remove SpEL via -Dspring.graal.remove-spel-support=true
and JMX via -Dspring.graal.remove-jmx-support=true.

BackgroundPreinitializer are now disabled since they do not make sense with
GraalVM native.

spring-graal-feature is now added as a regular Maven dependency in order to make
the new org.springframework.boot.NativePropertiesListener taken in account when
the agent is used.

Key samples and petclinic ones have been updated to take advantage of those
optimizations. Spring Fu samples now also takes advantages of
spring-projects-experimental/spring-fu#269 and those capabilities.

In the long run, these "not so easy to maintain substitutions" could maybe be
replaced by a new GraalVM capability that would monitor used classes by the
JVM via an agent and pass this list to native-image compiler to remove those
unused classes from the native image in order to load classes lazily like
the JVM does. It would also have the advantage to not require an explicit
option to enable those optimizations.

Closes spring-atticgh-109
dsyer pushed a commit to scratches/spring-graalvm-native that referenced this issue Sep 23, 2020
This commit introduces various optimizations that allow to significantly
reduce Spring Boot applications footprint when compiled as native images.

The first one is the capability to remove XML parsers (see related
oracle/graal#2327 GraalVM issue) including those configured habitually
by Spring. XML Parsers from Logback, Tomcat, Spring Boot, Spring Framework
Core/WebMvc/WebFlux can be disabled via -Dspring.graal.remove-xml-support=true
and is implemented via various substitutions.
Notice for now FormHttpMessageConverter is used instead of
AllEncompassingFormHttpMessageConverter due to oracle/graal#2458.

It is now also possible to remove SpEL via -Dspring.graal.remove-spel-support=true
and JMX via -Dspring.graal.remove-jmx-support=true.

BackgroundPreinitializer are now disabled since they do not make sense with
GraalVM native.

spring-graal-feature is now added as a regular Maven dependency in order to make
the new org.springframework.boot.NativePropertiesListener taken in account when
the agent is used.

Key samples and petclinic ones have been updated to take advantage of those
optimizations. Spring Fu samples now also takes advantages of
spring-projects-experimental/spring-fu#269 and those capabilities.

In the long run, these "not so easy to maintain substitutions" could maybe be
replaced by a new GraalVM capability that would monitor used classes by the
JVM via an agent and pass this list to native-image compiler to remove those
unused classes from the native image in order to load classes lazily like
the JVM does. It would also have the advantage to not require an explicit
option to enable those optimizations.

Closes spring-atticgh-109
@essobedo
Copy link

I've just faced a similar issue and confirm that the approach described by @christianwimmer did the trick, thank you very much 🙏

For this particular case, here is the code that works:

@TargetClass(Foo.class)
final class Target_Foo {
    @Substitute
    public Target_Foo() {
        ((Target_Bar) (Object) this).method2();
    }
}

@TargetClass(Bar.class)
final class Target_Bar {

    @Alias
    public void method2() {
    }
}

@wirthi
Copy link
Member

wirthi commented Feb 1, 2024

Solution was given above, no additional request for several years. Closing this ticket.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature spring spring related issue
Projects
Status: Done
Development

No branches or pull requests

7 participants