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

GraalVM native image compatibility #8779

Open
knutwannheden opened this issue Jun 12, 2019 · 69 comments
Open

GraalVM native image compatibility #8779

knutwannheden opened this issue Jun 12, 2019 · 69 comments

Comments

@knutwannheden
Copy link
Contributor

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

@lukaseder
Copy link
Member

@raderio

This comment was marked as off-topic.

@lukaseder

This comment was marked as off-topic.

@raderio

This comment was marked as off-topic.

@knutwannheden
Copy link
Contributor Author

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.

@theodiefenthal
Copy link

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) :)

@cluelessjoe
Copy link
Contributor

cluelessjoe commented Dec 14, 2019

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!

@lukaseder
Copy link
Member

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

@davinkevin
Copy link

davinkevin commented Jan 12, 2020

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

@knutwannheden
Copy link
Contributor Author

@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: oracle/graal#1863. It looks like the next GraalVM release might provide better error messages for this type of problem.

@jean-merelis
Copy link

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

@knutwannheden
Copy link
Contributor Author

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

@jean-merelis
Copy link

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

@victornoel
Copy link

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.

@victornoel
Copy link

victornoel commented Apr 19, 2020

I did some experimentation today with jooq and quarkus and graalvm native-image.

My findings, if it can be helpful one day:

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).

@victornoel
Copy link

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

@victornoel
Copy link

And by the way, with the above substitute class, it works with GraalVM 20.0.0 :)

@morki
Copy link

morki commented Apr 30, 2020

@victornoel would you enable me to contribute this to micronaut-sql project?

@victornoel
Copy link

@morki of course yes, great news then :)

@eiswind
Copy link

eiswind commented Feb 3, 2023

I can feel it. Just throw it into the corner.

@lukaseder
Copy link
Member

I can feel it. Just throw it into the corner.

😅

I'll try it again on linux maybe. Though, wait a sec, according to https://github.com/graalvm/graalvm-ce-builds/releases/tag/vm-22.3.1, AMD architecture is required also on linux.

The build server is:

lukaseder@dg-test1:~$ lscpu
Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Vendor ID:           GenuineIntel
Model name:          Intel(R) Xeon(R) CPU E5-2650 v4 @ 2.20GHz

That means, I won't be able to test this without using new machines?

@victornoel
Copy link

@lukaseder I believe amd64 here just means x86, not especially amd-brand cpu

@lukaseder
Copy link
Member

@lukaseder I believe amd64 here just means x86, not especially amd-brand cpu

Well, it does say "Windows (amd64)". Anyway, I'll find out next week.

@victornoel
Copy link

@lukaseder the error message you got said "32-bit architecture x86 unsupported", is it possible you are using a 32-bit Windows version and not 64-bit?

@lukaseder
Copy link
Member

@victornoel Not really, all my machines are running 64 bit Windows, but indeed, this Visual Studio stuff installed itself in Program Files (x86), so perhaps that was 32 bit (the cl.exe and native-image.exe)

@sdeleuze
Copy link

sdeleuze commented Feb 6, 2023

For running native image on Windows, you can check this. Native image support on Windows will become simpler and more reliable in the upcoming GraalVM 23.0 release, see this related tweet and related issue (for now, I advise to not store your project in a path with spaces).

@dsvensson
Copy link

fyi, https://en.wikipedia.org/wiki/AMD64

@lukaseder
Copy link
Member

How to say I don't know jack about hardware without saying I don't know jack about hardware 😅.

@driverpt
Copy link

Any ETA on this one ?

@anshuman-mor
Copy link

@lukaseder - Is it just the generated Record* types which are to be registered with AOT or any other JOOQ related types?

@lukaseder
Copy link
Member

I don't know

@ThoSap
Copy link

ThoSap commented May 29, 2024

In my experience GraalVM reflection is needed for jOOQ records, POJOs, UDTs, DAOs, packages and routines.

Basically everything that is generated by the jOOQ code generation, except the table class that extends TableImpl<?>, as these classes are used with for example DSL#fetch*Into or returning which use reflection internally.

I have a project that is in use in production that uses Quarkus + jOOQ + GraalVM, and there I needed to add these reflection so working with tables, UDTs, packages/routines works at all in the native-image.

I generate the Quarkus @RegisterForReflection class like this with a custom Gradle task:
https://stackoverflow.com/questions/65798326/quarkus-native-reflection-configuration-for-whole-package/70870930#70870930 (outdated version without UDT's, packages/routines, only a small change in the regex is needed).

@anshuman-mor
Copy link

@lbkulinski & @ThoSap - Thanks for replying so quickly.

@ThoSap - Do you know something similar available for spring boot as well?

@lukaseder
Copy link
Member

Thanks a lot, @ThoSap

To everyone who is impatiently waiting for an ETA here, think about it this way. The Graal folks broke the WORA promise that Java had for so many years. This means, everyone has to now find out themselves how to work around this and it's really painful as this issue documents. You folks already made this choice voluntarily, but I didn't. For jOOQ, this would mean prioritising irrelevant (to jOOQ) infrastructure investigations over many other much more useful things (to jOOQ).

There are other, similar "weird" integrations that keep demanding attention to "non-essential" stuff. In jOOQ, everything SQL, mapping, database related is essential. Everything integration with what not is "non-essential." This includes:

  • Spring Boot integrations
  • Quarkus integrations
  • Micronaut integrations
  • R2DBC integrations (ugh)
  • Vert.x integrations
  • The gradle integration
  • Kotlin integration (though, this benefits a lot of folks)
  • Scala integration (don't get me started on Scala 3)

And for anyone who hates themselves, try combining 2-3 of the above for extra integration fun. So many gifts that keep on giving :(

I would be very happy to address this issue here if someone did the "hard parts" of setting up a build that works out of the box, everywhere, using jOOQ, e.g. based on one of these projects:

Once such an example is set up, jOOQ can regression test it, and continue adding new stuff.

Unfortunately, jOOQ doesn't have a devrel whose job is to write 100s of basic integration tutorials about arbitrary tech to generate some SEO traffic for a totally unrelated product 😅 (who enjoys this, really?)

So, this would be a highly appreciated contribution to the jOOQ ecosystem, if anyone is interested. The jOOQ CI/CD pipeline uses:

  • Linux (I can live without being able to reproduce stuff on Windows machines, though that would be really cool, too!)
  • Jenkins
  • Maven
  • bash

I prefer not to use anything else, including Gradle, GitHub actions, etc.

@ThoSap
Copy link

ThoSap commented May 29, 2024

@lbkulinski & @ThoSap - Thanks for replying so quickly.

@ThoSap - Do you know something similar available for spring boot as well?

If you use Gradle you could adapt my custom writeJooqReflectionClass Groovy task from the linked StackOverflow to generate the GraalVM Reflection hints reflect-config.json file for Spring Boot as outlined here.
https://docs.spring.io/spring-boot/reference/native-image/introducing-graalvm-native-images.html#native-image.introducing-graalvm-native-images.understanding-aot-processing

@lukaseder I think this is exactly what jOOQ should do for GraalVM compatibility in the jOOQ Maven/Gradle plugin, generate this GraalVM reflection-config.json file if enabled by a new Maven/Gradle code generation flag.
Of course with tests in place that test a native-image in runtime.
https://www.graalvm.org/jdk21/reference-manual/native-image/dynamic-features/Reflection/#manual-configuration

Maybe I could work on a PR for this functionality.

@lukaseder
Copy link
Member

@lukaseder I think this is exactly what jOOQ should do for GraalVM compatibility in the jOOQ Maven/Gradle plugin, generate this GraalVM reflection-config.json file if enabled by a new Maven/Gradle code generation flag.

Yes, that's what I had in mind. If I can then regression test this file with a simple demo project, I'll add this to the CI/CD pipeline, aand possibly even start refactoring internals to avoid reflection where unnecessary.

@rvaidya
Copy link

rvaidya commented Aug 8, 2024

I've been working on building my app using GraalVM native and so far jOOQ actually seems to be working fine with generated configs using automated tracing: https://www.graalvm.org/latest/reference-manual/native-image/metadata/AutomaticMetadataCollection/

Given that jOOQ is a code generation tool (so there's no static reflection config to prescribe) and this approach seemingly works, it really seems like this should be an exercise left to the user - at most perhaps include a link to the above doc page within jOOQ documentation.

[edit] As an addendum, both jooq (and its dependencies that GraalVM complains about) as well as your generated model source need to be marked for initialization at build time.

@bylidev
Copy link

bylidev commented Aug 13, 2024

@rvaidya I thought that but it seems they use reflection

java.lang.IllegalStateException: Could not construct new record
at org.jooq.impl.Tools.recordFactory(Tools.java:1509)
at org.jooq.impl.Tools.newRecord(Tools.java:1367)
at org.jooq.impl.Tools.newRecord(Tools.java:1360)

    static final <R extends Record> Supplier<R> recordFactory(Class<? extends R> type, AbstractRow<? extends R> row) {
        if (type != AbstractRecord.class && type != Record.class && !InternalRecord.class.isAssignableFrom(type)) {
            try {
                Constructor<? extends R> constructor = (Constructor)Reflect.accessible(type.getDeclaredConstructor());
                return () -> {
                    try {
                        return (Record)constructor.newInstance();
                    } catch (Exception var2) {
                        Exception e = var2;
                        throw new IllegalStateException("Could not construct new record", e);
                    }
                };
            } catch (Exception var3) {
                Exception e = var3;
                throw new IllegalStateException("Could not construct new record", e);
            }
        } else {

@rcomblen
Copy link

rcomblen commented Sep 9, 2024

Working happily with Spring Boot 3.3 using Native GraalVM and jOOQ.

I'm using DAOs as Spring beans in addition to the usual hand crafted queries.

I just add reflections to my classpath

<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.10.2</version>
</dependency>

annotate my SpringBoot application with

@ImportRuntimeHints(MyRuntimeHintsRegistrar.class)

Where MyRuntimeHintsRegistrar reads:

@Slf4j
public class MyRuntimeHintsRegistrar implements RuntimeHintsRegistrar {


    List<String> packagesToScan = List.of(
            "whatever.package.generated.jooq"
            // Add any other packages where generated classes need to be registered
    );

    private final BindingReflectionHintsRegistrar bindingReflectionHintsRegistrar = new BindingReflectionHintsRegistrar();


    @Override
    public void registerHints(RuntimeHints hint, ClassLoader classLoader) {
        for (String packageName : packagesToScan) {
            registerPackage(hint, packageName);
        }
    }

    private void registerPackage(RuntimeHints hint, String packageName) {
        Reflections reflections = new Reflections(packageName, new SubTypesScanner(false));
        Set<Class<?>> allTypes = reflections.getSubTypesOf(Object.class);
        log.info("Found " + allTypes.size() + " classes for package " + packageName);
        allTypes.stream().map(it -> it.getName()).sorted().forEach(it -> log.info("Registering " + it));
        allTypes.forEach(type -> {
            // Reusing behavior of @RRegisterReflectionForBinding annotation
            bindingReflectionHintsRegistrar.registerReflectionHints(hint.reflection(), type);
        });
        reflections.getSubTypesOf(Serializable.class).forEach(type -> hint.serialization().registerType(type));
    }
}

@rvaidya
Copy link

rvaidya commented Sep 10, 2024

@bylidev Reflection is used, but you can generate reflection metadata that can be passed to GraalVM using the automated tracing. Start your Java app up with automated tracing, and then exercise as much code as you can at runtime - either through automated tests or doing so by hand. The link in my earlier comment is the official documentation for this.

@bylidev
Copy link

bylidev commented Sep 10, 2024

@bylidev Reflection is used, but you can generate reflection metadata that can be passed to GraalVM using the automated tracing. Start your Java app up with automated tracing, and then exercise as much code as you can at runtime - either through automated tests or doing so by hand. The link in my earlier comment is the official documentation for this.

I tried using the GraalVM agent to do that, but it didn't work. Anyways, I'm going to try @rcomblen's solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests