Somebody please clarify me the below to grasp the java memory allocation and management better. Thanks.
Q1) What is the difference between the below 3 code fragments: Why three different exist? ( In terms of when memory allocation )
Fragment1:
Class C
{
StringBuffer sb = new StringBuffer();
C(){}
}
Fragment2:
Class C
{
StringBuffer sb;
C()
{
sb = new StringBuffer();
}
}
Fragment3:
Class C
{
C()
{
StringBuffer sb = new StringBuffer();
}
}
Q2) How an object created without any reference variable will be maintained.
For example, new C(); new C().Hello();
How to understand their memory management, default values, scope!!
Q3) Difference between the below 2 fragments:
Fragment1
Class C
{
int a;
C(){}
}
Fragment2
Class C
{
C(){int a;}
}
Q1) The fragment 1 and fragment 2 are equivalent. If the class C had more than one constructor there would be a difference. In the fragment 1 variant you would write the initialization only once, in the fragment 2 variant you need to write it in each constructor.
In fragment 3 the variable sb is a local variable in the constructor and only visible there. The StringBuffer object can be garbage collected when the constructor ends.
Q2) It will not be maintained, after creation it can be garbage collected immediately. In the case of new C().Hello(); the object is only guaranteed to exist until the Hello() method exits.
Q3) fragment 1 declares a class field, fragment 2 a local variable in the constructor.
Fragment1 and Fragment2 are effectively the same. They both have the same scope, and create the same object. In the latter, this is done in the constructor. That is the difference. In my view, members should usually be initialised in the constructor.
Fragment3 scope is different. Once the constructor ends, C is garbage collected. That is because, when a method is finished, all local objects are dereferenced. Once there is no reference pointing at an instance, the garbage collector does what it does best. Collects the damn garbage.
The three different examples exist because.. well.. they can be used in several different situations. You might have a member that relies on another member, so can only be initialised after the first member was.
Example
public class Test
{
private A a;
private B b;
public Test()
{
b = new B();
// As you can see, b needs to exist first.
a = new A(b);
}
How an object created without any reference variable will be maintained. For example, new C(); new C().Hello(); How to understand their memory management, default values, scope!!
If there is no reference to an object, then it will be garbage collected. When you declare new A() it exists for as long as you use it. The second the program steps over that line of code (or collection of byte code as it were), the Garbage Collector cleans up again.
Q3) Difference between the below 2 fragments:
In the first example, a can be used anywhere in the class. This is called a global variable or, more specifically, an instance variable. In the second example, you declare a local variable. This means that it can only be used inside the method it is declared in. In this case, the constructor.
An addition to the other answers:
If a new object is created, the JVM will always allocate memory in the heap of the running program and place that object there. In all your example fragments, the resulting StringBuffer object will be placed in the heap.
Creating a new object with the new keyword also returns a reference to that object. This reference can be assigned to a variable. And here comes the difference of your example fragments. In fragment 1 and 2 you are assigning this reference to an instance variable (aka field), which is part of an object's data - here an instance of class C. Thus, these instance variables also reside in the heap. As long as there is also a reference to your C instance - maybe in your main method - there will be for sure a reference to the contained StringBuffer instance.
In fragment 3 you assign this reference to a local variable. The memory for a local variable is allocated on the stack, not on the heap. When the method ends, this memory allocation will also be discarded. There is no (local) variable anymore, that can hold a reference to an object.
An object is considered eligible for garbage collection, if there is no reference anymore to it. In your fragment 3, this will be the case for the StringBuffer instance after the constructor ends. Note, that the Java garbage collector does not immediately run and delete all garbage. It will run at an appropriate time of the JVM's choice.
Related
when does instance variable of a static method gets memory in java?
it is perfectly right to create instance variable in static method (either in parameter or declaring inside the function), but i want to know when does the instance variable of static method is allocated memory, if no object of the class is created?
Actually i meant to say the local variable inside static method
Firstly, the term instance variable is not accurate, I am assuming that you are asking about local variable such as a and b in the example below:
void method(int a) {
int b = 3;
}
In Java, only primitives and references are stored on stack, objects are stored in heap when they are constructed. Stack will be cleaned as soon as the scope ends, heap is cleaned by garbage collector.
Here is an example:
public class Main {
static A a = new A();
static void method() {
int b = 2;
C c = new C();
}
}
The first time your code refers to Main, class loader will load the class and initialize all its static fields - object new A() will go into heap. Nothing more happens here, method method could as well not exist.
When you call method method, it will add value 2 on the stack, then it will add reference c on the stack which will be pointing to the object new C() in the heap.
When method exists, 2 and c are removed from the stack (there is actually no removal, but the top of the stack is changed to two positions below so these two values will be overriden whenever something else comes onto stack), while new C() will remain in heap until garbage collector triggers. It's likely that it will be garbage collected immediately as GC may detect that there are no more references to this object.
If you declare a variable or use parameter inside a static method, its not at all instance variable. Its a local variable and it will be initialized once the method gets invoked
static void methodTest(int i) {
String s = "Hello";
}
Here s is a local variable to that method.
and i is the function parameter which is also a local variable to the method
There is not such thing as an instance variable in a static method.
If you mean parameters and local variables, those are allocated on stack (any created objects being allocated on heap as usual).
Static fields of the class will be initialized when the class is loaded.
Instance variables of a class will be allocated (and possibly initialized) when an instance is constructed.
The variable defined by static method is still local variable in scope of the method, just as if non-static method created local variable. However, problem is that the variable never gets garbage collected, as long as the class loader (usually main class, which gets "unloaded" only at runtime termination, which is like scratching your left ear with your right hand) is not unloaded and garbage collected. And objects get GC'd only if they are not referenced anymore, and in case of static fields, they have tendency to be referenced even when nothing uses them because of the behavior I described. So in large applications, where memory and resources are issue, it is pretty bad idea to declare anything inside static methods since you pretty soon pollute the memory with LOCAL VARIABLES that cannot be collected.
Suppose an Activity A has some static member variables, since statics are loaded in memory when class is first loaded by VM and stays around, I wonder what happens to Activity with respect to garbage collection if other class B is holding any static variable of class A.?
Will it not be collected?
Will it be collected and statics are initialized to initial values?
Classes for example purposes
public class Activity {
public static int primitiveStatic = 42;
public static Object objectStatic = new Object();
}
public class B {
public Object referenceField = null;
}
public class C {
public int primitiveField = 0;
}
A simple model of a Java object instance is a memory area containing, in addition to space for each of its instance members (non-static), some administrative information including a reference to its class object. The class object (the entity in memory at runtime) contains various pieces of information about the class, including (relevant to this question) space for each of the static members of the class. Note that some of this is JVM dependent.
The key thing to note is that static members are stored in or with the class object at runtime (not in any instance object).
In the example classes above, the Activity class object at runtime would have two variables, one primitive integer variable (primitiveStatic) and one reference of Object type (objectStatic). Every instance of the class would have its own distinct memory area, containing not much more than a single reference to the class object. An instance of B has space for a single object reference. An instance of C has space for a single primitive integer value.
The garbage collector can remove and finalize any object in memory which is eligible for collection. This does apply also to class objects, but it is not as simple as for instance objects, where the object is eligible if there are simply no references to it. Class objects and static fields are rarely eligible, but in cases where the class is unloaded, they are. See this documentation for more information on class unloading.
I believe the cases you are wondering about include these:
Case 1
new Activity();
//or
Activity a = new Activity();
a = null;
Case 1 after set up and assignments are completed.
The class is loaded, creating the class object and static variables as described above. An instance is created, as described above. The instance is immediately eligible for garbage collection. When collected, the instance is destroyed, removing the reference to the class object. If it is the end of the program or in other certain cases, the class object may also be garbage collected, removing the primitiveStatic and objectStatic variables. In this case, the new Object() which was referred to by objectStatic now also has no references to it, and is in turn eligible for garbage collection in the normal way.
Case 2
B b = new B();
b.referenceField = Activity.objectStatic;
Case 2 after setup and assignments are completed.
A new B instance is created (and the class object for class B) as described above. The Activity class is loaded and class object created if it has not been already. The referenceField in b is set to refer to the same location as the objectStatic field, which is found in or with the Activity class object. If the Activity class is unloaded (happens in some cases but not common), its class object is removed as described in //1. This time, the new Object() still has a reference to it, in b.referenceField, so is not eligible for collection. We are left with the B class object and the new Object() and an instance, b, with a single reference to each.
Case 3
Activity a = new Activity();
B b = new B();
b.referenceField = a.objectStatic;
a = null;
Case 3 after setup and assignments are completed.
The Activity class is loaded, and class object created if they aren't already, as described above. An instance is created, as described above. The same for the B class. By finding a's class reference and locating it there, the static reference objectStatic is obtained from a and assigned to b.referenceField. This is a copy assignment of the reference value, so there is no reference between b and a or Activity, but b now contains a reference to the new Object() constructed by the Activity class. a = null means that the Activity instance initially referred to by a becomes eligible for garbage collection. Its reference to the Activity class object is removed. The Activity class object may become eligible for garbage collection. If it is, the static fields it contains are cleared. The new Object() referred to by objectStatic now has a single reference, in b, so is not eligible for garbage collection. We are left with this object, and the B class object, and b which contains a single reference to each (identical to case //2)
Case 4
Activity a = new Activity();
C c = new C();
c.primitiveField = a.primitiveStatic;
a = null;
Case 4 after setup and assignments are completed.
Like in //3, the Activity class is loaded, and class object created if they aren't already, and an instance is created, as described above. The same for the C class. By finding a's class reference and locating it there, the static primitive primitiveStatic is obtained from a and assigned to c.primitiveField. This is simply a copy assignment, so there is no reference between c and a or Activity. a = null means that the Activity instance initially referred to by a becomes eligible for garbage collection. Its reference to the Activity class object is removed. The Activity class object may become eligible for garbage collection. If it is, the static fields it contains are cleared. The new Object() referred to by objectStatic now has no references, so is eligible for garbage collection. We are left with the C instance, c, with a primitive int value of 42 in its primitiveField.
In all of these cases, no object instance is prevented from being garbage collected by something else having references to objects also referred to by its class static fields (and even the class and its static values can be garbage collected in certain circumstances), even when those field values are 'owned' by the class (e.g. final and initialised in and by the class.)
Things to watch out for are that if the objectStatic field is final, the object it refers to will almost never be collected: the Activity class must be unloaded for it to become eligible for collection. This could be a problem if you have lots of static object references which are not used after program setup, since they will stick around and fill up memory even though they aren't used.
You cannot hold reference to a static variable (or any variable) of a Class.
One can only hold references to objects, not the variable itself.
Eg,
class MainActivity {
public static Object obj = new Object();
}
class B {
private Object ref = MainActivity.obj;
}
In this case, only the new Object() is being referenced by B (and hence cannot be GCed). Not the variable obj (or the class MainActivity) itself.
Is it a good practice to create an Object inside a loop. I am pointing towards the following code:
for(some condition){
SomeClass a = new SomeClass ();
System.out.println(a);
}
So this would create a new instance of SomeClass for each iteration. So number of instances will be equal to number of iterations. And then these will later be collected by GC.
Is it better to reuse a SomeClass object inside the loop. Something like this:
SomeClass a = null;
for(some condition) {
a = new SomeClass();
System.out.println(a);
}
As far as I understand this, the second way is better as this will just create the SomeClass object once and will reuse it in every iteration. But I am doubtful. Please confirm this, or let me know where my fundamentals are incorrect.
The difference is that in your second case, your a variable will still be in scope when the loop is over
other than that, they're essentially the same, even from a garbage collection point of view.
Strings are reference types(albeit immutable ones), and it doesn't really matter whether you declare a new variable for them or just overwrite the same variable each time. You're still creating a brand new string every time.
Be careful not confuse the 'Object' itself and a 'Reference' to an 'Object':
For instance the following code creates a (null) Reference, but no object is created.
Object a = null;
The following code create boths an Object AND a reference to that object (the reference is held in a variable called 'a'):
Object a = new Object();
The following code creates new Object and 'repoints' an existing (reference) variable to point to the new Object: if the variable 'a' already held another reference, 'a' forgots it. [but that doesn't mean other variables may still point to the old object referenced by 'a'].
a = new Object(); // it is the reference 'a' that is 're-used' here not the object...
Everytime you re-run the that statement above in your loop; you are indeed creating a new object ; and you are 're-pointing' 'a' to that new object.
The previous reference (i.e. reference held in 'a') will be forgotten each time; and (assuming we have a single-threaded program here) that means the object it pointed to will have zero references pointing at it now: which means the object is eligible for Garbage Collection. Whether this Garbage collection happens or not at this point in time - I don't know I'm afraid.
But I would say : that there is no difference in your coding examples in terms of when Garbage Collection happens; whether or not the 'pointer-type' is already defined as an 'Object' outside of the loop, or repeatedly redefined within the loop.
The following (useless) examples might help illustrate the difference between the 'Create-an-Object' and 'Point-a-Reference' actions that the code does in one go:
// This creates an object ; but we don't hold a reference to it.
public class TestClass {
public static void main(String[] args) {
for (int n=0;n<100;n++) {
new Object();
}
}
}
And to contrast:
// This creates a reference ; but no object is created
// This is identical to setting the reference to 'null'.
public class TestClass {
public static void main(String[] args) {
for (int n=0;n<100;n++) {
Object o;
}
}
}
Both create an equivalent amount of strings because String is immutable. Anytime a String is assigned a new value, a new String is created.
Let's assume you meant to use a mutable object in your example.
Option 1
for(some condition)
{
Object o = new Object();
System.out.println(o);
}
This will create a new Object o for each iteration of the loop.
Option 2
Object o;
for(some condition)
{
o = new Object();
System.out.println(o);
}
This will create a new Object o for each iteration of the loop.
Even for a mutable object, you get the same result either way!
the 2nd is not "better".
String a="foo"; reuse a literal string from string pool. That is, no matter you declare the a in/outside the loop, there is no difference in terms of memory. But they have different scope. I think it is another issue.
even if with your edited version, with general SomeClass, it is not like what you thought:
the second way is better as this will just create the SomeClass object once and will reuse it in every iteration .
It creates new object in each loop step. a is just a reference to the object. The point is, if the object(s) you created referenced by other objects, GC will not collect it, and release the memory. For example, the old (<=java1.6) String.subString() method, it holds the original String as char[], so GC won't clean the original String.
You are confusing the variable you assign an object to, to the actual object instance.
Both code samples create the equivalent amount of objects. The second one will keep one instance in larger scope, thus it will be available for a longer time.
according to my knowledge - in bigger application (not in this) but in bigger is better to use static block for object creation - because static block code is executed only once when class is loaded into memory. Technically, you can can have multiple static blocks in a class, although it doesn’t make much sense
remember: Static block can access only static variables and methods
The only difference is that in the second case, variable will still be in scope when the loop is over ,no. of objects that are created in both the cases are equal as Strings are immutable
as you have just edit the question still in this case new Objects are created in the memory at each iteration in both the cases
Since the topic has changed quite a bit. I update:
If you really want to reuse the once create object you will have to write that code yourself. It could follow this principle:
SomeClass a = new SomeClass();
for(some condition) {
a.reset();
//do something with a
}
Where the SomeClass.reset() method handles all the details (which are dependant on your actual usage of the object).
it is all about scope,
if you do your second way:
SomeType someFunction(){
...
SomeClass a = null;
for(some condition) {
a = new SomeClass();
System.out.println(a);
}
...
return something
}
object a will exist in memory till end of someFunction while for first method, its lifecycle is within single iteration of loop
class A
{
B b;
public A()
{
b = new B(this);
//initialization of class A variables
}
public void meth1()
{
}
}
class B
{
A a;
public B(A a)
{
this.a = a;
}
}
I know that this reference shouldn't be passed in this way,but what happens if this is done
Some other class calls the class A constructor. when is the "this" reference actually allocated memory? would it be assigned memory as soon as A's constructor is called before even super() is called.
Suppose class B is a thread and since B has A's reference can B call the methods on A before A's constructor doesn't even return if "this" reference is not allocated memory yet.
The memory for the object is allocated before any constructor is executed. Otherwise the constructor would have not place to write the values of the variables.
Therefore you can pass out a reference to the current object (a.k.a this) to other pieces of code inside the constructor.
As you noted, the object is not fully constructed at that time and it's a bad idea to actually do that, but "just" because the values of the object can be in an inconsistent state. The memory is already allocated and reserved for that object at this point in time.
this is just a reference to the "current object", which you could think of as just another parameter that any non-static method gets. In fact in that's actually how the JVM treats it. See JVMS §2.6.1 Local Variables:
On instance method invocation, local variable 0 is always used to pass a reference to the object on which the instance method is being invoked (this in the Java programming language).
So the direct answer to "when is this allocated" is effectively: Whenever you call a method on an object.
this refers to current object and any object is allocated memory using "new"
The memory is allocated when JVM is processing new instruction. If for example your code looks like:
A a = new A();
^
here the memory for A is allocated
It indeed could be a problem to pass this to B. Constructor of B can invoke instance method of A before the constructor of A has been finished. You should move line to the end of constructor of A to avoid possible problems. Alternatively you could manage the object lifecycle from outside using setters.
this is assigned before the constructor is called. In fact, the super() call is not necessary. It only ensures that the creation stuff of the parent class is done, which doesn't matter if the parent class is Object. Also, A's methods are usable as soon as the object is created (even before the constructor is called) so if B got the reference to A in the constructor, it can use A's methods just like A itself in the constructor. Just be sure to make A's methods so that they can be used when A is not fully initialized, or just create and start B after the initialization is complete.
As long as you don't modify A or call methods on A or it's members in the constructor of B it will work. ( See other answers)
If you call a method on an not completely initialized object (after construction) it's not defined what happens. Especially if you use multiple threads (see memory barrier).
More on this topic:
How do JVM's implicit memory barriers behave when chaining constructors?
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...