Maven project in Intellij not finding native dll files

Started by sterfpaul, September 29, 2017, 14:58:09

Previous topic - Next topic

sterfpaul

Runing the example code from https://www.lwjgl.org/guide. Doesn't seem to work for me in Intellij.

I copied the dependencies from https://www.lwjgl.org/customize.

When i run my main class i get the following exception:

Quote[LWJGL] Failed to load a library. Possible solutions:
   a) Add the directory that contains the shared library to -Djava.library.path or -Dorg.lwjgl.librarypath.
   b) Add the JAR that contains the shared library to the classpath.
[LWJGL] Enable debug mode with -Dorg.lwjgl.util.Debug=true for better diagnostics.
[LWJGL] Enable the SharedLibraryLoader debug mode with -Dorg.lwjgl.util.DebugLoader=true for better diagnostics.
Exception in thread "main" java.lang.UnsatisfiedLinkError: Failed to locate library: lwjgl.dll
   at org.lwjgl@3.1.3/org.lwjgl.system.Library.loadSystem(Library.java:146)
   at org.lwjgl@3.1.3/org.lwjgl.system.Library.loadSystem(Library.java:66)
   at org.lwjgl@3.1.3/org.lwjgl.system.Library.<clinit>(Library.java:49)
   at org.lwjgl@3.1.3/org.lwjgl.system.MemoryUtil.<clinit>(MemoryUtil.java:60)
   at org.lwjgl@3.1.3/org.lwjgl.system.MemoryStack.<init>(MemoryStack.java:60)
   at org.lwjgl@3.1.3/org.lwjgl.system.MemoryStack.create(MemoryStack.java:79)
   at org.lwjgl@3.1.3/org.lwjgl.system.MemoryStack.create(MemoryStack.java:70)
   at java.base/java.lang.ThreadLocal$SuppliedThreadLocal.initialValue(ThreadLocal.java:284)
   at java.base/java.lang.ThreadLocal.setInitialValue(ThreadLocal.java:180)
   at java.base/java.lang.ThreadLocal.get(ThreadLocal.java:170)
   at org.lwjgl@3.1.3/org.lwjgl.system.MemoryStack.stackGet(MemoryStack.java:605)
   at org.lwjgl@3.1.3/org.lwjgl.system.MemoryStack.stackPush(MemoryStack.java:614)
   at org.lwjgl@3.1.3/org.lwjgl.system.Callback.<clinit>(Callback.java:38)

So it seems like the classpath is not setup correctly.

Intellij start the program with the following command:

Quote"D:\Program Files\Java\jdk-9\bin\java" "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2017.1.1\lib\idea_rt.jar=54444:D:\Program Files\JetBrains\IntelliJ IDEA 2017.1.1\bin" -Dfile.encoding=UTF-8 -p D:\Projects\civcraft\civcraft-opengl\target\classes;<my maven repo>\repository\org\lwjgl\lwjgl-opengl\3.1.3\lwjgl-opengl-3.1.3.jar;<my maven repo>\repository\org\lwjgl\lwjgl\3.1.3\lwjgl-3.1.3.jar;<my maven repo>\repository\org\lwjgl\lwjgl-glfw\3.1.3\lwjgl-glfw-3.1.3.jar;<my maven repo>\repository\org\lwjgl\lwjgl\3.1.3\lwjgl-3.1.3-natives-windows.jar;<my maven repo>\repository\org\lwjgl\lwjgl-opengl\3.1.3\lwjgl-opengl-3.1.3-natives-windows.jar;<my maven repo>\repository\org\lwjgl\lwjgl-glfw\3.1.3\lwjgl-glfw-3.1.3-natives-windows.jar;<my maven repo>\repository\org\slf4j\slf4j-api\1.7.21\slf4j-api-1.7.21.jar;<my maven repo>\repository\org\apache\logging\log4j\log4j-core\2.4.1\log4j-core-2.4.1.jar;<my maven repo>\repository\org\apache\logging\log4j\log4j-api\2.4.1\log4j-api-2.4.1.jar;<my maven repo>\repository\com\google\inject\guice\4.1.0\guice-4.1.0.jar;<my maven repo>\repository\javax\inject\javax.inject\1\javax.inject-1.jar;<my maven repo>\repository\aopalliance\aopalliance\1.0\aopalliance-1.0.jar;<my maven repo>\repository\com\google\guava\guava\19.0\guava-19.0.jar;<my maven repo>\repository\com\google\inject\extensions\guice-assistedinject\4.1.0\guice-assistedinject-4.1.0.jar;<my maven repo>\repository\com\google\inject\extensions\guice-multibindings\4.1.0\guice-multibindings-4.1.0.jar -m nl.civcraft.opengl/nl.civcraft.opengl.CivcraftOpenGl

This seems to put the native jars on the classpath.

I'm using Intellij Ultimate 2017.2.5 and JDK-9 on windows.

Does anyone know what i'm doing wrong?

sterfpaul

I found that using Library.class.getResource("lwjgl.dll") returns null, while Library.class.getClassLoader().getResource("lwjgl.dll") does return the dll Resource.
This seems to be why the SharedLibraryLoader is not started.

sterfpaul

As a workaround I extracted the dlls and added them as a library. But i would still like to know why the 'normal' route didn't work.

spasi

What output do you get when running with -Dorg.lwjgl.util.Debug=true and  -Dorg.lwjgl.util.DebugLoader=true?

Also, the Install page of the LWJGL 3 wiki might help.

sterfpaul

Quote[LWJGL] Version: 3.1.3 SNAPSHOT
[LWJGL]     OS: Windows 10 v10.0
[LWJGL]    JRE: 9 amd64
[LWJGL]    JVM: OpenJDK 64-Bit Server VM v9+181 by Oracle Corporation
[LWJGL] Loading library (system): lwjgl
[LWJGL]    lwjgl.dll not found in java.library.path
[LWJGL] Failed to load a library. Possible solutions:
   a) Add the directory that contains the shared library to -Djava.library.path or -Dorg.lwjgl.librarypath.
   b) Add the JAR that contains the shared library to the classpath.
Exception in thread "main" java.lang.UnsatisfiedLinkError: Failed to locate library: lwjgl.dll

spasi

I was able to reproduce this and it is indeed a problem with Class.getResource() that breaks the SharedLibraryLoader. Using context.getClassLoader().getResource() fixes it, the next snapshot (3.1.4 build 3) will work with all JARs in the module path. Details:

The Class.getResource() method has been revised in Java 9 to not return any non-class resources, unless they belong to the same module as the module that defines the receiver class (+ access restrictions based on the caller and whether the module is open or not). When the LWJGL JAR files are added to the module path, they become automatic modules, they can access all other automatic modules and the unnamed module, and everything else can access them. The problem is that the natives JAR is a different module from the corresponding classes JAR. So, Class.getResource() cannot access the native libraries, because it doesn't look anywhere else other than the module of the class. Going through the ClassLoader bypasses this restriction, it is able to look into all open modules and find the resource.

There are two workarounds that can make it work with the current binaries:

- Use the classpath instead of the module path for LWJGL.
- Use the new --patch-module parameter for all LWJGL modules. For example:

java -cp <classpath> -p <module path> --add-modules ALL-MODULE-PATH \
--patch-module org.lwjgl=lwjgl-natives-windows.jar \
--patch-module org.lwjgl.glfw=lwjgl-glfw-natives-windows.jar \
...more here.. \
my.main.Class

sterfpaul