Both - Kotlin's coroutines are a runtime for green threading. The implementation of that runtime could use Java's green threads for many things and where the developer UX or guarantees aren't there, fall back on other primitives. But users of Kotlin could also just use Java's new virtual threads if they don't need anything fancy from Kotlin's coroutine runtime.
You probably wouldn't want to _mix_ these threading approaches in a single codebase unless Kotlin's coroutines become a literal "dev UX facade" because otherwise things like ThreadLocals (and whatever Kotlin provides as an alternative) can get out of sync.
You probably wouldn't want to _mix_ these threading approaches in a single codebase unless Kotlin's coroutines become a literal "dev UX facade" because otherwise things like ThreadLocals (and whatever Kotlin provides as an alternative) can get out of sync.