java deallocates memory automatically? - java

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.)

Related

Memory usage in Java

What i would like to ask is this:
String str1;
for(int i=0;i<10;i++){
str1 = Integer.toString(i);
}
will this create 1 string object and reassign it's value 10 times or will it create 10 String Objects eating 10*(String's Bytes) from memory?
That will create 10 different string objects, each assigned to the str1 variable in turn. All but the final one (the one currently referenced by str1) will be available for garbage collection at the end of the loop.
There are different concepts at play:
Assignments are stored in stack memory.
Objects are stored in heap space
Because integers and strings are immutable, each time you do Integer.toString() an instance of string will be created, so you will have 10 instances of String in heap.
on each loop run, you are telling str1 to point at each of those specific instances, but it is replaced immediately by the next run.
Garbage collector will check eventually which heap objects do not have a stack memory reference and collect them to throw them into oblivion.
It will create 10 of them. String is actually immutable. But the garbage collector will take care of all that if needs be.
You can see that in the doc ;)
https://docs.oracle.com/javase/7/docs/api/java/lang/String.html
In java String is immutable, by immutable, we mean that Strings are constant, their values cannot be changed after they are created.
from specification
a string literal always refers to the same instance of class String.
This is because string literals - or, more generally, strings that are
the values of constant expressions - are "interned" so as to share
unique instances, using the method String.intern.
in this case it will create 10 immutable string objects.
A lot of answers have been provided and I won't add to them anymore. Moving forward, if you are interested into how the JVM memory management works, I would suggest to checkout Java Memory Management course by Matt Greencroft, https://www.udemy.com/java-memory-management/. I bought it 2 years ago during a sale and it was worth it.
I ran your code in an infinite loop with a 5 secs. pause.
class MemoryTest {
public static void main(String[] args) throws InterruptedException {
while (true) {
String str1;
for (int i = 0; i < 10; i++) {
str1 = Integer.toString(i);
}
Thread.sleep(5000);
System.out.println("Running...");
}
}
}
This is the result of Visual VM + Visual GC plugin, thanks to the course. I have been running it for 12 mins. and only 1 garbage collection has been executed by the JVM. Even in an infinite loop, the JVM is smart enough to keep the memory in S1 space and never execute more than one GC and never put the object in Old space.

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.

Create new object and select older object for garbage collection

In the code snippet below, new String object will be created to to store the modified new string as Strings are immutable in java. But i'm not sure which one will create new object and which one of them will be marked for garbage collection?
String s1 = "It";
String s2 = "was";
String s3 = s1+" "+s2;
s2+=" roses";
s3 = s3+s2+" roses all the way";
System.out.println(s3);
It depends on scope of your code snippet.
If all code is inside one method all of them will be in garbage after execution.
Garbage Collector works on count of references to the object.
As example you declare a new reference String s1 inside a method and assign to something. Then method executed and upon completion there is no more references. So, go to garbage.
This is a brief, basic explanation, the actual behavior can vary based on compiler and JVM used. Also there are a lot of articles available that go into this topic in depth and can provide more detailed explanations.
These literals will be put in the JVM's string pool and never be GC'ed. (i.e. they will exist in memory for the duration of the JVM.
"It", "was", " ", " roses", " roses all the way"
Then, as far as the String references are concerned, It depends on the scope of the variables. I will assume local method level for this answer:
String s1 = "It"; // a reference will be created on the stack
String s2 = "was"; // a reference will be created on the stack
String s3 = s1+" "+s2; // a reference will be created on the stack for s3, and then two temp objects will be created in memory, one for s1+" ", one for concatenating the result with +s2. (this operation can vary greatly based on how compiler optimizes), the first one will become eligible for GC immediately.
s2+=" roses"; // same as above.
s3 = s3+s2+" roses all the way"; // same as above but the object s3 was pointing to will become eligible for GC immediately.
System.out.println(s3); // no memory allocation.
When the method ends, s1, s2, and s3 references will be cleared from the stack and any remaining objects pointed to become eligible for GC.
Hope this helps, remember this is a very basic explanation, I recommend reading up on this topic, as how it will actually behave can vary greatly depending on how the compiler decides to optimize. (For example, the compiler may see all these temporary references and concatenations are not needed and discard them)
Note: Since you are concatenating to create strings, you may want to consider the Mutable alternatives like StringBuffer or StringBuilder which can help optimize.

Java String Immutability storage when String object is changed

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.

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