Short answer: Java stubs are expressive and live in the test code; a spec mock is generated from the contract and serves every language. The first is a code-level description of the API; the second is a rendering of the source. The boundary is the JVM.

What Java stubs guarantee

Maximum control over matching, transformations, and state in the same language as the tests. They are a separate, maintained description of the API.

What a spec mock guarantees

PropertyJava stubsSpec mock
SourceTest codeContract
LanguageJVMAny
On changeUpdate codeOn save
DriftCommonRare

Why the language boundary matters

A JVM mock serves the JVM tests. A spec mock serves every client, so a polyglot team shares one target.

The decision rule

Java stubs are right for a JVM codebase that wants control. A spec mock is right for a multi-language team that wants the contract to own the mock.

This is part of the Powerduck vs WireMock comparison. Next, read spec vs code.