I think pass by copy is a consequence of being modifiable.
The other solution is to stack allocate and pass a pointer but as i said, unlike in C#, i do not think it's possible to do that in Java.
In Go, you can stack allocate but when you send a pointer (that escapes), the compiler will heap allocate the object.
My point is that pass by copy and pass by value do the same thing, they copy the value representation. In other words, pass by copy means exactly pass by value.