title: Google OR-Tools: Getting java.lang.UnsatisfiedLinkError: com.google.ortools.util.mainJNI.new_Domain__SWIG_2(JJ)J for JobShop problem
body: <p>I am attempting to run the JobShop problem in Java. An example for this does not exist in the examples/java folder, but it does exist in the C++, C# and Python examples. So I took the C# example, and converted it to Java. It compiles fine, but it gives me a SWIG linker error. Where am I going wrong?</p>
  
  <p>Here is the source code that compiles fine on my machine:</p>
  
  <pre><code>import com.google.ortools.sat.CpModel;
  import com.google.ortools.sat.CpSolver;
  import com.google.ortools.sat.CpSolverStatus;
  import com.google.ortools.sat.IntVar;
  import com.google.ortools.sat.IntervalVar;
  
  import java.util.ArrayList;
  import java.util.List;
  import java.util.SortedMap;
  import java.util.TreeMap;
  
  /**
   * JobShop example.
   *
   */
  
  public class JobshopSat {
      static class Task {
          public Task(int taskId, int jobId, int duration, int machine)
          {
              TaskId = taskId;
              JobId = jobId;
              Duration = duration;
              Machine = machine;
              Name = "T" + taskId + "J" + jobId + "M" + machine + "D" + duration;
          }
          public int TaskId;
          public int JobId;
          public int Machine;
          public int Duration;
          public String Name;
      }
  
      //Number of machines.
      public final int machinesCount = 3;
      //horizon is the upper bound of the start time of all tasks.
      public final int horizon = 300;
      //this will be set to the size of myJobList variable.
      public int jobsCount;
  
      /* Search time limit in milliseconds. if it's equal to 0, then no time limit will be used. */
  
      public final int timeLimitInSeconds = 0;
      public static List&lt;List&lt;Task&gt;&gt; myJobList = new ArrayList&lt;List&lt;Task&gt;&gt;();
  
      public void initTaskList() {
          List&lt;Task&gt; taskList = new ArrayList&lt;Task&gt;();
          taskList.add(new Task(0, 0, 65, 0));
          taskList.add(new Task(1, 0, 5, 1));
          taskList.add(new Task(2, 0, 15, 2));
          myJobList.add(taskList);
  
          taskList = new ArrayList&lt;Task&gt;();
          taskList.add(new Task(0, 1, 15, 0));
          taskList.add(new Task(1, 1, 25, 1));
          taskList.add(new Task(2, 1, 10, 2));
          myJobList.add(taskList);
  
          taskList = new ArrayList&lt;Task&gt;();
          taskList.add(new Task(0, 2, 25, 0));
          taskList.add(new Task(1, 2, 30, 1));
          taskList.add(new Task(2, 2, 40, 2));
          myJobList.add(taskList);
  
          taskList = new ArrayList&lt;Task&gt;();
          taskList.add(new Task(0, 3, 20, 0));
          taskList.add(new Task(1, 3, 35, 1));
          taskList.add(new Task(2, 3, 10, 2));
          myJobList.add(taskList);
  
          taskList = new ArrayList&lt;Task&gt;();
          taskList.add(new Task(0, 4, 15, 0));
          taskList.add(new Task(1, 4, 25, 1));
          taskList.add(new Task(2, 4, 10, 2));
          myJobList.add(taskList);
  
          taskList = new ArrayList&lt;Task&gt;();
          taskList.add(new Task(0, 5, 25, 0));
          taskList.add(new Task(1, 5, 30, 1));
          taskList.add(new Task(2, 5, 40, 2));
          myJobList.add(taskList);
  
          taskList = new ArrayList&lt;Task&gt;();
          taskList.add(new Task(0, 6, 20, 0));
          taskList.add(new Task(1, 6, 35, 1));
          taskList.add(new Task(2, 6, 10, 2));
          myJobList.add(taskList);
  
          taskList = new ArrayList&lt;Task&gt;();
          taskList.add(new Task(0, 7, 10, 0));
          taskList.add(new Task(1, 7, 15, 1));
          taskList.add(new Task(2, 7, 50, 2));
          myJobList.add(taskList);
  
          taskList = new ArrayList&lt;Task&gt;();
          taskList.add(new Task(0, 8, 50, 0));
          taskList.add(new Task(1, 8, 10, 1));
          taskList.add(new Task(2, 8, 20, 2));
          myJobList.add(taskList);
  
          jobsCount = myJobList.size();  // Count
      }
  
      public static void main(String[] args) {
          JobshopSat jobshopSat = new JobshopSat();
          jobshopSat.initTaskList();
          CpModel model = new CpModel();
  
          // ----- Creates all intervals and integer variables -----
  
          // Stores all tasks attached interval variables per job.
          List&lt;List&lt;IntervalVar&gt;&gt; jobsToTasks = new ArrayList&lt;List&lt;IntervalVar&gt;&gt;(jobshopSat.jobsCount);
          List&lt;List&lt;IntVar&gt;&gt; jobsToStarts = new ArrayList&lt;List&lt;IntVar&gt;&gt;(jobshopSat.jobsCount);
          List&lt;List&lt;IntVar&gt;&gt; jobsToEnds = new ArrayList&lt;List&lt;IntVar&gt;&gt;(jobshopSat.jobsCount);
  
          // machinesToTasks stores the same interval variables as above, but
          // grouped my machines instead of grouped by jobs.
          List&lt;List&lt;IntervalVar&gt;&gt; machinesToTasks = new ArrayList&lt;List&lt;IntervalVar&gt;&gt;(jobshopSat.machinesCount);
          List&lt;List&lt;IntVar&gt;&gt; machinesToStarts = new ArrayList&lt;List&lt;IntVar&gt;&gt;(jobshopSat.machinesCount);
  
          for (int i = 0; i &lt; jobshopSat.machinesCount; i++) {
              machinesToTasks.add(new ArrayList&lt;IntervalVar&gt;());
              machinesToStarts.add(new ArrayList&lt;IntVar&gt;());
          }
  
          // Creates all individual interval variables.
          for (List&lt;Task&gt; job: myJobList) {
              jobsToTasks.add(new ArrayList&lt;IntervalVar&gt;());
              jobsToStarts.add(new ArrayList&lt;IntVar&gt;());
              jobsToEnds.add(new ArrayList&lt;IntVar&gt;());
              for (Task task : job) {
                  IntVar start = model.newIntVar(0, jobshopSat.horizon, task.Name);
                  IntVar end = model.newIntVar(0, jobshopSat.horizon, task.Name);
                  IntervalVar oneTask = model.newIntervalVar(start, task.Duration, end, task.Name);
  
                  jobsToTasks.get(task.JobId).add(oneTask);
                  jobsToStarts.get(task.JobId).add(start);
                  jobsToEnds.get(task.JobId).add(end);
                  machinesToTasks.get(task.Machine).add(oneTask);
                  machinesToStarts.get(task.Machine).add(start);
              }
          }
  
          // ----- Creates model -----
  
          // Creates precedences inside jobs.
          for (int j = 0; j &lt; jobsToTasks.size(); ++j) {
              for (int t = 0; t &lt; jobsToTasks.get(j).size() - 1; ++t) {
                  model.addLessOrEqual(jobsToEnds.get(j).get(t), jobsToStarts.get(j).get(t + 1));
                  // model.Add(jobsToEnds.get(j).get(t) &lt;= jobsToStarts.get(j).get(t + 1));
              }
          }
  
          // Adds no_overkap constraints on unary resources.
          for (int machineId = 0; machineId &lt; jobshopSat.machinesCount; ++machineId) {
              IntervalVar[] myArray = new IntervalVar[machinesToTasks.get(machineId).size()];
              machinesToTasks.get(machineId).toArray(myArray);
              model.addNoOverlap(myArray);
          }
  
          // Creates array of end_times of jobs.
          IntVar[] allEnds = new IntVar[jobshopSat.jobsCount];
          for (int i = 0; i &lt; jobshopSat.jobsCount; i++) {
              int sz = jobsToEnds.get(i).size();
              allEnds[i] = jobsToEnds.get(i).get(sz-1);
          }
  
          // Objective: minimize the makespan (maximum end times of all tasks) of the problem.
          IntVar makespan = model.newIntVar(0, jobshopSat.horizon, "makespan");
          model.addMaxEquality(makespan, allEnds);
          model.minimize(makespan);
  
          // Create the solver.
          CpSolver solver = new CpSolver();
          // Set the time limit.
          if (jobshopSat.timeLimitInSeconds &gt; 0) {
              // solver.StringParameters = "max_time_in_seconds:" + jobshopSat.timeLimitInSeconds;
              solver.getParameters().setMaxTimeInSeconds(jobshopSat.timeLimitInSeconds);
          }
          // Solve the problem.
          CpSolverStatus status = solver.solve(model);
  
          if (status == CpSolverStatus.OPTIMAL) {
              System.out.println("Makespan = " + solver.objectiveValue());
              for (int m = 0; m &lt; jobshopSat.machinesCount; ++m)
              {
                  System.out.println("Machine {" + m + "}:");
                  SortedMap&lt;Long, String&gt; starts = new TreeMap&lt;Long, String&gt;();
                  for(IntVar var: machinesToStarts.get(m)) {
                      starts.put(solver.value(var), var.getName());
                  }
                  for (long key: starts.keySet()) {
                      System.out.println("  Task {" + starts.get(key) + "} starts at {" + key + "}");
                  }
              }
          }
          else
          {
              System.out.println("No solution found!");
          }
      }
  }
  </code></pre>
  
  <p>I am building and running it from the top-most folder as follows (Note this is exactly as the other examples would run):</p>
  
  <pre><code>anupambagchi:202[or-tools-binary] make build SOURCE=examples/java/JobshopSat.java
  mkdir classes/JobshopSat
  "/Library/Java/JavaVirtualMachines/openjdk-12.0.1.jdk/Contents/Home/bin/javac" -d classes/JobshopSat \
   -cp lib/com.google.ortools.jar:lib/protobuf.jar \
   examples/java/JobshopSat.java
  rm -f lib/JobshopSat.jar
  "/Library/Java/JavaVirtualMachines/openjdk-12.0.1.jdk/Contents/Home/bin/jar" cvf lib/JobshopSat.jar -C classes/JobshopSat .
  added manifest
  adding: JobshopSat$Task.class(in = 918) (out= 532)(deflated 42%)
  adding: JobshopSat.class(in = 6212) (out= 2877)(deflated 53%)
  
  anupambagchi:203[or-tools-binary] make run SOURCE=examples/java/JobshopSat.java
  "/Library/Java/JavaVirtualMachines/openjdk-12.0.1.jdk/Contents/Home/bin/java" -Xss2048k -Djava.library.path=lib \
   -cp lib/JobshopSat.jar:lib/com.google.ortools.jar:lib/protobuf.jar \
   JobshopSat
  Exception in thread "main" java.lang.UnsatisfiedLinkError: com.google.ortools.util.mainJNI.new_Domain__SWIG_2(JJ)J
      at com.google.ortools.util.mainJNI.new_Domain__SWIG_2(Native Method)
      at com.google.ortools.util.Domain.&lt;init&gt;(Domain.java:68)
      at com.google.ortools.sat.CpModel.newIntVar(CpModel.java:70)
      at JobshopSat.main(JobshopSat.java:132)
  make: *** [run] Error 1
  </code></pre>
  
  <p>Kindly help me identify the problem. Thanks.</p>