When we write like this:
{
new A().test();
}
The memory of A will be collected by gc after this function return(I knew that it's possible for collection, not be collected right now). The question is, how does the jvm make sure the memory of A won't be realise during the test() excuting(I assume the gc is a independent thread). I thought the compiler may change the statement into this:
{
//cover it in a scope
{
A temp = new A();
temp.test();
}
//outside the scope, temp is no longer stay in stack, so that A's memory can be colllected
}
This is just a conjecture.
BTW, very sorry for my poor English, please use simple syntax(to answer or explain), thanks.
The compiler generates byte code that ensures there is a temporary reference to the A on the stack, somewhat like your example.
The gc checks for reachability of objects. Your object is allocated on the heap and a reference to it is placed on the stack of the current method being executed, which makes it reachable by the gc, so it won't be collected.
When your method returns that stack memory is not "reachable" anymore, so that single reference to the object in the heap is gone, so the gc is free to mark it for collection.
Your "temp" variable is just a pretty name for that reference that the compiler creates anyway.
Related
I'm looking for a way to delete an object in Java, make it eligible for GC. I have a Java class that needs to have its delete() method called.
public class SomeObj {
// some implementation stuff
//...
void delete() {
//remove yourself from some lists in the program
//...
this = null; // <- this line is illegal
//delete this; <- if I was in C++, I could do this
}
}
How should I do this? Apparently, I'm going to have to refactor my code because this smells like bad design.
For better or worse, Java is a language that runs in a garbage-collecting environment. An object has some kind of existence in an application so longer as it is reachable via references. Once it is no longer reachable -- when no other object holds a reference to it -- it is "deleted" so far as the application is concerned.
That the object still has some after-life in the heap is a matter for the garbage collector, not the application. An application that depends on being able to control the existence of objects to which there are no references is broken in some logical sense.
The usual, semi-legitimate reason for wanting to nudge an unreferenced object out of the heap for good is to conserve heap space. There have been many, many occasions when I've known when an object is really finished with better than the garbage collector ever could. Objects that store temporary results with method scope are a good example. I'm primarily a C and C++ developer, and I really want a method on java.lang.Object called ImDoneWithYouNow(). Sadly, it doesn't exist, and we have to rely on the GC implementation to take care of memory management.
You don't need (and really shouldn't have) a "destructor". Once no other object references the object in question, it becomes eligible for garbage collection, and will be removed by the garbage collector when it sees fit.
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.
In some library found on google code I came across this util method:
public static void gc(){
Object obj = new Object();
WeakReference ref = new WeakReference<Object>(obj);
obj = null;
while(ref.get()!=null)
System.gc();
}
Its doc says it provides a reliable way to call GC, because calling System#gc() is just a hint without any guarantees. I showed it my senior, and he said I should think about why this method is invalid.
I read some articles on weak references but I'm still confused.
Can somebody show me the point?
I have direct experience with the supposed "safe GC" idiom you have posted.
It doesn't work.
The reason is quite simple: just the fact that a weak ref is cleared is not a signal that the object has been collected; it only means that it has become unreachable through any strong or soft reference. In my experience this signal arrives before the object is reclaimed.
A better attempt would be to use a Phantom reference, which at least ensures that the object has entered the finalizable state, but once again, it can still be occupying the heap, and in practice it still is occupying it. Another explanation could be that this particular object, obviously residing in Eden space, did get reclaimed, but the GC run which did it was not exhaustive and there is more memory to reclaim in other generations.
On the other hand, I have very reliably used this trivial idiom:
for (int i = 0; i < 3; i++) { System.gc(); Thread.sleep(500); }
Try it and see if it works for you. The sleep part is optional: it is needed only if System.gc() uses concurrent sweeping.
If you object to the apparent fickleness of this approach, just remember that any approach to explicit GC-ing is fickle. This one is at least honest about it—and just happens to work on actual systems. It is, naturally, non-portable and can cease to work at any time for a large array of reasons. Even so, it is the best you'll ever get.
The point is, that System.gc() does not need to clean up all weak references. And consider some Java virtual machines too. If System.gc for once (the first time) does decide to not clean that reference, it is very likely to the next call. Hence you have a possibly infinite loop. Probably depending on other threads changing the state for the garbage collection to terminate the loop.
So: once is enough.
There is no way to guarantee a GC call because just as the documentation says System.gc is just a hint that can be ignored by the system.
So assume that the JVM ignores System.gc - in that case the whole thing just loops until some other part of the systems causes a GC. If you run single-threaded or nobody else allocates much memory you basically create an inifite loop here.
The point is that your thread will stop and wait until the weak reference is cleared, thus "simulating" garbage collection. There's no guarantee when (or indeed even IF) this will actually happen.
You could be stuck waiting on this while for a long, long time.
Programmatic we need to ensure that, when a obj is removed then its corresponding entry should be removed. Only then, that object becomes a candidate for garbage collection. Otherwise, even though it is not used at run-time, this stale object will not be garbage collected.
The object to which this reference refers, or null if this reference object has been cleared.
As your object reference of WeakReference class. so it will not give null. but after removing gc., it provide null.
Object obj = new Object();
WeakReference ref = new WeakReference<Object>(obj);
obj = null;
if(ref.get()!=null)
{
System.gc();
System.out.println("remove ref");
}
if(ref.get()!=null){
System.out.println("not execute");
}
Output:
remove ref
Don't assign null value to obj.
Object obj = new Object();
WeakReference ref = new WeakReference<Object>(obj);
if(ref.get()!=null)
{
System.gc();
System.out.println("remove ref");
}
if(ref.get()!=null){
System.out.println("execute");
}
Output:
remove ref
execute
Code that tries to force GC is usually a sign for an underlying bigger problem (i.e. design issue or missing knowledge on the developers part).
I have seen a few use cases where calling System.gc() in production code actually makes sense, for example, before printing the current memory usage - it doesn't matter if the values are off but we'd like to improve chances the values are as small as possible. Of course, we knew that GC was enabled - we used this to automatically detect memory leaks on a QA system.
In general, calling System.gc() yells "my code is buggy and I don't know how to fix it!".
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).
I would like to know how to place a local variable in memory? In method1, do the variable take a place into memory, one time?
In method2, do the variable take a place after deleting old place in memory, for each time?
public void method1() {
Object obj = null;
for(.....) {
obj = come from other-->
}
}
public void method2() {
for(.....) {
Object obj = come from other-->
}
}
You have a local variables which may be in a register or once in memory.
You also have an object which the local variable references. This will be created on each iteration in both cases.
They are effectively the same, except I would prefer the second case if it is possible as it narrows the scope of the local variable.
Each method call is associated with Activation Record that is stored on a call stack. The activation record holds references to the memory blocks in heap corresponding to the method level variables. Once the method call returns to the caller, this activation record will be removed from the stack and the memory references are potentially available to be garbage-collected.
In your case,
the obj in the first method, it's reference is stored in the call stack and the actual memory is on the heap and this is done once per method call.
the obj in the for loop in the second method is created once for each iteration and goes out of scope at the end of each iteration. So, the reference and the memory on the heap are allocated for each iteration.
The local variables are usually (unless e.g. optimized away) kept on the stack memory. But they can only store primitive values or references. The referenced objects themselves are usually allocated on the heap (withstanding any JIT optimization).
See Stack based memory allocation (Wikipedia) vs. Heap based memory allocation (Wikipedia).
Storing values on the stack is very cheap. Similar to a function call, where you store the return pointer on the stack. It does not require much more than incrementing the stack pointer (and you can imagine that incrementing a dedicated CPU register is fast!)
The object itself is different. Note that theoretically, some java compiler or JIT might be able to optimize your second code better, because you indicate clearly that the value is not needed for the next iteration. (An even better compiler should be able to figure this out itself.)
In general, a modern compiler should produce the same machine code after optimization for both cases. (This may happen in the JIT compiler, so the Java bytecode may still show the difference).
Anyway: do not try to overoptimize by reusing local variables. Instead, write explicit code and let the compiler optimize. By using a fresh variable inside the loop, you make it explicit that it is not reused anywhere. This can prevent some programming errors!
I believe in both cases a new Object is created in memory for every iteration. It is up to the garbage collector to notice that there are no references to any but the most 'recent' Object.
Objects in method1 and method2 will be placed in heap, but java compiler perform Escape analysis for determination we need release this kind of object after method execution or not. Escape analysis is implemented in Java Standard Edition 6