When Is The Object Eligible For Garbage Collection? - java

In the code below, given that amethod has been called. At what point/line is the Object originally referenced by myObject, eligible for Garbage Collection?
class Test {
private Object classObject;
public void amethod() {
Object myObject = new Object();
classObject = myObject;
myObject = null;
}
}
And if classObject or amethod had an access modifier of public, protected, default or static, would it affect what point the Object is eligible for Garbage Collection? If so, how would it be affected?
My first thought is that the Object is eligible for Garbage Collection when the Test object is eligible for Garbage Collection.
But then again. The optimizer may know that the classObject is never read from in which case classObject = myObject; would be optimized out and myObject = null; is the point it is eligible for Garbage Collection.

The object will not become a candidate for garbage collection until all references to it are discarded. Java objects are assigned by reference so when you had
classObject = myObject;
You assigned another reference to the same object on the heap. So this line
myObject = null;
Only gets rid of one reference. To make myObject a candidate for garbage collection, you have to have
classObject = null;

From Book OCA Java SE 7
An object is marked as eligible to be garbage collected when it
can no longer be accessed, which can happen when the object goes out
of scope. It can also happen when an object’s reference variable is
assigned an explicit null value or is reinitialized.

This is actually addressed precisely by the Java Language Specification, §12.6.1, Implementing Finalization :
Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable. For example, 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.
Another example of this occurs if the values in an object's fields are stored in registers. The program may then access the registers instead of the object, and never access the object again. This would imply that the object is garbage. …
But
… Note that this sort of optimization is only allowed if references are on the stack, not stored in the heap.
For example, consider the Finalizer Guardian pattern:
class Foo {
private final Object finalizerGuardian = new Object() {
protected void finalize() throws Throwable {
/* finalize outer Foo object */
}
}
}
The finalizer guardian forces super.finalize to be called if a subclass overrides finalize and does not explicitly call super.finalize.
If these optimizations are allowed for references that are stored on the heap, then a Java compiler can detect that the finalizerGuardian field is never read, null it out, collect the object immediately, and call the finalizer early. This runs counter to the intent: the programmer probably wanted to call the Foo finalizer when the Foo instance became unreachable. This sort of transformation is therefore not legal: the inner class object should be reachable for as long as the outer class object is reachable.
This example can be applied 1:1 to your example, as long as the object is referenced by the instance field classObject, it can not get garbage collected earlier than the Test instance containing the reference.
Note, however, that the aggressive optimizations mentioned in the specification are still allowed, when being applied to the code using the Test instance. The earlier-than-expected collection may happen, as long as both, the Test instance and the referenced object are collected together. In this case, the following aspect specified in §12.6 applies:
The Java programming language imposes no ordering on finalize method calls. Finalizers may be called in any order, or even concurrently.
So it’s perfectly possible that the Test instance is collected earlier than the object referenced by classObject whereas the “inner” object’s finalizer is invoked earlier. The only thing that is guaranteed, is, that when the inner object’s finalizer runs, the outer object is unreachable (or has a pending or concurrent finalization). Since in your example, neither has a non-trivial finalizer, that doesn’t matter anyway…

Your idea that the private object may be GC'd right away because no other code is able to access it does have some traction, but this would mess with the general semantics of Java memory management. For example, if that object implemented finalize, and Java semantics clearly dictates when an object is eligible for garbage collection, that finalizer method would be have to be called against the specification.
Also note that the object in turn may reference other objects, with even more complicated possible outcomes. Not to mention the object is reachable by Reflection anytime and it would make no sense for the field to be observed to suddenly change to null even if no code could have made that assignment.
To conclude, there are many reasons why your idea of optimization would not work in the wider picture.

No object is eligible for garbage collection here because you are creating two reference for the same object and you are giving null to only one reference but other reference is still pointing your object

Since you are holding myObject in classObject(reference is maintained), it(object in memory referenced through classObject) will not be available for Garbage collection until instance of Test is freed up/unloaded.

In the code below, given that amethod has been called. At what point/line is the Object originally referenced by myObject, eligible for Garbage Collection?
Your question is nonsensical because there is a disconnect between your high-level source code and the low-level representation (global roots in registers, on the stack and in global variables) that the garbage collector sees.
Your phrase "eligible for garbage collection" presumably means at what point does a heap-allocated block of memory become unreachable. So your question can only be answered by making a lot of (dubious) assumptions about what heap allocates and how long the generated code will keep references.

Related

Java 8 is this assertion about finalize method correct? [duplicate]

This question already has answers here:
Reference to object during finalize
(5 answers)
Closed 3 years ago.
I been reading the book OCA Java SE 8 Programmer I Exam Guide by Kathy Sierra + Bert Bates.
There is something about the finalize method I don't get it quite well. It states on page 218:
Calling finalize() can actually result in saving an object from deletion.
Later on page 222:
You can make an object ineligible for GC from within finalize().
English is not my native language, but what I understand in both scenarios is that the finalize() method can prevent the object from being garbage collected? Is this so? Or am I misinterpreting it?
This is really more of a theoretical thing: objects are eligible for garbage collection when they aren't referenced from other live objects anymore.
Thus: you could try to create such a reference within finalize(). Which would then theoretically prevent the object from being removed.
There is actually a "pattern name" for that: object resurrection. Now, if this is a pattern, or more of an anti pattern is open for debate.
(personally: I would never do that, and I have never been in a situation where it would have been necessary to use this pattern)
Finalize is a method called by JVM and not by the user, this method is executed just before an object is being garbage collected, you can override the finalize method to do cleanup operations before the object is disposed or as the book stated it is possible that you can prevent the object from being garbage collected.
You can refer below code as an example of saving an object from being garbage collected.
class Example {
    static Example y;
    void func() {
        Example x = new Example();
    }
    pubic void finalize() {
        y = this; // Putting the reference id
        // of the current object
        // into the static variable y
        System.out.println("The object won't be collected by the garbage collector");
    }
    public static void main(String a[]) {
        func(); // function called
    }
}
Well, that is true.
finalize() method is being called when GC decides that the object should be deleted but it doesn't mean, that the object will be removed anyway right after finalize finishes.
IT DOESN'T WORK THIS WAY:
_________________________
IF shouldBeRemoved(object)
object.finalize();
remove(object);
After finalize executes, GC will check once more if the object should still be removed. To qualify for removal, an object shouldn't be referenced from any object that is reachable from the root objects.
IT WORKS THIS WAY
_________________
LABEL
IF shouldBeRemoved(object)
object.finalize();
IF shouldBeRemoved(object)
remove(object);
ELSE
GOTO LABEL
Let's imagine the following case:
class Foo {
Application a;
Foo(){};
#Override
public void finalize() {
this.a = Application.getInstance();
}
}
Where Application is a class which represents the root object of the Application. In this case, as a is still reachable, the object of class Foo that qualified for removal right before, has just resurrected.
IMPORTANT REMARK
You are not guaranteed, that the finalize will be called, as it requires another object to take care of finalize method being called, so in case there is no enough free space on the heap, object might be destroyed without calling finalize.

The behaviour of making a non-volatile reference to a volatile object in Java

Coming from C/C++, I am a little confused about volatile object behavior in Java.
I understand that volatile in Java has two properties:
Won't bring object into cache, always keep it in main memory.
Guarantee "happen-before"
However I am not sure what happens if I make a new non-volatile reference to object. For example,
class Example {
private volatile Book b = null;
public init() { b = new Book(...); }
public use() {
Book local = b;
local.read();
}
}
AFAIK, volatile means the "book object" that b is referencing to should be in main memory. Compiler probably implement reference as pointer internally, so the b pointer probably sit in cache. And to my understanding, volatile is a qualifier for object, not for reference/pointer.
The question is: in the use method, the local reference is not volatile. Would this "local" reference bring the underlying Book object from main memory into cache, essentially making the object not "volatile"?
There is no such thing as a “volatile object” nor “always keep it in main memory” guarantees.
All that volatile variables of a reference type guaranty, is that there will be a happens-before relationship between a write to that variable and a subsequent read of the same variable.
Since happens-before relationships are transitive, they work for your example code, i.e. for b = new Book(...) all modifications made to the Book instance are committed before the reference is written to b and hence for Book local = b; local.read(); the read() is guaranteed to see all these modification made by the other thread before writing the reference.
This does not imply that the Book instance’s memory was special. E.g. modifications made to the instance after the reference has been written to b may or may not be visible to other threads and other threads may perceive only some of them or see them as if being made in a different order.
So it doesn’t matter which way you get the reference to the object, all that matters is whether the changes are made before or after publishing a reference to that object through b. Likewise, it doesn’t matter how you perform the read access to the object, as long as you do it after having acquired the reference by reading b.
With local.read(); you are accessing the object via the local variable local and within read(), the same reference will be accessed though this, but all that matters is that you have acquired the reference by reading b before reading the object’s state.
volatile is about the reference, not the object.
It guarantees that any thread reading the variable b after another thread has set the value of b will get the value assigned to b by the other thread, and not some cached value.

Java Multithreading : changing variable from multiple threads

Say I have class
public class OuterClass
{
public static WorkerClass worker;
}
In thread 1
The following command is executed
Outerclass.worker.doLongRunningOperation();
while the doLongRunningOperation is executed, in thread 2
Outerclass.worker = new WokerClass();
What will happen to the doLongRunningOperation in thread 1?
Will the worker Object referenced by thread 1 be garbage collected, only after the doLongRunningOperation is complete or can it be abruptly terminated to garbage collect worker Object.
Edit :
I think it should be GC'ed, since it is no longer referenced. But what will happen to the doLongRunningOperation? will it be terminated abruptly?
The Java garbage collector (GC) reclaims objects that are not traceable starting from a set of GC roots. That is, if object A is referenced by object B, and object B is referenced by object C, and object C is referenced by a root, then objects A, B, and C are all safe from the garbage collector.
So what are the roots? I don't know the complete answer, but I do know that the root set includes every local variable and parameter in every running thread.
So, if some local variable or argument in thread 1 still has a reference to the original WorkerClass instance, then the instance will continue to live.
The original WorkerClass instance will only be reclaimed when it is not referenced by any local or arg in any thread or, by any field in any traceable object. When that happens, it won't matter to your program any more because your program will no longer have any means to access the object.
P.S., "arguments and locals" includes hidden variables that are part of the Java implementation, and it includes implicit variable such as the this reference in every object method. Your original WorkerClass instance can not be reclaimed as long any method call on it (e.g., doLongRunningOperation) still is active.

Java Memory Model: Is it safe to create a cyclical reference graph of final instance fields, all assigned within the same thread?

Can somebody who understand the Java Memory Model better than me confirm my understanding that the following code is correctly synchronized?
class Foo {
private final Bar bar;
Foo() {
this.bar = new Bar(this);
}
}
class Bar {
private final Foo foo;
Bar(Foo foo) {
this.foo = foo;
}
}
I understand that this code is correct but I haven't worked through the whole happens-before math. I did find two informal quotations that suggest this is lawful, though I'm a bit wary of completely relying on them:
The usage model for final fields is a simple one: Set the final fields for an object in that object's constructor; and do not write a reference to the object being constructed in a place where another thread can see it before the object's constructor is finished. If this is followed, then when the object is seen by another thread, that thread will always see the correctly constructed version of that object's final fields. It will also see versions of any object or array referenced by those final fields that are at least as up-to-date as the final fields are. [The Java® Language Specification: Java SE 7 Edition, section 17.5]
Another reference:
What does it mean for an object to be properly constructed? It simply means that no reference to the object being constructed is allowed to "escape" during construction. (See Safe Construction Techniques for examples.) In other words, do not place a reference to the object being constructed anywhere where another thread might be able to see it; do not assign it to a static field, do not register it as a listener with any other object, and so on. These tasks should be done after the constructor completes, not in the constructor. [JSR 133 (Java Memory Model) FAQ, "How do final fields work under the new JMM?"]
Yes, it is safe. Your code does not introduce a data race. Hence, it is synchronized correctly. All objects of both classes will always be visible in their fully initialized state to any thread that is accessing the objects.
For your example, this is quite straight-forward to derive formally:
For the thread that is constructing the threads, all observed field values need to be consistent with program order. For this intra-thread consistency, when constructing Bar, the handed Foo value is observed correctly and never null. (This might seem trivial but a memory model also regulates "single threaded" memory orderings.)
For any thread that is getting hold of a Foo instance, its referenced Bar value can only be read via the final field. This introduces a dereference ordering between reading of the address of the Foo object and the dereferencing of the object's field pointing to the Bar instance.
If another thread is therefore capable of observing the Foo instance altogether (in formal terms, there exists a memory chain), this thread is guaranteed to observe this Foo fully constructed, meaning that its Bar field contains a fully initialized value.
Note that it does not even matter that the Bar instance's field is itself final if the instance can only be read via Foo. Adding the modifier does not hurt and better documents the intentions, so you should add it. But, memory-model-wise, you would be okay even without it.
Note that the JSR-133 cookbook that you quoted is only describing an implementation of the memory model rather than then memory model itself. In many points, it is too strict. One day, the OpenJDK might no longer align with this implementation and rather implement a less strict model that still fulfills the formal requirements. Never code against an implementation, always code against the specification! For example, do not rely on a memory barrier being placed after the constructor, which is how HotSpot more or less implements it. These things are not guaranteed to stay and might even differ for different hardware architectures.
The quoted rule that you should never let a this reference escape from a constructor is also too narrow a view on the problem. You should not let it escape to another thread. If you would, for example, hand it to a virtually dispatched method, you could not longer control where the instance would end up. This is therefore a very bad practice! However, constructors are not dispatched virtually and you can safely create circular references in the manner you depicted. (I assume that you are in control of Bar and its future changes. In a shared code base, you should document tightly that the constructor of Bar must not let the reference slip out.)
Immutable Objects (with only final fields) are only "threadsafe" after they are properly constructed, meaning their constructor has completed. (The VM probably accomplishes this by a memory barrier after the constructor of such objects)
Lets see how to make your example surely unsafe:
If the Bar-Constructor would store a this-reference where another thread could see it, this would be unsafe because Bar isnt constructed yet.
If the Bar-Constructor would store a foo-reference where another thread could see it, this would be unsafe because foo isnt constructed yet.
If the Bar-Constructor would read some foo-fields, then (depending on the order of initialization inside the Foo-constructor) these fields would always be uninitialized. Thats not a threadsafety-problem, just an effect of the order of initialization. (Calling a virtual method inside a constructor has the same issues)
References to immutable Objects (only final fields) which are created by a new-expression are always safe to access (no uninitialized fields visible). But the Objects referenced in these final fields may show uninitialized values if these references were obtained by a constructor giving away its this-reference.
As Assylias already wrote: Because in your example the constructors stored no references to where another thread could see them, your example is "threadsafe". The created Foo-Object can safely be given other threads.

Method local variables and stack and heap

While reading on Thread Safety I came across this issue.
If I'm correct method local Primitives and object references lives inside a stack and actual objects pointed by the references inside the stack lives in the heap.
But when it comes to method local non primitive object initialization, wouldn't that cause a concurrency issue ? I mean if the method locals non primitives lives in the heap and only the pointers lives in the stacks, isn't it the same as of instance variables ?
Can someone please help me to understand this....
PS
Think of two threads with each having two stacks of their own and one heap. What I understood is that the two threads keep their method local primitive variables inside their stacks. I have no issue with that.
But what if we have a method with non primitive method local variables ? Then if the object for that variable is stored inside the heap, both the threads will have the access to the same object, won't they ? So if that's the case there would be Sync problems.
That is what I'm asking.
Thanks
But what if we have a method with non primitive method local variables
? Then if the object for that variable is stored inside the heap, both
the threads will have the access to the same object, won't they ? So
if that's the case there would be Sync problems.
I wonder why you will think the two references will refer to the same object.
The creation of the object referred is explicitly done by new (or other similar method, but idea is the same)
Therefore, unlike in C++, if you are declaring this in Java
Foo foo;
there is no Foo object instantiated. foo is just a pointer pointing to nothing.
This will create you a Foo object instance in heap.
Foo foo = new Foo();
If two thread is running this piece of code, thread 1 will have a Foo reference in stack, and ask to allocate a new Foo object in heap, and then assign the address of that Foo obj to the reference foo. Thread 2 is doing the same. Note that Thread 2 is also asking to allocate a new Foo object, it will be a different object from what Thread 1 is allocated.
That's the basic (and much simplified) idea.
Both threads could have access to the same object if they both have a reference to the object. If you have a method like the following:
public String concat(String a, String b) {
StringBuilder builder = new StringBuilder();
builder.append(a);
builder.append(b);
return builder.toString();
}
The StringBuilder object is indeed in the heap, but only one thread has a reference to this object. No other thread can have a reference to this StringBuilder. So it's inherently thread-safe.
If, on the contrary, you have the following:
public String concat(String a, String b) {
final StringBuilder builder = new StringBuilder();
new Thread(new Runnable() {
#Override
public void run() {
builder.append("haha!");
}
}).start();
builder.append(a);
builder.append(b);
return builder.toString();
}
Then you have a thread-safety issue, because you shere the locally created object reference with another thread, and StringBuilder is not thread-safe.
But what if we have a method with non primitive method local variables ? Then if the object for that variable is stored inside the heap, both the threads will have the access to the same object, won't they ? So if that's the case there would be Sync problems
You partially answered your own question.That reference value is stored in the stack but the actual object content is stored in heap and when you call new Object() each thread creates different new object that will be stored in the heap and each thread access the object it has created using the reference value stored in its own stack
Local variables are either primitives, references to objects created somewhere else (if you do an assignation), or references to newly created objects (using "new" operator)
For the first case, as you said, there is no issue.
For the last case, as you are locally craeting a new object, a new object will be created at every call, so no concurrency issue because there will be one object in the heap for each call
But for the second case, as the object has been created somewhere else, you have to think about concurrency
Just to toss in my thoughts regarding what may be your point of confusion: the heap is not managed like the stack. It is shared, yes - in that objects created by all threads are in the heap. However as each object is created, it's given a unique location/space in the heap. Two methods on two threads running concurrently and creating an object instance will create distinctly different objects in the shared heap.
They're created in this shared heap so that if method foo returns the object reference, or stores it, or calls another method that indirectly stores it... it won't be destroyed when foo returns and the stack is popped.
The magic of having a garbage collector is that you don't have to keep track of this "stuff" and destroy it yourself at some appropriate point in the future. Keeps your code simple, lets you focus on algorithms (or learning to program). But I digress...

Categories