解决Java模块化项目 Azure Identity 模块加载失败问题
2025-01-29 19:50:01
解决Java模块化项目中使用 Azure Identity 模块的问题
使用 Java 模块化项目时,依赖项的管理方式可能导致一些初学者难以理解的错误。在使用 com.azure.identity
模块时,就可能会出现 Module not found
这样的异常。本文探讨这一问题的根源并提供几种解决方案,帮助开发者克服模块化 Java 项目中可能遇到的挑战。
问题分析
上述错误 java.lang.module.FindException: Module msal4j.persistence.extension not found
表明 JVM 在运行时无法找到 msal4j.persistence.extension
这个模块。从构建文件来看,该依赖已经被正确地添加到 build.gradle.kts
文件中。 进一步的错误, module not found: msal4j.persistence.extension
表明 module-info.java
也存在同样的问题。根本原因在于, msal4j.persistence.extension
是一个自动模块 。
自动模块 并不是传统意义上的模块,它们只是为了兼容那些不符合 Java 9 及以上版本模块化规范的 JAR 文件。自动模块不能直接通过模块名引入到你的模块中。 它们被放入一个名为未命名模块的模块图中,它们具有模块的所有可读性、并且不属于模块层级的任何其他层级。因此,显式在 module-info.java
中 requires
它将会导致错误。
解决方案
以下是一些可用于解决该问题的方法。
方案一:移除 module-info.java
中的依赖
最直接的办法,是避免尝试直接在模块符 module-info.java
中显式引用自动模块。修改 module-info.java
文件,删除对 msal4j.persistence.extension
的 requires
语句。
修改后的 src/main/java/module-info.java
:
module com.example {
requires java.base;
requires com.azure.identity;
exports com.example;
}
步骤:
- 修改
src/main/java/module-info.java
文件,删除requires msal4j.persistence.extension;
行。 - 运行构建任务:
.\\gradlew run
。
该方法简单快捷,适合对模块化细节不太关心,但仍然需要正常运行应用的开发者。 这样处理之后, 依赖可以正确找到。
方案二:使用 --add-modules
启动 JVM
这个方法可以显式指示 JVM 包含指定的模块。这种方案相对灵活,能控制启动时的模块加载。可以通过添加 --add-modules
参数来使自动模块“成为”一个常规模块,从而使你的应用程序在模块化环境中有意义地使用这些自动模块。
操作步骤:
-
修改
build.gradle.kts
,配置 application 启动参数application { mainClass = "com.example.Main" mainModule = "com.example" applicationDefaultJvmArgs = listOf("--add-modules","msal4j.persistence.extension") }
-
确保
module-info.java
包含所有必要的其他依赖。比如示例中的com.azure.identity
。 -
执行
.\\gradlew run
,启动程序。
通过添加启动参数, JVM 会把自动模块当作显式模块对待,问题就可以得到解决。 需要特别注意在运行时指定这些额外的模块名。
方案三:调整 msal4j-persistence-extension
依赖方式
另外一种方式是在build.gradle.kts
强制该依赖被添加到编译期的类路径,尽管它的运行不属于模块图本身。我们可以通过配置让它在模块路径中可用。这样做实际上在模块之外公开它,但却依然有效,尽管并非在纯粹的模块方式中执行。
build.gradle.kts
的修改 :
dependencies {
implementation(platform("com.azure:azure-sdk-bom:1.2.28"))
implementation("com.azure:azure-identity")
implementation("com.azure:azure-core")
implementation ("com.microsoft.azure:msal4j-persistence-extension:1.3.0") {
isTransitive = true
}
configurations.implementation{
resolutionStrategy.force("net.java.dev.jna:jna:5.13.0")
resolutionStrategy.force("net.java.dev.jna:jna-platform:5.13.0")
resolutionStrategy.force("org.slf4j:slf4j-api:1.7.36")
resolutionStrategy.force("com.microsoft.azure:msal4j:1.17.1")
}
}
在此配置中,需要调整和固定内部传递的依赖以强制他们进入运行时模块路径中。这种方案本质上将自动模块放入依赖关系树中的适当位置, 解决了模块的依赖问题。这种做法并不推荐, 除非必须这样做, 并了解相关的风险。
操作步骤 :
- 按照上述示例修改
build.gradle.kts
。 - 运行
.\\gradlew run
检查问题是否被修复。 - 确保
module-info.java
文件中不存在requires msal4j.persistence.extension;
。
该方案更为精细地控制了模块依赖和传递,适合对类加载有更高级要求的开发者。这种配置允许模块正确启动和运行,但是这需要对Gradle依赖关系图,传递性依赖等理解。
总结
在 Java 模块化项目中使用 com.azure.identity
模块时遇到的问题通常由 msal4j.persistence.extension
的自动模块特性引起。开发者可以通过移除 module-info.java
中的依赖,使用 --add-modules
启动参数, 或者在build.gradle.kts
中强制设置该模块传递性依赖的路径等方式解决该问题。 选择合适的方案,取决于具体项目的需求和对模块化程度的要求。 如果仅需要正常运行,第一种方案更为推荐。 理解这些方案和它们背后的原理能帮助开发者更好的解决 Java 模块化问题。