I believe that the direction of a managed language with value types is a good goal.
I especially like Java’s plan of introducing them: according to the latest design iteration, there will be 3 buckets of objects: current identity-having ones, value classes and primitive classes.
The second category would drop identity, but will keep nullability (for example two DateTime instance of the same value will be considered equal on a VM-level, allowing for optimizations like allocating DateTime’s inside an array serially, or stack-allocation. Nullability is important because there is no sane default value choice for for example a DateTime. But this value can be encoded cleverly similarly to what Rust does with optional)
The third category will loose nullability as well and current primitives will be migrated to it. So a ComplexInt “class” will be possible to implement with “zero” overhead.
My point being that there are two ways of improving performance, either showing more knobs to manipulate, or to raise the abstraction level, allowing cleverer optimizations. C# does the former, while Java never went that route, and I think that the latter approach better fits a managed language and can easily push it for like 90% better performance at a fraction of developer complexity.