Skip to content

Commit a118e1e

Browse files
CopilotCopilot
andcommitted
Add JavaDoc comments to non-private methods in ClassLoaderUtils
Added JavaDoc with Example Usage sections to 9 non-private methods: - getDefaultClassLoader(ClassLoader) - doLoadClass(ClassLoader, String) - doGetInheritableClassLoaders(ClassLoader) - findClassLoader(ClassLoader) - logOnFindLoadedClassInvocationFailed(ClassLoader, String, Throwable) - buildCacheKey(ClassLoader, String) - ResourceType.DEFAULT.normalize(String) - ResourceType.CLASS.normalize(String) - ResourceType.PACKAGE.normalize(String) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent dfb6217 commit a118e1e

1 file changed

Lines changed: 166 additions & 0 deletions

File tree

microsphere-java-core/src/main/java/io/microsphere/util/ClassLoaderUtils.java

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,22 @@ public static ClassLoader getDefaultClassLoader() {
216216
return getDefaultClassLoader(classLoader);
217217
}
218218

219+
/**
220+
* Returns the given {@link ClassLoader} if it is non-null, otherwise falls back to
221+
* the {@linkplain ClassLoader#getSystemClassLoader() system ClassLoader}. A {@code null}
222+
* classLoader typically indicates the bootstrap ClassLoader.
223+
*
224+
* <h3>Example Usage</h3>
225+
* <pre>{@code
226+
* ClassLoader cl = Thread.currentThread().getContextClassLoader();
227+
* ClassLoader effective = ClassLoaderUtils.getDefaultClassLoader(cl);
228+
* // If cl is null (bootstrap), effective will be the system ClassLoader
229+
* }</pre>
230+
*
231+
* @param classLoader the {@link ClassLoader} to use, may be {@code null}
232+
* @return the provided classLoader if non-null, or the system ClassLoader otherwise
233+
* @since 1.0.0
234+
*/
219235
static ClassLoader getDefaultClassLoader(ClassLoader classLoader) {
220236
// classLoader is null indicates the bootstrap ClassLoader
221237
return classLoader == null ? getSystemClassLoader() : classLoader;
@@ -546,6 +562,29 @@ public static Class<?> loadClass(@Nullable ClassLoader classLoader, @Nullable St
546562
return doLoadClass(actualClassLoader, className);
547563
}
548564

565+
/**
566+
* Loads a {@link Class} with the specified name using the given {@link ClassLoader}.
567+
* Returns {@code null} for blank class names. If the class cannot be loaded, this method
568+
* attempts to resolve it as a primitive type before returning {@code null}.
569+
*
570+
* <h3>Example Usage</h3>
571+
* <pre>{@code
572+
* ClassLoader cl = Thread.currentThread().getContextClassLoader();
573+
* Class<?> klass = ClassLoaderUtils.doLoadClass(cl, "java.lang.String");
574+
* System.out.println(klass); // class java.lang.String
575+
*
576+
* Class<?> primitive = ClassLoaderUtils.doLoadClass(cl, "int");
577+
* System.out.println(primitive); // int
578+
*
579+
* Class<?> missing = ClassLoaderUtils.doLoadClass(cl, " ");
580+
* System.out.println(missing); // null
581+
* }</pre>
582+
*
583+
* @param classLoader the {@link ClassLoader} used to load the class
584+
* @param className the fully qualified name of the class to load, may be blank
585+
* @return the loaded {@link Class}, or {@code null} if the name is blank or the class cannot be found
586+
* @since 1.0.0
587+
*/
549588
protected static Class<?> doLoadClass(ClassLoader classLoader, String className) {
550589
if (isBlank(className)) {
551590
return null;
@@ -1000,6 +1039,24 @@ public static Set<ClassLoader> getInheritableClassLoaders(@Nullable ClassLoader
10001039
return unmodifiableSet(doGetInheritableClassLoaders(actualClassLoader));
10011040
}
10021041

1042+
/**
1043+
* Traverses the parent chain of the given {@link ClassLoader} and collects every
1044+
* ClassLoader in the hierarchy into a {@link Set}, starting from the provided
1045+
* classLoader up to (but not including) the bootstrap ClassLoader ({@code null} parent).
1046+
*
1047+
* <h3>Example Usage</h3>
1048+
* <pre>{@code
1049+
* ClassLoader appCl = ClassLoaderUtils.class.getClassLoader();
1050+
* Set<ClassLoader> hierarchy = ClassLoaderUtils.doGetInheritableClassLoaders(appCl);
1051+
* // hierarchy contains appCl and its parent (e.g. PlatformClassLoader)
1052+
* hierarchy.forEach(cl -> System.out.println(cl));
1053+
* }</pre>
1054+
*
1055+
* @param classLoader the starting {@link ClassLoader}; must not be {@code null}
1056+
* @return a non-null {@link Set} of ClassLoaders in the inheritance chain
1057+
* @throws NullPointerException if {@code classLoader} is {@code null}
1058+
* @since 1.0.0
1059+
*/
10031060
@Nonnull
10041061
static Set<ClassLoader> doGetInheritableClassLoaders(ClassLoader classLoader) throws NullPointerException {
10051062
Set<ClassLoader> classLoadersSet = newLinkedHashSet();
@@ -1752,6 +1809,25 @@ static ClassLoader getCallerClassLoader(int invocationFrame) {
17521809
return classLoader;
17531810
}
17541811

1812+
/**
1813+
* Resolves the effective {@link ClassLoader} to use. Returns the provided classLoader
1814+
* if it is non-null; otherwise delegates to {@link #getDefaultClassLoader()} to obtain
1815+
* a suitable default.
1816+
*
1817+
* <h3>Example Usage</h3>
1818+
* <pre>{@code
1819+
* ClassLoader provided = new URLClassLoader(new URL[0]);
1820+
* ClassLoader result = ClassLoaderUtils.findClassLoader(provided);
1821+
* // result == provided
1822+
*
1823+
* ClassLoader fallback = ClassLoaderUtils.findClassLoader(null);
1824+
* // fallback is the thread-context or system ClassLoader
1825+
* }</pre>
1826+
*
1827+
* @param classLoader the {@link ClassLoader} to use, may be {@code null}
1828+
* @return the provided classLoader if non-null, or the default ClassLoader otherwise
1829+
* @since 1.0.0
1830+
*/
17551831
@Nullable
17561832
static ClassLoader findClassLoader(@Nullable ClassLoader classLoader) {
17571833
return classLoader == null ? getDefaultClassLoader() : classLoader;
@@ -1775,11 +1851,50 @@ static Class<?> invokeFindLoadedClassMethod(ClassLoader classLoader, String clas
17751851
return loadedClass;
17761852
}
17771853

1854+
/**
1855+
* Logs an error message when the reflective invocation of
1856+
* {@link ClassLoader#findLoadedClass(String)} fails. The log includes the class name,
1857+
* the ClassLoader instance, and the current JVM vendor and version for diagnostics.
1858+
*
1859+
* <h3>Example Usage</h3>
1860+
* <pre>{@code
1861+
* try {
1862+
* // attempt reflective findLoadedClass invocation
1863+
* } catch (Throwable e) {
1864+
* ClassLoaderUtils.logOnFindLoadedClassInvocationFailed(
1865+
* Thread.currentThread().getContextClassLoader(),
1866+
* "com.example.MyClass", e);
1867+
* }
1868+
* }</pre>
1869+
*
1870+
* @param classLoader the {@link ClassLoader} on which the invocation was attempted
1871+
* @param className the name of the class that was being looked up
1872+
* @param e the {@link Throwable} that caused the failure
1873+
* @since 1.0.0
1874+
*/
17781875
static void logOnFindLoadedClassInvocationFailed(ClassLoader classLoader, String className, Throwable e) {
17791876
logger.error("The findLoadedClass(className : '{}' : String) method of java.lang.ClassLoader[{}] can't be invoked in the current JVM[vendor : {} , version : {}]",
17801877
className, classLoader, JAVA_VENDOR, JAVA_VERSION, e);
17811878
}
17821879

1880+
/**
1881+
* Builds a cache key by concatenating the class name with the hash code of the given
1882+
* {@link ClassLoader}. This key uniquely identifies a class within a specific ClassLoader
1883+
* for caching purposes.
1884+
*
1885+
* <h3>Example Usage</h3>
1886+
* <pre>{@code
1887+
* ClassLoader cl = Thread.currentThread().getContextClassLoader();
1888+
* String key = ClassLoaderUtils.buildCacheKey(cl, "com.example.MyClass");
1889+
* // key is something like "com.example.MyClass1234567890"
1890+
* System.out.println(key);
1891+
* }</pre>
1892+
*
1893+
* @param classLoader the {@link ClassLoader} whose hash code is appended to the key
1894+
* @param className the fully qualified class name
1895+
* @return a cache key string composed of the class name and ClassLoader hash code
1896+
* @since 1.0.0
1897+
*/
17831898
static String buildCacheKey(ClassLoader classLoader, String className) {
17841899
String cacheKey = className + classLoader.hashCode();
17851900
return cacheKey;
@@ -1829,6 +1944,21 @@ boolean supports(String name) {
18291944
return true;
18301945
}
18311946

1947+
/**
1948+
* Returns the resource name as-is without any transformation, since
1949+
* the {@code DEFAULT} resource type applies no normalization.
1950+
*
1951+
* <h3>Example Usage</h3>
1952+
* <pre>{@code
1953+
* String name = "META-INF/services/com.example.MyService";
1954+
* String normalized = ResourceType.DEFAULT.normalize(name);
1955+
* // normalized is "META-INF/services/com.example.MyService"
1956+
* }</pre>
1957+
*
1958+
* @param name the resource name to normalize
1959+
* @return the same resource name, unchanged
1960+
* @since 1.0.0
1961+
*/
18321962
@Override
18331963
public String normalize(String name) {
18341964
return name;
@@ -1853,6 +1983,24 @@ boolean supports(String name) {
18531983
return endsWith(name, CLASS_EXTENSION);
18541984
}
18551985

1986+
/**
1987+
* Normalizes a class resource name by replacing package-separator dots with
1988+
* slashes and ensuring the name ends with the {@code .class} extension.
1989+
* Returns {@code null} if the input is {@code null}.
1990+
*
1991+
* <h3>Example Usage</h3>
1992+
* <pre>{@code
1993+
* String normalized = ResourceType.CLASS.normalize("com.example.MyClass.class");
1994+
* // normalized is "com/example/MyClass.class"
1995+
*
1996+
* String withoutExt = ResourceType.CLASS.normalize("com.example.MyClass");
1997+
* // withoutExt is "com/example/MyClass.class"
1998+
* }</pre>
1999+
*
2000+
* @param name the class resource name to normalize, may be {@code null}
2001+
* @return the normalized path-style class resource name, or {@code null} if {@code name} is {@code null}
2002+
* @since 1.0.0
2003+
*/
18562004
@Override
18572005
public String normalize(String name) {
18582006
if (name == null) {
@@ -1887,6 +2035,24 @@ boolean supports(String name) {
18872035
return !CLASS.supports(name) && !contains(name, SLASH) && !contains(name, BACK_SLASH);
18882036
}
18892037

2038+
/**
2039+
* Normalizes a package resource name by replacing dots with slashes and
2040+
* ensuring the result ends with a trailing slash. Returns {@code null}
2041+
* if the input is {@code null}.
2042+
*
2043+
* <h3>Example Usage</h3>
2044+
* <pre>{@code
2045+
* String normalized = ResourceType.PACKAGE.normalize("com.example.mypackage");
2046+
* // normalized is "com/example/mypackage/"
2047+
*
2048+
* String alreadySlashed = ResourceType.PACKAGE.normalize("com/example/mypackage/");
2049+
* // alreadySlashed is "com/example/mypackage/"
2050+
* }</pre>
2051+
*
2052+
* @param name the dot-separated package name to normalize, may be {@code null}
2053+
* @return the slash-separated package path ending with a slash, or {@code null} if {@code name} is {@code null}
2054+
* @since 1.0.0
2055+
*/
18902056
@Override
18912057
String normalize(String name) {
18922058
if (name == null) {

0 commit comments

Comments
 (0)