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

Open
#1,036 0 comments 0 reactions 0 assignees View on GitHub
bug
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.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.