I have written a C++ JNI Java Launcher. It works if I launch a java program that doesn't use JavaFX, but it creates a core dump if I try to launch a JavaFX program with it. Here's the code:
The core dump only occurs if I use my native launcher. If I run the JavaFX program with the same arguments using java
at the command line, there's no problem. It runs as expected.
Here's the content of the hs_err file, in a pastebin.
Rather than paste in code from a handful of files, I created a repository with two branches with complete runnable examples.
You can run the examples by editing build.sh
and run-native.sh
and changing the line jdk="/usr/lib/jvm/java-11-oracle"
to be accurate for your system. Then:
./build.sh #compiles the java program and cpp program
./run-native.sh #Sets LD_LIBRARY_PATH and runs the compiled cpp program
or
./run-with-java.sh #only on "withjfx" branch, runs via java at cli.
As you should see, the No JavaFX
version runs fine, but the JavaFX
version only runs via invoking the java
executable, it core dumps if executed via my native launcher.
Finally, here's the dump I get when I try to run the JavaFX version using the native launcher:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007f77513575d8, pid=15281, tid=15301
#
# JRE version: Java(TM) SE Runtime Environment (11.0.1+13) (build 11.0.1+13-LTS)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (11.0.1+13-LTS, mixed mode, tiered, compressed oops, g1 gc, linux-amd64)
# Problematic frame:
# j java.util.Arrays$ArrayList.<init>([Ljava/lang/Object;)V+6 java.base@11.0.1
#
# Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport %p %s %c %d %P" (or dumping to /home/joshua/work/javalaunch/core.15281)
#
# An error report file with more information is saved as:
# /home/joshua/work/javalaunch/hs_err_pid15281.log
Compiled method (c2) 326 208 4 java.util.Objects::requireNonNull (14 bytes)
total in heap [0x00007f7758e10d90,0x00007f7758e10fc8] = 568
relocation [0x00007f7758e10f08,0x00007f7758e10f18] = 16
main code [0x00007f7758e10f20,0x00007f7758e10f60] = 64
stub code [0x00007f7758e10f60,0x00007f7758e10f78] = 24
metadata [0x00007f7758e10f78,0x00007f7758e10f80] = 8
scopes data [0x00007f7758e10f80,0x00007f7758e10f90] = 16
scopes pcs [0x00007f7758e10f90,0x00007f7758e10fc0] = 48
dependencies [0x00007f7758e10fc0,0x00007f7758e10fc8] = 8
Could not load hsdis-amd64.so; library not loadable; PrintAssembly is disabled
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
#
./run-native.sh: line 6: 15281 Aborted (core dumped) ./bin/launch
On the recommendation of a user here, based on the previous crash, I installed hsdis-amd64.so onto my system and pointed LD_LIBRARY_PATH
at it. I still get a core dump, it looks like all it did was let the core dump load a disassembler:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007f9e6e2015d8, pid=17530, tid=17550
#
# JRE version: Java(TM) SE Runtime Environment (11.0.1+13) (build 11.0.1+13-LTS)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (11.0.1+13-LTS, mixed mode, tiered, compressed oops, g1 gc, linux-amd64)
# Problematic frame:
# j java.util.Arrays$ArrayList.<init>([Ljava/lang/Object;)V+6 java.base@11.0.1
#
# Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport %p %s %c %d %P" (or dumping to /home/joshua/work/so-question/core.17530)
#
# An error report file with more information is saved as:
# /home/joshua/work/so-question/hs_err_pid17530.log
Compiled method (c2) 372 187 4 java.util.Objects::requireNonNull (14 bytes)
total in heap [0x00007f9e75cbb890,0x00007f9e75cbbac8] = 568
relocation [0x00007f9e75cbba08,0x00007f9e75cbba18] = 16
main code [0x00007f9e75cbba20,0x00007f9e75cbba60] = 64
stub code [0x00007f9e75cbba60,0x00007f9e75cbba78] = 24
metadata [0x00007f9e75cbba78,0x00007f9e75cbba80] = 8
scopes data [0x00007f9e75cbba80,0x00007f9e75cbba90] = 16
scopes pcs [0x00007f9e75cbba90,0x00007f9e75cbbac0] = 48
dependencies [0x00007f9e75cbbac0,0x00007f9e75cbbac8] = 8
Loaded disassembler from hsdis-amd64.so
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
#
./run-native.sh: line 6: 17530 Aborted (core dumped) ./bin/launch
Update: I've duplicated this issue on both Ubuntu 18.04 and Windows 7.
I figured it out. The issue is in on line 35 with the arguments that are passed the JVM's main method:
env->CallStaticVoidMethod( cls, main, " ");
We are passing a c-string to Java where java expect a java.lang.String[]. Once anyone tries to read that argument, the JVM crashes. JavaFX must be reading the arguments at some point between main and start(), and crashing as a result.
The correct line is either
env->CallStaticVoidMethod( cls, main, "(I)V");
(I haven't tested this one, but it's the common line from the example code provided by the java folks)
or:
jclass classString = env->FindClass("java/lang/String");
jobjectArray argsToJava = env->NewObjectArray(0, classString, NULL);
env->CallStaticVoidMethod( cls, main, argsToJava );