apache / apache/maven-compiler-plugin
Output directories missing from javac --class-path in maven-compiler-plugin 4.0.0-beta-4 breaks mixed Kotlin+Java projects
- Dominant language
- Java
- Stars
- 261
- Forks
- 191
- Avg merge
- 1d 5h
- Merged PRs (30d)
- 8
Description
### Affected version
4.0.0-beta-4
### Bug description
## Environment
| Component | Version |
|-----------|---------|
| Maven | 4.0.0-rc-5 |
| maven-compiler-plugin | 4.0.0-beta-4 |
| JDK | 21 |
| kotlin-maven-plugin | 2.3.20-RC |
| OS | Windows 11 |
A minimal reproducer project is attached.
## Description
In a mixed Kotlin+Java project, `kotlin-maven-plugin` runs first during the `compile` phase
and writes `.class` files to `target/classes`. `maven-compiler-plugin` then invokes javac in
the **same phase** to compile Java sources that **reference those Kotlin classes**. This requires
`target/classes` to be on javac's `--class-path`.
The same applies to the `test-compile` phase: kotlinc test-compile writes `.class` files to
`target/test-classes`, after which javac needs `target/test-classes` on its `--class-path`.
With maven-compiler-plugin **3.15.0** both phases worked correctly.
With maven-compiler-plugin **4.0.0-beta-4** both are broken:
- `target/classes` is absent from javac's `--class-path` during `compile`
- `target/test-classes` is absent from javac's `--class-path` during `test-compile`
## Project structure (attached reproducer)
```
src/
main/
kotlin/org/example/Greeter.kt ← compiled by kotlinc → target/classes
java/org/example/Main.java ← uses Greeter, compiled by javac
test/
kotlin/org/example/GreeterTestHelper.kt ← compiled by kotlinc → target/test-classes
kotlin/org/example/GreeterKotlinTest.kt
java/org/example/GreeterJavaTest.java ← uses Greeter + GreeterTestHelper, compiled by javac
```
## Steps to reproduce
Run in attached project:
```
./mvnw package
```
## Expected behavior
javac can see `.class` files produced by earlier compilers that ran in the same phase, because
the output directory is on the `--class-path`.
## Actual behavior
### `compile` phase — `target/classes` missing
`Main.java` fails because `Greeter.class` (written by kotlinc moments earlier) is not on
javac's `--class-path`:
```
[INFO] --- compiler:4.0.0-beta-4:compile (default-compile) @ repro-mixed-java-kotlin ---
[INFO] Compiling all files.
[ERROR] cannot find symbol
symbol: class Greeter
location: class org.example.Main
at src\main\java\org\example\Main.java[5,32]
[INFO] Summary of compiler messages:
1 compiler.err.cant.resolve.location
Total:
1 error
[ERROR] COMPILATION ERROR: Cannot compile org.example:repro-mixed-java-kotlin:jar:1.0-SNAPSHOT main classes.
[INFO] For trying to compile from the command-line, use:
javac @target\javac.args
[INFO] --------------------------------------------------------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] --------------------------------------------------------------------------------------------------------------------------
[INFO] Total time: 5.619 s
[INFO] Finished at: 2026-02-25T23:19:14+01:00
[INFO] --------------------------------------------------------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:4.0.0-beta-4:compile (default-compile) on project repro-mixed-java-kotlin: Cannot compile org.example:repro-mixed-java-kotlin:jar:1.0-SNAPSHOT main classes.
[ERROR] The first error is: cannot find symbol
[ERROR] symbol: class Greeter
[ERROR] location: class org.example.Main
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the '-e' switch
[ERROR] Re-run Maven using the '-X' switch to enable verbose output
```
The plugin writes javac's arguments to `target/javac.args`. It confirms the problem directly:
```
--source 21
--target 21
--module-version 1.0-SNAPSHOT
--class-path "C:\Users\alexa\.m2\repository\org\jetbrains\kotlin\kotlin-stdlib\2.3.20-RC\kotlin-stdlib-2.3.20-RC.jar;C:\Users\alexa\.m2\repository\org\jetbrains\annotations\13.0\annotations-13.0.jar"
--source-path "src\main\java"
-d "target\classes"
"src\main\java\org\example\Main.java"
```
`target/classes` appears only as `-d` (output destination) but **never** on `--class-path`.
### `test-compile` phase — `target/test-classes` missing
`GreeterJavaTest.java` fails because `GreeterTestHelper.class` (written by kotlinc test-compile
moments earlier) is not on javac's `--class-path`:
```
[INFO] --- compiler:4.0.0-beta-4:testCompile (default-testCompile) @ repro-mixed-java-kotlin ---
[INFO] Recompiling all files because all source files changed.
[ERROR] package GreeterTestHelper does not exist
at src\test\java\org\example\GreeterJavaTest.java[16,65]
[INFO] Summary of compiler messages:
1 compiler.err.doesnt.exist
Total:
1 error
[ERROR] COMPILATION ERROR: Cannot compile org.example:repro-mixed-java-kotlin:jar:1.0-SNAPSHOT test classes.
[INFO] For trying to compile from the command-line, use:
javac @C:\Users\alexa\IdeaProjects\Maven4_testing\repro-mixed-java-kotlin\target\javac-test.args
[INFO] --------------------------------------------------------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] --------------------------------------------------------------------------------------------------------------------------
[INFO] Total time: 5.897 s
[INFO] Finished at: 2026-02-25T23:21:53+01:00
[INFO] --------------------------------------------------------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:4.0.0-beta-4:testCompile (default-testCompile) on project repro-mixed-java-kotlin: Cannot compile org.example:repro-mixed-java-kotlin:jar:1.0-SNAPSHOT test classes.
[ERROR] The first error is: package GreeterTestHelper does not exist
```
`target/javac-test.args` confirms this. The plugin's `--class-path` does include
`target/classes` (as a normal test dependency) but **not** `target/test-classes`:
```
--class-path "C:\Users\alexa\IdeaProjects\Maven4_testing\repro-mixed-java-kotlin\target\classes;C:\Users\alexa\.m2\repository\org\junit\jupiter\junit-jupiter\6.0.3\junit-jupiter-6.0.3.jar;C:\Users\alexa\.m2\repository\org\jetbrains\kotlin\kotlin-stdlib\2.3.20-RC\kotlin-stdlib-2.3.20-RC.jar;C:\Users\alexa\.m2\repository\org\junit\jupiter\junit-jupiter-api\6.0.3\junit-jupiter-api-6.0.3.jar;C:\Users\alexa\.m2\repository\org\junit\jupiter\junit-jupiter-params\6.0.3\junit-jupiter-params-6.0.3.jar;C:\Users\alexa\.m2\repository\org\jetbrains\annotations\13.0\annotations-13.0.jar;C:\Users\alexa\.m2\repository\org\opentest4j\opentest4j\1.3.0\opentest4j-1.3.0.jar;C:\Users\alexa\.m2\repository\org\junit\platform\junit-platform-commons\6.0.3\junit-platform-commons-6.0.3.jar;C:\Users\alexa\.m2\repository\org\apiguardian\apiguardian-api\1.1.2\apiguardian-api-1.1.2.jar;C:\Users\alexa\.m2\repository\org\jspecify\jspecify\1.0.0\jspecify-1.0.0.jar"
--source-path "C:\Users\alexa\IdeaProjects\Maven4_testing\repro-mixed-java-kotlin\src\test\java"
-d "C:\Users\alexa\IdeaProjects\Maven4_testing\repro-mixed-java-kotlin\target\test-classes"
"C:\Users\alexa\IdeaProjects\Maven4_testing\repro-mixed-java-kotlin\src\test\java\org\example\GreeterJavaTest.java"
```
## Workaround
Just to use maven-compiler plugin of version 3.15.0.
OR
Use `maven-dependency-plugin:build-classpath` to materialize the dependency classpath as a
path-separated string, then prepend the output directories via `` /
``. Two separate properties are needed because test-scope JARs (e.g.
`junit-jupiter`) must be included for `testCompile` but not for `compile`:
```xml
org.apache.maven.plugins
maven-dependency-plugin
build-classpath
initialize
build-classpath
dep.classpath
compile
test
org.apache.maven.plugins
maven-compiler-plugin
--class-path
${project.build.testOutputDirectory}${path.separator}${project.build.outputDirectory}${path.separator}${dep.classpath}
--class-path
${project.build.testOutputDirectory}${path.separator}${project.build.outputDirectory}${path.separator}${dep.classpath}
```
The `dep.classpath` / `test.dep.classpath` properties are set at `initialize` phase and are
therefore unavailable at POM parse time (IDEs may highlight them red; this is a false alarm).
The attached project's `pom.xml` contains the full working workaround.
This workaround is non-trivial and fragile.
[repro-mixed-java-kotlin.zip](https://github.com/user-attachments/files/25559487/repro-mixed-java-kotlin.zip)
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.