-
Notifications
You must be signed in to change notification settings - Fork 429
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
Using picocli with GraalVM's native-image tool #410
Comments
I haven’t tried GraalVM yet, unsure when I’ll be able to get to it. Would you be able to provide a patch or pull request for the picocli user manual? That would be great! |
I am working on it. I have encountered another issue while doing so, see #417. My plan is to add an example and a section in the user manual. Do you sync the user manual with the wiki automatically or is that done manually? |
Thanks for #417! The manual on the wiki is out of date. Please modify the If instructions are non-trivial or longer than a few paragraphs we can create a separate documentation page (and link from and back to the index page). |
I'm highly interested! As I develop a (hobby) command line application in Java with AOT should help a lot. |
@stengerh I can update the wiki to the latest version of the user manual if that helps. |
@remkop I don't think this will be necessary. I am working on a chapter for the user manual. I took a closer at picocli and AOT compilation, so there will be more information than in my post above. However I got side-tracked by summer-time activities. ;) I can push a preliminary version later this week. I still want to clean up some rough edges before I create a pull request. Here's a summary of my findings so far:
It would be nice to AOT compile and run the picocli unit tests to get a more complete picture but this would require a testing framework which does not rely on runtime reflection (particularly Class.forName). I haven't looked into this yet. |
That all sounds awesome. Take your time and enjoy the summer! (Sounds like you have a lot of material there. Maybe interesting to also write it up in a blog post or an article for InfoQ, DZone or JavaCodeGeeks.) |
@stengerh I’m still very interested in this. |
I tried picocli on the latest GraalVM and it's not working out of the box. Hopefully as graal matures it'll support this use case. |
@bootstraponline Thanks for reporting this! I haven't had a chance to look at GraalVM yet. Looking at the stack trace in that ticket, the issue may be that GraalVM does not discover the default constructor via reflection. If not explicitly used in the code, this constructor may have been removed from the byte code by Graal. You may be able to work around this by providing a custom |
GraalVM has a bunch of issues right now (~140 on GitHub alone). I think even if this specific problem was resolved, it's not mature enough for real world use.
I'm hoping the bug report helps the Graal team figure out the problem. If picocli starts working out of the box that'll be amazing. |
FYI I solved the reflection issue and ran into another Graal bug. Here's the reflection config I used: The Graal team is investigating. |
Thanks for pushing this issue and thanks for keeping me in the loop! |
It might be an idea to add a command line tool to picocli to generate the https://github.com/oracle/graal/blob/master/substratevm/REFLECTION.md |
Agreed. That was my next step if graal worked. |
Another idea is to create an annotation processor that generates code (either java source code or byte code) for a class with picocli annotations such that the |
A first version of ReflectionConfigGenerator is available in the new picocli-codegen module. This generates JSON that can be specified in the Could you give it a try? |
An article that describes how to use the tool is here: https://github.com/remkop/picocli/wiki/Picocli-on-GraalVM:-Blazingly-Fast-Command-Line-Apps Feedback welcome! |
Closing this ticket. The |
* add documentation to codegen README for generating config during the build * add --output option to specify a destination file * add test * modify exclusions system.property name to `picocli.codegen.excludes` (was `picocli.converters.excludes`) * update release notes
I tried the code gen using
I deleted all the system classes in main.json which aren't from my app.
I think, unfortunately, graal isn't Kotlin compatible. Hopefully future versions of Graal expand compatibility. $ native-image -H:ReflectionConfigurationFiles=main.json -jar flank-SNAPSHOT.jar --report-unsupported-elements-at-runtime
Build on Server(pid: 46750, port: 50862)
[flank-SNAPSHOT:46750] classlist: 2,799.63 ms
[flank-SNAPSHOT:46750] (cap): 823.23 ms
[flank-SNAPSHOT:46750] setup: 1,066.87 ms
warning: unknown locality of class Lkotlin/coroutines/CoroutineContext$plus$1;, assuming class is not local. To remove the warning report an issue to the library or language author. The issue is caused by Lkotlin/coroutines/CoroutineContext$plus$1; which is not following the naming convention.
[flank-SNAPSHOT:46750] analysis: 15,986.16 ms
error: Non-reducible loop
Detailed message:
Error: Non-reducible loop
Call path from entry point to kotlin.collections.SlidingWindowKt$windowedIterator$1.invokeSuspend(Object):
at kotlin.collections.SlidingWindowKt$windowedIterator$1.invokeSuspend(SlidingWindow.kt)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:234)
at com.oracle.svm.core.jdk.RuntimeSupport.executeHooks(RuntimeSupport.java:142)
at com.oracle.svm.core.jdk.RuntimeSupport.executeStartupHooks(RuntimeSupport.java:87)
at com.oracle.svm.core.JavaMainWrapper.run(JavaMainWrapper.java:156)
at com.oracle.svm.core.code.CEntryPointCallStubs.com_002eoracle_002esvm_002ecore_002eJavaMainWrapper_002erun_0028int_002corg_002egraalvm_002enativeimage_002ec_002etype_002eCCharPointerPointer_0029(generated:0)
Original exception that caused the problem: org.graalvm.compiler.core.common.PermanentBailoutException: Non-reducible loop
at org.graalvm.compiler.java.BciBlockMapping.computeBlockOrder(BciBlockMapping.java:876)
at org.graalvm.compiler.java.BciBlockMapping.build(BciBlockMapping.java:524)
at org.graalvm.compiler.java.BciBlockMapping.create(BciBlockMapping.java:1103)
at org.graalvm.compiler.java.BytecodeParser.build(BytecodeParser.java:804)
at org.graalvm.compiler.java.BytecodeParser.buildRootMethod(BytecodeParser.java:782)
at org.graalvm.compiler.java.GraphBuilderPhase$Instance.run(GraphBuilderPhase.java:95)
at org.graalvm.compiler.phases.Phase.run(Phase.java:49)
at org.graalvm.compiler.phases.BasePhase.apply(BasePhase.java:197)
at org.graalvm.compiler.phases.Phase.apply(Phase.java:42)
at org.graalvm.compiler.phases.Phase.apply(Phase.java:38)
at com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.parse(MethodTypeFlowBuilder.java:204)
at com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.apply(MethodTypeFlowBuilder.java:323)
at com.oracle.graal.pointsto.flow.MethodTypeFlow.doParse(MethodTypeFlow.java:310)
at com.oracle.graal.pointsto.flow.MethodTypeFlow.ensureParsed(MethodTypeFlow.java:300)
at com.oracle.graal.pointsto.flow.MethodTypeFlow.addContext(MethodTypeFlow.java:107)
at com.oracle.graal.pointsto.DefaultAnalysisPolicy$DefaultVirtualInvokeTypeFlow.onObservedUpdate(DefaultAnalysisPolicy.java:186)
at com.oracle.graal.pointsto.flow.TypeFlow.notifyObservers(TypeFlow.java:347)
at com.oracle.graal.pointsto.flow.TypeFlow.update(TypeFlow.java:389)
at com.oracle.graal.pointsto.BigBang$2.run(BigBang.java:508)
at com.oracle.graal.pointsto.util.CompletionExecutor.lambda$execute$0(CompletionExecutor.java:174)
at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1402)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Error: Processing image build request failed |
Thanks for the info! Do you think there is anything picocli can do to help with this? |
Unless you want to redesign picocli to work based on a Kotlin compiler plugin to fully avoid reflection, I don't think so. Reflection doesn't play nice with the current version of graal ( The picocli library and ReflectionConfigGenerator are easy to use. |
I have tried to use the AOT compilation with the GraalVM' native-image tool. I tried something similar to the example from the picocli documentation first, i.e.
This was unsuccessful as the compiled native executable did not seem to parse and bind the arguments to the commands fields. What did work though was to let picocli do the annotation processing in the JVM which generated the image, i.e. in a static field initializer:
I am posting this here so that others can benefit from it. It would be nice if you included instructions for using native-image with picocli into the documentation. :)
The text was updated successfully, but these errors were encountered: