-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
[GR-24133] JNI error while building SWT native image on MacOS #2232
Comments
Ok so I have some kind of update for this ticket. After many tests, I finally discovered it works as expected if I include the SWT source code manually in my project source directory. The native-image performs the compilation and the executable works fine on MacOS now. So it seems that, using the official SWT jar file, native-image isn't able to perform the compilation. But if I remove the jar from the classpath and instead copy the SWT source code in my source dir, let maven compile it, create a jar file then execute native image, it works flawlessly. Don't know what's wrong with the official MacOS cocoa SWT jar, here is the URL of the latest version : https://repo1.maven.org/maven2/org/eclipse/platform/org.eclipse.swt.cocoa.macosx.x86_64/3.114.0/org.eclipse.swt.cocoa.macosx.x86_64-3.114.0.jar Is it because the jar includes shared libraries ? But it was the same for the Windows and Linux versions of the jar, which both work fine |
I'm running into the same issue on graalvm java 11. Any idea how to fix it when I'm not using maven? I'm using gradle for build, and I'm running it on github actions. |
I got it working successfully on Windows, Linux and MacOS with GraalVM 20.0.0 java 11 version. I just took the SWT java sources and add them to my project source path (do not use the JAR provided by SWT), run the GraalVM agent to generate config files for JNI, reflection, resources and proxies, and it will work at native compilation time. Of course you will have to also download the SWT native shared libraries and add the "-Dswt.library.path=/path/to/shared/libraries" option when running the native image. Just take care because SWT sources differ for each operating system. |
I did some more investigation here and it seems like the main difference is that the SWT jar is compiled using the eclipse compiler, and not the standard java compiler. After some further investigation, it seems to be mainly a difference in static initialization order. I was able to reproduce similar issue even at runtime, with the "wrong" initialization order. The first error that actually appear is:
Later errors are probably caused by this one, so I think they should be ignored until proved otherwise. The issue boils down to a circular dependency between SWT's OS class and Selector class. OS class has This somehow appears to work when public enum EnumClass {
VAL1("val1");
public final String x;
EnumClass(String param) {
x = param;
TestClass.takeEnum(this, param);
}
}
public class TestClass {
public static final String VAL = EnumClass.VAL1.x;
private static java.util.Map<String, EnumClass> VALUES;
public static void takeEnum(EnumClass e, String s) {
if (VALUES == null) {
VALUES = new java.util.HashMap<>();
}
VALUES.put(s, e);
}
}
public class Main {
public static void main(String... args) {
System.out.println(TestClass.VAL);
}
} Now just if we compile and run it with java, it works just fine. It also works when it's compiled "naively" with But in SWT case, the generated configuration causes initializing some classes at build time. In this example,
we get the following stacktrace:
Which is exactly what the issue is in case of SWT, but in different stage of compilation (because I'm forcing it with a parameter, and in case of SWT it's indirectly forced by configuration) I'm going to investigate further but this is what I found so far. |
The main difference that I can see in the bytecode, is that eclipse compiler generates a synthetic method that initializes tableswitch map, while With this in mind, I got a small self contained case that reproduces the issue: // EnumClass.class
public enum EnumClass {
VAL1("val1");
public final String x;
EnumClass(String param) {
x = param;
TestClass.takeEnum(this, param);
}
static EnumClass value(String s) {
return TestClass.getEnum(s);
}
}
// Main.class
import java.lang.reflect.*;
public class Main {
public static void main(String... args) throws Throwable { // used reflection here to generate configuration that I then reused as "jni" config
System.out.println(TestClass.getEnum("val1"));
Method m = Main.class.getDeclaredMethod("doThing", String.class);
System.out.println(m.invoke(null, "val1"));
}
static long doThing(String s) {
switch (EnumClass.value(s)) {
case VAL1: return 0;
default: return -1;
}
}
}
// TestClass.class
public class TestClass {
public static final String VAL = EnumClass.VAL1.x;
private static java.util.Map<String, EnumClass> VALUES;
public static void takeEnum(EnumClass e, String s) {
if (VALUES == null) {
VALUES = new java.util.HashMap<>();
}
VALUES.put(s, e);
}
public static EnumClass getEnum(String s) { return VALUES.get(s); }
} Then I add this to jni config json file: [
{
"name":"Main",
"methods":[{"name":"doThing","parameterTypes":["java.lang.String"] }]
}
] If the code is compiled with javac, it works fine. If it's compiled with
For completeness, here is bytecode comparison: |
I think @vjovanov is currently working on a fix for this |
@christianwimmer FYI: There is an Internal ticket (GR-24133) for this issue |
Any progress with this issue? |
Describe GraalVM and your environment :
Run the following to capture compiler version
cl.exe
cc -v
gcc --version
Run the following to capture linker version
cl.exe
cc -Wl,-v
gcc -Wl,--version
java -Xinternalversion
:Have you verified this issue still happens when using the latest snapshot?
No
Describe the issue
Try to build a simple Hello World SWT application works both on Linux and Windows 10 with GraalVM 20.0.0 java8 CE, but not on Mac OS. Despite running the agent to generate JNI and other configuration files, it fails at build image time with an error :
Describe the full native-image command
Capture full native-image command by running with the `--verbose` flag e.g.:
Code snippet or code repository that reproduces the issue
Steps to reproduce the issue
Please include both build steps as well as run steps
./mvnw -Pagent clean package
to generate/update configuration files with GraalVM agent./mvnw -Pnative clean package
to launch the native image buildingExpected behavior
On Windows 10 and Ubuntu 18.04 LTS, using same version of GraalVM 20.0.0 java 8 CE, native image building succeed and the given native image work as expected : a SWT window opens with a Hello world message.
On Mac OS, it should work the same way.
Additional context
Don't know if it's the problem, but on MacOS, I had to add the VM option
-XstartOnFirstThread
in order to make the Java program and the GraalVM agent work :produces this error :
After adding the
-XstartOnFirstThread
VM option to the java command, the agent works as expected the SWT window opens correctly and the GraalVM config files are generated. But still the native image fails at build time. I tried to add the option-J-XstartOnFirstThread
to the native-image command but it didn't solve the problem.The text was updated successfully, but these errors were encountered: