Jooq: GraalVM compatibility

Created on 12 Jun 2019  路  27Comments  路  Source: jOOQ/jOOQ

It should be checked if jOOQ is GraalVM compatible. I.e. whether native Substrate VM images can be built for applications built on jOOQ.

Functionality All Editions Medium Enhancement

Most helpful comment

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");
    }
}

All 27 comments

@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...?

The problem appears to be the DefaultRecordMapper as it uses MethodHandles 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 the native-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 on ProxyMapper, 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 by native-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...

Was this page helpful?
0 / 5 - 0 ratings