如何在Java9中使用Java应用程序加载所有jar?

时间:2017-10-02 03:26:04

标签: java classloader java-9

出于某种原因,我想获得所有加载的jar文件路径。 以前在java8上,我使用

完成了这个
<ul class="nav navbar-nav navbar-right">
    <li><a href="#!/">Home</a></li>
    <li><a href="#!/insertLeaveDetails">Insert Leave</a></li>
    <li><a href="#!/currentYearDetails">Current Year</a></li>
</ul>

但在Java 9中,SystemClassLoader无法转换为URLClassLoader。

目前我正在使用for (java.net.URL url : ((java.net.URLClassLoader) A.class.getClassLoader()).getURLs()) { try { String path = url.toString(); if (path.startsWith("file:/")) path = path.substring(6); path = java.net.URLDecoder.decode(path, "UTF-8"); } catch (Exception e) { e.printStackTrace(); } } ,但这需要花费很多,所以我在这里要求采取更温和的方式来实现这一目标。

1 个答案:

答案 0 :(得分:2)

试试这个:

/**
 *
 * @author hengyunabc 2017-10-12
 *
 */
public class ClassLoaderUtils {
    @SuppressWarnings({ "restriction", "unchecked" })
    public static URL[] getUrls(ClassLoader classLoader) {
        if (classLoader instanceof URLClassLoader) {
            return ((URLClassLoader) classLoader).getURLs();
        }

        // jdk9
        if (classLoader.getClass().getName().startsWith("jdk.internal.loader.ClassLoaders$")) {
            try {
                Field field = Unsafe.class.getDeclaredField("theUnsafe");
                field.setAccessible(true);
                Unsafe unsafe = (Unsafe) field.get(null);

                // jdk.internal.loader.ClassLoaders.AppClassLoader.ucp
                Field ucpField = classLoader.getClass().getDeclaredField("ucp");
                long ucpFieldOffset = unsafe.objectFieldOffset(ucpField);
                Object ucpObject = unsafe.getObject(classLoader, ucpFieldOffset);

                // jdk.internal.loader.URLClassPath.path
                Field pathField = ucpField.getType().getDeclaredField("path");
                long pathFieldOffset = unsafe.objectFieldOffset(pathField);
                ArrayList<URL> path = (ArrayList<URL>) unsafe.getObject(ucpObject, pathFieldOffset);

                return path.toArray(new URL[path.size()]);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
        return null;
    }
}