3.依据是否 isAbsolute 决定是否直接加载 library
name 是绝对路径的话,直接创建 File 实例,调用 loadLibrary0(),继续加载该文件 。具体见下章节 。检查 loadLibrary0 的结果,true 即表示加载成功,结束;false 即表示加载失败,抛出 UnsatisfiedLinkError
Can't load xxx
name 非绝对路径并且获取的 ClassLoader 存在的话,通过 findLibrary() ,根据 so 名称获得 lib 绝对路径,并创建指向该路径的 File 实例 libfile 。并确保该文件的路径是绝对路径 。反之,抛出 UnsatisfiedLinkError 。
ClassLoader.findLibrary failed to return an absolute path: xxx
此后也是调用 loadLibrary0() 继续加载该文件,并检查 loadLibrary0 的结果,处理同上 。
4.假使 ClassLoader 不存在,遍历 system 路径字符串数组的元素 。
通过 mapLibraryName() 分别将 lib name 映射到平台关联的 lib 完整名称并返回,具体见下章节 。创建当前遍历的 path 下 libfile 实例 。调用 loadLibrary0() 继续加载该文件,并检查结果:
- true 则直接结束
- false 的话,通过 mapAlternativeName() 获取该 lib 可能存在的替代文件名,比如将后缀替换为 jnilib
- 如果再度 map 后的 libfile 不为空,调用 loadLibrary0() 再度加载该文件并检查结果,true 则直接结束;反之,进入下一次循环
5.至此,如果仍未成功找到 library 文件,则在 ClassLoader 存在的情况下,到 usr 路径字符串数组中查找 。
- 遍历 usr 路径字符串数组的元素
- 后续逻辑和上述一致,只是 map 时候的前缀不同,是 usr_paths 的元素
6.最终进行默认处理,即抛出 UnsatisfiedLinkError,提示在 java.library.path propery 代表的路径下也未找到 so 文件 。
no xx in java.library.path
// java/lang/ClassLoader.javastatic void loadLibrary(Class<?> fromClass, String name,boolean isAbsolute) {ClassLoader loader =(fromClass == null) ? null : fromClass.getClassLoader();if (sys_paths == null) {usr_paths = initializePath("java.library.path");sys_paths = initializePath("sun.boot.library.path");}if (isAbsolute) {if (loadLibrary0(fromClass, new File(name))) {return;}throw new UnsatisfiedLinkError("Can't load library: " + name);}if (loader != null) {String libfilename = loader.findLibrary(name);if (libfilename != null) {File libfile = new File(libfilename);if (!libfile.isAbsolute()) {throw new UnsatisfiedLinkError(...);}if (loadLibrary0(fromClass, libfile)) {return;}throw new UnsatisfiedLinkError("Can't load " + libfilename);}}for (int i = 0 ; i < sys_paths.length ; i++) {File libfile = new File(sys_paths[i], System.mapLibraryName(name));if (loadLibrary0(fromClass, libfile)) {return;}libfile = ClassLoaderHelper.mapAlternativeName(libfile);if (libfile != null && loadLibrary0(fromClass, libfile)) {return;}}if (loader != null) {for (int i = 0 ; i < usr_paths.length ; i++) {File libfile = new File(usr_paths[i],System.mapLibraryName(name));if (loadLibrary0(fromClass, libfile)) {return;}libfile = ClassLoaderHelper.mapAlternativeName(libfile);if (libfile != null && loadLibrary0(fromClass, libfile)) {return;}}}// Oops, it failedthrow new UnsatisfiedLinkError("no " + name + " in java.library.path");} / ClassLoader#initializePath() /
从 System 中获取对应 property 代表的 path 到数组中 。
1.先调用 getProperty() 从 JVM 中取出配置的路径,默认的是 "" 。
其中的 checkKey() 将检查 key 名称是否合法,null 的话抛出 NullPointerException:
key can't be null
如果为"",抛出 IllegalArgumentException:
key can't be empty
后面通过 getSecurityManager() 获取 SecurityManager 实例,检查是否存在该 property 的访问权限 。
2.如果允许引用路径元素并且存在的话,将路径字符串的 char 取出进行拼接、计算得到路径字符串数组 。
3.反之通过 indexOf(/) 统计 / 出现的次数,并创建一个 / 次数 + 1 的数组 。
4.遍历该路径字符串,通过 substring() 将各 / 的中间 path 内容提取到上述数组中 。
5.最后返回得到的 path 数组 。
// java/lang/ClassLoader.javaprivate static String[] initializePath(String propname) {String ldpath = System.getProperty(propname, "");String ps = File.pathSeparator;...i = ldpath.indexOf(ps);n = 0;while (i >= 0) {n++;i = ldpath.indexOf(ps, i + 1);}String[] paths = new String[n + 1];n = i = 0;j = ldpath.indexOf(ps);while (j >= 0) {if (j - i > 0) {paths[n++] = ldpath.substring(i, j);} else if (j - i == 0) {paths[n++] = ".";}i = j + 1;j = ldpath.indexOf(ps, i);}paths[n] = ldpath.substring(i, ldlen);return paths;}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 一篇讲明白DevOps时代下的持续架构实践
- HTTP缓存看这一篇就够了
- |紫砂壶不挂水就不是好壶吗?
- 天津市|职场人的仕途,无非就是这三个阶段
- 2月逛花市,就选四种漂亮花,浇点水就能活,花开一整年
- 5种花一晒就蔫,放暗处越长越绿,养不好都是弄反了
- 市场营销专业就业方向怎么样,最新市场营销专业当前的就业形势分析
- |老婆打疫苗非要穿露肩连衣裙,戴着口罩就不怕丢脸了吗?
- 出口营销策划方案怎么做,未来出口营销就业前景
- 贺兰山|自己一知半解,却嘲讽壮壮没文化。那就说说《满江红》的贺兰山吧
