private static AppData loadMainClassWithCustomLoader(File classpathFile, String[] args) throws Exception {
    List<URL> classpathUrls = new ArrayList<>();
    StringBuilder classpathString = new StringBuilder();
    List<String> pathElements = readLinesAndDeleteFile(classpathFile);
    for (String pathElement : pathElements) {
      classpathUrls.add(toUrl(new File(pathElement)));
      if (classpathString.length() > 0) classpathString.append(File.pathSeparator);
      classpathString.append(pathElement);
    }
    System.setProperty("java.class.path", classpathString.toString());

    int startArgsIdx = 2;

    List<String> properties = Collections.emptyList();
    if (args.length > startArgsIdx && "@vm_params".equals(args[startArgsIdx - 1])) {
      properties = readLinesAndDeleteFile(new File(args[startArgsIdx]));
      startArgsIdx += 2;
    }

    String[] mainArgs;
    if (args.length > startArgsIdx && "@app_params".equals(args[startArgsIdx - 1])) {
      List<String> lines = readLinesAndDeleteFile(new File(args[startArgsIdx]));
      mainArgs = lines.toArray(new String[0]);
      startArgsIdx += 2;
    }
    else {
      mainArgs = Arrays.copyOfRange(args, startArgsIdx, args.length);
    }

    String mainClassName = args[startArgsIdx - 1];
    ClassLoader loader = new URLClassLoader(classpathUrls.toArray(new URL[0]), null);
    String systemLoaderName = System.getProperty("java.system.class.loader");
    if (systemLoaderName != null) {
      try {
        loader = (ClassLoader)Class.forName(systemLoaderName).getConstructor(new Class[]{ClassLoader.class}).newInstance(new Object[]{loader});
      }
      catch (Exception ignored) { }
    }
    Class<?> mainClass = loader.loadClass(mainClassName);
    Thread.currentThread().setContextClassLoader(loader);

    return new AppData(properties, mainClass, mainArgs);
  }
private static AppData loadMainClassWithCustomLoader(File classpathFile, String[] args)