问题
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:
- Install Microsoft Visual C++ Redistributable for Visual Studio
- Download and extract the OR-Tools library for Java
- 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).
- 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>
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