kwhat / jnativehook

Global keyboard and mouse listeners for Java.
Other
1.73k stars 344 forks source link

Can't get this to custome jre as modular project #421

Open X-Engineer-001 opened 1 year ago

X-Engineer-001 commented 1 year ago

Hello, I'm just a undergraduate CSIE student who just graduated several months ago. I'm using the jnativehook-2.2.2.jar with eclipse on win 11 and win 10. When running in the IDE, anything works fine. However, even the most simple GlobalMouseListenerExample you provided can't make it to a custom jre.

If I use jlink to create a costume jre as modular project and run that jre after, I get this: Sep 23, 2022 7:59:44 PM com.github.kwhat.jnativehook.GlobalScreen SEVERE: URI scheme is not "file" Exception in thread "main" java.lang.UnsatisfiedLinkError: URI scheme is not "file" at com.github.kwhat.jnativehook@2.2.2/com.github.kwhat.jnativehook.GlobalScreen.(GlobalScreen.java:91) at test/test.GlobalMouseListenerExample.main(GlobalMouseListenerExample.java:31)

The module_info.java: module test { requires java.desktop; requires com.github.kwhat.jnativehook; exports test; }

The commands: C:\Users\fabin\eclipse-workspace\test>"C:\Program Files\Java\jdk-17.0.4.1\bin\jlink" --module-path "C:\Users\fabin\eclipse-workspace\test" --add-modules test --output jre C:\Users\fabin\eclipse-workspace\test>jre\bin\java -m test/test.GlobalMouseListenerExample

I also tried: C:\Users\fabin\eclipse-workspace\test>"C:\Program Files\Java\jdk-17.0.4.1\bin\jlink" --module-path "C:\Users\fabin\eclipse-workspace\test" --add-modules test,com.github.kwhat.jnativehook --output jre C:\Users\fabin\eclipse-workspace\test>jre\bin\java -m test/test.GlobalMouseListenerExample Got same result.

And note that the most baffling parts are that "jlink builded the custom jre without any error/exeption" and "it runs fine in IDE". It went wrong only when run as a built costume jre.

C:\Users\fabin\eclipse-workspace\test>"C:\Program Files\Java\jdk-17.0.4.1\bin\jdeps" --print-module-deps C:\Users\fabin\eclipse-workspace\test

Error: Missing dependencies: classes not found from the module path and classpath. To suppress this error, use --ignore-missing-deps to continue.

test test.GlobalMouseListenerExample -> com.github.kwhat.jnativehook.GlobalScreen not found test.GlobalMouseListenerExample -> com.github.kwhat.jnativehook.NativeHookException not found test.GlobalMouseListenerExample -> com.github.kwhat.jnativehook.mouse.NativeMouseEvent not found test.GlobalMouseListenerExample -> com.github.kwhat.jnativehook.mouse.NativeMouseInputListener not found test.GlobalMouseListenerExample -> com.github.kwhat.jnativehook.mouse.NativeMouseListener not found test.GlobalMouseListenerExample -> com.github.kwhat.jnativehook.mouse.NativeMouseMotionListener not found

(Annotation: I definitely had registered jnativehook-2.2.2.jar into module path, and I put it in "C:\Users\fabin\eclipse-workspace\test" which is the project directory of the project built with nothing more than the GlobalMouseListenerExample you provided)

Runing C:\Users\fabin\eclipse-workspace\test>"C:\Program Files\Java\jdk-17.0.4.1\bin\jdeps" --print-module-deps C:\Users\fabin\eclipse-workspace\test\bin\test which jdeps only the "GlobalMouseListenerExample.class" (as that's the only class in the Package "test") gives same result.

Giving you the whole test project directory: test.zip

X-Engineer-001 commented 1 year ago

I did too many search and too many test. I'm tired of trying something that seems to be unsolvable by me...... Pls help if I got something missing.

kwhat commented 1 year ago

To be honest, I have no idea how to use jlink or what it does but based on the exception I suspect you need to do your own native library loading.

As a convenience, this library has a built in loader that will try and extract the appropriate native shared library from the distribution jar. I cannot stress enough that this is a convenience to make getting up and running easy and was never designed as an end all distribution for everyone using this library.

Oracle and Sun before them expected the user of libraries like this to specify the java.library.path in addition to your normal class path. Anyone using this library outside of the prepackaged jar format or redistributing it for use with in a larger program should consider using this property. You will need to extract the appropriate .dll, .dylib or .so from the /lib/ path in the jar to the java.library.path you want to use in order to make it work.

As an additional convenience, you may override how this library locates the native libraries it loads by implementing your own NativeLibraryLocator. The getLibraries() method just needs to return an iterator of all (likely just one) native libraries you want to load. They just need to be read-accessible by the running Java process. In order for this library to use your NativeLibraryLocator implementation you will need to set the jnativehook.lib.locator property to your fully qualified class name. For example: java -jar my.jar -Djnativehook.lib.locator=my.fully.qulified.name.NativeLibraryLocator

You can take a look at the DefaultLibraryLocator to see how it works by default right now. I strongly suggest putting the files it is extracting from /lib/ in the JNativeHook jar to some place on the file system along with the rest of your jar dependencies.

I don't know how much longer this library locator mechanism will remain in this library. As previously mentioned, I provided this as a convenience to help people get up and running quickly. However, it seems that it ends up causing a lot of issues when people go to deploy this library. Forcing people to do something like the following well make them realize what their deployment / distribution should look like.

jar xf jnativehook-2.2.2.jar com/github/kwhat/jnativehook/lib
java -jar jnativehook-2.2.2.jar -Djava.library.path=com/github/kwhat/jnativehook/lib/linux/x86_64/

Hopefully that helps. Any thoughts on the NativeLibraryLocator staying or going would be appreciated.

X-Engineer-001 commented 1 year ago

Opps...... I'm fear that maybe this went out of the scope of my abilities, and I can't even confirm whether that's the case or not due to being busy currently. Despite not completely understanding, I really appreciate your reply. I'll comeback to study one day. Thank you.

siordache commented 1 year ago

I created a sample project that uses jlink to create a custom runtime image and jpackage to create platform-specific packages/installers for the NativeHookDemo application.

The project uses Gradle as the build tool and implements a custom NativeLibraryLocator.