docs: void launchJar(JobInstance job, Map<String, String> parameters, ClassloaderManager clm, EngineApiProxy h) throws JobRunnerException
      {
          // 1 - Create the proxy.
          Object proxy = null;
          Class injInt;
          try
          {
              injInt = this.loadClass("com.enioka.jqm.api.JobManager");
              proxy = Proxy.newProxyInstance(this, new Class[] { injInt }, h);
          }
          catch (Exception e)
          {
              throw new JobRunnerException("could not create proxy API object", e);
          }
  
          // 2 - Meta data used by runners
          Map<String, String> metaprms = new HashMap<>();
          metaprms.put("mayBeShared", "" + this.mayBeShared);
  
          // 3 - Load the target class inside the context class loader
          String classQualifiedName = job.getJD().getJavaClassName();
          jqmlogger.debug("Will now load class: " + classQualifiedName);
  
          Class c = null;
          try
          {
              // using payload CL, i.e. this very object
              c = loadClass(classQualifiedName);
          }
          catch (Exception e)
          {
              throw new JobRunnerException("could not load class " + classQualifiedName, e);
          }
          jqmlogger.trace("Class " + classQualifiedName + " was correctly loaded");
  
          // 4 - Determine which job runner should take the job and launch!
          List<String> allowedRunners = clm.getJobRunnerClasses();
          if (job.getJD().getClassLoader() != null && job.getJD().getClassLoader().getAllowedRunners() != null
                  && !job.getJD().getClassLoader().getAllowedRunners().isEmpty())
          {
              allowedRunners = Arrays.asList(job.getJD().getClassLoader().getAllowedRunners().split(","));
          }
          for (String runnerClassName : allowedRunners)
          {
              Boolean canRun = false;
              Class runnerClass = null;
              Method run;
              Object runner;
              try
              {
                  // Note we load the runner class inside the engine CL (with plugins), not the payload CL.
                  // NOTHING is allowed inside the payload CL which was not specifically asked for. (ext dir or lib dir)
                  runnerClass = clm.getPluginClassLoader().loadClass(runnerClassName);
              }
              catch (Exception e)
              {
                  throw new JobRunnerException(
                          "could not load a runner: check your global parameters, or that the plugin for this runner is actually present "
                                  + runnerClassName,
                          e);
              }
              try
              {
                  runner = runnerClass.newInstance();
              }
              catch (Exception e)
              {
                  throw new JobRunnerException(
                          "could not create an instance of a runner: it may not have a no-args constructor. " + runnerClassName, e);
              }
  
              try
              {
                  Method m = runnerClass.getMethod("canRun", Class.class);
                  canRun = (Boolean) m.invoke(runner, c);
              }
              catch (Exception e)
              {
                  throw new JobRunnerException("invocation of canRun failed on the runner plugin " + runnerClassName, e);
              }
  
              if (canRun)
              {
                  jqmlogger.trace("Payload is of type: " + runnerClassName);
  
                  try
                  {
                      run = runnerClass.getMethod("run", Class.class, Map.class, Map.class, Object.class);
                  }
                  catch (Exception e)
                  {
                      throw new JobRunnerException("could not find run method for runner plugin " + runnerClassName, e);
                  }
  
                  // We are ready to actually run the job instance. Time for all event handlers.
                  if (job.getJD().getClassLoader() != null)
                  {
                      for (ClHandler handler : job.getJD().getClassLoader().getHandlers())
                      {
                          String handlerClass = handler.getClassName();
                          Map<String, String> handlerPrms = new HashMap<>();
                          for (Map.Entry<String, String> hprm : handler.getParameters().entrySet())
                          {
                              handlerPrms.put(hprm.getKey(), hprm.getValue());
                          }
  
                          try
                          {
                              Method handlerRun = loadClass(handlerClass).getMethod("run", Class.class, injInt, Map.class);
                              Object handlerInstance = loadClass(handlerClass).newInstance();
                              handlerRun.invoke(handlerInstance, c, proxy, handlerPrms);
                          }
                          catch (Exception e)
                          {
                              throw new JobRunnerException("event handler could not be loaded or run: " + handlerClass, e);
                          }
                      }
                  }
  
                  // Go for real.
                  try
                  {
                      run.invoke(runner, c, metaprms, parameters, proxy);
                      return;
                  }
                  catch (InvocationTargetException e)
                  {
                      if (e.getCause() instanceof RuntimeException)
                      {
                          // it may be a Kill order, or whatever exception...
                          throw (RuntimeException) e.getCause();
                      }
                      else
                      {
                          throw new JobRunnerException("Payload has failed", e);
                      }
                  }
                  catch (Exception e)
                  {
                      throw new JobRunnerException("Could not launch a job instance (engine issue, not a payload issue", e);
                  }
              }
          }
  
          throw new JobRunnerException(
                  "This type of class cannot be launched by JQM. Please consult the documentation for more details. Available runners: "
                          + allowedRunners);
      }