Java程序运行时如何获取依赖列表?(无Maven环境)
在Java程序运行时获取依赖列表的几种方案
嘿,这个需求很常见,尤其是当你的程序要在没有Maven的环境运行时,总不能让用户手动去查依赖对吧?下面给你几个靠谱的实现方式:
1. 利用ClassLoader遍历已加载的Jar包
Java的类加载器可以获取到当前JVM中已加载的所有资源,其中就包含你的项目依赖的Jar文件。你可以写一段代码,遍历这些资源并提取Jar的名称和版本信息。
示例代码如下:
import java.net.URL; import java.security.CodeSource; import java.util.HashSet; import java.util.Set; public class DependencyLogger { public static void logDependencies() { Set<String> dependencies = new HashSet<>(); // 获取当前类的类加载器 ClassLoader classLoader = DependencyLogger.class.getClassLoader(); if (classLoader instanceof java.net.URLClassLoader) { URLClassLoader urlClassLoader = (URLClassLoader) classLoader; for (URL url : urlClassLoader.getURLs()) { String urlStr = url.getFile(); // 过滤出Jar文件,提取名称 if (urlStr.endsWith(".jar")) { String jarName = urlStr.substring(urlStr.lastIndexOf('/') + 1); dependencies.add(jarName); } } } // 打印依赖列表 System.out.println("当前程序依赖的Jar包:"); for (String dep : dependencies) { System.out.println("- " + dep); } } public static void main(String[] args) { logDependencies(); // 你的程序逻辑... } }
注意:这种方式只能获取到已经被类加载器加载的Jar包,如果有些依赖是动态加载的,可能不会被列出来。
2. 打包时嵌入依赖清单(推荐)
如果你用Maven打包,可以借助maven-shade-plugin或者maven-resources-plugin,在打包阶段把dependency:tree的结果写入到Jar包内部的一个文件中,然后程序启动时直接读取这个文件即可。
步骤1:配置Maven插件,嵌入依赖信息
在pom.xml中添加以下配置,让Maven在打包时生成依赖列表文件:
<build> <plugins> <!-- 生成依赖树并写入文件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>3.6.0</version> <executions> <execution> <id>generate-dependency-tree</id> <phase>prepare-package</phase> <goals> <goal>tree</goal> </goals> <configuration> <outputFile>${project.build.outputDirectory}/dependencies.txt</outputFile> <outputType>text</outputType> </configuration> </execution> </executions> </plugin> <!-- 打包时包含生成的依赖文件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.3.0</version> <configuration> <includes> <include>**/dependencies.txt</include> </includes> </configuration> </plugin> </plugins> </build>
步骤2:程序启动时读取依赖文件
import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; public class DependencyLogger { public static void logDependencies() { try (InputStream is = DependencyLogger.class.getResourceAsStream("/dependencies.txt"); BufferedReader reader = new BufferedReader(new InputStreamReader(is))) { String line; System.out.println("程序依赖列表:"); while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (Exception e) { System.err.println("读取依赖列表失败:" + e.getMessage()); } } public static void main(String[] args) { logDependencies(); // 你的程序逻辑... } }
这种方式的优点是能获取到完整的依赖树(包括传递依赖),而且不需要在运行时依赖任何工具,完全依赖打包阶段生成的静态文件。
3. Java 9+模块化项目:使用Module API
如果你的项目是基于Java 9及以上的模块化系统开发的,可以直接使用Module API来获取模块的依赖信息:
import java.lang.module.ModuleDescriptor; import java.util.Set; public class DependencyLogger { public static void logDependencies() { // 获取当前模块的描述符 Module currentModule = DependencyLogger.class.getModule(); ModuleDescriptor descriptor = currentModule.getDescriptor(); // 获取依赖的模块 Set<ModuleDescriptor.Requires> requires = descriptor.requires(); System.out.println("当前模块依赖的模块:"); for (ModuleDescriptor.Requires req : requires) { System.out.println("- " + req.name() + (req.version().isPresent() ? " (版本:" + req.version().get() + ")" : "")); } } public static void main(String[] args) { logDependencies(); // 你的程序逻辑... } }
注意:这种方式只适用于模块化项目,获取的是模块级别的依赖,而不是Jar包级别的。
内容的提问来源于stack exchange,提问作者Mattew Eon




