如何在JDK 9及以上版本中获取引导类路径
sun.boot.class.path替代方案) 我完全理解你在JDK版本升级时碰到的这个头疼问题——JDK 9开始直接移除了sun.boot.class.path这个内部系统属性,导致调用System.getProperty("sun.boot.class.path")直接返回null。别急,我们可以用JDK 9引入的模块化API来拿到等效的路径信息,完全不需要依赖-Xbootclasspath选项。
推荐方案:通过模块层获取系统模块路径
JDK 9+的引导类库已经全面模块化,原来的引导类路径对应的正是**引导模块层(Boot Module Layer)**里所有系统模块的位置。我们可以遍历这些模块来收集路径,代码示例如下:
import java.lang.module.ModuleReference; import java.nio.file.Path; import java.util.stream.Collectors; public class BootClasspathResolver { public static void main(String[] args) { String bootClasspath = ModuleLayer.boot().modules().stream() // 获取模块的引用实例 .map(module -> module.getReference()) // 获取模块的存储位置(返回Optional<URI>) .map(ModuleReference::location) // 过滤掉没有明确位置的内置模块 .filter(location -> location.isPresent()) .map(location -> location.get()) // 转换为Path格式后转成字符串 .map(Path::toString) // 用冒号拼接成和旧版sun.boot.class.path一致的格式 .collect(Collectors.joining(":")); System.out.println(bootClasspath); } }
运行这段代码后,你会得到类似这样的输出(和你期望的格式一致):
/usr/lib/jvm/java-10-openjdk-amd64/lib/modules/java.base.jmod:/usr/lib/jvm/java-10-openjdk-amd64/lib/modules/java.xml.jmod:/usr/lib/jvm/java-10-openjdk-amd64/lib/modules/java.desktop.jmod:...
注:JDK 10的系统模块是以.jmod文件形式存在的,和JDK 8的.jar格式不同,但本质都是系统类库的载体,路径的冒号分隔形式和旧版完全匹配。
备选方案:遍历JRE lib目录获取Jar文件
如果你只需要JRE lib目录下的Jar文件路径(对应JDK 8引导类路径的部分内容),可以通过java.home系统属性拼接路径后遍历,代码如下:
import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Collectors; public class AlternativeBootPathGetter { public static void main(String[] args) { String javaHome = System.getProperty("java.home"); Path jreLibPath = Paths.get(javaHome, "lib"); try { String bootPath = Files.walk(jreLibPath) // 只保留文件(排除目录) .filter(Files::isRegularFile) // 筛选出Jar格式的文件 .filter(path -> path.toString().endsWith(".jar")) .map(Path::toString) .collect(Collectors.joining(":")); System.out.println(bootPath); } catch (Exception e) { e.printStackTrace(); } } }
不过这个方法有局限性:模块化后部分系统类库以.jmod形式存在于lib/modules目录下,这个方法会漏掉这些模块,所以更推荐第一种基于模块化API的方案。
补充说明
JDK 9移除sun.boot.class.path是因为模块化系统重构了类加载机制,这个属性属于非标准的内部API,官方不再提供支持。使用模块化API获取路径是符合JDK后续版本规范的做法,兼容性和稳定性更好。
内容的提问来源于stack exchange,提问作者Gayan Weerakutti

