Gradle集成PMD扫描OSGi Bundles时出现NoClassDefFoundException求助
Let's break down what's causing the NoClassDefFoundException in your Gradle PMD setup and how to fix it:
The Root Cause
Your current configuration has a critical mistake in the tasks.withType(Pmd) block:
configureForSourceSet = file('../bundles/**/*.class')
PMD is designed to scan source code files, not compiled .class files. By pointing it to class files, you're forcing PMD to perform bytecode analysis, which requires resolving all dependent classes across your bundles. Since these classes aren't properly available in the PMD classpath for each subproject, you get the NoClassDefFoundException.
The command-line PMD tool works because you're likely targeting source directories directly, skipping the bytecode analysis that's causing the issue in Gradle.
Step-by-Step Fixes
Remove the incorrect
configureForSourceSetline
This is the main culprit. Delete that line entirely—Gradle's PMD plugin automatically detects the source sets for each subproject by default.Ensure all bundles are recognized as subprojects
Make sure yoursettings.gradleincludes all bundle subprojects so Gradle can manage their dependencies properly:include 'bundles:*'Explicitly configure PMD to scan source directories (optional but recommended)
To make your configuration clearer, you can explicitly tell PMD to target the main source set's Java files:tasks.withType(Pmd) { source = sourceSets.main.java.srcDirs }Add compile classpath to PMD if type resolution is needed
If your custom PMD rules require resolving class types (e.g., checking inheritance or method signatures), you need to provide PMD with the compile classpath for each subproject. This ensures it can find dependent classes from other bundles:tasks.withType(Pmd) { classpath = sourceSets.main.compileClasspath }Just make sure you've properly configured inter-bundle dependencies in each subproject's
build.gradle(e.g.,implementation project(':bundles:bundle2')if bundle1 depends on bundle2).Verify your PMD rule set path
Double-check that${sbDir}/MyJavaRules.xmlis correctly resolved in each subproject. IfsbDiris a project-level variable, you might need to qualify it withrootProjectto ensure consistency:ruleSets = ["${rootProject.sbDir}/MyJavaRules.xml"]
Final pmd.gradle Example
Here's how your corrected pmd.gradle might look:
subprojects { apply plugin: 'pmd' pmd { consoleOutput = true toolVersion = "6.21.0" reportsDir = file("${rootProject.projectDir}/pmd/reports") // Use root project dir for centralized reports ruleSets = ["${rootProject.sbDir}/MyJavaRules.xml"] ignoreFailures = true } tasks.withType(Pmd) { source = sourceSets.main.java.srcDirs classpath = sourceSets.main.compileClasspath } }
This setup will scan each bundle's source code directly, use the correct classpath for type resolution if needed, and avoid the class not found errors you're seeing.
内容的提问来源于stack exchange,提问作者user826323

