lightgbm4j icon indicating copy to clipboard operation
lightgbm4j copied to clipboard

UnsatisfiedLinkError: 'long com.microsoft.ml.lightgbm.lightgbmlibJNI.new_voidpp()'

Open mbicanic opened this issue 1 year ago • 1 comments

I'm trying to use lightgbm4j to integrate a LightGBM model into a Flink Java application, managed through Maven.

Everything works without issues on my local Windows and PopOS! machines, but fails on CentOS7 and RHEL9.3 remote servers. The only error I receive is the one in the title:

java.lang.UnsatisfiedLinkError: 'long com.microsoft.ml.lightgbm.lightgbmlibJNI.new_voidpp()'
  at com.microsoft.ml.lightgbm.lightgbmlibJNI.new_voidpp(Native Method)
  at com.microsoft.ml.lightgbm.lightgbmlib.new_voidpp(lightgbmlib.java:785)
  at io.github.metarank.lightgbm4j.LGBMBooster.loadModelFromString(LGBMBooster.java:236)
  ...

I am aware CentOS7 is fairly outdated by today's standards, but I would expect things to work just fine on RHEL9.

I inspected the lib_lightgbm.so library within the official lightgbm4j JAR (downloaded from Maven Repository) and found that its dependencies are:

  • libstdc++.so.6
  • libm.so.6
  • libgomp.so.1
    • I know this one can be an issue, so I triple checked - it is installed and available
  • libgcc_s.so.1
  • libpthread.so.0
  • libc.so.6
  • ld-linux-x86-64.so.2

All of the libraries are present on all the Linux machines (PopOS!, CentOS7, RHEL9.3). glibc is 2.34 on RHEL9.3, 2.14 on CentOS7 and 2.35 on PopOS!.

I build the project using mvn clean compile assembly:single to get a fat JAR with all dependencies inside. After running it with java -Djava.library.path=<paths_to_dirs_containing_the_native_libraries> -jar target/fatjar.jar, it fails due to the error mentioned above.

I also unzipped the official JAR and extracted the lib_lightgbm.so and lib_lightgbm_swig.so libraries to a custom directory. Then I built a tiny Java program to check whether loading the lightgbm libraries works via a System.loadLibrary("_lightgbm"); call:

public class Main {
  static {
    System.loadLibrary("_lightgbm");
    System.loadLibrary("_lightgbm_swig");
  }
  public static void main(String[] args) {
    System.out.println(System.getProperty("java.library.path"));
  }
}

(note that the library name has an underscore because that's how it's distributed in the official JAR, and Java automatically appends the lib prefix to the name, so it effectively searches for lib_lightgbm.so, which is how the file is named in the JAR).

The mini program works fine on the RHEL9.3 machine - there are no errors, and the program outputs the following paths: /usr/lib64:/usr/lib:/path/to/lgbm/library/extracted/from/official/jar

Any help would be appreciated!

mbicanic avatar Feb 20 '24 12:02 mbicanic

Update: the application successfully starts when I provide the LIGHTGBM_NATIVE_LIB_PATH environment variable, which shouldn't have any effect on the application (I literally just copied your .so files into a different location, without rebuilding).

mbicanic avatar Feb 20 '24 13:02 mbicanic