diff --git a/cdap-common/src/main/java/io/cdap/cdap/common/app/MainClassLoader.java b/cdap-common/src/main/java/io/cdap/cdap/common/app/MainClassLoader.java index 7abfb69e46c7..f5012269ab72 100644 --- a/cdap-common/src/main/java/io/cdap/cdap/common/app/MainClassLoader.java +++ b/cdap-common/src/main/java/io/cdap/cdap/common/app/MainClassLoader.java @@ -21,6 +21,7 @@ import io.cdap.cdap.api.dataset.Dataset; import io.cdap.cdap.common.dataset.DatasetClassRewriter; import io.cdap.cdap.common.lang.ClassLoaders; +import io.cdap.cdap.common.lang.ClassPathResources; import io.cdap.cdap.common.lang.CombineClassLoader; import io.cdap.cdap.common.lang.FilterClassLoader; import io.cdap.cdap.common.lang.GuavaClassRewriter; @@ -104,11 +105,8 @@ public static MainClassLoader createFromContext(FilterClassLoader.Filter filter, if (classLoader instanceof URLClassLoader) { classpath.addAll(Arrays.asList(((URLClassLoader) classLoader).getURLs())); - } else if (classLoader == ClassLoader.getSystemClassLoader()) { - addClassPath(classpath); } else { - // No able to create a new MainClassLoader - return null; + classpath.addAll(ClassPathResources.getClasspathUrls()); } classpath.addAll(Arrays.asList(extraClasspath)); @@ -180,27 +178,6 @@ public byte[] rewriteClass(String className, InputStream input) throws IOExcepti return rewrittenCode; } - /** - * Adds {@link URL} to the given list based on the system classpath. - */ - private static void addClassPath(List urls) { - String wildcardSuffix = File.pathSeparator + "*"; - // In case the system classloader is not a URLClassLoader, use the classpath property (maybe from non Oracle JDK) - for (String path : Splitter.on(File.pathSeparatorChar) - .split(System.getProperty("java.class.path"))) { - if ("*".equals(path) || path.endsWith(wildcardSuffix)) { - for (File jarFile : DirUtils.listFiles(new File(path), "jar")) { - try { - urls.add(jarFile.toURI().toURL()); - } catch (MalformedURLException e) { - // Shouldn't happen. Propagate the exception. - throw Throwables.propagate(e); - } - } - } - } - } - private boolean isRewriteNeeded(String className) throws IOException { return guavaClassRewriter.needRewrite(className) || levelDBClassRewriter.needRewrite(className) diff --git a/cdap-common/src/main/java/io/cdap/cdap/common/lang/ClassPathResources.java b/cdap-common/src/main/java/io/cdap/cdap/common/lang/ClassPathResources.java index cad29784d4e9..501e746223da 100644 --- a/cdap-common/src/main/java/io/cdap/cdap/common/lang/ClassPathResources.java +++ b/cdap-common/src/main/java/io/cdap/cdap/common/lang/ClassPathResources.java @@ -19,14 +19,19 @@ import io.cdap.cdap.common.internal.guava.ClassPath; import io.cdap.cdap.common.internal.guava.ClassPath.ClassInfo; import io.cdap.cdap.common.internal.guava.ClassPath.ResourceInfo; +import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; +import java.nio.file.NoSuchFileException; +import java.nio.file.Paths; +import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.stream.Collectors; import org.apache.twill.api.ClassAcceptor; @@ -41,6 +46,33 @@ public final class ClassPathResources { private static final Logger LOG = LoggerFactory.getLogger(ClassPathResources.class); + /** + * Return a list of all URL entries from the java class path. + * + * @return list of all URL entries from the java class path. + */ + public static List getClasspathUrls() { + List urls = new ArrayList<>(); + + // wildcards are expanded before they are places in java.class.path + // for example, java -cp lib/* will list out all the jars in the lib directory and + // add each individual jars as an element in java.class.path. The exception is if + // the directory doesn't exist, then it will be preserved as lib/*. + for (String path : System.getProperty("java.class.path").split(File.pathSeparator)) { + try { + urls.add(Paths.get(path).toRealPath().toUri().toURL()); + } catch (NoSuchFileException e) { + // ignore anything that doesn't exist + } catch (MalformedURLException e) { + // should never happen + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException("Unable to get class path entry " + path, e); + } + } + return urls; + } + /** * Returns the base set of resources needed to load the specified {@link Class} using the * specified {@link ClassLoader}. Also traces and includes the dependencies for the specified diff --git a/cdap-runtime-ext-dataproc/src/main/java/io/cdap/cdap/runtime/spi/runtimejob/DataprocJobMain.java b/cdap-runtime-ext-dataproc/src/main/java/io/cdap/cdap/runtime/spi/runtimejob/DataprocJobMain.java index 68d3c0aa578e..843c9ac87031 100644 --- a/cdap-runtime-ext-dataproc/src/main/java/io/cdap/cdap/runtime/spi/runtimejob/DataprocJobMain.java +++ b/cdap-runtime-ext-dataproc/src/main/java/io/cdap/cdap/runtime/spi/runtimejob/DataprocJobMain.java @@ -24,6 +24,7 @@ import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Files; +import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; @@ -181,7 +182,11 @@ private static URL[] getClasspath(List jarFiles) throws IOException { // Add the system class path to the URL list for (String path : System.getProperty("java.class.path").split(File.pathSeparator)) { - urls.add(Paths.get(path).toRealPath().toUri().toURL()); + try { + urls.add(Paths.get(path).toRealPath().toUri().toURL()); + } catch (NoSuchFileException e) { + // ignore anything that doesn't exist + } } return urls.toArray(new URL[0]); diff --git a/cdap-spark-core-base/src/main/java/io/cdap/cdap/app/runtime/spark/distributed/SparkContainerLauncher.java b/cdap-spark-core-base/src/main/java/io/cdap/cdap/app/runtime/spark/distributed/SparkContainerLauncher.java index b150207163f3..a6d2055aa4fe 100644 --- a/cdap-spark-core-base/src/main/java/io/cdap/cdap/app/runtime/spark/distributed/SparkContainerLauncher.java +++ b/cdap-spark-core-base/src/main/java/io/cdap/cdap/app/runtime/spark/distributed/SparkContainerLauncher.java @@ -22,11 +22,11 @@ import io.cdap.cdap.app.runtime.spark.classloader.SparkContainerClassLoader; import io.cdap.cdap.app.runtime.spark.python.SparkPythonUtil; import io.cdap.cdap.common.lang.ClassLoaders; +import io.cdap.cdap.common.lang.ClassPathResources; import io.cdap.cdap.common.lang.FilterClassLoader; import io.cdap.cdap.common.logging.StandardOutErrorRedirector; import io.cdap.cdap.common.logging.common.UncaughtExceptionHandler; import java.io.Closeable; -import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; @@ -102,9 +102,7 @@ public static void launch(String mainClassName, String[] args, boolean removeMai Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler()); Set urls = new LinkedHashSet<>(); - for (String path : System.getProperty("java.class.path").split(File.pathSeparator)) { - urls.add(Paths.get(path).toRealPath().toUri().toURL()); - } + urls.addAll(ClassPathResources.getClasspathUrls()); ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();