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.
Related
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.
Let's say a method returns some value, but when I call it, I don't assign any variable to accept this RV. Then where does it go? Will GC collect it? Would it be a problem if I use this kind of method tons of times in my code?
Then where does it go?
It doesn't go anywhere. The value / reference is simply discarded. It is as if you assigned it to a local variable that immediately goes out of scope.
Will GC collect it?
It will be garbage collected when the garbage collector detects that it is unreachable. In your example, the method doesn't put the object reference anywhere else, so it will be unreachable immediately.
Note that even if the object is immediately unreachable, it may take some time for the GC to notice this and collect it. (But that's not a bad thing. It is considerably more efficient to forget the object reference and deal with later than to try to reclaim the space immediately.)
Would it be a problem if I use this kind of method tons of times in my code?
Not necessarily. The example code is not doing anything useful, and hence the overheads of allocating the object and then garbage collected are simply a waste of resources. But if it was doing something useful, the overheads are not likely to be a problem. (In ideal conditions, allocating and garbage collecting an object is cheap in Java.)
Unnecessary allocation can be a problem in some cases though:
If you are running with a heap that is too small for the application's working set of objects, the overheads can ramp up.
HotSpot's default "throughput" GC will "stop the world" while the GC is running, so excessive allocations will increase the number o f GC pauses that you experience. (This may or may not matter ... depending on the application.) You can mitigate this by using CMS or G1 as your collector, but that introduces overheads in other areas.
Assuming the value isn't referenced anywhere else, it will be garbage collected
Will GC collect it?
Yes. Since there would be no live reference to the Object returned it would be eligible for GC.
Would it be a problem if I use this kind of method tons of times in my code?
It should not. All the returned Objects will be GCed.
There's nothing that special about a return value over a local variable, consider:
public Object example {
Object a = new Object();
return new Object();
}
Then if I briefly explain how return values work:
When a method starts a new "stack-frame" is pushed on to the stack. It is an area of memory that includes parameter and local variable storage including the return value. It also knows where to return to.
When the method executes, new objects are created on the heap and only pointers to them exist in the stack.
After the code for the method has been run the value of a non-void return method is passed back to the calling method and stored in it's stack frame.
If a non-void return method's value isn't required by the caller, then it will share the same fate as any other local variable in that stack frame. And that is it's value is no longer used. If that value was an object, then garbage collection is already aware of it and is now able to ascertain that it is not referenced and can be collected.
I understand that strings (at least in Java) are immutable. I'm not trying to empty the contents of the string.
If I did, I'd use this: output.setText( outputString );
My question is: if you wanted to minimize the amount of space a program requires by relinquishing the bits storing the string, is there a way to do this?
In Java, garbage collection is done by JVM. So the answer to your question is no.
At best you can make the object eligible for garbage collection by making sure that the Object is not referenced anywhere.One way is to make any variable reference as null which is referring the object in question and calling System.gc().
String outputString ="Some Value";
outputString =null
The object "Some Value" in heap memory is not being referenced from anywhere and becomes eligible for garbage collection.
System.gc() hints the JVM to do garbage collection. There is no guarantee that the object will be freed from heap memory.
There is an automated garbage collector in Java.
In Java, as the developer does not explicitly remove the memory in the
program code, the garbage collector finds the unnecessary (garbage)
objects and removes them.
http://www.cubrid.org/blog/dev-platform/understanding-java-garbage-collection/
In the following example there are two functionally equivalent methods:
public class Question {
public static String method1() {
String s = new String("s1");
// some operations on s1
s = new String("s2");
return s;
}
public static String method2() {
final String s1 = new String("s1");
// some operations on s1
final String s2 = new String("s2");
return s2;
}
}
however in first(method1) of them string "s1" is clearly available for garbage collection before return statement. In second(method2) string "s1" is still reachable (though from code review prospective it's not used anymore).
My question is - is there anything in jvm spec which says that once variable is unused down the stack it could be available for garbage collection?
EDIT:
Sometimes variables can refer to object like fully rendered image and that have impact on memory.
I'm asking because of practical considerations. I have large chunk of memory-greedy code in one method and thinking if I could help JVM (a bit) just by splitting this method into few small ones.
I really prefer code where no reassignment is done since it's easier to read and reason about.
UPDATE: per jls-12.6.1:
Java compiler or code generator may choose to set a variable or parameter that will no longer be used to null to cause the storage for such an object to be potentially reclaimable sooner
So it looks like it's possible for GC to claim object which still visible. I doubt, however that this optimisation is done during offline compilation (it would screw up debugging) and most likely will be done by JIT.
No, because your code could conceivably retrieve it and do something with it, and the abstract JVM does not consider what code is coming ahead. However, a very, very, very clever optimizing JVM might analyze the code ahead and find that there is no way s1 could ever be referenced, and garbage collect it. You definitely can't count on this, though.
If you're talking about the interpreter, then in the second case S1 remains "referenced" until the method exits and the stack frame is rolled up. (That is, in the standard interpreter -- it's entirely possible for GC to use liveness info from method verification. And, in addition (and more likely), javac may do its own liveness analysis and "share" interpreter slots based on that.)
In the case of the JITC, however, an even mildly optimizing one might recognize that S1 is unused and recycle that register for S2. Or it might not. The GC will examine register contents, and if S1 has been reused for something else then the old S1 object will be reclaimed (if not otherwise referenced). If the S1 location has not been reused then the S1 object might not be reclaimed.
"Might not" because, depending on the JVM, the JITC may or may not provide the GC with a map of where object references are "live" in the program flow. And this map, if provided, may or may not precisely identify the end of the "live range" (the last point of reference) of S1. Many different possibilities.
Note that this potential variability does not violate any Java principles -- GC is not required to reclaim an object at the earliest possible opportunity, and there's no practical way for a program to be sensitive to precisely when an object is reclaimed.
VM is free to optimized the code to nullify s1 before method exit (as long as it's correct), so s1 might be eligible for garbage earlier.
However that is hardly necessary. Many method invocations must have happened before the next GC; all the stack frames have been cleared anyway, no need to worry about a specific local variable in a specific method invocation.
As far as Java the language is concerned, garbages can live forever without impact program semantics. That's why JLS hardly talks about garbage at all.
in first of them string "s1" is clearly available for garbage collection before return statement
It isn't clear at all. I think you are confusing 'unused' with 'unreachable'. They aren't necessarily the same thing.
Formally speaking the variable is live until its enclosing scope terminates, so it isn't available for garbage collection until then.
However "a Java compiler or code generator may choose to set a variable or parameter that will no longer be used to null to cause the storage for such an object to be potentially reclaimable sooner" JLS #12.6.1.
Basically stack frames and static area are considered as roots by GC. So if object is referenced from any stack frame its considered alive. The problem with reclaiming some objects from active stack frame is that GC works in parallel with application(mutator). How do you think GC should find out that object is unused while method is in progress? That would require a synchronization which would be VERY heavy and complex, in fact this will break the idea of GC to work in parallel with mutator. Every thread might keep variables in processor registers. To implement your logic, they should also be added to GC roots. I cant even imagine how to implement it.
To answer you question. If you have any logic which produces a lot of objects which are unused in the future, separate it to a distinct method. This is actually a good practice.
You should also take int account optimizations by JVM(like EJP pointed out). There is also an escape analysis, which might prevent object from heap allocation at all. But rely your codes performance on them is a bad practice
What happens if you run the following code..
while (true) {
String x = new String("ABC");
}
in terms of memory?
Is String x allocated on the stack or on the heap? Will the program eventually crash because of a memory overflow, or will garbage collection prevent that? Does the new keyword always create the object on the heap? When is an object created on the stack?
Thanks!
Is String x allocated on the stack or on the heap?
x isn't a String. It is a reference to a String. The reference is a local variable, and so goes on the stack. The String is an object, and so goes on the heap.
Will the program eventually crash because of a memory overflow
Probably not.
or will garbage collection prevent that?
It should.
Does the new keyword always create the object on the heap?
Yes.
When is an object created on the stack?
Never ... unless the JVM decides it cannot escape the current scope and so decides to do so.
Using new, yes, puts objects on the heap. Objects that are no longer accessible by any thread can be garbage collected. Whether you run out of memory or not depends on the size of data your program uses, and if you are good at 'releasing' objects you dont need any more (think: memory leaks are bad).
In your example, you will be running the garbage collector like crazy, which I think is what you are intending to demonstrate.
Local variables go on the stack.
In theory, new creates on the Heap, and non-objects (i.e., ints, chars and so on) are created on the stack. The only exception, afaik, are strings, created on the stack as well. In practice, the JIT compiler of many modern JVMs will see that, in some cases, objects created with new can be created on the stack (for example, local objects that are not referenced outside of the current function).
The garbage collector will take care of the deallocation for you, that's its purpose, but of course you can run out of memory if you create and keep references on too many objects at the same time (try creating a list with a billion strings, for example).