Re: How java passes object references?
- From: "Peter Duniho" <NpOeStPeAdM@xxxxxxxxxxxxxxxx>
- Date: Sat, 26 Apr 2008 10:19:30 -0700
On Sat, 26 Apr 2008 00:42:13 -0700, pek <kimwlias@xxxxxxxxx> wrote:
[...]
So, what I understood is memory allocations could be "visualized" as
blocks containing smaller blocks that also contain smaller etc. So,
for instance, The Heap is a block that contains instances of objects,
which are also blocks that contain instance members and method blocks
that contain local variables.
Almost. There's no such thing as "method blocks". I believe (*) Java uses the same sort of stack convention as many other languages, including C++ and C#. Local variables are allocated on the stack, not the heap. It gets a little confusing if you look too deeply in the implementation, because at some level on conventional operations systems (Windows, Linux, Unix, OS X, etc.) you're dealing with a single process memory space and everything gets allocated from there.
But those are implementation details that I think you shouldn't concern yourself with. From a practical point of view, you'll have more success if you realize that local variables are allocated in a fundamentally different way from class instances. The former are allocated on the same stack that's used for function calling, while the latter are allocated from the heap.
If you really want to consider local variables as allocated in some sort of mythical "method block", it's probably true that few predictions one might make using that understanding would be wrong. You could probably get away with it. But IMHO it's not the most precise way to think about it.
(*) I wrote "I believe" because I'm actually relatively new to the Java language. But my understanding is that Java byte-code is compiled "just-in-time" into a platform-efficient representation that is actually executed, and that would mean using platform-supported run-time mechanisms like a stack. It's theoretically possible to implement Java with individual heap allocations for each function call, but that would be relatively inefficient and I don't believe any mainstream implementation of Java would do it that way.
[...]
So, if I'm getting this correctly, when C++ compiles the code, it sees
that o points to h which points to the actual instance of the object
in memory.
Sort of. When C++ compiles the code (and in similar languages), in the caller it passes an address of the parameter to the method. The method itself, which could be compiled separately from the caller, is compiled to use the address passed to it in the appropriate way.
There's no point at which the called method literally knows that "h" is being passed. All it knows is that some variable of a specific type was used as a parameter, and it's been passed a reference (address, pointer, whatever you want to call it) to that variable.
So, every time it does anything to o it follows this route
in order to accomplish this change. So, in the same sense, if change()
would call again another method that also expects a Human class and
passes o, the compiler would have to do one more step to get to the
instance in memory. Am I correct here?
That depends on what you mean by "call again another method". Is that method expecting a "by reference" parameter? Then the same reference that was passed to change() could be passed to the other method. Otherwise, a copy of the variable (i.e. whatever you get by dereferencing the reference to the original parameter) is passed.
In other words, if change() calls another method, if "o" is passed by reference, then the original variable passed to change() would be changed if the other method changes it locally. If "o" is passed by value (i.e. the default in C++ and C#), then a copy of the variable is passed and changes made to the local parameter in the other method change() called will not be seen in the original variable.
Or put another way, passing by reference and passing by value work with each other in exactly the way one would (should) expect.
So when allocating local memory for o, it would simply allocate a
pointer pointing at h which is also a pointer pointing at the instance
variable. If this is correct, I'm getting a pretty good picture right
now. :D
Yes, that's a reasonably accurate way to describe it (where "allocating local memory" means an allocation on the stack frame for the method change()).
[...]
So, I'm assuming that C#, as opposed to Java, doesn't have pass-by-
object-reference.
No. C# has the same pass-by-value semantics that Java has. When you pass an object variable, the value of that variable -- which is a reference to an object -- is passed as a copy, just as in Java. C# _also_ has pass-by-reference, using the "ref" or "out" keywords, but by default C# passes things exactly the same as Java does.
[...]
I think I have just learned a fundamental difference about what a
class variable actually is in Java and, probably, values and
variables. So, what I understood here is that "o" in C++ is either:
A) If it's passed by value, it is a variable that its' value is
allocated into its' respective context in memory (namely, local, class
member etc.)
B) If it's passed by reference, it is a variable that it doesn't
actually has a value, rather, a pointer that either points to the
allocated memory or to another pointer
That's correct. C++ has additional ways to reference class instances and pass them as parameters as well, but the two above points accurately describe a variable typed simply as a class and the ways it can be passed.
While in Java, class variables aren't either one of C++'s. It's rather
a combination. A class variables' value is a reference. This means
that when I change the value of a variable, I assign it with a new
reference.
Yes.
References allocate memory and are basically pointers
pointing to an object instance in memory.
Define "allocate memory". A reference represents memory that's been allocated. But the reference itself doesn't allocate memory. It's the consequence of allocating memory.
Other than that minor nit, yes...references are basically pointers pointing to an object instance in memory.
So, Java has something like
an additional "layer" where reference are between a variable and it's
value.
I'm not sure I'd call it an additional layer. It's just a different kind of variable. C++ has variables that reference object instances too; it's just that C++ is more explicit in using them (using the "*" syntax).
And when passing here and there a variable, you are actually
copying its' value, which is a reference. It's something like saying
that all class variables in Java are of type Reference with a value of
an object (super-extraordinary-oversimplified).
Yes, that's true. Keep in mind that this is specifically with respect to class type variables. These would be called "reference types". Java (and C#) also has "value types", which are things like "int", "boolean", etc. Variables of those types don't reference an instance; they simply "are" that instance.
[...]In fact, given that Java doesn't support passing by reference, I'm a bit
confused as to why the question wound up here. :) [...]
Well, I as I tried to explain, I'm trying to write a presentation
about what happens under the hood about pass-by-value, pass-by-
reference and (as I think of a better way to name Java's own) pass-
reference-by-value. I want to create an illustration about memory
allocations in all three situations and what Java does and why.
Well, one of the reasons I pointed you to Jon's article is that you seem to be breaking the scenarios down into the wrong divisions. In particular, Java's "pass-reference-by-value", as you call it, is really just "pass-by-value". It's no different from "pass-by-value" in any other language (especially when you consider that Java has non-reference types, and other languages have reference types, either of which can be passed "by-value").
There is "passing by reference" and there is "passing by value". As far as parameter passing goes, that's really all anyone should need to know. Java only has "passing by value".
On top of that, there are "reference types" and "value types". Java has both reference and value types, but Java always passes both by value. However, a different language like C++ or C# has both passing by reference and passing by value, and can pass both references and values with by-reference or by-value semantics.
I admit, it's a bit confusing because the words "reference" and "value" are used in two different ways. I don't really mind the disparity myself, but if it's difficult to keep track of, you might try substituting "pointer" and "non-pointer" for the type names. Then you have:
-- pass non-pointer by value
-- pass pointer by value
-- pass non-pointer by reference
-- pass pointer by reference
Java has the first two. C++ and C# have all four.
Once again, I can't thank you enough... Wait.. I think I can. Since
this "research" will also wind up on my blog, how about a reference to
your blog/website? You've helped me extremely. Mines is (and I hope I
don't get filtered for this) http://pekalicious.treazy.com.
I appreciate the offer, but I don't have anything that I need advertising. (I don't even have a blog anyway). I'm happy just to hear that I've been helpful. :)
Pete
.
- Follow-Ups:
- Re: How java passes object references?
- From: Lew
- Re: How java passes object references?
- References:
- How java passes object references?
- From: pek
- Re: How java passes object references?
- From: Peter Duniho
- Re: How java passes object references?
- From: pek
- How java passes object references?
- Prev by Date: Re: What is the difference and relation between an interface and its method?
- Next by Date: Re: Composition vs. inheritance
- Previous by thread: Re: How java passes object references?
- Next by thread: Re: How java passes object references?
- Index(es):
Relevant Pages
|