But there's a lot of magic involved in transforming Java to class files, and then there's a lot of further magic in resolving, loading, and eventually executing classes.
It's not like writing a basic cache is very hard...or just "borrow" one from an OS implementation.
The super pedant in me, of course, would say they're a sliver in the middle because they're targeted at running in a software-implemented VM instead of on a real machine architecture, and that this isn't all that different from in-memory interpreter bytecode or something like a .pyc written to disk...
But then something like the more complicated loaders for native executables is a sliver in the middle, too. And then you look at something like the AS/400 with super-high level "instructions" and these distinctions get super, super muddy.