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

Cannot open (null)/lib/libjawt.dylib #14

Open
mipastgt opened this issue Aug 10, 2022 · 8 comments
Open

Cannot open (null)/lib/libjawt.dylib #14

mipastgt opened this issue Aug 10, 2022 · 8 comments

Comments

@mipastgt
Copy link

I tried the latest Liberica NIK according to this announcement:
https://bell-sw.com/announcements/2022/08/05/liberica-native-image-kit-22-2-0-and-21-3-3-builds-are-out/

I installed the software on macOS 12.5 and verified that the given SwingSet2 demo worked like advertised.

Then I tried to do exactly the same with an application of my own which is a Jetbrains Compose desktop app but Compose also uses AWT for the windowing, so this should work. Building the software works like before without any error but when I try to run my application I only get this:

Cannot open (null)/lib/libjawt.dylib: dlopen((null)/lib/libjawt.dylib, 0x0009): tried: '(null)/lib/libjawt.dylib' (no such file)

It seems as if some path element is undefined (null) but I have no clue why. If there is no obvious solution to this problem and you are willing to have a look at it I could provide the full demo project and all build steps to reproduce the problem.

@voitylov
Copy link

Hi Michael!

Could you provide the means to reproduce this issue?

@mipastgt
Copy link
Author

The project can be found here: https://github.com/mipastgt/JavaForumStuttgartTalk2022/tree/main/PolySpiralMpp
./gradlew packageUberJarForCurrentOS should create the executable jar file in PolySpiralMpp/build/compose/jars/PolySpiral-macos-x64-1.0.0.jar
The step by step build commands can be found here:
commands.txt
and the build log is here:
build.txt

Thanks for looking into this!

@mipastgt
Copy link
Author

If this upload works you can skip building the project and just use the jar here:
PolySpiral-macos-x64-1.0.0.jar.zip

@petermz
Copy link
Collaborator

petermz commented Aug 11, 2022

Hi Michael, thank you for reporting this. We'll take a look

@AlexanderScherbatiy
Copy link

The "Cannot open (null)/lib/libjawt.dylib: dlopen((null)/lib/libjawt.dylib" exception is reported by https://github.com/JetBrains/skiko library.

It uses "java.home" to create a path to jawt lib and dlopen to dynamically access native JAWT_GetAWT method:
https://github.com/JetBrains/skiko/blob/c08102bbf9742c920c4ce6e90bffc09c5a202772/skiko/src/jvmMain/cpp/common/jawt.cc#L81

I checked the way where JAWT_GetAWT is called directly from Skiko_GetAWT method (Toolkit.getDefaultToolkit() is called before from java to initialize awt stuff):

extern "C" jboolean Skiko_GetAWT(JNIEnv *env, JAWT *awt) {
    return JAWT_GetAWT(env, awt);
}

and add jawt dependency to skiko shared lib:

diff --git a/skiko/build.gradle.kts b/skiko/build.gradle.kts
index 2bbfbeca..646c5c56 100644
--- a/skiko/build.gradle.kts
+++ b/skiko/build.gradle.kts
@@ -912,6 +912,8 @@ fun createLinkJvmBindings(
                     "-lGL",
                     "-lX11",
                     "-lfontconfig",
+                    "-ljawt",
+                    "-L$jdkHome/lib",

It works when I run SkiaAwtSample with java on my Linux desktop (should work on MacOS as well, though the path to lib may need to be updated on Windows).

But running a native image for SkiaAwtSample with these changes fails with exception that System.load("skiko-...") method from Library.loadLibraryOrCopy() method is unable to load skiko library because it depends on jawt.

https://github.com/JetBrains/skiko/blob/c08102bbf9742c920c4ce6e90bffc09c5a202772/skiko/src/jvmMain/kotlin/org/jetbrains/skiko/Library.kt#L20

./skiaawtsample.appkt 
Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: Can't load library: /home/user/.skiko/572ee76a5b715a182f9f0974c6e1cf705133b076e707a5fc9c73bc16990fa6a9/libskiko-linux-x64.so
	at com.oracle.svm.core.jdk.NativeLibrarySupport.loadLibraryAbsolute(NativeLibrarySupport.java:104)
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:125)
	at java.lang.Runtime.load0(Runtime.java:768)
	at java.lang.System.load(System.java:1837)
	at org.jetbrains.skiko.Library.loadLibraryOrCopy(Library.kt:20)
	at org.jetbrains.skiko.Library.findAndLoad(Library.kt:117)
	at org.jetbrains.skiko.Library.load(Library.kt:63)
ldd ~/.skiko/572ee76a5b715a182f9f0974c6e1cf705133b076e707a5fc9c73bc16990fa6a9/libskiko-linux-x64.so 
	linux-vdso.so.1 (0x00007ffdcbbfd000)
	libGL.so.1 => /lib/x86_64-linux-gnu/libGL.so.1 (0x00007f244b23a000)
	libX11.so.6 => /lib/x86_64-linux-gnu/libX11.so.6 (0x00007f244b0fd000)
	libfontconfig.so.1 => /lib/x86_64-linux-gnu/libfontconfig.so.1 (0x00007f244b0b6000)
	libjawt.so => not found
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f244af67000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f244ad75000)

I will try to look the other ways which could help to properly use JAWT_GetAWT native method with GraalVM in skiko library.

@AlexanderScherbatiy
Copy link

AlexanderScherbatiy commented Aug 23, 2022

The solution to use JAWT_GetAWT native method with GraalVM could be linking the skiko library with static jawt lib.
I checked it only with test example on my Linux desktop.

Example:
JAWTExample.java

public class JAWTExample {

    static {
        System.loadLibrary("JAWTExample");
    }

    public static void main(String[] args) {
        long jawt = getJAWT();
        System.out.printf("jawt: %d%n", jawt);

    }

    private static native long getJAWT();
}

JAWTExample.c

#include <jni.h>
#include <jawt_md.h>

#include "JAWTExample.h"

/*
 * Class:     JAWTExample
 * Method:    getJAWT
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL Java_JAWTExample_getJAWT(JNIEnv *env, jclass cls) {

    printf("[native] call getJAWT\n");

    JAWT *awt = new JAWT();
    awt->version = (jint)JAWT_VERSION_9;
    jboolean result = JAWT_GetAWT(env, awt);

    return (result == JNI_TRUE) ? (jlong) awt : 0;
}

Link static jawt library:

$GRAALVM/bin/javac -h . JAWTExample.java
g++ -g -shared -fPIC -I$GRAALVM/include -I$GRAALVM/include/linux -I. JAWTExample.c -o libJAWTExample.so -l:libjawt.a -l:libawt_xawt.a -l:libawt.a -L$GRAALVM/lib

The libJAWTExample.so does not have dependencies to jawt lib:

ldd libJAWTExample.so 
	linux-vdso.so.1 (0x00007fff621ec000)
	libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fbd0887f000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fbd08730000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbd0853e000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fbd08ae2000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fbd08523000)

JAWT_GetAWT symbol is included into the JAWTExample shared library:

nm -D libJAWTExample.so | grep JAWT_GetAWT
000000000000d210 T JAWT_GetAWT

Make a native image:

$GRAALVM/bin/native-image -classpath . -Djava.library.path=. JAWTExample

To run the native image it needs to pass -Djava.library.path=. parameter:

./jawtexample  -Djava.library.path=.
[native] call getJAWT
jawt: 93859320197264

I believe it should work for skiko library as well.

@AlexanderScherbatiy
Copy link

I created a request to update skiko lib so it would be possible to use it with GraalVM. JetBrains/skiko#580

@mipastgt
Copy link
Author

Thanks. I subscribed to the new issue too. Let's see what happens.

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

No branches or pull requests

4 participants