Java String Immutability storage when String object is changed - java

I understood that if a String is initialized with a literal then it is allotted a space in String Pool and if initialized with the new Keyword it create a String's object. But I am confused with a case which is written below.
My question is what if a String is created with the new keyword and then it value is updated with a literal?
E.g.
String s = new String("Value1"); -- Creates a new object in heap space
then what if write the next statement as below.
s = "value2";
So my question is,
1 Will it create a String literal in a String Pool or it will update the value of that object?
2 If it creates a new literal in String Pool what will be happened to the currently existed object? Will it be destroyed or it will be there until the garbage collector is called.
This is a small string if the string is say of the thousands of characters then I am just worried about the space it uses. So my key question is for the space.
Will it immediately free the space from the heap after assigning the literal?
Can anyone explain what what value goes where from the first statement to the second and what will happened to the memory area (heap and String Pool).

Modifying Strings
The value is not updated when running
s = "value2";
In Java, except for the primitive types, all other variables are references to objects. This means that only s is pointing to a new value.
Immutability guarantees that the state of an object cannot change after construction. In other words, there are no means to modify the content of any String object in Java. If you for instance state s = s+"a"; you have creates a new string, that somehow stores the new text.
Garbage collection
This answer already provides an in-depth answer. Below a short summary if you don't want to read the full answer, but it omits some details.
By default new String(...) objects are not interned and thus the normal rules of garbage collection apply. These are just ordinary objects.
The constant strings in your code, which are interned are typically never removed as it is likely that eventually you will refer back to these.
There is however a side-note in the answer that sometimes classes are dynamically (un)loaded, in which case the literals can be removed from the pool.
To answer your additional questions:
Will it immediately free the space from the heap after assigning the literal?
No, that would not be really efficient: the garbage collector needs to make an analysis about which objects to remove. It is possible that you shared the references to your old string with other objects, so it is not guaranteed that you can recycle the object. Furthermore there is not much wrong with storing data no longer useful, as long as you don't need to ask additional memory to the operating system (compare it with you computer, as long as you can store all your data on your hard disk drive, you don't really have to worry about useless files, from the moment you would have to buy an additional drive, you will probably try to remove some files first). The analysis requires some computational effort. In general a garbage collector only runs when it (nearly) runs out of memory. So you shouldn't worry much about memory.
Can anyone explain what what value goes where from the first statement to the second and what will happened to the memory area (heap and String Pool).
Your first string:
String s = new String("Value1");
is a reference to the heap. If you call the command, it will allocate space on the heap for the string.
Now if you call:
s = "value2";
"value2" is an element of the String Pool, it will remain there until your program ends.
Since you don't have a reference to your old string (value1), anymore. That object is a candidate for collection. If the garbage collector later walks by, it will remove the object from the heap and mark the space as free.

If you need to change a string, you can always create a new one that contains
the modifications.
Java defines a peer class of String, called StringBuffer, which allows strings to be altered.

Related

Unreachable literal created during "new String(..)"?

So a new String("abc"); creates an object in Heap & a literal "abc" in the String pool as per many of the answers I found. Since the new keyword was used, there should be no references to the String literal in the pool.
Does this mean -
a. The literal will be GC'ed in the next run (assuming no other references were created to the literal later on)?
b. If (the answer to a is) yes, it sounds fairly easy for JVM to free the literal in the pool as soon as the object is created, instead of waiting for GC. Why is this not done?
c. If (the answer to a is) no, what would be the reason for the an unreachable literal to not be GC'ed?
Since the new keyword was used, there should be no references to the String literal in the pool.
That is not correct. There is probably1 a reachable reference to the String object that corresponds to the literal. My recollection is that the reference is stored in the same "frame" that holds the static fields for the class. In practice, this reference will continue to be reachable until the enclosing class is unloaded by the garbage collector. (That typically never happens.)
So the answers are:
a. The literal will be GC'ed in the next run (assuming no other references were created to the literal later on)?
No.
c. If (the answer to a is) no, what would be the reason for the an unreachable literal to not be GC'ed?
The String object corresponding to the literal is NOT unreachable. For example, it needs to be reachable if there is any possibility that the new String("abc") statement could be executed again.
Since it is difficult for the JVM runtime to determine that a statement (that was determined to be reachable at compile time) won't be executed more than once at runtime, and since there is little performance benefit in doing that, the runtime assumes that all string literals need to be reachable for the lifetime of the Java classes2 that define them.
Finally, as #Holger points out, it makes no practical difference when String literal objects become unreachable. We know that they will be present (in some form) if they are needed. That's all that really matters.
1 - The actual behavior is highly implementation dependent. In early JVMs, the String objects for class literals were interned eagerly. Later on this changed to lazy interning. It would even be possible to re-intern a String object every time the string literal is used, though this would be very inefficient in general. Then we need to consider various things that optimizer could do. For example, it could notice that the String object for the literal never escapes and is used in a way that doesn't actually require interning. Or it could notice that the entire expression could be optimized away.
2 - I mean classes. The things that correspond to a Class object. Not instances of those classes.
Since new String("abc"); is object and not interned it will be garbage collected in next GC run.
However GC won't be immediately running just to collect this string object due to various performance reasons & availability of space.
Using System.gc(); also doesn't guarantee that it'll run (this is just suggestion to the GC to run.)
GC runs with many reason few are like below (also depends on VM)
More Memory allocation in specific generation is failling.
Heap allocation Or Objects presence reaching threshold etc.

java deallocates memory automatically?

I was looking for a method to turn a byte array into a string, the only way I found is this:
String s1="horse";
String s2;
byte[] b=s1.getBytes();
s2=new String(b);
So my questions are, is there any other way to convert a byte array to a string without creating a new instance of String?
Also if I repeatedly did:
String s;
while(true){
s=new String();
}
Would take up more and more memory, or it is automatically deallocated and reallocated? If the memory were deallocated automatically, I would no longer have to look for an alternative method to convert an array of bytes to a string.
P.S.(I want s2 to be "horse")
P.S.2(Sorry my bad english)
The comment by Johannes is a good starting place as Garbage collection is a key concept in Java.
To answer your questions though, no you will need to create a new instance of string when initializing with a byte array.
In your second code snippet:
String s;
while(true){
s=new String();
}
What we have is a String 's' which is a String pointer to nothing. Then in your loop you point this to a String object on the heap. When you reassign 's' in the loop it will allocate more memory for your new String and then the garbage collector will pick up the old String object from the heap. This is because the object has nothing referencing it anymore.
Here's a good article on string immutability.
So my questions are, is there any other way to convert a byte array to a string without creating a new instance of String?
No there isn't. Java strings are immutable. That means that you cannot update / replace the characters in a string. Converting a byte array to an existing string would violate immutability.
String s;
while (true) {
s = new String();
}
Would take up more and more memory, or it is automatically deallocated and reallocated?
Memory is automatically reclaimed by the Garbage collector (GC). The GC runs occasionally, identifies objects that are no longer reachable; i.e. that the program cannot find anymore. Those objects are then deleted.
That is the simple version. In reality not all "lost" objects are reclaimed at the same time, and there are some special kinds of reachability that are handled differently.
Anyway, in your example, each time the program goes around the loop, a new String object is created, and the reference to the previous String is lost. Then later (as required) the GC finds and deletes the lost objects.
If the memory were deallocated automatically, I would no longer have to look for an alternative method to convert an array of bytes to a string.
It is, and you don't.
In Java, you just let the runtime system deal with allocation and deallocation of object memory. (Just make sure that you don't cause objects to remain reachable by accident.)

How does variable memory allocation work?

When I create new object for String builder and use that variable then how memory allocation work and what is result of my code snippet my sample code is
1)
String nextPoint=new StringBuilder().append("My").append("next").append("point").toString();
System.out.println(nextPoint);
2)
StringBuilder downPoint=new StringBuilder().append("My").append("next").append("point");
System.out.println(downPoint.toString());
Which variables/instance can consume memory?? which solution is better when i'm using "nextPoint" varaible or "downPoint" variable?
Which variables/instance can consume memory?
Every class occupies memory. How much depends on the class. Every object occupies heap memory. How much depends on its class. Many classes and objects also contain references to other objects, and those other objects occupy their own heap memory. Some objects also have associated native resources, which occupy an idiosyncratic amount of memory. Local variables occupy stack memory appropriate for their type, though under some circumstances certain local variables may share the same stack memory as others.
In your case (1):
String nextPoint=new StringBuilder().append("My").append("next").append("point").toString();
System.out.println(nextPoint);
variable nextPoint is a local reference variable, consuming stack memory (for a reference, not a whole String). It is initialized by creating a new StringBuilder object (on the heap) and appending three Strings to it (each one an object occupying heap memory), and then creating a new String object (also occupying heap memory), and storing a reference to it in nextPoint. The StringBuilder will have some kind of associated storage for the accumulated character data; this will not overlap that of any of the Strings involved.
Your case (2) differs only in that a reference to the StringBuilder is retained instead of a reference to the generated String. That may have implications for code that follows, but it makes no difference to which objects are created and what memory is needed.
which solution is better when i'm using "nextPoint" varaible or "downPoint" variable?
It depends on what you want to do afterward. If you're not going to use either of those variables again then the difference is purely stylistic.
what is result of my code snippet [?]
Put it in a class, run it, and find out for yourself. Or figure it out from the code. This one is not something you should need us to answer for you.
Both snippets do the same sequence of method calls, being
new StringBuilder().append("My").append("next").append("point").toString(),
so their memory usage is (mostly) the same. Only snippet (1) stores a reference to the StringBuilder in a variable, and (2) stores the resulting String reference. But as references are the same size, no matter what the refer to, that results in the same number of bytes occupied.

String Constant Pool memory sector and garbage collection

I read this question on the site How is the java memory pool divided? and i was wondering to which of these sectors does the "String Constant Pool" belongs?
And also does the String literals in the pool ever get GCed?
The intern() method returns the base link of the String literal from the pool.
If the pool does gets GCed then wouldn't it be counter-productive to the idea of the string pool? New String literals would again be created nullifying the GC.
(It is assuming that only a specific set of literals exist in the pool, they never go obsolete and sooner or later they will be needed again)
As far as I know String literals end up in the "Perm Gen" part of non-Heap JVM memory. Perm Gen space is only examined during Full GC runs (not Partials).
In early JVM's (and I confess I had to look this up because I wasn't sure), String literals in the String Pool never got GC'ed. In the newer JVM's, WeakReferences are used to reference the Strings in the pool, so interned Strings can actually get GC'ed, but only during Full Garbage collections.
Reading the JavaDoc for String.intern() doesn't give hints to the implementation, but according to this page, the interned strings are held by a weak reference. This means that if the GC detects that there are no references to the interned string except for the repository that holds interned strings then it is allowed to collect them. Of course this is transparent to external code so unless you are using weak references of your own you'll never know about the garbage collection.
String pooling
String pooling (sometimes also called as string canonicalisation) is a
process of replacing several String objects with equal value but
different identity with a single shared String object. You can achieve
this goal by keeping your own Map (with possibly soft
or weak references depending on your requirements) and using map
values as canonicalised values. Or you can use String.intern() method
which is provided to you by JDK.
At times of Java 6 using String.intern() was forbidden by many
standards due to a high possibility to get an OutOfMemoryException if
pooling went out of control. Oracle Java 7 implementation of string
pooling was changed considerably. You can look for details in
http://bugs.sun.com/view_bug.do?bug_id=6962931 and
http://bugs.sun.com/view_bug.do?bug_id=6962930.
String.intern() in Java 6
In those good old days all interned strings were stored in the PermGen
– the fixed size part of heap mainly used for storing loaded classes
and string pool. Besides explicitly interned strings, PermGen string
pool also contained all literal strings earlier used in your program
(the important word here is used – if a class or method was never
loaded/called, any constants defined in it will not be loaded).
The biggest issue with such string pool in Java 6 was its location –
the PermGen. PermGen has a fixed size and can not be expanded at
runtime. You can set it using -XX:MaxPermSize=96m option. As far as I
know, the default PermGen size varies between 32M and 96M depending on
the platform. You can increase its size, but its size will still be
fixed. Such limitation required very careful usage of String.intern –
you’d better not intern any uncontrolled user input using this method.
That’s why string pooling at times of Java 6 was mostly implemented in
the manually managed maps.
String.intern() in Java 7
Oracle engineers made an extremely important change to the string
pooling logic in Java 7 – the string pool was relocated to the heap.
It means that you are no longer limited by a separate fixed size
memory area. All strings are now located in the heap, as most of other
ordinary objects, which allows you to manage only the heap size while
tuning your application. Technically, this alone could be a sufficient
reason to reconsider using String.intern() in your Java 7 programs.
But there are other reasons.
String pool values are garbage collected
Yes, all strings in the JVM string pool are eligible for garbage
collection if there are no references to them from your program roots.
It applies to all discussed versions of Java. It means that if your
interned string went out of scope and there are no other references to
it – it will be garbage collected from the JVM string pool.
Being eligible for garbage collection and residing in the heap, a JVM
string pool seems to be a right place for all your strings, isn’t it?
In theory it is true – non-used strings will be garbage collected from
the pool, used strings will allow you to save memory in case then you
get an equal string from the input. Seems to be a perfect memory
saving strategy? Nearly so. You must know how the string pool is
implemented before making any decisions.
source.
String literals don't get created into the pool at runtime. I don't know for sure if they get GC'd or not, but I suspect that they do not for two reasons:
It would be immensely complex to detect in the general case when a literal will not be used anymore
There is likely a static code segment where it is stored for performance. The rest of the data is likely built around it, where the boundaries are also static
Strings, even though they are immutable, are still objects like any other in Java. Objects are created on the heap and Strings are no exception. So, Strings that are part of the "String Literal Pool" still live on the heap, but they have references to them from the String Literal Pool.
For more please refer this link
`http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally.html`
Edited Newly :
public class ImmutableStrings
{
public static void main(String[] args)
{
String one = "someString";
String two = new String("someString");
one = two = null;
}
}
Just before the main method ends, how many objects are available for garbage collection? 0? 1? 2?
The answer is 1. Unlike most objects, String literals always have a reference to them from the String Literal Pool. That means that they always have a reference to them and are, therefore, not eligible for garbage collection.
neither of our local variables, one or two, refer to our String object, there is still a reference to it from the String Literal Pool. Therefore, the object is not elgible for garbage collection.The object is always reachable through use of the intern() method

lifetime of variable in java

private void func()
{
String str = "hi!";
}
this is my code.
suppose I called func() in the onCreate event.
I want to the near exact time, if thats possible to be determined, when GC will free the memory used by str.
Actually str stores a password.
and i want to free it as soon as I can.
currently after using str I set its value to something irrelevant.
I heard GC is the only thing that can free memories?
is that correct?
is there any other way of freeing the memory of a variable.
I want to the near exact time, if thats possible to be determined,
when GC will free the memory used by str.
Bad luck, you can't have it.
Solution: store it in a char[] instead of a String, and zero out all elements of the char[] when you are done with it.
Once the garbage collector is satisfied that there is no longer references to it, it becomes eligible for garbage collection.
However, because this is a String, i recall this literal will still be in the String pool, however its object reference will be destroyed by the GC.
You can't however influence the behavior of the GC.
In your case of the method, the variable goes out of scope each time the method exits, when it goes out of scope, it becomes eligible for GC, but whether GC decides to free it, we can't control or predict.
First, java will hold this string as long as it wants. Theoretically until the JVM terminates. So what? Who can connect to it and bring the value? And how?
But if you afraid very much you can call System.gc() that will probably trigger the GC to run and remove the value. Still no guarantee.
There is yet another trick. String contains its content is private field char[] value. You can overwrite it using reflection, so no one will know your password.
The str is not the problem in your case, when you are declaring a string, it is allocated in string pool of your application. You should create an array of chars instead.
Regarding the GC, you don not have any assurance when will collect that memory.
I don't know very well the Dalvik VM but in standard Java there is no way to freeup the memory from your example because the string "hi!" lives in the constant pool.
If you change to
String str = new String("hi!");
that gives a string on the heap and can be GC.
You can call System.gc() but this is merely advisory if you look at the java docs. You can't force a garbage collection in java and in general it's not a good idea to try.
If you really need a solution for this, you'd need to write your own custom password reader/writer using either byte arrays or JNI, and of course be very careful the password never gets turned into an Object. Otherwise you've lost.

Categories

Resources