作用:Java 中加载类和查找资源的路径
jdk8
.java
jdk9
.base/share/classes/jdk/internal/loader/URLClassPath.java
jdk10
.base/share/classes/jdk/internal/loader/URLClassPath.java
jdk11
.base/share/classes/jdk/internal/loader/URLClassPath.java
jdk12
.base/share/classes/jdk/internal/loader/URLClassPath.java
jdk13
.base/share/classes/jdk/internal/loader/URLClassPath.java
本文针对 jdk8
// 保存所有的查找路径 private ArrayList<URL> path = new ArrayList<>();Stack<URL> urls = new Stack<>();// 初始为空,根据 urls 生成 loadersArrayList<Loader> loaders = new ArrayList<>();// 判断路径和 jar 包是否有相应的 Loader,没有才会放入 loaders 和 lmapHashMap<String, Loader> lmap = new HashMap<>();
/** * 根据给定的 URL 创建 URLClassPath * 使用给定的 URL 顺序查找 Resource 和 jar * 如果 URL 以 '/' 结尾则被认定为路径,否则被认定为 jar 文件 */
public URLClassPath(URL[] urls, URLStreamHandlerFactory factory, AccessControlContext acc) {for (int i = 0; i < urls.length; i++) { path.add(urls[i]); } push(urls); if (factory != null) { jarHandler = ateURLStreamHandler("jar"); } if (DISABLE_ACC_CHECKING) { this.acc = null; } else { this.acc = acc; }
}
public URLClassPath(URL[] urls) { this(urls, null, null); }
public URLClassPath(URL[] urls, AccessControlContext acc) { this(urls, null, acc); }
URLClassPath 在哪里被使用到
public URLClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory) { super(parent); // this is to make the stack depth consistent with 1.1 SecurityManager security = SecurityManager();if (security != null) { security.checkCreateClassLoader(); } acc = Context(); ucp = new URLClassPath(urls, factory, acc);
}public URLClassLoader(URL[] urls, ClassLoader parent) { super(parent); // this is to make the stack depth consistent with 1.1 SecurityManager security = SecurityManager();if (security != null) { security.checkCreateClassLoader(); } this.acc = Context(); ucp = new URLClassPath(urls, acc);
}URLClassLoader(URL[] urls, ClassLoader parent, AccessControlContext acc) { super(parent); // this is to make the stack depth consistent with 1.1 SecurityManager security = SecurityManager();if (security != null) { security.checkCreateClassLoader(); } this.acc = acc; ucp = new URLClassPath(urls, acc);
}public URLClassLoader(URL[] urls) { super(); // this is to make the stack depth consistent with 1.1 SecurityManager security = SecurityManager();if (security != null) { security.checkCreateClassLoader(); } this.acc = Context(); ucp = new URLClassPath(urls, acc);
} URLClassLoader(URL[] urls, AccessControlContext acc) { super(); // this is to make the stack depth consistent with 1.1 SecurityManager security = SecurityManager(); if (security != null) { security.checkCreateClassLoader(); } this.acc = acc; ucp = new URLClassPath(urls, acc);
}
jdk1.8中 AppClassLoader 和 ExtClassLoader 都继承于 URLClassLoader,生成 UrlClassPath 的时候:
AppClassLoader 传入"java.class.path"对应的路径
ExtClassLoader 传入"
// 儿子找爹可以通过 *.ClassLoader()实现,爹找儿子属于 JVM 实现层级上的东西,随时可能在版本迭代中被删除。
private static native int[] getLookupCacheForClassLoader(ClassLoader loader, String name); private synchronized int[] getLookupCache(String name) { if (lookupCacheURLs == null || !lookupCacheEnabled) { return null; } int[] cache = getLookupCacheForClassLoader(lookupCacheLoader, name); if (cache != null && cache.length > 0) { int maxindex = cache[cache.length - 1]; // cache[] is strictly ascending. if (!ensureLoaderOpened(maxindex)) { if (DEBUG_LOOKUP_CACHE) { System.out.println("Expanded loaders FAILED " + loaders.size() + " for maxindex=" + maxindex);} return null; } } return cache;
} public Resource getResource(String name, boolean check) { if (DEBUG) { println(Resource("" + name + "")");} Loader loader; int[] cache = getLookupCache(name); for (int i = 0; (loader = getNextLoader(cache, i)) != null; i++) { Resource res = Resource(name, check); if (res != null) { return res; } } return null;
} private synchronized Loader getNextLoader(int[] cache, int index) { if (closed) { return null; } if (cache != null) { if (index < cache.length) { Loader loader = (cache[index]); if (DEBUG_LOOKUP_CACHE) { System.out.println("HASCACHE: Loading from : " + cache[index] + " = " + BaseURL()); } return loader; } else { return null; // finished iterating over cache[] } } else { return getLoader(index); }
} private synchronized Loader getLoader(int index) { if (closed) { return null; } // Expand URL search path until the request can be satisfied or the URL stack is empty. while (loaders.size() < index + 1) { // Pop the next URL from the URL stack URL url; synchronized (urls) { if (pty()) { return null; } else { url = urls.pop(); } } // Skip this URL if it already has a Loader. (Loader may be null in the case where URL has not been opened but is referenced by a JAR index.) String urlNoFragString = URLUtil.urlNoFragString(url); if (ainsKey(urlNoFragString)) { continue; } // Otherwise, create a new Loader for the URL. Loader loader; try { loader = getLoader(url); // If the loader defines a local class path then add the URLs to the list of URLs to be opened. URL[] urls = ClassPath(); if (urls != null) { push(urls); } } catch (IOException e) { // Silently ignore continue; } catch (SecurityException se) { // Always silently ignore. The context, if there is one, that this URLClassPath was given during construction will never have permission to access the URL. if (DEBUG) { println("Failed to access " + url + ", " + se); } continue; } // Finally, add the Loader to the search path. validateLookupCache(loaders.size(), urlNoFragString); loaders.add(loader); lmap.put(urlNoFragString, loader); } if (DEBUG_LOOKUP_CACHE) { System.out.println("NOCACHE: Loading from : " + index); } (index);
}// 根据 url 生成 Loader
private Loader getLoader(final URL url) throws IOException { try { return java.security.AccessController.doPrivileged( new java.security.PrivilegedExceptionAction<Loader>() { @Override public Loader run() throws IOException { String file = File(); if (file != null && dsWith("/")) { if ("file".Protocol())) { return new FileLoader(url); } else { return new Loader(url); } } else { return new JarLoader(url, jarHandler, lmap, acc); } } }, acc); } catch (java.security.PrivilegedActionException pae) { throw (IOException) Exception(); }
}
// 新添加进去的导致查找缓存失效
private synchronized void validateLookupCache(int index, String urlNoFragString) { if (lookupCacheURLs != null && lookupCacheEnabled) { if (index < lookupCacheURLs.length && urlNoFragString.equals(URLUtil.urlNoFragString(lookupCacheURLs[index]))) {return; } if (DEBUG || DEBUG_LOOKUP_CACHE) { System.out.println("WARNING: resource lookup cache invalidated " + "for lookupCacheLoader at " + index); } disableAllLookupCaches(); // lookupCacheEnabled = false; }
}// 操作 urls 的几个方法
// getLoader(int index) 中// 增加查找路径
public synchronized void addURL(URL url) { if (closed) { return; } synchronized (urls) { if (url == null || ains(url)) { return; } // 在 Stack 的头部添加元素 urls.add(0, url); path.add(url); if (lookupCacheURLs != null) { // 查找缓存是静态的("java.class.path"、dirs"),动态添加的查找缓存导致其不可使用 disableAllLookupCaches(); } }
}// java.URLClassLoader
private final URLClassPath ucp;
// java.URLClassLoader#addURL
protected void addURL(URL url) { ucp.addURL(url);
}
getLookupCache 查找缓存是为了提高查找速度,作用如下:
如果 lookupCacheURLs包 含{a.jar,b.jar,c.jar,d.jar},并且包“ foo”仅存在于a.jar和c.jar中,则getLookupCache(“ foo / Bar.class”)将返回 {0,2}。
作用和 sun.misc.MetaIndex 差不多
关于SavedProperty(“ableSharedLookupCache”)
ableSharedLookupCache 是 JVM 实现层面的参数。
URLClassPath 查找缓存相关的代码在 jdk9 中已经被删除
.html
本文发布于:2024-02-04 23:29:37,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170718848460744.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |