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

Switch from AutomaticFeature to Feature and pass in via --feature #25976

Merged
merged 1 commit into from Jun 17, 2022

Conversation

zakkak
Copy link
Contributor

@zakkak zakkak commented Jun 6, 2022

While the Feature interface is API, the annotation AutomaticFeature is
not in the API. That is intentional: if a feature is necessary, then it
should be added via the --features=... option in a
native-image.properties file.

Source: oracle/graal#4616

Implements 1st part of #25943

Marking as Draft till tested completes on my fork.

@quarkus-bot quarkus-bot bot added the area/core label Jun 6, 2022
@gastaldi
Copy link
Contributor

gastaldi commented Jun 6, 2022

@zakkak there are other Feature classes implemented using @AutomaticFeature in the codebase (extensions like Liquibase, Hibernate, to name a few).

Should they be migrated to this strategy too?

UPDATE: Just saw it's part of #25943

@zakkak
Copy link
Contributor Author

zakkak commented Jun 6, 2022

@zakkak there are other Feature classes implemented using @AutomaticFeature in the codebase (extensions like Liquibase, Hibernate, to name a few).

Should they be migrated to this strategy too?

UPDATE: Just saw it's part of #25943

Yup I forgot about those. We will need to do the migration for them as well and see how to only include them when it makes sense (i.e. based on reachability).

@zakkak zakkak force-pushed the autofeature-to-feature branch 2 times, most recently from 08a35eb to 2845c08 Compare June 7, 2022 11:13
@zakkak zakkak marked this pull request as ready for review June 7, 2022 11:13
@zakkak zakkak requested a review from galderz June 7, 2022 11:13
@quarkus-bot

This comment has been minimized.

@gastaldi
Copy link
Contributor

gastaldi commented Jun 8, 2022

Looks good to me, added a minor suggestion for better type check purposes

Copy link
Contributor

@gastaldi gastaldi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use GraalVM in other parts, so better follow the pattern :)

@zakkak zakkak requested a review from gastaldi June 8, 2022 05:30
@quarkus-bot

This comment has been minimized.

@sberyozkin
Copy link
Member

@stuartwdouglas Can you also have a look please ?

Copy link
Contributor

@gastaldi gastaldi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@quarkus-bot

This comment has been minimized.

@zakkak zakkak force-pushed the autofeature-to-feature branch 2 times, most recently from 5561b92 to ba749b7 Compare June 9, 2022 09:12
Copy link
Member

@gsmet gsmet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks good to me except for one small interrogation regarding nested classes and escaping.

for (NativeImageFeatureBuildItem nativeImageFeature : nativeImageFeatures) {
featuresList.add(nativeImageFeature.getQualifiedName());
}
nativeImageArgs.add("--features=" + String.join(",", featuresList));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this work properly if one of the feature is a nested class? I'm worried about $ escaping.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's an interesting question, I'll give it a try.

PS: Why would one define a feature as a nested class though?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PS: Why would one define a feature as a nested class though?

People are weird :).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good question, and possible :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to my tests the $ is being properly escaped but we still can't use nested classes for defining a Feature even when using @AutomaticFeature (i.e. without this PR).

native-image fails with:

Error: Error instantiating Feature class io.quarkus.runtime.graal.DisableLoggingFeature$NestedDisableLoggingFeature. Ensure the class is not abstract and has a no-argument constructor.
com.oracle.svm.core.util.UserError$UserException: Error instantiating Feature class io.quarkus.runtime.graal.DisableLoggingFeature$NestedDisableLoggingFeature. Ensure the class is not abstract and has a no-argument constructor.
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.util.UserError.abort(UserError.java:84)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.FeatureHandler.registerFeature(FeatureHandler.java:180)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.FeatureHandler.registerFeatures(FeatureHandler.java:128)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.setupNativeImage(NativeImageGenerator.java:836)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:559)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:519)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:407)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:585)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:128)
Caused by: java.lang.NoSuchMethodException: io.quarkus.runtime.graal.DisableLoggingFeature$NestedDisableLoggingFeature.<init>()
	at java.base/java.lang.Class.getConstructor0(Class.java:3349)
	at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2553)
	at org.graalvm.nativeimage.base/com.oracle.svm.util.ReflectionUtil.lookupConstructor(ReflectionUtil.java:81)
	at org.graalvm.nativeimage.base/com.oracle.svm.util.ReflectionUtil.lookupConstructor(ReflectionUtil.java:76)
	at org.graalvm.nativeimage.base/com.oracle.svm.util.ReflectionUtil.newInstance(ReflectionUtil.java:95)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.FeatureHandler.registerFeature(FeatureHandler.java:178)
	... 7 more

Explicitly defining the default public constructor doesn't help either.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is essentially happening because inner classes don't actually have "a no-argument constructor" since the seemingly no-argument default constructor of inner classes takes as argument an instance of the outer class. However, GraalVM doesn't handle this case so it doesn't support defining nested Features.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static nested features should work though, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! In that case everything works as expected ($ gets escaped and the feature gets registered).

E.g.:

...
[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildRunner] /home/zakkak/code/graal/sdk/latest_graalvm_home/bin/native-image -J-Djava.util.logging.manager=org.jboss.logmanager.LogManager -J-Dsun.nio.ch.maxUpdateArraySize=100 -J-Dio.netty.leakDetection.level=DISABLED -J-Dio.netty.allocator.maxOrder=3 -J-Dvertx.logger-delegate-factory-class-name=io.quarkus.vertx.core.runtime.VertxLogDelegateFactory -J-Dvertx.disableDnsResolver=true -J-Duser.language=en -J-Duser.country=IE -J-Dfile.encoding=UTF-8 --features=io.quarkus.runner.Feature,io.quarkus.runtime.graal.ResourcesFeature,io.quarkus.runtime.graal.DisableLoggingFeature\$NestedDisableLoggingFeature -H:-ParseOnce -J--add-exports=java.security.jgss/sun.security.krb5=ALL-UNNAMED -J--add-opens=java.base/java.text=ALL-UNNAMED -H:InitialCollectionPolicy=com.oracle.svm.core.genscavenge.CollectionPolicy\$BySpaceAndTime -H:+JNI -H:+AllowFoldMethods -J-Djava.awt.headless=true -H:FallbackThreshold=0 --link-at-build-time -H:+ReportExceptionStackTraces -g -H:DebugInfoSourceSearchPath=app-sources -H:-AddAllCharsets -H:EnableURLProtocols=http -H:NativeLinkerOption=-no-pie -H:-UseServiceLoaderFeature -H:+StackTrace -J--add-exports=org.graalvm.nativeimage.builder/com.oracle.svm.core.jni=ALL-UNNAMED -J--add-exports=org.graalvm.nativeimage.builder/com.oracle.svm.core.jdk=ALL-UNNAMED -J--add-exports=org.graalvm.nativeimage.builder/com.oracle.svm.core.jdk.localization=ALL-UNNAMED -J--add-exports=org.graalvm.nativeimage.base/com.oracle.svm.util=ALL-UNNAMED quarkus-integration-test-awt-999-SNAPSHOT-runner -jar quarkus-integration-test-awt-999-SNAPSHOT-runner.jar
...
[1/7] Initializing...                                                                                   (17.0s @ 0.16GB)
 Version info: 'GraalVM 22.2.0-dev Java 11 CE'
 Java version info: '11.0.16+5-jvmci-22.2-b03'
 C compiler: gcc (redhat, x86_64, 12.1.1)
 Garbage collector: Serial GC
 5 user-specific feature(s)
 - io.quarkus.awt.runtime.graal.AwtFeature
 - io.quarkus.runner.Feature
 - io.quarkus.runtime.graal.DisableLoggingFeature$NestedDisableLoggingFeature
 - io.quarkus.runtime.graal.ResourcesFeature
 - org.graalvm.home.HomeFinderFeature: Finds GraalVM paths and its version number

Notice the --features=io.quarkus.runner.Feature,io.quarkus.runtime.graal.ResourcesFeature,io.quarkus.runtime.graal.DisableLoggingFeature\$NestedDisableLoggingFeature parameter.

}
return null;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the difference now, thanks

@gastaldi gastaldi added the triage/needs-rebase This PR needs to be rebased first because it has merge conflicts label Jun 9, 2022
@geoand
Copy link
Contributor

geoand commented Jun 16, 2022

This needs a rebase

@zakkak
Copy link
Contributor Author

zakkak commented Jun 16, 2022

I addressed the comments and rebased the branch, it is again ready for review.

@quarkus-bot

This comment has been minimized.

@gsmet
Copy link
Member

gsmet commented Jun 16, 2022

@zakkak please run the formatter :)

While the Feature interface is API, the annotation AutomaticFeature is
not in the API. That is intentional: if a feature is necessary, then it
should be added via the --features=... option in a
native-image.properties file.

Source: oracle/graal#4616
@gsmet gsmet added triage/waiting-for-ci Ready to merge when CI successfully finishes and removed triage/needs-rebase This PR needs to be rebased first because it has merge conflicts labels Jun 16, 2022
@gastaldi gastaldi merged commit 57fb652 into quarkusio:main Jun 17, 2022
@quarkus-bot quarkus-bot bot added this to the 2.11 - main milestone Jun 17, 2022
@quarkus-bot quarkus-bot bot removed the triage/waiting-for-ci Ready to merge when CI successfully finishes label Jun 17, 2022
@zakkak zakkak deleted the autofeature-to-feature branch August 12, 2022 05:56
zakkak added a commit to zakkak/quarkus that referenced this pull request Aug 12, 2022
In quarkusio#25976 we switched from
using the @AutomaticFeature annotation to explicitly passing the
required features using the --features parameter.

Given that `@AutomaticFeature`s (including the `SerializationFeature`) are
always registered before non-automatic ones there is no longer the need
to have an explicit dependency on `SerializationFeture`.
miador pushed a commit to miador/quarkus that referenced this pull request Sep 6, 2022
In quarkusio#25976 we switched from
using the @AutomaticFeature annotation to explicitly passing the
required features using the --features parameter.

Given that `@AutomaticFeature`s (including the `SerializationFeature`) are
always registered before non-automatic ones there is no longer the need
to have an explicit dependency on `SerializationFeture`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants