Within a class that extends Thread, consider the following example:
public void run() {
while (workToDo) {
JSONObject json = new JSONObject(getNextMap());
publishJSON(json.toString());
// thread sleep
}
}
Is each instance of json still referenced as long as the thread is running, or are they freed each time new is called? Should this be moved to a method, i.e. publishJSON(getJson(getNextMap())?
To have a reference to object then it must be a local used variable (while in local scope) or contained in a member variable of a class instance.
I don't see any of the two in your example since after each while iteration the local variable can't be referenced anymore. So, unless you do something with json that saves a reference to it elsewhere, they are eligible for garbage collection.
Mind that this doesn't imply that the GC will collect the no-more-referenced instances after every iteration since its behavior is not predictable from a developer point of view. You just know that eventually they'll be collected.
Related
I have confusions on how GC works in Java.
Below is the code snippet that confuse me:
private Data data = new Data();
void main() {
for (int i = 0; i < 100 ; i++) {
MyThread thread = new MyThread(data);
thread.start();
}
System.gc();
// Long running process
}
class MyThread extends Thread {
private Data dataReference;
MyThread(Data data) {
dataReference = data;
}
}
In the above example if gc is called before continuing further (// Long running process)
will the local threads will be garbage collected?
Or GC will mark them (MyThread local references) as alive since it holds the reference to global reference data?
The MyThread instances may be garbage collected only after they are done (i.e. their run method is done). After the for loop ends, any instances of MyThread whose run method is done may be garbage collected (since there are no references to them).
The fact the the MyThread instances each hold a reference to a Data instance that doesn't get garbage collected doesn't affect the time the MyThread instances become eligible for garbage collection.
Your MyThread instances will not be eligible for garbage collection until they have finished running.
The thread stack and local variables for any live (i.e. started but not terminated) thread are reachable by definition.
A reachable object is any object that can be accessed in any potential continuing computation from any live thread. (JLS 12.6.1)
Furthermore, since a live thread could call Thread.currentThread(), the thread's Thread object must also be reachable as long as the thread is live ... irrespective of any other references to it.
However, if the reference to a Thread object becomes unreachable before the start() method has been called, it will be eligible for garbage collection. If this was not so, creating and not starting a Thread would be a memory leak!
You can always call to the garbage collection and but it is not guaranteed to run at the same time. (may or may not depending on your system). because garbage collection running under the daemon thread which is a low priority thread.
An object becomes eligible for Garbage collection or GC if it's not reachable from any live threads or by any static references. In other words, you can say that an object becomes eligible for garbage collection if its all references are null. Cyclic dependencies are not counted as the reference so if object A has a reference to object B and object B has a reference to Object A and they don't have any other live reference then both Objects A and B will be eligible for Garbage collection.
garbage-collection-in-java
There is no grantee that a gc will be executed after a System.gc(); call. A System.gc() call simply SUGGESTS that the VM do a garbage collection.
And thread is not the target for a gc. A thread won't be cleaned up unless its finished running.
Generally speaking, objects are juedged to be alive, if they are still referenced by others.
You should never be calling System.gc. The system will call it for you when low on memory.
In Java, GC works on a system called Mark and Sweep. The algorithm works like this
Start with a set of root objects (GC roots) and a set of all the objects allocated.
Mark those roots
Mark every object reachable from those roots, by visiting every field of these objects recursively.
When every possible object is marked, walk the list of all objects. If an item is not marked, free it.
(This is a simplification, the modern implementation works sort of like this, but is far more sophisticated).
So what is a GC root? Any object stored in a local variable still in scope, in a static variable, in a JNI reference, and all threads that are currently running.
So no, a thread won't be cleaned up unless its finished running. That's why threads so easily create a memory leak- as long as they run, any object they have a reference to cannot be freed because a GC root (the thread) has a reference to it.
But the relationship always goes down from the root to other objects. If Foo holds a reference to Bar, Foo can be deleted regardless of if Bar can be. But if Foo can't be deleted, then neither can Bar.
I am a bit confused GC aspect when it comes to the instance variables, especially fields.
So, if an object holds references to its field objects, these won't be eligible for garbage collection until the object itself is. Since Threads are GC roots and every object must have been created on some Thread only, thread won't let go of any objects created on it and the entire object hierarchy from a Thread shall remain for a considerable time before getting garbage collected.
On the other hand, if an object lets go of the field objects, calling a getter for these objects will end up in returning null later.
So, what are the facts here?
Clarification for "field objects"(as asked in comments)
By field objects I mean, the field members of an object that are themselves objects
Edit 2: A bit more elaboration
So, you see Threads are execution units having representation in memory through the Thread object instance. Any code execution that is happening anywhere is happening on some Thread.
How would this execution happen?
Well, through the execution of some code in a method. What would that make this object created?
A Local variable
And, that would make it a GC root.
Btw, for a method call, there is a stack for that particular call and this is what I have been referring to here.
It ain't so simple as #louis-wasserman said - "Yes, naturally" or for that matter not that natural..(?)
I investigated some more and found the answer on...where you would expect it probably - Java Language Specification
2.7. Representation of Objects
The Java Virtual Machine does not mandate any particular internal
structure for objects.
In some of Oracle’s implementations of the Java Virtual Machine, a
reference to a class instance is a pointer to a handle that is itself
a pair of pointers: one to a table containing the methods of the
object and a pointer to the Class object that represents the type of
the object, and the other to the memory allocated from the heap for
the object data.
Yes, that settles it. Even though, JLS doesn't mandate on the internal structure of an java.lang.Object, it would be likely that a structure similar to Oracle's JVM might be used.
This has bigger implication that you might think. Imagine a very heavy object holding one very bulky member field object. Hmmm...a Bitmap maybe. A Bitmap of 10MB and the other object simply holds the image's title:
bulky_object = {bitmap, title}
If you create up this object as a local variable inside a method inside a nested scope(for example's sake), the container object is eligible for garbage collection after the scope gets over but if you decide to hold a reference to the bitmap(the field) object after the scope, the containing object won't have been collected fully:
void someMethod(){
// Outer block of the method
bitmap_ref;
// Nested block starts
{
some_object = new some_object();
// Hold a ref to the bitmap
bitmap_ref = some_object.bitmap;
}
// Nested block has ended. some_object is eligible for GC and is not accessible as a GC root
// anymore
// bitmap_ref shall remain available alive and well here as we are holding a ref to it
// Also, some_object garbage collection may have happened leaving bitmap_ref alive
}
This would seem like an object leak here.
public List<Map<String,class1>> methodName(String Parameter)
{
//create instance of List
List<Map<Strig,class1>> list1 = new ArrayList<Map<String,class1>>();
for(ArrayList arrayList : someGlobalList)
{
//create instance of class1
//Initialize class1 with values in arrayList
//Put this class1 as a value to tempMap which is created inside this loop
//Put that tempMap into List
}
return list1;
}
My doubt
I understand that we cannot guarantee garbage collection. But this question says that when we return a local reference that will not be garbage collected. In my case, class1 is a local Object. But I am returning list1. Is it safe to use those objects from the caller function as list1.get("key"). It will return the class1 Object. Can I safely use the class members?
An object is only eligible for garbage collection after the last reference to it is no longer reachable from your code.
Let's count the references to your newly created object. Each class1 object is only referenced from the list at the moment, so let's look at the references to the list itself.
You have one reference called list1.
Then you return a value. This creates a second reference, which is placed in the stack and passed up to the caller.
List<...> result = theObj.methodName("foo");
During that process the first reference (list1) is no longer accessible, but the reference that was returned back is still accessible - it will be assigned to the variable result in this case. So you still have one valid and accessible reference to the list. Therefore, every reference inside the list is also valid and accessible.
So yes, it is completely safe to use.
There are languages other than Java, where you can allocate an object in stack space. That is, the object itself is allocated locally. Returning a reference to such an object is unsafe as the stack frame is popped. Take this example in C, that returns a pointer to the beginning of a local array:
char *bad_string(void)
{
/* BAD BAD BAD */
char buffer[] = "local string";
return buffer;
}
But in Java, objects are always allocated in heap space (barring internal optimizations which are not visible to the programmer and are checked to be safe, as mentioned in the comments).
An object allocated by the new operator is never "popped", and always obeys the rules of garbage collection. Stack/local method space is only used for primitives and references, and you never get a reference to any of those, only to objects. Thus, if you have a reference to something, you can trust that its memory is safe.
Yes, you'll be able to access all the objects contained in the list object (list1) you are returning (including objects of type class1) as long as its reference is assigned to a reference variable in the method that called methodName.
This is because there is no such thing as a local object. Objects live in the heap (unlike local variables which live on the stack) and they will only be eligible for garbage collection if there are no more reachable references to it.
Yes. The moment list1 leaves the frame ( is returned by the function ), it and all of it's references stop being "local variables" and will not be candidates for garbage collection until there are no longer any references to "list1"
In my case, class1 is a local Object. But I am returning list1
If a reference leaks from a method, then that object can be used (safely? is again another question which is dependent on the exact definition of safe). In your case since you are returning list1, all local fields referenced by list1 (recursively) can be accessed without NPE (or the fear of them being GCed) because your list has a strong reference to those instances.
If you are talking about thread safety, then it depends on how many threads have access to this leaked reference(s).
You need to have only one reference. Objects referenced by this first referenced object will be free from GC as well.. and so on up the tree.
As far as I know objects are available to be garbage collected when assigning a null value to the variable :
Object a = new Object;
a = null; //it is now available for garbage collection
or when the object is out of scope due to the method's execution is done:
public void gc(){
Object a = new Object;
} //once gc method is done the object where a is referring to will be available for garbage collection
given with the out of scope isn't also the same when the application just ended?
class Ink{}
public class Main {
Ink k = new Ink();
public void getSomething(){
//method codes here
}
public static void main(String[] args) {
Main n = new Main();
}
}
where I expect 2 objects (Ink object and Main object) should be garbage collected when the application ends.
When the Java application terminates, the JVM typically also terminates in the scope of the OS, so GC at that point is moot. All resources have returned to the OS after as orderly a shutdown of the JVM as the app defined.
You are confusing the event of an object becoming eligible for garbage collection with the actual process of collecting garbage or, more precisely, reclaiming memory.
The garbage collector doesn’t run just because a reference became null or an object went out of scope, that would be a waste of resources. It usually runs because either, memory is low or CPU resources are unused.
Also, the term “garbage collection” is misleading. The actual task for the JVM is to mark all objects being still alive (also known as reachable objects). Everything else is considered reclaimable, aka garbage. Since at the termination of the JVM, the entire memory is reclaimed per se, there is no need to search for reachable references.
That said, it’s helpful to understand, that most thinking about the memory management is useless. E.g. in your code:
public void gc(){
Object a = new Object;
// even here the object might get garbage collected as it is unused in subsequent code
}
the optimizer might remove the entire creation of the object, as it has no observable effect. Then, there will no garbage collection, as the object hasn’t been created in the first place.
See also here.
JVM monitors the GC roots - if an object is not available from a GC root, then it is a candidate for garbage collections. GC root can be
local variables
active java threads
static variables
jni references
I have been, without a question, using the final keyword for years to denote fields that should not change for the lifetime of an instance/class. Suddenly this occured to me...
So given this example:
public class TestFinalGC{
private TestFinalGC(){}
private final Object obj = new Object();
public static void main(String []args){
TestFinalGC instance = new TestFinalGC();
// instance Ref -> actual instance ->? obj ref-> actual obj
System.out.println(instance.obj);
instance = null;
//say GC makes sweep here... what happens?
//lets assume theres more code, obj would obviously be eligible for GC on app exit.
}
}
How does the obj member NOT leak here? Are final fields automatically WeakReferences such that if the strong references to parent(s) are nulled, they are eligible for garbage collection?
The JLS does not seem to note anything special about final
Update:
So this question of mine was founded on the premise that "reachability" and strong/weak references are closely related. There is this confusing oracle doc on reachability that leads me to believe that nested references should always be "strongly reachable". Hence, I do null my nested object references in all my objects, but it appears that this obviously should not be the case from all of the comments I am receiving.
So regarding "reachability", then, is it simply just that nested object references are no longer considered "reachable" if parent references are no longer reachable?
It could be is true that the premise of this problem is incorrect, but there is still intriguing information to consolidate here.
As Makoto suggested, there is simply nothing special about final in variable declarations as far as GC is concerned. In your example code
private final Object obj = new Object();
will be garbage collected at the same time as
private Object obj = new Object();
Both are strong references, but are invalidated and garbage collected together with their parent class TestFinalGC instance. That is because when the instance is GC'd, the reference fields are destroyed as well and the references do not exist any more. obj's reference count thus decreases by one.
However, should you write something like
Object x = myTestFinalGC.obj; // only works if your obj is not private, of course
Then the object will not be garbage collected because it will still have one reference lingering around (assuming this particular line of code is in another class instance that remains alive when myTestFinalGC is garbage collected.
tl;dr: memory allocations are garbage collected when their hard reference count drops to zero (and the collector runs, of course). final doesn't change this fact.