− | I think the crux of the problem lies in the unnadstenridg of the term reference , and I think this answer on the SO thread linked above hits on this nicely: The crux of the matter is that the word reference in the expression pass by reference means something completely different from the usual mening of the word reference in Java.Usually in Java reference means a a reference to an object. But the technical terms pass by reference/value from programming language theory is talking about a reference to the memory cell holding the variable, which is someting completely different. In C++, a reference to a value and the physical memory address of that value are the same thing (well, due to the OS managing memory, it's actually a virtual memory address, but let's ignore that). In Java, a reference to a value (i.e. object) and the physical memory address are NOT the same thing, since the VM moves objects around during its operation. Instead, a reference is a symbol managed on the VMs symbol table, and is updated with a new address whenever the object is moved around in memory. For obvious reasons, Java doesn't allow direct access to physical addresses. The following example demonstrates:#include void foo(int &x) { printf( Foo before: %d @ %p\n , x, &x); x = 20; printf( Foo after: %d @ %p\n , x, &x);}void bar(int *x) { printf( Bar before: %d @ %p\n , *x, x); *x = 30; printf( Bar after: %d @ %p\n , *x, x);}void baz(int *x) { printf( Baz before: %d @ %p\n , *x, x); int y = 40; x = y; printf( Baz after: %d @ %p\n , *x, x);}int main() { int x = 10; printf( Initial: %d @ %p\n , x, &x); foo(x); printf( Main after foo: %d @ %p\n , x, &x); bar(&x); printf( Main after bar: %d @ %p\n , x, &x); baz(&x); printf( Main after baz: %d @ %p\n , x, &x); return 0;}Output:Initial: 10 @ 0x7fffe99c981cFoo before: 10 @ 0x7fffe99c981cFoo after: 20 @ 0x7fffe99c981cMain after foo: 20 @ 0x7fffe99c981cBar before: 20 @ 0x7fffe99c981cBar after: 30 @ 0x7fffe99c981cMain after bar: 30 @ 0x7fffe99c981cBaz before: 30 @ 0x7fffe99c981cBaz after: 40 @ 0x7fffe99c97fcMain after baz: 30 @ 0x7fffe99c981cAt this point it should be clear that the way I've defined the method baz above is how Java performs method calls for non-primitives. All such method calls pass only references to objects, but any changes to the references themselves (not the values they refer to!) remain within the scope of the callee. This subtle distinction means that the call is technically by value, even though we're providing only references as parameters.
| + | This topic sometimes coefusns developers that are analyzing heap dumps as they expect particular locals to be reported as roots but they aren't present in the dump. When a debugger agent is running then you will notice that are locals do appear to be in scope. This is necessary to allow the developer access them in the debugger. |