diff --git a/hbase-common/src/test/java/org/apache/hadoop/hbase/ClassFinder.java b/hbase-common/src/test/java/org/apache/hadoop/hbase/ClassFinder.java index a28869279ff..ba6d8a29fd7 100644 --- a/hbase-common/src/test/java/org/apache/hadoop/hbase/ClassFinder.java +++ b/hbase-common/src/test/java/org/apache/hadoop/hbase/ClassFinder.java @@ -49,6 +49,7 @@ public class ClassFinder { private FileNameFilter fileNameFilter; private ClassFilter classFilter; private FileFilter fileFilter; + private ClassLoader classLoader; public interface ResourcePathFilter { boolean isCandidatePath(String resourcePath, boolean isJar); @@ -114,16 +115,27 @@ public class ClassFinder { } } - public ClassFinder() { - this(null, null, null); + // To control which classloader to use while trying to find jars/classes + public ClassFinder(ClassLoader classLoader) { + this(null, null, null, classLoader); } - public ClassFinder(ResourcePathFilter resourcePathFilter, - FileNameFilter fileNameFilter, ClassFilter classFilter) { + public ClassFinder() { + this(ClassLoader.getSystemClassLoader()); + } + + public ClassFinder(ResourcePathFilter resourcePathFilter, FileNameFilter fileNameFilter, + ClassFilter classFilter) { + this(resourcePathFilter, fileNameFilter, classFilter, ClassLoader.getSystemClassLoader()); + } + + public ClassFinder(ResourcePathFilter resourcePathFilter, FileNameFilter fileNameFilter, + ClassFilter classFilter, ClassLoader classLoader) { this.resourcePathFilter = resourcePathFilter; this.classFilter = classFilter; this.fileNameFilter = fileNameFilter; this.fileFilter = new FileFilterWithName(fileNameFilter); + this.classLoader = classLoader; } /** @@ -147,9 +159,9 @@ public class ClassFinder { final String path = packageName.replace('.', '/'); final Pattern jarResourceRe = Pattern.compile("^file:(.+\\.jar)!/" + path + "$"); - Enumeration resources = ClassLoader.getSystemClassLoader().getResources(path); - List dirs = new ArrayList(); - List jars = new ArrayList(); + Enumeration resources = this.classLoader.getResources(path); + List dirs = new ArrayList<>(); + List jars = new ArrayList<>(); while (resources.hasMoreElements()) { URL resource = resources.nextElement(); @@ -270,7 +282,7 @@ public class ClassFinder { private Class makeClass(String className, boolean proceedOnExceptions) throws ClassNotFoundException, LinkageError { try { - Class c = Class.forName(className, false, this.getClass().getClassLoader()); + Class c = Class.forName(className, false, classLoader); boolean isCandidateClass = null == classFilter || classFilter.isCandidateClass(c); return isCandidateClass ? c : null; } catch (ClassNotFoundException classNotFoundEx) { diff --git a/hbase-common/src/test/java/org/apache/hadoop/hbase/TestClassFinder.java b/hbase-common/src/test/java/org/apache/hadoop/hbase/TestClassFinder.java index 20091b59522..24a4c0fad2e 100644 --- a/hbase-common/src/test/java/org/apache/hadoop/hbase/TestClassFinder.java +++ b/hbase-common/src/test/java/org/apache/hadoop/hbase/TestClassFinder.java @@ -28,7 +28,6 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; -import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.HashSet; @@ -70,6 +69,8 @@ public class TestClassFinder { private static String basePath = null; + private static CustomClassloader classLoader; + @BeforeClass public static void createTestDir() throws IOException { basePath = testUtil.getDataTestDir(TestClassFinder.class.getSimpleName()).toString(); @@ -83,6 +84,8 @@ public class TestClassFinder { } assertTrue(testDir.mkdirs()); LOG.info("Using new, clean directory=" + testDir); + + classLoader = new CustomClassloader(new URL[0], ClassLoader.getSystemClassLoader()); } @AfterClass @@ -99,7 +102,7 @@ public class TestClassFinder { packageAndLoadJar(c1, c3); packageAndLoadJar(c2); - ClassFinder allClassesFinder = new ClassFinder(); + ClassFinder allClassesFinder = new ClassFinder(classLoader); Set> allClasses = allClassesFinder.findClasses( makePackageName("", counter), false); assertEquals(3, allClasses.size()); @@ -113,7 +116,7 @@ public class TestClassFinder { packageAndLoadJar(c1, c2); packageAndLoadJar(c1); - ClassFinder allClassesFinder = new ClassFinder(); + ClassFinder allClassesFinder = new ClassFinder(classLoader); Set> allClasses = allClassesFinder.findClasses( makePackageName("", counter), false); assertEquals(2, allClasses.size()); @@ -131,7 +134,7 @@ public class TestClassFinder { packageAndLoadJar(c1, c2); packageAndLoadJar(c3); - ClassFinder allClassesFinder = new ClassFinder(); + ClassFinder allClassesFinder = new ClassFinder(classLoader); Set> nestedClasses = allClassesFinder.findClasses( makePackageName(NESTED, counter), false); assertEquals(2, nestedClasses.size()); @@ -153,7 +156,7 @@ public class TestClassFinder { return !fileName.startsWith(PREFIX); } }; - ClassFinder incClassesFinder = new ClassFinder(null, notExcNameFilter, null); + ClassFinder incClassesFinder = new ClassFinder(null, notExcNameFilter, null, classLoader); Set> incClasses = incClassesFinder.findClasses( makePackageName("", counter), false); assertEquals(1, incClasses.size()); @@ -173,7 +176,7 @@ public class TestClassFinder { return !c.getSimpleName().startsWith(PREFIX); } }; - ClassFinder incClassesFinder = new ClassFinder(null, null, notExcClassFilter); + ClassFinder incClassesFinder = new ClassFinder(null, null, notExcClassFilter, classLoader); Set> incClasses = incClassesFinder.findClasses( makePackageName("", counter), false); assertEquals(1, incClasses.size()); @@ -212,7 +215,7 @@ public class TestClassFinder { return !isJar || !resourcePath.equals(excludedJarResource); } }; - ClassFinder incClassesFinder = new ClassFinder(notExcJarFilter, null, null); + ClassFinder incClassesFinder = new ClassFinder(notExcJarFilter, null, null, classLoader); Set> incClasses = incClassesFinder.findClasses( makePackageName("", counter), false); assertEquals(1, incClasses.size()); @@ -228,7 +231,7 @@ public class TestClassFinder { final String classNamePrefix = name.getMethodName(); String pkgNameSuffix = name.getMethodName(); LOG.info("Created jar " + createAndLoadJar(pkgNameSuffix, classNamePrefix, counter)); - ClassFinder allClassesFinder = new ClassFinder(); + ClassFinder allClassesFinder = new ClassFinder(classLoader); String pkgName = makePackageName(pkgNameSuffix, counter); Set> allClasses = allClassesFinder.findClasses(pkgName, false); assertTrue("Classes in " + pkgName, allClasses.size() > 0); @@ -259,10 +262,10 @@ public class TestClassFinder { } }; String pkgName = makePackageName(pkgNameSuffix, counter); - ClassFinder allClassesFinder = new ClassFinder(); + ClassFinder allClassesFinder = new ClassFinder(classLoader); Set> allClasses = allClassesFinder.findClasses(pkgName, false); assertTrue("Classes in " + pkgName, allClasses.size() > 0); - ClassFinder notThisClassFinder = new ClassFinder(null, notThisFilter, null); + ClassFinder notThisClassFinder = new ClassFinder(null, notThisFilter, null, classLoader); Set> notAllClasses = notThisClassFinder.findClasses(pkgName, false); assertFalse(contains(notAllClasses, classNameToFilterOut)); assertEquals(allClasses.size() - 1, notAllClasses.size()); @@ -284,10 +287,10 @@ public class TestClassFinder { } }; String pkgName = makePackageName(pkgNameSuffix, counter); - ClassFinder allClassesFinder = new ClassFinder(); + ClassFinder allClassesFinder = new ClassFinder(classLoader); Set> allClasses = allClassesFinder.findClasses(pkgName, false); assertTrue("Classes in " + pkgName, allClasses.size() > 0); - ClassFinder notThisClassFinder = new ClassFinder(null, null, notThisFilter); + ClassFinder notThisClassFinder = new ClassFinder(null, null, notThisFilter, classLoader); Set> notAllClasses = notThisClassFinder.findClasses(pkgName, false); assertFalse(contains(notAllClasses, clazz.getSimpleName())); assertEquals(allClasses.size() - 1, notAllClasses.size()); @@ -304,7 +307,7 @@ public class TestClassFinder { } }; String thisPackage = this.getClass().getPackage().getName(); - ClassFinder notThisClassFinder = new ClassFinder(notExcJarFilter, null, null); + ClassFinder notThisClassFinder = new ClassFinder(notExcJarFilter, null, null, classLoader); Set> notAllClasses = notThisClassFinder.findClasses(thisPackage, false); assertFalse(notAllClasses.contains(this.getClass())); } @@ -313,7 +316,7 @@ public class TestClassFinder { public void testClassFinderDefaultsToOwnPackage() throws Exception { // Correct handling of nested packages is tested elsewhere, so here we just assume // pkgClasses is the correct answer that we don't have to check. - ClassFinder allClassesFinder = new ClassFinder(); + ClassFinder allClassesFinder = new ClassFinder(classLoader); Set> pkgClasses = allClassesFinder.findClasses( ClassFinder.class.getPackage().getName(), false); Set> defaultClasses = allClassesFinder.findClasses(false); @@ -331,8 +334,8 @@ public class TestClassFinder { private static Class makeClass(String nestedPkgSuffix, String className, long counter) throws ClassNotFoundException { - return Class.forName( - makePackageName(nestedPkgSuffix, counter) + "." + className + counter); + String name = makePackageName(nestedPkgSuffix, counter) + "." + className + counter; + return Class.forName(name, true, classLoader); } private static String makePackageName(String nestedSuffix, long counter) { @@ -412,11 +415,19 @@ public class TestClassFinder { // Add the file to classpath. File jarFile = new File(path); assertTrue(jarFile.exists()); - URLClassLoader urlClassLoader = (URLClassLoader)ClassLoader.getSystemClassLoader(); - Method method = URLClassLoader.class - .getDeclaredMethod("addURL", new Class[] { URL.class }); - method.setAccessible(true); - method.invoke(urlClassLoader, new Object[] { jarFile.toURI().toURL() }); + classLoader.addURL(jarFile.toURI().toURL()); return jarFile.getAbsolutePath(); } -}; + + // Java 11 workaround - Custom class loader to expose addUrl method of URLClassLoader + private static class CustomClassloader extends URLClassLoader { + + public CustomClassloader(URL[] urls, ClassLoader parentLoader) { + super(urls, parentLoader); + } + + public void addURL(URL url) { + super.addURL(url); + } + } +}