Does a class hold references to its field objects? - java

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.

Related

What occurs when object is created in Java?

My teacher gave me a question:
"What occurs when objects are created in Java".
To the best of my knowledge, memory allocation, variable initialization and constructor method invocation happen when an object is created.
But my teacher said that I was almost right. The 2 later things are right, except memory heap. Instead, he said the memory allocation occurs. I think that object is stored in heap, so my teacher is wrong. Do you think so?
As always, the best place to find a solution for these kinds of questions is in the Java Language Specification.
Specifically, from the section on new instance creation, it can be understood that this is the sequence when a new object is created, as long as no exceptions occur:
Memory is allocated.
Fields are initialized to their default values.
The "first line" of the chosen constructor is invoked, unless it's an Object. By first line I mean either explicit call to super() or this(), or an implicit call to super().
The instance initializer is executed and the fields are initialized to their requested values (actually field initialization is usually compiled as an inline part of the instance initializer).
The rest of the constructor code is executed.
Now, it is possible that your teacher is talking about memory allocation as an actual operating system call - and in that case he's right in the sense that the JVM manages its own heap and thus a Java memory allocation does not necessarily translate to an OS memory allocation call (although it may).
I'll answer that using a simple example.
Say you have a class Car. Now you write:
Car car;
car = new Car();
The first statement creates a reference with car in the stack.
In the second statement, the Car class will be loaded to the main memory, then it will allocate memory for the members of Car in the heap. When this happens, the members will be initialized with values provided by the JVM.
While the JVM is running the program, whenever a new object is created, the JVM reserves as portion of the Heap for that object (where the object will be stored). The amount of Heap that gets reserved is based on the size of the object.
The JVM maps out this segment in the Heap to represent all of the attributes of the object being stored. A reference (address in Heap) to the object is kept by the JVM and stored in a table that allows the JVM to keep track of all the objects that have been allocated on the Heap. The JVM uses these references to access the objects later (when the program accesses the object).
On top of what other people have said, if this is the first use of the object then its Class must be initialised -as described in the JLS (the section before the one on new instance creation!).
This basically involves loading into memory the necessary information about the class i.e. creating a Klass object for the static variables and method table to live. This may also involve loading super classes and interfaces. This is all carried out by the ClassLoader.
When object is created in java then these 6 step will be happens one by one---
1.JVM allocates 8 bytes of memory for the reference variable & assign default value as null.
JVM will verify whether class loading is done or not,if class is already loaded then it will ignore or else it will perform class loading.
At the time of class loading ,if any static variable are there then it will allocating memory.
By using new operator,object memory will e created inside heap memory.
At the time of object creation,if any instance variables are there then those will allocate memory inside object Memory.
It will assign object memory address to the reference variable which is created first.

to ensure a java method is thread safe

is it enough to use only local variables and no instance variables. Thus only using memory on the stack (per thread).
But what happens when you create a new MyObject that is local to the method. Doesn't the new object get created on the heap ? Is it thread safe becuase the reference to it is local (thread safe) ?
It is thread safe because if it is only referenced by variables in that particular method (it is, as you said, a local variable), then no other threads can possibly have a reference to the object, and therefore cannot change it.
Imagine you and I are pirates (threads). You go and bury your booty (the object) on an island (the heap), keeping a map to it (the reference). I happen to use the same island for burying my booty, but unless you give me your map, or I go digging all over the island (which isn't allowed on the island of Java), I can't mess with your stash.
Your new MyObject is thread-safe because each call to the method will create its own local instance on the heap. None of the calls refer to a common method; if there are N calls, that means N instances of MyObject on the heap. When the method exits, each instance is eligible for GC as long as you don't return it to the caller.
Well, let me ask you a question: does limiting your method to local variables mean your method can't share a resource with another thread? If not, then obviously this isn't sufficient for thread safety in general.
If you're worried about whether another thread can modify an object you created in another thread, then the only thing you need to worry about is never leaking a reference to that object out of the thread. If you achieve that, your object will be in the heap, but no other thread will be able to reference it so it doesn't matter.
Edit
Regarding my first statement, here's a method with no instance variables:
public void methodA() {
File f = new File("/tmp/file");
//...
}
This doesn't mean there can't be a shared resource between two threads :-).
Threre's no way to other threads to access such object reference. But if that object is not thread-safe, then the overall thread-safety is compromised.
Consider for example that MyObject is a HashMap.
The argument that if it's in the heap, it's not thread-safe, is not valid. The heap is not accessible via pointer arithmetic, so it doesn't affect where the object is actually stored (besides ThreadLocal's).

Does the object which is the entry point of a Java program get garbage collected?

If I have a class Sample and I have an instance method, instanceMethod in it.
The class has a main method where I create an object of Sample itself and call it's instanceMethod without using a reference variable.
like this:
new Sample().instanceMethod();
inside the main.
Since this object has NO reference, will the garbage collector collect it ?
In Java1, I don't believe the object can be collected while instanceMethod() is being executed. In the main method's stack frame there is a reference to the object, at least logically (the JIT compiler may elide it). The fact that you're not assigning it to a variable doesn't affect the bytecode very much.
Of course when instanceMethod() completes, the object may be eligible for garbage collection - but it may not. For example, instanceMethod() may store a reference to this in a static variable.
Basically it's not worth getting hung up over intricate corner cases - just rely on the GC collecting objects which can't be reached any more in any way, but not collecting objects which may still be in use.
1 In .NET an object can still be garbage collected while an instance method is executing "in" the object, if the JIT compiler can prove that none of its variables will be read again. It's very confusing, and can cause very subtle bugs.

Is there any consequences of setting an reference to null in java?

If I have a reference pointing to some some java object, and do something like:
myObject=null;
Will the "lost data" of the old object be correctly freed by the JVM Garbage Collector? Something similar in C (with a pointer, would result in trash and a possible memory leak).
I am using null attribution in a java program and would like to now if it is "safe".
If myObject only holds memory ( say large internal array ), then setting this reference to null is enough.
If, on the other hand, it holds some other kind of resource that you've allocated ( Closeable, Thread, ExecutorService, etc ), you must take care to properly shut down these resources.
Even though some of them may have finalize method they may be called too late ( or even never ) for your system to have a desirable effect.
It is a very common mistake for somebody switching from C++ to Java, and I am guilty as charged here. In my first real Java project I would periodically run out of file handle, because I was not calling close after being done with them. Needless to say with a 512MB heap, GC would never feel the need to start finalizing my IO objects before it was too late.
Assuming that there are no other references to the object, this is a good way to free memory up for the GC. (Actually, aside from weak references and the like, it's basically the only way: make the object unreachable from any live variables.) Note that there is no schedule for when an object might get garbage collected once it becomes unreachable.
EDIT: As others have pointed out, setting myObject to null is unnecessary if myObject is going out of scope anyway. When the variable itself is no longer available as a path to reach the object it references, then it doesn't matter to the GC system whether or not it contains a reference or null.
Your assumption is correct, but you don't usually need to specifically do that.
Let's say your "myObject" is used in another object. At some point in the lifetime of your application's execution, this object will stopped being referenced by any other object, and thus will be marked for deletion by the GC. Them myObject will be marked for deletion as well. As soon as all references to a given object disappear, the GC will eventually reclaim the memory.
There are (rare) exceptions, like event handling, where the dependency between two objects cannot be properly automatically ended, and you may end up with a memory leak: when you subscribe to an event on another class, then the subscriber cannot be collected even when there's no "direct" references to it. In that specific case, it might be interesting to clear the link manually.
Yes, that is the purpose of the garbage collector in the JVM. The JVM may at some later time call the finalize method of the object, and then it may discard the associated storage.
Yes, it's sometimes a GOOD idea to set Java object references (pointers) null. This may (if there are no other references to the object) "free" the object sooner than would otherwise occur. This is especially helpful when you have large "networks" of intertwined objects.
At worst case, you're costing one additional memory store.
Yes, The object the reference pointed to is eligible for garbage collection (if there are no other live references to the object) when:
The method returns - if it was initially created with method local scope
Immediately - if it is an instance or class variable

Java de-allocate an object from the heap

In Java, to unload an object from the heap, is it sufficient to simply write myObject = null; and the GC will take care of it from there?
EDIT : Ok let me explain my use case, since everyone is assuming that I shouldn't explicitly null objects, I shouldn't worry about it, etc. That's missing the point. I am serializing an object, and am "consuming" a field of this object before I serialize it in order to save disk space. And before you jump down my throat for this, too, I cannot declare this field transient because I am including this field in the object sometimes, but not others.
Does setting an object to null have any effect on the GC?
In some modern VMs, actively setting a reference to null hinders the garbage collector. You should just forget about that.
For knowing when an object is garbage collected, look at the java.lang.ref package - although I can honestly say that in 16 years of Java programming, I've never needed to know when an object is garbage collected.
Can you elaborate on why you think you need this?
No; all references to that object must be lost/nulled. In practice this is something you shouldn't worry about.
Your object will be de-allocated when it is no longer used. Just be aware that any references left to the object will keep the object on the heap and simply assigning null to any single reference will not cause the underlying object to magically go away.
No, and no. myObject = null; will only help if there are no other references to the object, and in most cases it's superfluous because local objects go out of scope at the end of each method.
As for when objects are actually deallocated, that's completely up to the GC. What you can do is add a finalize method that will be called just before the object is deallocated, but this is problematic as well and should not be relied on.

Categories