@InterfaceAudience.Private
  public static void addDependencyJarsForClasses(Configuration conf, Class<?>... classes)
    throws IOException {

    FileSystem localFs = FileSystem.getLocal(conf);
    Set<String> jars = new HashSet<>();
    // Add jars that are already in the tmpjars variable
    jars.addAll(conf.getStringCollection("tmpjars"));

    // add jars as we find them to a map of contents jar name so that we can avoid
    // creating new jars for classes that have already been packaged.
    Map<String, String> packagedClasses = new HashMap<>();

    // Add jars containing the specified classes
    for (Class<?> clazz : classes) {
      if (clazz == null) continue;

      Path path = findOrCreateJar(clazz, localFs, packagedClasses);
      if (path == null) {
        LOG.warn("Could not find jar for class " + clazz + " in order to ship it to the cluster.");
        continue;
      }
      if (!localFs.exists(path)) {
        LOG.warn("Could not validate jar file " + path + " for class " + clazz);
        continue;
      }
      jars.add(path.toString());
    }
    if (jars.isEmpty()) {
      return;
    }
    conf.set("tmpjars", jars.stream().collect(Collectors.joining(",")));
  }
Add the jars containing the given classes to the job's configuration such that JobClient will
ship them to the cluster and add them to the DistributedCache. N.B. that this method at most
adds one jar per class given. If there is more than one jar available containing a class with
the same name as a given class, we don't define which of those jars might be chosen.
@param conf    The Hadoop Configuration to modify
@param classes will add just those dependencies needed to find the given classes
@throws IOException if an underlying library call fails.
hbase-mapreduce/src/main/java/org/apache/hadoop/hbase/mapreduce/TableMapReduceUtil.java