jOOQ
jOOQ copied to clipboard
GraalVM native image compatibility
It should be checked if jOOQ is GraalVM compatible. I.e. whether native Substrate VM images can be built for applications built on jOOQ.
Indeed, apparently there are problems:
- https://twitter.com/andrus_a/status/1137225290126635009
- https://habr.com/ru/post/454790/
https://github.com/oracle/graal/issues/1342
@raderio Thanks for linking. Is there a specific reason why you linked to that particular issue, as that issue does not seem to talk about jOOQ...?
It is from article https://habr.com/ru/post/454790/
The problem appears to be the DefaultRecordMapper
as it uses MethodHandle
s which are not supported by the Substrate VM.
For applications not using this feature a workaround may be to build the native image using the --report-unsupported-elements-at-runtime
flag.
Sorry, I already deleted my prior comment with jooq related issues. I upgraded to docker image graalvm-ce:19.3.0 for building (instead of prior 19.2.3) and got other errors, but none jooq related any more (or errors earlier not yet coming to jooq errors, don't know yet) :)
We're currently thinking of a Proof of concept using jOOQ and potentially GraalVM. This issue makes us unsure about jOOQ's roadmap regarding GraalVM.
Am i right to assume it's something close "jOOQ intends to support GraalVM but won't spend dedicated resource on it upfront and depending on the issue it might a blocker"?
By the way can jOOQ already be used to build native app thanks to Jigsaw? I guess so but you know better for sure :)
thanks again for jOOQ!
jOOQ intends to support GraalVM
Yes, we intend to
but won't spend dedicated resource on it upfront
We'll spend time on this eventually, but it hasn't been a priority yet
and depending on the issue it might a blocker
We don't know yet
By the way can jOOQ already be used to build native app thanks to Jigsaw? I guess so but you know better for sure :)
We don't know yet
I have the following error when trying to build a very simple "insert" example with graalvm and JOOQ.
[INFO] Executing: /opt/graalvm-ce-java11-19.3.0.2/bin/native-image -cp /root/.m2/repository/info/picocli/picocli/4.1.4/picocli-4.1.4.jar:/root/.m2/repository/org/postgresql/postgresql/42.2.9/postgresql-42.2.9.jar:/root/.m2/repository/org/jooq/jooq/3.12.3/jooq-3.12.3.jar:/root/.m2/repository/org/reactivestreams/reactive-streams/1.0.2/reactive-streams-1.0.2.jar:/root/.m2/repository/javax/xml/bind/jaxb-api/2.3.0/jaxb-api-2.3.0.jar:/project/target/picocli-jooq-1.0-SNAPSHOT.jar -H:+TraceClassInitialization --initialize-at-build-time=org.jooq.SQLDialect$ThirdParty --no-fallback --allow-incomplete-classpath --report-unsupported-elements-at-runtime -H:Class=com.gitlab.davinkevin.picoclijooq.JooqInsert -H:Name=picocli-jooq
Build on Server(pid: 220, port: 44951)*
[picocli-jooq:220] classlist: 3,516.75 ms
[picocli-jooq:220] (cap): 696.44 ms
[picocli-jooq:220] setup: 2,073.97 ms
[picocli-jooq:220] (typeflow): 20,944.14 ms
[picocli-jooq:220] (objects): 13,785.14 ms
[picocli-jooq:220] (features): 1,053.07 ms
[picocli-jooq:220] analysis: 37,198.56 ms
[picocli-jooq:220] (clinit): 734.82 ms
[picocli-jooq:220] universe: 1,773.30 ms
[picocli-jooq:220] (parse): 4,200.23 ms
[picocli-jooq:220] (inline): 3,796.12 ms
[picocli-jooq:220] (compile): 24,276.35 ms
[picocli-jooq:220] compile: 33,663.41 ms
[picocli-jooq:220] image: 2,211.34 ms
[picocli-jooq:220] write: 577.23 ms
Fatal error: java.lang.RuntimeException: java.lang.RuntimeException: host C compiler or linker does not seem to work: java.lang.RuntimeException: returned 1
Running command: cc -v -o /project/target/picocli-jooq -z noexecstack -Wl,--gc-sections -Wl,--dynamic-list -Wl,/tmp/SVM-15716260340844484512/exported_symbols.list -Wl,-x -L/tmp/SVM-15716260340844484512 -L/opt/graalvm-ce-java11-19.3.0.2/lib -L/opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64 /tmp/SVM-15716260340844484512/picocli-jooq.o /opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64/libffi.a /opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64/libstrictmath.a /opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64/libjvm.a /opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64/liblibchelper.a /opt/graalvm-ce-java11-19.3.0.2/lib/libnet.a /opt/graalvm-ce-java11-19.3.0.2/lib/libjava.a /opt/graalvm-ce-java11-19.3.0.2/lib/libzip.a /opt/graalvm-ce-java11-19.3.0.2/lib/libnio.a /opt/graalvm-ce-java11-19.3.0.2/lib/libextnet.a -lm -lpthread -ldl -lpthread -lz -lrt
Using built-in specs.
COLLECT_GCC=cc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.8.5 20150623 (Red Hat 4.8.5-39.0.3) (GCC)
COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/
LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-o' '/project/target/picocli-jooq' '-z' 'noexecstack' '-L/tmp/SVM-15716260340844484512' '-L/opt/graalvm-ce-java11-19.3.0.2/lib' '-L/opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64' '-mtune=generic' '-march=x86-64'
/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2 --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o /project/target/picocli-jooq -z noexecstack /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o -L/tmp/SVM-15716260340844484512 -L/opt/graalvm-ce-java11-19.3.0.2/lib -L/opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../.. --gc-sections --dynamic-list /tmp/SVM-15716260340844484512/exported_symbols.list -x /tmp/SVM-15716260340844484512/picocli-jooq.o /opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64/libffi.a /opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64/libstrictmath.a /opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64/libjvm.a /opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64/liblibchelper.a /opt/graalvm-ce-java11-19.3.0.2/lib/libnet.a /opt/graalvm-ce-java11-19.3.0.2/lib/libjava.a /opt/graalvm-ce-java11-19.3.0.2/lib/libzip.a /opt/graalvm-ce-java11-19.3.0.2/lib/libnio.a /opt/graalvm-ce-java11-19.3.0.2/lib/libextnet.a -lm -lpthread -ldl -lpthread -lz -lrt -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crtn.o
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0x0): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0xc8): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0x208): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0x408): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0x608): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0x648): more undefined references to `Java_java_lang_invoke_MethodHandle_invokeBasic' follow
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0x7c0): undefined reference to `Java_java_lang_invoke_MethodHandleNatives_staticFieldBase'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0x890): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0x9d8): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0xb08): undefined reference to `Java_java_lang_invoke_MethodHandleNatives_staticFieldOffset'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0xc98): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0xd70): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0xdd8): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0xdf0): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
collect2: error: ld returned 1 exit status
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:600)
at java.base/java.util.concurrent.ForkJoinTask.get(ForkJoinTask.java:1006)
at com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:462)
at com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:315)
at com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:454)
at com.oracle.svm.hosted.server.NativeImageBuildServer.executeCompilation(NativeImageBuildServer.java:402)
at com.oracle.svm.hosted.server.NativeImageBuildServer.lambda$processCommand$8(NativeImageBuildServer.java:339)
at com.oracle.svm.hosted.server.NativeImageBuildServer.withJVMContext(NativeImageBuildServer.java:420)
at com.oracle.svm.hosted.server.NativeImageBuildServer.processCommand(NativeImageBuildServer.java:336)
at com.oracle.svm.hosted.server.NativeImageBuildServer.processRequest(NativeImageBuildServer.java:280)
at com.oracle.svm.hosted.server.NativeImageBuildServer.lambda$serve$7(NativeImageBuildServer.java:240)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.RuntimeException: host C compiler or linker does not seem to work: java.lang.RuntimeException: returned 1
Running command: cc -v -o /project/target/picocli-jooq -z noexecstack -Wl,--gc-sections -Wl,--dynamic-list -Wl,/tmp/SVM-15716260340844484512/exported_symbols.list -Wl,-x -L/tmp/SVM-15716260340844484512 -L/opt/graalvm-ce-java11-19.3.0.2/lib -L/opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64 /tmp/SVM-15716260340844484512/picocli-jooq.o /opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64/libffi.a /opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64/libstrictmath.a /opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64/libjvm.a /opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64/liblibchelper.a /opt/graalvm-ce-java11-19.3.0.2/lib/libnet.a /opt/graalvm-ce-java11-19.3.0.2/lib/libjava.a /opt/graalvm-ce-java11-19.3.0.2/lib/libzip.a /opt/graalvm-ce-java11-19.3.0.2/lib/libnio.a /opt/graalvm-ce-java11-19.3.0.2/lib/libextnet.a -lm -lpthread -ldl -lpthread -lz -lrt
Using built-in specs.
COLLECT_GCC=cc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.8.5 20150623 (Red Hat 4.8.5-39.0.3) (GCC)
COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/
LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-o' '/project/target/picocli-jooq' '-z' 'noexecstack' '-L/tmp/SVM-15716260340844484512' '-L/opt/graalvm-ce-java11-19.3.0.2/lib' '-L/opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64' '-mtune=generic' '-march=x86-64'
/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2 --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o /project/target/picocli-jooq -z noexecstack /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o -L/tmp/SVM-15716260340844484512 -L/opt/graalvm-ce-java11-19.3.0.2/lib -L/opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../.. --gc-sections --dynamic-list /tmp/SVM-15716260340844484512/exported_symbols.list -x /tmp/SVM-15716260340844484512/picocli-jooq.o /opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64/libffi.a /opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64/libstrictmath.a /opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64/libjvm.a /opt/graalvm-ce-java11-19.3.0.2/lib/svm/clibraries/linux-amd64/liblibchelper.a /opt/graalvm-ce-java11-19.3.0.2/lib/libnet.a /opt/graalvm-ce-java11-19.3.0.2/lib/libjava.a /opt/graalvm-ce-java11-19.3.0.2/lib/libzip.a /opt/graalvm-ce-java11-19.3.0.2/lib/libnio.a /opt/graalvm-ce-java11-19.3.0.2/lib/libextnet.a -lm -lpthread -ldl -lpthread -lz -lrt -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crtn.o
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0x0): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0xc8): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0x208): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0x408): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0x608): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0x648): more undefined references to `Java_java_lang_invoke_MethodHandle_invokeBasic' follow
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0x7c0): undefined reference to `Java_java_lang_invoke_MethodHandleNatives_staticFieldBase'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0x890): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0x9d8): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0xb08): undefined reference to `Java_java_lang_invoke_MethodHandleNatives_staticFieldOffset'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0xc98): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0xd70): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0xdd8): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
/tmp/SVM-15716260340844484512/picocli-jooq.o:(.data+0xdf0): undefined reference to `Java_java_lang_invoke_MethodHandle_invokeBasic'
collect2: error: ld returned 1 exit status
at com.oracle.svm.hosted.image.NativeBootImageViaCC.write(NativeBootImageViaCC.java:382)
at com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:652)
at com.oracle.svm.hosted.NativeImageGenerator.lambda$run$0(NativeImageGenerator.java:445)
at java.base/java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1407)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177)
Error: Image build request failed with exit status 1
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:27 min
[INFO] Finished at: 2020-01-12T12:48:09Z
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.graalvm.nativeimage:native-image-maven-plugin:19.3.0:native-image (default-cli) on project picocli-jooq: Execution of /opt/graalvm-ce-java11-19.3.0.2/bin/native-image -cp /root/.m2/repository/info/picocli/picocli/4.1.4/picocli-4.1.4.jar:/root/.m2/repository/org/postgresql/postgresql/42.2.9/postgresql-42.2.9.jar:/root/.m2/repository/org/jooq/jooq/3.12.3/jooq-3.12.3.jar:/root/.m2/repository/org/reactivestreams/reactive-streams/1.0.2/reactive-streams-1.0.2.jar:/root/.m2/repository/javax/xml/bind/jaxb-api/2.3.0/jaxb-api-2.3.0.jar:/project/target/picocli-jooq-1.0-SNAPSHOT.jar -H:+TraceClassInitialization --initialize-at-build-time=org.jooq.SQLDialect$ThirdParty --no-fallback --allow-incomplete-classpath --report-unsupported-elements-at-runtime -H:Class=com.gitlab.davinkevin.picoclijooq.JooqInsert -H:Name=picocli-jooq returned non-zero result -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
I've included the flag from @knutwannheden but without success. I'm looking for another solution, but reading traces of native-image compilation is a bit cryptic 😅.
Code can be found here: https://gitlab.com/davinkevin/picocli-jooq
@davinkevin Thanks for your feedback. We have not really had time to look into supporting GraalVM. The error message being reported indeed looks very cryptic and similar to what is being reported here: https://github.com/oracle/graal/issues/1863. It looks like the next GraalVM release might provide better error messages for this type of problem.
I did a PoC a few weeks ago using Quarkus and jOOQ and was able to successfully build a native image with GraalVM. But I had to configure all generated Record classes to use Reflection. Unfortunately I had to add Hibernate ORM, even without using it, because jOOQ makes some reference to javax.persistence.Column
@jean-merelis Thanks for reporting back.
Yes, jOOQ unfortunately depends on the JPA API, due to the features of the DefaultRecordMapper
. There is however a plan to move this component out into a separate opt-in Maven module, so that this dependency can be removed from jOOQ core. If you don't use this feature at runtime, you should however not have to include the dependency. Additionally, as you are probably also aware, you don't need the whole of Hibernate but just the JPA API: https://mvnrepository.com/artifact/javax.persistence/javax.persistence-api/2.2.
Can you elaborate a bit more on the problem with the generated record classes? jOOQ's AbstractRecord
class has some methods which depend on the DefaultRecordMapper
, which uses Java reflection. I can see that this could be problematic for the native image compiler. But I am unsure if this is what you are referring to.
Regarding your PoC, it would be very nice if you could document the required steps / configuration here in a comment.
Generated record classes use reflection in some way, so them need to be registered to use reflection. In Quarkus there are two ways to register a class for reflection. 1- Use the @RegisterForReflection annotation 2- Using a json file with the information of class to be registered (file: reflection-config.json)
I created a project to demonstrate the use of jOOQ with Quarkus https://github.com/jean-merelis/jOOQ-mcve
This successfully creates a native image.
Prerequisites:
- GraalVM graalvm-ce-19.2.1 installed and configured, more info here
- java-8 (java11 can be used, but for this project I used java8)
- Postgres with database name: jooq_mcve_8779
To create native image: ./mvnw package -Pnative
To run native image: ./target/jooq-mcve-1.0-runner
It only takes 0.009s for the app to go up.
In your browser navigate to http://localhost:8080/mcve
2- Using a json file with the information of class to be registered (file: reflection-config.json)
The jOOQ maven plugin could be responsible of creating such a file I think.
I did some experimentation today with jooq and quarkus and graalvm native-image.
My findings, if it can be helpful one day:
- it works with graal 19.3.1 but not with 20.0.0 (I get this bug: https://github.com/oracle/graal/issues/2345)
- the dependency
javax.persistence-api
was indeed needed for the build to happen without problem (an alternative could be to use thenative-image
option--allow-incomplete-classpath
) - but the main problem is the one discussed above:
-
DefaultRecordMapper
has some of its code relying on invocation handler (in particular in DefaultRecordMapper.ProxyMapper`) and it's not meant to be something supported, see https://github.com/oracle/graal/blob/master/substratevm/DYNAMIC_PROXY.md - Using the
--report-unsupported-elements-at-runtime
option of native-image hides the problem as long as at runtime you don't rely onProxyMapper
, which should be quite ok. - It is not really recommended to use
--report-unsupported-elements-at-runtime
since it can hide many other problems
-
I would IMHO recommend that if we want jooq to support GraalVM seriously, that all this dynamic proxy thing be moved to an opt-in/out mechanism so that we don't have to find a workaround.
Another solution would be to provide, in the form of a module to add to the classpath, some mean to disable the ProxyMapper
implementation, see for example https://quarkus.io/guides/writing-extensions#replacing-classes-in-the-native-image (what is explained there does not need quarkus I think, as long as the substitute/delete annotated class is on the classpath).
For the record, adding the following class in the classpath is enough to satisfy graalvm so that --report-unsupported-elements-at-runtime
is not needed anymore:
@TargetClass(className = "org.jooq.impl.DefaultRecordMapper", innerClass = "ProxyMapper")
final class ProxyMapper_Substitute {
@Substitute
private Object proxy() {
throw new UnsupportedOperationException("Can't work with GraalVM native");
}
}
And by the way, with the above substitute class, it works with GraalVM 20.0.0 :)
@victornoel would you enable me to contribute this to micronaut-sql project?
@morki of course yes, great news then :)
@victornoel Hi, I tried to contribute this to Micronaut as a mentioned, and image build is now working.
I had to add -H:ClassInitialization=org.jooq.SQLDialect$ThirdParty:build_time
, maybe just Micronaut thing.
But now in runtime, it is failing with:
Caused by: java.lang.IllegalArgumentException: Class org.jooq.types.UShort[] is instantiated reflectively but was never registered. Register the class by using org.graalvm.nativeimage.hosted.RuntimeReflection
at com.oracle.svm.core.genscavenge.graal.AllocationSnippets.checkArrayHub(AllocationSnippets.java:172)
at org.jooq.impl.DefaultDataType.<init>(DefaultDataType.java:298)
at org.jooq.impl.DefaultDataType.<init>(DefaultDataType.java:282)
at org.jooq.impl.DefaultDataType.<init>(DefaultDataType.java:278)
at org.jooq.impl.DefaultDataType.<init>(DefaultDataType.java:262)
at org.jooq.impl.SQLDataType.<clinit>(SQLDataType.java:303)
at com.oracle.svm.core.hub.ClassInitializationInfo.invokeClassInitializer(ClassInitializationInfo.java:350)
at com.oracle.svm.core.hub.ClassInitializationInfo.initialize(ClassInitializationInfo.java:270)
Did you have similar problem? Can you help me with solving this, please?
@victornoel I solved it by using this reflection-config.json:
[
{
"name": "java.time.LocalDate[]",
"allPublicConstructors": true
},
{
"name": "java.time.LocalDateTime[]",
"allPublicConstructors": true
},
{
"name": "java.time.LocalTime[]",
"allPublicConstructors": true
},
{
"name": "java.time.ZonedDateTime[]",
"allPublicConstructors": true
},
{
"name": "java.time.OffsetDateTime[]",
"allPublicConstructors": true
},
{
"name": "java.time.OffsetTime[]",
"allPublicConstructors": true
},
{
"name": "java.time.ZoneOffset[]",
"allPublicConstructors": true
},
{
"name": "java.time.Instant[]",
"allPublicConstructors": true
},
{
"name": "java.sql.Timestamp[]",
"allPublicConstructors": true
},
{
"name": "java.math.BigInteger[]",
"allPublicConstructors": true
},
{
"name": "java.math.BigDecimal[]",
"allPublicConstructors": true
},
{
"name": "org.jooq.types.UNumber[]",
"allPublicConstructors": true
},
{
"name": "org.jooq.types.DayToSecond[]",
"allPublicConstructors": true
},
{
"name": "org.jooq.types.UByte[]",
"allPublicConstructors": true
},
{
"name": "org.jooq.types.UInteger[]",
"allPublicConstructors": true
},
{
"name": "org.jooq.types.ULong[]",
"allPublicConstructors": true
},
{
"name": "org.jooq.types.Unsigned[]",
"allPublicConstructors": true
},
{
"name": "org.jooq.types.UShort[]",
"allPublicConstructors": true
},
{
"name": "org.jooq.types.YearToMonth[]",
"allPublicConstructors": true
},
{
"name": "org.jooq.types.YearToSecond[]",
"allPublicConstructors": true
},
{
"name": "org.jooq.RowId[]",
"allPublicConstructors": true
},
{
"name": "org.jooq.Result[]",
"allPublicConstructors": true
},
{
"name": "org.jooq.JSON[]",
"allPublicConstructors": true
},
{
"name": "org.jooq.JSONB[]",
"allPublicConstructors": true
}
]
@morki that's surprising, do you know where this reflective instantiation happens in the jooq code? Or is it in some classes generated by the jooq maven plugin?
@victornoel I use gradle plugin, but it seem these are coming from DefaultDataType
class. The compilation is ok without them, but they are created reflectively at runtime and throws exception. I must dig deaper, I was just following every runtime failure and adding appropriate classes. I don't event understand why are those "array" classes created this way...
@victornoel it's pretty hard with every native build running 10 minutes on my machine :D
@morki yes hehe, having a lot of memory helps I noticed, I went from 5-7mn on my personal computer to 2mn on my work computer :)
I successfully build a very simple application triggering a JOOQ insert with native-image
and able to remove some parameters from the native-image
execution: https://gitlab.com/davinkevin/picocli-jooq (and for the information, the build is "short" for me with this example, around ~30 seconds which is cool for developer experience).
@lukaseder is there anything we can do (PR or something else) to help with this issue? The reflection
file could be integrated in the library and will be used by native-image
if found, which could be simpler for developer (and this could evolve with the library).
Sorry for the delay, @davinkevin
@lukaseder is there anything we can do (PR or something else) to help with this issue? The
reflection
file could be integrated in the library and will be used bynative-image
if found, which could be simpler for developer (and this could evolve with the library).
I'll be happy to get back to you when this will be prioritised. Without starting to add relevant builds / tests on our side, I can't really say what can be done to help...
FWIW, https://gitlab.com/davinkevin/picocli-jooq as kindly provided by @davinkevin is based on jOOQ 3.13.2. Times have changed and jOOQ 3.17.4 (current at the time of this writing) has moved forward a bit.
I got a variation of picocli-jooq
to work by simply extending the Graal reflection configuration with
diff --git a/src/main/resources/reflection-config.json b/src/main/resources/reflection-config.json
index e2b1aa9..f4aaedd 100644
--- a/src/main/resources/reflection-config.json
+++ b/src/main/resources/reflection-config.json
@@ -98,6 +98,18 @@
{
"name": "org.jooq.JSONB[]",
"allPublicConstructors": true
+ },
+ {
+ "name": "org.jooq.XML[]",
+ "allPublicConstructors": true
+ },
+ {
+ "name": "org.jooq.Geography[]",
+ "allPublicConstructors": true
+ },
+ {
+ "name": "org.jooq.Geometry[]",
+ "allPublicConstructors": true
}
]
The general gist (to the extent that I understand it from spending a few minutes on jOOQ) is that the jOOQ source file org/jooq/impl/SQLDataType.java
basically pages in plenty of jOOQ implementation types which universe building of Graal discarded from the native image. The exception stack traces thrown at runtime are quite helpful in pin-pointing this, i.e.
Exception in thread "main" java.lang.ExceptionInInitializerError
at ...
Caused by: java.lang.NullPointerException
at ...
at org.jooq.impl.SQLDataType.<clinit>(SQLDataType.java:735)
... 14 more
really points to the specific type that needs to be registered with universe building in Graal.
Note that I am just poking at Graal and jOOQ at the same time, so please do not consider the above supportable advice - it's just FYI and entertainment. From reading around I am confident in predicting that there are additional traps around reflection and class loading that affect the combination of Graal and jOOQ.
https://medium.com/graalvm/enhancing-3rd-party-library-support-in-graalvm-native-image-with-shared-metadata-9eeae1651da4 https://www.infoq.com/news/2022/08/graalvm-22-2/
Contribute over here: https://github.com/oracle/graalvm-reachability-metadata/blob/master/CONTRIBUTING.md
@ThoSap - I hereby release the above snippet into the public domain, under any license you prefer (and it'd suffer from "Mangel an Erfindungshöhe" anyway) ;)