Skip to content

Commit

Permalink
Merge pull request cdapio#15049 from cdapio/CDAP-20548-consolidate-cl…
Browse files Browse the repository at this point in the history
…asspath-logic

CDAP-20548 fix MainClassLoader class path logic
  • Loading branch information
albertshau authored Apr 7, 2023
2 parents 86c382e + 1c6b585 commit 898bcdc
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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<URL> 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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<URL> getClasspathUrls() {
List<URL> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -181,7 +182,11 @@ private static URL[] getClasspath(List<String> 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]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -102,9 +102,7 @@ public static void launch(String mainClassName, String[] args, boolean removeMai
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler());

Set<URL> 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();

Expand Down

0 comments on commit 898bcdc

Please sign in to comment.