Java is this Garbage Collected - java

Lets says I have the code in the entity class:
this.setCurrentState(new NormalState(this));
if in the normal state class I switch the state of the entity to:
entity.setCurrentState(new HungryState(entity));
will the NormalState object be garbage collected event though it holds a reference to the entity that is still active or will it not cause memory leaks?

Java's garbage collector removes all objects who don't have any references to them. If calling the setCurrentState method replaces the stored reference to the instance of NormalState and there isn't another reference to that object in the whole VM, then it's marked as garbage and thus, it'll be collected.

The garbage collector removes all objects not being used; if your NormalState is not held in a variable, nor being used by code, it will be garbage collected. The Entity will also be garbage collected if NormalState was the only object containing a reference to it.
For example, given two classes, A and B, where A contains a B as so:
public class A {
B inner = new B();
public A(B in) {
inner = in;
}
}
myB will be garbage collected (When our A is collected) in the following example:
public static void main(String[] args) {
B myB;
//setting a value with = returns the value
//myB = new B() -> myB
A firstObject = new A(myB = new B())
//bad coding practice, but the fastest way to clear variables
firstObject = null;
myB = null;
}
However, the following will not garbage collect myB because there's still a reference:
public static void main(String[] args) {
B myB;
A firstObject = new A(myB = new B())
A secondObject = new A(myB);
//clear references. secondObject still has a reference to what was myB.
//the now unnamed B will not be collected until secondObject changes.
firstObject = null;
myB = null;
}
NOTE: It's very annoying trying to name an object; as long as it has a variable, it's easy to say myB, but even after your stop calling it myB, it's still there in the computer. I don't know what to call it because I stopped calling it myB when I did myB = null;.

Related

Is it possible to assign a java object with only the attributes that are available?

I have a java pojo class as below
public class ClassA {
private String a;
private String b;
private String c;
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
public String getC() {
return c;
}
public void setC(String c) {
this.c = c;
}
}
And I am using it in another class as below
public class Test {
public static void main(String[] args) {
ClassA ca1 = new ClassA();
ca1.setA("One");
ClassA ca2 = new ClassA();
ca2 = ca1;
System.out.println(ca2);
}
}
The output is: ClassA#53bd815b[a=One,b=<null>,c=<null>]
Is it possible that when I assign ca1 to ca2, ca2 will have only the attribute "a" and not have the other attributes, "b" and "c" as no values are assigned to them?
Your code:
ClassA ca2 = new ClassA();
ca2 = ca1;
… makes no sense. You instantiate a new object of class ClassA. You assign a reference to that object to be stored in a reference variable named ca2. Then you immediately assign another reference to a different object to that same reference variable ca2.
So there was no point to the first of those two lines. Logically, you could replace those two lines with the following, and end up with the same effect.
ClassA ca2 = ca1;
You asked:
is it possible that when I assign ca1 to ca2, ca2 will have only the attribute "a" and not have the other attributes, "b" and "c" as no values are assigned to them.
If you are asking if the second ClassA object can somehow absorb values from the first, the Answer is “No”.
Your two instances of ClassA are separate and distinct from one another. Each holds its own state (member field values). That state is not altered by you assigning a reference to either into a reference variable.
In your Question’s code, you end up with two objects in memory:
One has one member field assigned a value, and the other two yields are null. That object has two reference variables pointing to it.
The other object has all three of its member fields null, with none of the three ever assigned a value. This object has no references left pointing to it. Having no references means this object is effectively “forgotten”, or lost. This object is now a candidate for the garbage collection. After garbage collection, the memory used by this object is freed up to be used for other purposes.
The key concept here is that ca1 and ca2 are not themselves objects. They are reference variables, also known as pointers. They know where to find a particular object. They can each point to different objects, or they can both point to the same object.
See the illustration I made in another Answer of mine on a similar Question.
When you declare ClassA ca2, you are not saying that ca2 is a ClassA, you are saying ca2 will track the location in memory of an object of that class and only that class (and its subclasses).
As for the output of toString being called implicitly by System.out.println, you should override toString yourself to generate whatever output you choose.

Where the instance variables and instance methods are stored in java?

In the below program, does it mean that 3 instance variables and 3 instance methods are created and memory is allocated to them ?
class Foo{
String name = "";
public void greet(String name){
this.name = name;
}
}
class Greetings {
public static void main (String[] args) {
Foo ob = new Foo();
Foo ob1 = new Foo();
Foo ob2 = new Foo();
ob.greet("hello friends");
ob1.greet("welcome to java");
ob2.greet("let us learn");
System.out.println(ob.name);
System.out.println(ob1.name);
System.out.println(ob2.name);
}
}
The Java Language Specification does not say anything about how memory is organized, or how objects, methods, and classes are represented.
So, the answer is: you can't and shouldn't know.
All the 3 objects are stored in a heap memory. The size of the heap increases decreases as the application runs. The new operator here allocates memory to the object in the heap. Which means each time you say new in the statement a separate memory space is allocated to that object in the heap The methods are stored in JVM internal heap.
you can find a simple example of how memory is managed for objects in java here

Pointers and objects in java

let's consider the following code:
public class Test {
private int a;
public Test(){
this.a = 1;
}
public static void main(String[] args) {
Test A = new Test();
Test B = A;
// TEST1
B.a = 0;
System.out.println(A); // prints 0
// TEST2
B = null;
System.out.println(A); // also prints 0
}
public String toString(){
return Integer.toString(this.a);
}
}
In TEST1, we modify B and then A is modified because B points to A.
I may understand why in TEST2 A doesn't become null, because B now points to null.
But the results of the two tests seem contradictory: why A doesn't become null ?
Thanks.
The variables A and B were both referencing the same object. B.a = 0 is altering that object. But when you reassign B = null, you're not altering the object. You're just altering the variable.
Test A = new Test();
The variable A points to an instance of type Test
Test B = A;
The variable B points to the same instance as variable A does.
B.a = 0;
The instance, variable B is pointing to (the same instance variable A points to), is changed.
B = null;
Variable B does not point to any instance anymore, while variable A still points to the same instance of type Test as before.
The main thing to understand is that variables A and B do hold a pointer to an instance of type Test. The instance of type Test is represented somewhere in memory and many variables may reference (point) to it.
The expression:
B.a = 0;
means: find the instance B is pointing at and modify its state in memory.
The expression:
B = null;
means: let B point to some other instance in memory (in your case to no instance at all). While the expression:
B = A;
means: let B point to the same instance in memory as A does point to.
By making object b null, you just cut the referance between the test object which resides in the heap and the B. The other referance between the test object and the A remains regardless of the other referances of the object unless you cut it or changed it.
regards
In Java variables are stored in the stack, while objects themselves are stored in the heap. Primitive type values are also stored in the stack, thus primitive type variables don't touch heap at all. But object variables on the stack contain heap addresses instead of values themselves. So by assigning null to B you change the B's (and only B's) value on the stack, but the heap value remains unchanged, and A's value on the stack remains unchanged, so A still references the same object in the heap allowing you to access its attributes and methods.

Does ArrayList.clear() nullify all objects inside recurcively?

Let's say I have such a class:
class C
{
int a, b;
ArrayList<int> c = new ArrayList();
};
and such a collection:
ArrayList<ArrayList<C>> MyList = new ArrayList<ArrayList<C>>();
Would calling MyList.clear() nullify all the references to every ArrayList in the MyList and any additional objects inside of the each ArrayList in MyList? So, more precisely, will all elements inside class C.c be nullified as well as C.a and C.b?
No, but if nothing else has reference to them, they will be eligible for garbage collection.
E.g., simpler example:
class Foo {
Date dt;
Foo() {
this.dt = new Date();
}
}
ArrayList<Foo> list = new ArrayList<Foo>();
list.add(new Foo());
list.clear();
As of the clear, the Foo object's dt has not been "nulled" or anything, but the Foo object and the things only it refers to (the Date inside it, in this case) are eligible for garbage collection.
Whereas:
class Foo {
Date dt;
Foo() {
dt = new Date();
}
}
ArrayList<Foo> list = new ArrayList<Foo>();
Foo f = new Foo();
list.add(f);
list.clear();
Here, the Foo object isn't eligible for garbage collection, because f still refers to it even though the list doesn't. Of course, if f is a local variable in a method, then as soon as the method returns, f goes out of scope — at which point, if nothing else has a reference to the object, it's eligible for GC. But that's beside the point, the point is that when the clear completes, the object is still referenced (by f).
If c is the only object that contains strong references to the contained lists then eventually they'll be garbage collected.
They won't be directly emptied though, just removed from the containing list. For example
ArrayList<C> inner = new ArrayList<C>();
inner.add(new C());
ArrayList<ArrayList<C>> outer = new ArrayList<ArrayList<C>();
ArrayList<ArrayList<C>> outer2 = new ArrayList<ArrayList<C>();
outer.add(inner);
outer2.add(inner);
outer.clear();
In this situation inner will be removed from outer but not from inner2, and since there will be another strong reference to inner, it's not eligible for garbage collection. Otherwise it will be released evenually, but all at once, not by emptying the inner elements.

Is it not required to allocate memory explicitly using new before assigning value to data through a function call in java

There are three classes.
public class A
{
private B b;
private C c;
public void abcMethod(){
c = new C(this);
b = c.xyzMethod(); // Doubt is here.
}
}
public class B
{
int i;
public void setI( int i){
this.i=i;
}
public int getI(){
return i;
}
}
public class C
{
public B xyzMethod(){
B b = new B();
b.setI(10);
return b;
}
}
You may have noticed where my doubt is on the code. My question is-
1) why "new" is not required to allocate memory for the object b?
Probable answer: "Is it due to the reason that being a data member it has been already allocated memory while object of A got created."
2) Is my probable answer is correct? If its correct, why have we allocated memory to object c using new? Perhaps, its due the reason that "this" was to be passed to the object. So for proper initialization we used new with argument "this".
3) If I am correct at point 2 above, what does happen to the previously allocated memory to object c as new will allocate new chunk of memory and assign the new address to c? Garbage collected?
4) So from above points, we can say memory is allocated for the objects which are members of a containing class, at the time of object creation of the containing class. And we can directly assign value to them with out calling new on them?
[I am from C++ background, and this does not happen in C++. If a class is having pointer or reference to other class, we need to explicitly allocate memory for them.]
Please, correct me where I am wrong or something is missing in my understanding.
Thanks and best regards.
1) why "new" is not required to allocate memory for the object b?
A new B is created by the method c.xyzMethod();
public B xyzMethod(){
B b = new B();
b.setI(10);
return b;
}
As you can see a fully functional B is created by this method, memory allocated for it and a reference to it is passed. Object A is fully entitled to keep a reference to this object. There is no difference between this and both declaring a variable and initialising an object on a single line
2) Is my probable answer is correct? If its correct, why have we
allocated memory to object c using new? Perhaps, its due the reason
that "this" was to be passed to the object. So for proper
initialization we used new with argument "this".
It is important to remember that object A does not need to allocate memory for object B, all class A needs is memory for a reference to object B. Object B can be kept elsewhere and many As can share the same B (although this isn't the case in your code)
3) If I am correct at point 2 above, what does happen to the
previously allocated memory to object c as new will allocate new chunk
of memory and assign the new address to c? Garbage collected?
Assuming there are no references to that object elsewhere (which is the case in your code) it will indeed become eligible to be garbage collected
4) So from above points, we can say memory is allocated for the
objects which are members of a containing class, at the time of object
creation of the containing class. And we can directly assign value to
them we out calling new on them?
Although practically you can consider objects to "contain" other objects this is just a human way of looking at it. For example the following circular dependency is perfectly fine (although sometimes unwise):
public class A {
private B b;
public A() {
}
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
public void main(String[] args){
A a=new A();
B b=new B();
a.setB(b);
b.setA(a);
//because all that a and b contain is references this circular referencing
//doesn't blow up
//this line is stupid, but perfectly valid
A referenceToAnA=b.getA().getB().getA().getB().getA();
}
}
public class B {
private A a;
public B() {
}
public void setA(A a) {
this.a = a;
}
public A getA() {
return a;
}
}
Final notes
Just like in C++ you must allocate memory for a new object by using the new keyword, it is however, not necessary to deallocate that memory, garbage collection deals with that
Thanks for the replies.Actually there was a misconception that is cleared out now. I was of the wrong notion that as the object b was created inside code of class C, we may need to use new again inside code of class A. But as pointed by #Richard Tingle, in A only there is reference and object can be created any where.
For this part:
[I am from C++ background, and this does not happen in C++. If a class
is having pointer or reference to other class, we need to explicitly
allocate memory for them.]
Again the behavior is similar in C++ also. We do not need to create the object "b" using "new" here because it has been created inside class C's method.Posted code for c++ below:
class B
{
int i;
public:
void setI(int i)
{
this->i=i;
}
int getI(){
return i;
}
};
class C
{
int x;
public:
B* returnB()
{
B *b = new B();
b->setI(10);
return b;
}
};
class A
{
private:
B *b;
C *c;
public:
B* getB(){
return b;
}
void setB(B *b){
this->b = b;
}
C* getC(){
return c;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A *a = new A(); // allocates memory for reference to object of B & C
C *c = new C(); // allocates memory for c
B *b = c->returnB(); // for b memory is allocated inside the function
// so there is no need of a "new" here.
a->setB(b);
cout << "value of i is: " << a->getB()->getI() << endl;
return 0;
}

Categories