Google OR-Tools in Intellij: UnsatisfiedLinkError

放肆的年华 提交于 2020-06-28 05:58:59

问题


I am setting up a java framework that should use the Google OR-Tools. The code below compiles successfully, but throws an exception at runtime:

Exception in thread "main" java.lang.UnsatisfiedLinkError: com.google.ortools.linearsolver.operations_research_linear_solverJNI.MPSolver_CLP_LINEAR_PROGRAMMING_get()I
    at com.google.ortools.linearsolver.operations_research_linear_solverJNI.MPSolver_CLP_LINEAR_PROGRAMMING_get(Native Method)
    at com.google.ortools.linearsolver.MPSolver$OptimizationProblemType.<clinit>(MPSolver.java:221)
    at Main.main(Main.java:15)

I am using Intellij 2018.3 on Windows 10. I spent a lot of time trying to get this run, but unsuccessful. Based on what I found on the internet, the exception might be caused by poor linking and/or missing external libraries on which OR-Tools depends. However, I don't have the background to resolve this issue, and also Intellij does not highlight anything. Any idea what the problem is?

For completion, this is the code I run:

import com.google.ortools.linearsolver.MPObjective;
import com.google.ortools.linearsolver.MPSolver;
import com.google.ortools.linearsolver.MPVariable;

public final class Main {

  public static void main(String[] args) {

    // Create the linear solver with the GLOP backend.
    MPSolver solver =
        new MPSolver("SimpleLpProgram", MPSolver.OptimizationProblemType.GLOP_LINEAR_PROGRAMMING);

    // Create the variables x and y.
    MPVariable x = solver.makeNumVar(0.0, 1.0, "x");
    MPVariable y = solver.makeNumVar(0.0, 2.0, "y");

    System.out.println("Number of variables = " + solver.numVariables());

    // Create a linear constraint, 0 <= x + y <= 2.
    MPConstraint ct = solver.makeConstraint(0.0, 2.0, "ct");
    ct.setCoefficient(x, 1);
    ct.setCoefficient(y, 1);

    System.out.println("Number of constraints = " + solver.numConstraints());

    // Create the objective function, 3 * x + y.
    MPObjective objective = solver.objective();
    objective.setCoefficient(x, 3);
    objective.setCoefficient(y, 1);
    objective.setMaximization();

    solver.solve();

    System.out.println("Solution:");
    System.out.println("Objective value = " + objective.value());
    System.out.println("x = " + x.solutionValue());
    System.out.println("y = " + y.solutionValue());
  }
}

回答1:


Disclaimer: more a long comment than an answer...

note: I supposed you are using the github repository of or-tools if you used the binary package it should be more or less the same...

1) You must load the jni library which will load the OR-Tools C++ libraries and its dependencies...

/** Simple linear programming example.*/
public class Main {
  static {
    System.loadLibrary("jniortools");
  }

  public static void main(String[] args) throws Exception {

2) Did you manage to run the java samples ?

make run SOURCE=ortools/linear_solver/samples/SimpleLpProgram.java

ref: https://developers.google.com/optimization/introduction/java#simple_example

3) As Kayaman pointed out, you must pass the folder where the java runtime can find the native libraries (i.e. the JNI wrapper jniortools.dll and its dependencies libortools.dll)

if you look at the console log you'll see the full command line:

java -Xss2048k -Djava.library.path=lib -cp lib\sample.jar;lib\com.google.ortools.jar;lib\protobuf.jar ...\sample

Which comes from, the makefiles/Makefile.java file:

JAVAFLAGS = -Djava.library.path=$(LIB_DIR)
...
ifeq ($(SOURCE_SUFFIX),.java) # Those rules will be used if SOURCE contain a .java file
$(CLASS_DIR)/$(SOURCE_NAME): $(SOURCE) $(JAVA_OR_TOOLS_LIBS) | $(CLASS_DIR)
    -$(DELREC) $(CLASS_DIR)$S$(SOURCE_NAME)
    -$(MKDIR_P) $(CLASS_DIR)$S$(SOURCE_NAME)
    "$(JAVAC_BIN)" -d $(CLASS_DIR)$S$(SOURCE_NAME) \
 -cp $(LIB_DIR)$Scom.google.ortools.jar$(CPSEP)$(LIB_DIR)$Sprotobuf.jar \
 $(SOURCE_PATH)
...
.PHONY: run # Run a Java program.
run: build
    "$(JAVA_BIN)" -Xss2048k $(JAVAFLAGS) \
 -cp $(LIB_DIR)$S$(SOURCE_NAME)$J$(CPSEP)$(LIB_DIR)$Scom.google.ortools.jar$(CPSEP)$(LIB_DIR)$Sprotobuf.jar \
 $(SOURCE_NAME) $(ARGS)
endif

src: https://github.com/google/or-tools/blob/46173008fdb15dae1dca0e8fa42a21ed6190b6e4/makefiles/Makefile.java.mk#L15 and https://github.com/google/or-tools/blob/46173008fdb15dae1dca0e8fa42a21ed6190b6e4/makefiles/Makefile.java.mk#L328-L333

note: you can run make detect_java to know the flags i.e. value of LIB_DIR note: if you did use the precompiled package the Makefile is here: https://github.com/google/or-tools/blob/stable/tools/Makefile.cc.java.dotnet

Then after you can try to add this option in Intellij...

You must understand that or-tools is a set of C++ native libraries which are wrapped to Java using the SWIG generator.




回答2:


To make it work using Intellij (over a windows machine) you need to:

  1. Install Microsoft Visual C++ Redistributable for Visual Studio
  2. Download and extract the OR-Tools library for Java
  3. In intellij, add jar dependency to the 2 jars under the lib folder of the extracted files (each of the 2 jars separately, do not add to lib folder itself. This is why).
  4. Add the lib library path to VM options. In Intellij edit your run-configuration and add to vm options: -Djava.library.path=<path to the lib folder that hold the jars>
  5. Load the jni library statically by adding the below code to your class (as mentioned here.)

    static { System.loadLibrary("jniortools"); }



来源:https://stackoverflow.com/questions/58819070/google-or-tools-in-intellij-unsatisfiedlinkerror

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!