The packaging works fine. Do all Java apps running on a host use the same classpath pointing to /usr/lib directories full of JAR files? Of course not. That's all that virtualenv is doing; the equivalent of managing /lib directories for an invocation of the interpreter.
I don't follow how these are at all similar other than you saying they are 'equivalent'. Typical java apps get their dependencies from the same maven-managed local repo. The tool itself is baroque but conceptually this is much simpler than creating magical 'environments' - the repository of dependencies, what dependencies a particular app uses and what version of the runtime it's invoked with are all separate and orthogonal to each other.
An even simpler way to think about it - imagine you just invented python and are designing the tooling around dependency management and packaging. Would you come up with 'environments'?
> Typical java apps get their dependencies from the same maven-managed local repo.
What? No, they don't. Typical Java apps are deployed on systems that don't even have Maven installed. Typical Java apps are executed with a classpath argument pointing to the libraries installed for the application. What are the directories containing those JARs (or an uberjar) except an "environment?"
Hell, the Java classloader interacts with the classpath in pretty much the exact same way that the Python interpreter interacts with a virtualenv.