private synchronized void loadNewJars() {
    // Refresh local jar file lists
    File[] files = localDir == null ? null : localDir.listFiles();
    if (files != null) {
      for (File file : files) {
        String fileName = file.getName();
        if (jarModifiedTime.containsKey(fileName)) {
          continue;
        }
        if (file.isFile() && fileName.endsWith(".jar")) {
          jarModifiedTime.put(fileName, file.lastModified());
          try {
            URL url = file.toURI().toURL();
            addURL(url);
          } catch (MalformedURLException mue) {
            // This should not happen, just log it
            LOG.warn("Failed to load new jar " + fileName, mue);
          }
        }
      }
    }

    // Check remote files
    FileStatus[] statuses = null;
    if (remoteDir != null) {
      try {
        statuses = remoteDirFs.listStatus(remoteDir);
      } catch (IOException ioe) {
        LOG.warn("Failed to check remote dir status " + remoteDir, ioe);
      }
    }
    if (statuses == null || statuses.length == 0) {
      return; // no remote files at all
    }

    for (FileStatus status : statuses) {
      if (status.isDirectory()) {
        continue; // No recursive lookup
      }

      Path path = status.getPath();
      String fileName = path.getName();
      if (!fileName.endsWith(".jar")) {
        if (LOG.isDebugEnabled()) {
          LOG.debug("Ignored non-jar file {}", fileName);
        }
        continue; // Ignore non-jar files
      }
      Long cachedLastModificationTime = jarModifiedTime.get(fileName);
      if (cachedLastModificationTime != null) {
        long lastModified = status.getModificationTime();
        if (lastModified < cachedLastModificationTime) {
          // There could be some race, for example, someone uploads
          // a new one right in the middle the old one is copied to
          // local. We can check the size as well. But it is still
          // not guaranteed. This should be rare. Most likely,
          // we already have the latest one.
          // If you are unlucky to hit this race issue, you have
          // to touch the remote jar to update its last modified time
          continue;
        }
      }
      try {
        // Copy it to local
        File dst = new File(localDir, fileName);
        remoteDirFs.copyToLocalFile(path, new Path(dst.getPath()));
        jarModifiedTime.put(fileName, dst.lastModified());
        URL url = dst.toURI().toURL();
        addURL(url);
      } catch (IOException ioe) {
        LOG.warn("Failed to load new jar " + fileName, ioe);
      }
    }
  }
Creates a DynamicClassLoader that can load classes dynamically from jar files under a specific
folder.
@param conf   the configuration for the cluster.
@param parent the parent ClassLoader to set.
hbase-common/src/main/java/org/apache/hadoop/hbase/util/DynamicClassLoader.java