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

fix: Ensure to load resource with global class loader #61

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

gudzpoz
Copy link

@gudzpoz gudzpoz commented Mar 15, 2024

Description

When gdx-jnigen-loader is put on the module path (to be loaded as an automatically named module in JPMS), it cannot load any libraries in a separate JAR anymore. This patch contains a simple fix to hopefully make things work when gdx-jnigen-loader is used as a named module.

Explanation

After Java 9, all classes are put within some modules. There are three kinds of modules:

  1. Unnamed modules: where classes from class path are put.
  2. Automatic modules: where classes from module path are put when the JAR doesn't explicitly declare a module.
  3. Explicitly declared modules.

With JPMS, Class#getResource by default loads resources only
from the current module, making SharedLibraryLoader malfunction,
whose purpose is to load libraries from other JARs (modules). In contrast, ClassLoader#getResource tries to find resources from all loaded modules, which should be used instead to allow using jnigen as an automatic module.

Reproducing Steps

Preparations

$ # The jnigen loader JAR
$ wget https://repo1.maven.org/maven2/com/badlogicgames/gdx/gdx-jnigen-loader/2.5.1/gdx-jnigen-loader-2.5.1.jar
$ # A JAR containing binaries built with jnigen
$ wget https://repo1.maven.org/maven2/party/iroiro/luajava/lua54-platform/3.5.0/lua54-platform-3.5.0-natives-desktop.jar

A Working Example

$ jshell --class-path lua54-platform-3.5.0-natives-desktop.jar:gdx-jnigen-loader-2.5.1.jar
jshell> import com.badlogic.gdx.utils.SharedLibraryLoader;
jshell> var loader = new SharedLibraryLoader();
jshell> loader.load("lua54");
jshell> // Library loaded with no exception thrown

A Failing One

$ jshell --module-path lua54-platform-3.5.0-natives-desktop.jar:gdx-jnigen-loader-2.5.1.jar --add-module gdx.jnigen.loader
jshell> import com.badlogic.gdx.utils.SharedLibraryLoader;
jshell> var loader = new SharedLibraryLoader();
jshell> loader.load("lua54");
|  Exception com.badlogic.gdx.utils.SharedLibraryLoadRuntimeException: Couldn't load shared library 'liblua5464.so' for target: Linux, x86, 64-bit
|        at SharedLibraryLoader.load (SharedLibraryLoader.java:174)
|        at (#4:1)
|  Caused by: com.badlogic.gdx.utils.SharedLibraryLoadRuntimeException: Unable to read file for extraction: liblua5464.so
|        at SharedLibraryLoader.readFile (SharedLibraryLoader.java:183)
|        at SharedLibraryLoader.loadFile (SharedLibraryLoader.java:339)
|        at SharedLibraryLoader.load (SharedLibraryLoader.java:170)
|        ...

@Berstanio
Copy link
Contributor

Hi, thank you for the detailed description!
When reading up on the docs of ClassLoader#getResource, I noticed the following:

Resources in named modules are subject to the encapsulation rules specified by Module.getResourceAsStream. Additionally, and except for the special case where the resource has a name ending with ".class", this method will only find resources in packages of named modules when the package is opened unconditionally (even if the caller of this method is in the same module as the resource).

(https://download.java.net/java/early_access/panama/docs/api/java.base/java/lang/ClassLoader.html)

I'm not really familiar with java modules, so I'm not sure about the implication of this. But I think we should be unaffected, since all resources are in the root directory?

@gudzpoz
Copy link
Author

gudzpoz commented Mar 15, 2024

I couldn't find any info on resources in root directories of modules, but they indeed seem opened when testing with the following setup.

+- module-info.java  -> exports only b.c
+- b/
|  +- c/
|  |  +- C.class
|  |  \- C.txt       -> accessible
|  |
|  +- B.class
|  \- B.txt          -> inaccessible
|
\- A.txt             -> accessible!!

But I don't think it will be a problem anyway. The JAR generated by the Ant pack-native task does not contain module-info.java, which means the JAR for binaries will never be an explicitly declared module, unless the user manually rebundles. (The other two categories, i.e., unnamed modules and automatic modules, simply open every package.)

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

Successfully merging this pull request may close these issues.

None yet

2 participants