Strings - Stack and heap in java - java

I know that Strings are stored on the heap and the reference to them is stored on the stack. So in the code below one would point to "John" on the heap from the stack and likewise two would point to "Smith" on the heap from the stack.
So what happens when i do one = two?
Does one now point to where two points to because two contains a reference to a point on the heap or does it change the "John" on the heap to "Smith"?
String one;
one = "John";
String two = "Smith"
one = two;

In your example, one now points to the same place as two. The original string on the heap "John" becomes garbage and is subject to garbage collection.
It's not possible to see in this example because String is immutable, but if these were mutable data structures such as an ArrayList, then modifying the object through one would make the same change visible through two, because they point to the same object.

Now one will point to the two .Since all string are immutable then when they are created then they are stored in heap and referenced by variable but when you make or assign new variable to same string then it will not explicitly create new string but just reference to same string which is in heap
from above picture you can easily understand the concept of immutability.
for reference Where does java reference variable stored?

Related

How to distinguish object and variable in java

I get stuck in this problem in java docs. The second problem's answer said that after the code execute, "Neither object is eligible for garbage collection. The array students is not eligible for garbage collection because it has one reference to the object studentName even though that object has been assigned the value null. The object studentName is not eligible either because students[0] still refers to it."
But I don't think studentName and students are object, they just variables to refer to objects, and they will not be garbage recycled. I think only the String "Peter Parker" is an object in the code below. What's wrong?
...
String[] students = new String[10];
String studentName = "Peter Parker";
students[0] = studentName;
studentName = null;
....
This statement is fundamentally wrong on more levels than confusing objects and variables.
You are right in that it confuses names and objects, to the highest amount ever seen. Not only is “reference to the object studentName” wrong as studentName is not an object, “even though that object has been assigned the value null” is even worse, as objects can not be assigned to null and what is supposed to explain that setting a reference to null does not imply that the referent becomes unreachable, is achieving the opposite.
But that’s not the end, as the entire logic is wrong. Let’s remove the names, to avoid that confusion. Then, the phrase reads as “The array … is not eligible for garbage collection because it has one reference to the object …”. That’s completely wrong. If X has a reference to Y, it does not prevent the garbage collection of X, as only references to X matter.
What may prevent the garbage collection of the array, is the variable students holding a reference to it, but of course, an author who fails to distinguish between variables and objects, is not able to express this relationship.
It’s worth noting, that if students is a local variable, it does not prevent the garbage collection of the array in every case, as explained in Can java finalize an object when it is still in scope? But skipping this in a tutorial may be acceptable for simplification, see also Lie-to-children.
Another issue is that objects created for string literals like "Peter Parker" will stay in memory as long as there’s at least one piece of code in the JVM having a reference to it, as all string literals (and compile-time constants of type string) of the same contents evaluate to the same object.
If you want to go the route of simplified reasoning about garbage collection, the students variable contains a reference to a String[] array instance, which is prevented from garbage collection due to this reference, and the array contains a reference to a String object, which prevents the String instance from garbage collection (in addition to other references which may exist).
Most of the time, you shouldn’t try to guess what the garbage collector could collect, because the very purpose of the garbage collector is to remove the burden of thinking about this from the developer.
Unfortunately, the doc does not clearly distinguish bewtween variables and objects. There are two objects in this snippet: the array new string[10] and the string "Peter Parker". In line 1 the variable students is set to a reference of the array object; in line 2 the variable studentName is set to a reference of the string object; in line 3 the array element 0 is set to a reference to the string object; and finally in line 4 the variable studentName is set to null.
Now the array object cannot be garbage collected because the variable students still holds a reference and the string objects cannot be garbage collected because the array element 0 still has a reference.
If there were a line 5 where the variable students is set to null as well, both objects could be garbage collected because both are no longer reachable (a string literal however is never garbage collected - but this for another reason). It does not matter that the array element 0 still has a reference to the string object in this case because the array object itself is no longer reachable.

java pass by value and memory and cpu utilization

Coming from a C background I have a very basic question: Does pass by value of a larger datatype like a String array invoke something like a copy constructor in java.
So would this code result in creating duplicate list in memory by copying list in list2.
Thus double memory and cpu utilization.
String[] getList() {
String[] list = new String...
...
return list;
}
String [] list2 = getList();
Is my assumption correct? If yes, is there an alternative like passing pointers in C.
PS: if we let garbage collector do the job of cleaning extra memory wont this be another set of cpu utilization of cycles of cleaning the memory which shouldn't have been created at first place.
No, it won't double memory and CPU usage. In Java, all non-primitive types are stored as references and those references are passed by value.
So in your example, the getList method will construct an array on the heap and return a reference to that array. No array copy involved; just a reference copy.
No, the contents of the array will not be copied. A reference pointing to the array on the heap will be passed instead.
Java does not have pointers, it has references. In Java, references pointing to objects on the heap are passed as arguments and returned by methods. Arrays are objects in Java, so they are treated this way too.

Java - why does assigning "null" to variable does not make it available for GC? (In this code snippet)

I was going through the online tutorial provided by oracle. One of the exercises has a question as follows:
The following code creates one array and one string object. How many references to those objects exist after the code executes? Is either object eligible for garbage collection?
...
String[] students = new String[10];
String studentName = "Peter Smith";
students[0] = studentName;
studentName = null;
...
Answer: There is one reference to the students array and that array has one reference to the string Peter Smith. Neither object is eligible for garbage collection.
(http://docs.oracle.com/javase/tutorial/java/javaOO/QandE/objects-answers.html)
Surely the last line means studentName is eligible for GC? Really confused, and I think this means I have not understood the nature of "null" and also object referencing properly, which is why I ask.
Before assigning null to studentName there are two references to "Peter Smith" (studentName and students[0]). After null is assigned to studentName, "Peter Smith" is still referenced by students[0]
What are the objects, actually, that cannot be garbage collected? "Peter Smith" and the String[10] array. Note these are the objects themselves, not the references to the objects! It is enough that just one reference exists to avoid garbage collection.
I use a mental trick which is to be verbose while reading code. It is easy to say "String" (vague) when what you mean is "String object" (the words in the String) or "String reference" (the variable pointing to the words) so this trick avoids this confusion.
Rewriting the pseudocode with my mental trick, labeling everything as object or reference the way I do in my mind:
1 String[] OBJECT student REFERENCE = new String[10] OBJECT;
2 String OBJECT studentName REFERENCE = "Peter Smith" OBJECT;
3 students[0] REFERENCE = studentName REFERENCE;
4 studentName REFERENCE = null;
In line 3 the String[0]_reference was pointed at the "Peter Smith" object. It is now clear that just the studentName reference was set to null but the "Peter Smith" object continues to exist and the array still points to it. Thus the objects aren't ever null, just one reference was nulled.
This page explains the fundamental java concept of references well (and how they are essentially just pointers)
http://javadude.com/articles/passbyvalue.htm
Though not about the question, it is directly relevant. Objects are referenced by pointers (references) in java. Understanding that should help a lot.

Construct a new Object() with the toString result of another Object

I was wondering if it was possible to get some String value of an Object to access that Object on the same machine (same RAM) or the same VM via that particular String.
e.g.
Object objA1 = new Object();
System.out.print(objA1.adress); => output: d146a6581ed9e
Object objExt = Object.buildFromMemoryAdress("d146a6581ed9e");
I hope you understand what I'm trying to understand.
EDIT: I found in
http://javapapers.com/core-java/address-of-a-java-object/#&slider1=1
a Class that allows me to get the String of the logical address of an instance on the (VM?) memory: sun.misc.Unsafe
I think I can also use Unsafe to retrieve an Object from the (restricted to the VM?) memory.
If not possible like this, how would I do it, and since it's out of curiosity are there any other languages (especially high end) that allow direct memory access like this?
It is incorrect to assume that the number that you see in the toString() result is the memory address.
It is, in fact, the object's hash code. If the object isn't modified, its hash code remains constant. However, its memory address can change at any time: a compacting garbage collector can decide to move the object in memory whenever it feels like it.
Absolutely not. In fact, it's clearly impossible, given that you can obviously have two different objects whose toString() methods return the same string. As a simple example:
Integer a = new Integer(10);
Integer b = new Integer(10);
Object x = Object.buildFromToString("10");
What should x refer to? The same object that a refers to, or the same object that b refers to?
toString() is not meant to return an object identifier - it's just meant to return some sort of textual representation of an object. Just because the default implementation returns something which looks a bit like an identifier shouldn't be taken as an indication that it should be used as an identifier.
If you want to store some way of accessing an object at some other point in time, I suggest you just store a reference to it as an Object variable.
No, this is not possible. Java objects are only accessible if you have a reference to those objects. What you can do is store your objects in a Map<String, Object> under a given name, and get back the reference of the object from its name, using the map.

Can I set the value of a String in Java without using a constructor?

How-Do/Can I set the value of a String object in Java (without creating a new String object)?
There are no "set" methods on String. Strings are immutable in Java. To change the value of a String variable you need to assign a different string to the variable. You can't change the existing string.
(without creating a new String object)
Assigning doesn't create a new object - it copies the reference. Note that even if you write something like this:
s = "hello";
it won't create a new string object each time it is run. The string object will come from the string pool.
Actually there is no way to do that in Java, the String objects are immutable by default.
In fact, that's one of the reason why using the "+" concatenation operator like "str1" + "str2" is terribly inefficient, because what it does is copy every string in order to produce a third one.
Depending on your need you should consider using StringBuilder
Strings are immutable so you cannot change the value of an already created string.
The String object is immutable in Java so any changes create a new String object. Use a StringBuilder if you want to make changes to a string like object without creating new objects. As a bonus the StringBuilder allows you to preallocate additional memory if you know something about the eventual length of your string.
I stumbled across this question because i have to set a string within an "enclosing type" - an anonymous type. But all variables i want to set inside and use outside must be final.
The simple solution is to use StringBuilder - it's an mutable String.
It depends a bit on your definition of object. If you mean the reference, no. A reference is always created. If you mean the memory used by the characters, sure.
Strings are interned (if possible) which means that in an assignment:
String s1 = "Hello";
String s2 = "Hello";
there are 2 references (pointers to a memory location), but Hello is in memory on only 1 place. This is one of the reasons Strings can't be modified.
Sure you can access the internal char array via reflection. But it's usually a bad idea to do so. More on http://www.eclipsezone.com/eclipse/forums/t16714.html.

Categories

Resources