There is a huge difference between an interpreter with a JIT compiler and an interpreter running on another interpreter that has one. These are not equivalent at all.
In the JRuby case, JRuby compiles Ruby to JVM bytecode.
Jython may do the same: rather than create cpython bytecode it may produce JVM bytecode which may be optimized by the JVM. However, I do not know anything about Jython performance and they could not be employing the same tactics as JRuby.
With modern Java features like lambdas coming into java 7 and 8 and other interesting languages like Scala, Groovy, etc being written for the JVM I'm sure things have come a long way since the time jython 2.4 was being developed on Java 5/6 and I'm sure the JVM has many more optimizations that dynamic languages may benefit from.
> other interesting languages like Scala, Groovy, etc being written for the JVM
I think Clojure is one of the most interesting so I'm keen you include it in your minimal list of examples. I don't think Clojure actually uses the Java 7 "invoke dynamic" bytecode though.
Mostly orthogonal. You can have an interpreter without a virtual machine (Basic or Python doesn't have one, just a runtime), and similarly a virtual machine without an interpreter.
An interpreter executes scripting instructions directly.
A virtual machine implements a faux (virtualized) cpu, with its instruction set etc, and executes its "assembly code" (with or without JITing).
(Things get complicated in that you can also have combinations of those concepts).
Python in CPython is executed after being compiled to the lower-level Python bytecode. Is this not sufficient to consider CPython to involve a virtual machine?
Almost all interpreters compile an ast to an "assembly code" that gets executed. CPython even executes that assembly code without seeing the source at all just like Java.