We have an application that uses OR-Tools, which consist on several modules (maven, all of which are Spring Boot modules), in particular:
- optimizer module, which loads the or-tools DLL through the following code:
public class Optimizer {
static {
try {
// extracts .dll from or-tools-windows jar and copies it into C:\users\my-user\AppData\Local\Temp\temp_ortools
// calls System.load("C:\users\my-user\AppData\Local\Temp\temp_ortools\jniortools.dll")
carregaBibliotecasORTools();
} catch (Exception e) {
log.info(e.getMessage());
} catch (Error e) {
log.info(e.getMessage());
}
}
public static OptimizerData getOptimizerData() {
OptimizerData optimizerData = new OptimizerData();
System.out.println("Instantiating Solver");
optimizerData.solver = MPSolver.createSolver("SCIP");
System.out.println("Solver Instantiated");
return optimizerData;
}
}
- service module, which uses:
@Service
public class PlanningService{
public void executePlan() {
OptimizerData optimizerData = Optimizer.getOptimizerData();
...
}
}
- web module (spring-boot-starter-web dependency ), which makes the service available through a controller
We have successfully run the code on the following situations:
- Running a test method (on netbeans) on the Optimizer module , which calls the
getOptimizerDatamethod - Generating a fat jar with the 3 modules (by building the web module on netbeans) and running the fat jar. the endpoint call works fine
However, when we run the web module on Netbeans the following error message is shown when calling the endpoint:
2021-05-09 22:59:38.587 ERROR 19300 --- [nio-8020-exec-8] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.UnsatisfiedLinkError: com.google.ortools.linearsolver.main_research_linear_solverJNI.MPSolver_createSolver(Ljava/lang/String;)J] with root cause
Some important observations:
- This seems like a netbeans-specific issue given the fat jar works fine
- We have executed the following method (System.load) in order to verify whether the library had in fact been loaded:
public static void listAllLoadedNativeLibrariesFromJVM() {
ClassLoader appLoader = ClassLoader.getSystemClassLoader();
ClassLoader currentLoader = LibraryLoader.class.getClassLoader();
ClassLoader[] loaders = new ClassLoader[] { appLoader, currentLoader };
for (int i=0; i<loaders.length; i++) {
final String[] libraries = ClassScope.getLoadedLibraries(loaders[i]);
for (String library : libraries) {
System.out.println("Loader " + loaders[i].getClass().getName() + " : " + library);
}
}
}
The results from this method were:
- Test file in Optimizer module (which worked fine):
Loader sun.misc.Launcher$AppClassLoader : C:\Program Files\Java\jdk1.8.0_281\jre\bin\zip.dll
Loader sun.misc.Launcher$AppClassLoader : C:\Users\my-user\AppData\Local\Temp\temp_ortools\jniortools.dll
Loader sun.misc.Launcher$AppClassLoader : C:\Program Files\Java\jdk1.8.0_281\jre\bin\zip.dll
Loader sun.misc.Launcher$AppClassLoader : C:\Users\my-user\AppData\Local\Temp\temp_ortools\jniortools.dll
- Fat .jar generated by compiling the web module (which worked fine):
Loader sun.misc.Launcher$AppClassLoader : C:\Program Files\Java\jre1.8.0_281\bin\zip.dll
Loader sun.misc.Launcher$AppClassLoader : C:\Program Files\Java\jre1.8.0_281\bin\management.dll
Loader sun.misc.Launcher$AppClassLoader : C:\Program Files\Java\jre1.8.0_281\bin\net.dll
Loader sun.misc.Launcher$AppClassLoader : C:\Program Files\Java\jre1.8.0_281\bin\nio.dll
Loader sun.misc.Launcher$AppClassLoader : C:\Users\my-user\AppData\Local\Temp\temp_ortools\jniortools.dll
Loader org.springframework.boot.loader.LaunchedURLClassLoader : C:\Program Files\Java\jre1.8.0_281\bin\zip.dll
Loader org.springframework.boot.loader.LaunchedURLClassLoader : C:\Program Files\Java\jre1.8.0_281\bin\management.dll
Loader org.springframework.boot.loader.LaunchedURLClassLoader : C:\Program Files\Java\jre1.8.0_281\bin\net.dll
Loader org.springframework.boot.loader.LaunchedURLClassLoader : C:\Program Files\Java\jre1.8.0_281\bin\nio.dll
Loader org.springframework.boot.loader.LaunchedURLClassLoader : C:\Users\my-user\AppData\Local\Temp\temp_ortools\jniortools.dll
- Netbeans 'run' command on the web module
Loader sun.misc.Launcher$AppClassLoader : C:\Program Files\Java\jdk1.8.0_281\jre\bin\zip.dll
Loader sun.misc.Launcher$AppClassLoader : C:\Program Files\Java\jdk1.8.0_281\jre\bin\management.dll
Loader sun.misc.Launcher$AppClassLoader : C:\Program Files\Java\jdk1.8.0_281\jre\bin\net.dll
Loader sun.misc.Launcher$AppClassLoader : C:\Program Files\Java\jdk1.8.0_281\jre\bin\nio.dll
Loader sun.misc.Launcher$AppClassLoader : C:\Users\my-user\AppData\Local\Temp\temp_ortools\jniortools.dll
Loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader : C:\Program Files\Java\jdk1.8.0_281\jre\bin\zip.dll
Loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader : C:\Program Files\Java\jdk1.8.0_281\jre\bin\management.dll
Loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader : C:\Program Files\Java\jdk1.8.0_281\jre\bin\net.dll
Loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader : C:\Program Files\Java\jdk1.8.0_281\jre\bin\nio.dll
Loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader : C:\Users\my-user\AppData\Local\Temp\temp_ortools\jniortools.dll