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.
Related
This question already has answers here:
How can non-final fields be used in a anonymous class class if their value can change?
(1 answer)
Lambdas: local variables need final, instance variables don't
(10 answers)
Why can an anonymous class access non-final class member of the enclosing class
(4 answers)
Closed 4 years ago.
This question is similar to Lambdas: local variables need final, instance variables don't,but the only difference is this question is valid even without lambda expressions i.e. valid even on Java7.
Here is the code snippet below.
public class MyClass {
Integer globalInteger = new Integer(1);
public void someMethod() {
Integer localInt = new Integer(2);
Runnable runnable = new Runnable() {
#Override
public void run() {
globalInteger = new Integer(11);//no error
localInt = new Integer(22);//error here
}
};
}
}
I am allowed to reassign globalInteger a new value but not to localInteger. Why is this difference?
To understand why non-local variables are allowed to change, we first need to understand why local variables aren't. And that's because local variables are stored on the stack (which instance (or static) variables aren't).
The problem with stack variables is that they're going to disappear once their containing method returns. However the instance of your anonymous class might live longer than that. So if accessing local variables were implemented naively, using the local variable from inside the inner class after the method returned would access a variable on a stack frame that no longer exists. That would either lead to a crash, an exception or undefined behavior depending on the exact implementation. Since that's clearly bad, access to local variables is implemented via copying instead. That is, all the local variables that are used by the class (including the special variable this) are copied into the anonymous object. So when a method of the inner class accesses a local variable x, it's not actually accessing that local variable. It's accessing a copy of it stored inside the object.
But what would happen if a local variable changed after the object was created or if a method of the object changed the variable? Well, the former would cause the local variable to change, but not the copy in the object, and the latter would change the copy, but not the original. So either way the two versions of the variable would no longer be the same, which would be very counter-intuitive to any programmer who doesn't know about the copying going on. So to avoid this problem, you're only allowed to access local variables if their value is never changed.
Instance variables don't need to be copied because they won't disappear until their containing object is garbage collected (and static variables never disappear) - since the anonymous object will contain a reference to the outer this, this won't happen until the anonymous object is garbage collected as well. So since they aren't copied, modifying them doesn't cause any issues and there's no reason to disallow it.
Because JVM has no machine instruction to assign a variable located at any stack frame which is different from the current stack frame.
because the lambda function is not part of the class.
Think about the following code (small changes of yours):
public Runnable func() {
Integer localInt = new Integer(2);
Runnable runnable = new Runnable() {
#Override
public void run() {
globalInteger = new Integer(11);//no error
localInt = new Integer(22);//error here
}
};
return runnable;
}
//Somewhere in the code:
Runnable r = func();
r.run(); // At this point localInt is not defined.
The complier tells you the error that variable in inner class must be final or effectively final. This is due to Java's 8 closure and how JVM captures the reference. The restriction is that the reference captured in the lambda body must be final (not re-assignable), and complier needs to ensure it doesn't reference copies of local variables.
so if you access instance variable, your lambda is really referencing this instance of the surrounding class, which is effective final (non-changing reference). In addition, if you use a wrapper class or array, the complier error also goes away.
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.
Object as a class variable causes the stackoverflow
public class stack {
stack obj = new stack(); // its obvious that during class loading obj will call class to
// load and infinite loop will occur.
}
Lets say i am using static in from class obj
public class stack {
static stack obj = new stack(); // it will not cause infinite loop and program will //execute successfully
}
Static variables are allocated in to the memory when the class is caught by JVM first time (As far I know).
Say during first time only if the JVM starts allocating the memory to the above static object variable. It will intern call the class again and this should also cause infinite loop . Somewhere i am wrong. Can somebody highlight where i am wrong.
No, declaring it as static won't cause an infinite loop. Here is why.
Static variables are initialized during the class loading time. So when your class loads for the first time, compiler will create an instance for the static variable, and that's it. This won't cause your class to load a second time. Since your class is not loading again, this process won't be repeated.
If you declare it as a non-static attribute, then it's a totally different story. Consider this -
public class stack {
stack obj = new stack();
........
}
This declaration is equivalent to -
public class stack {
stack obj;
public stack() {
obj = new stack(); // implicitly moved here by the compiler
}
........
}
From the last example, it's pretty obvious why there is an infinite recursion here. You are creating an instance of the stack class inside its own constructor, which in turn creates another, and then another,......and it goes on, resulting in a Stack Overflow.
Loading the "stack" class will induce creating an instance of "stack", saved as static field the stack class. Then, this instance of the stack class has nothing to load: No stack exception.
keyword Static has nothing to do with infinite loop. You can declare the field, method,class(static inner class)
Static Field :- Static fields are created and initialized when the class is first loaded. That happens when a static member of the class is referred to or when an instance of the class is created, whichever comes first.
Static method:- A method declared with the static keyword. Like static fields, static methods are associated with the class itself, not with any particular object created from the class. As a result, you don’t have to create an object from a class before you can use static methods defined by the class.
The best-known static method is main, which is called by the Java runtime to start an application. The main method must be static, which means that applications run in a static context by default.
Memory Perspective:- As class is loaded once and its definition is stored in permgen area of jvm, static variables are also stored there and will lie for the life cycle of jvm.
Static variables are allocated in to the memory when the class is caught by JVM first time
Not exactly.
The static variables are allocated when the class is loaded.
The static variable initialization is performed when the class is initialized. That may happen some time after the class is loaded.
Say during first time only if the JVM starts allocating the memory to the above static object variable. It will intern call the class again and this should also cause infinite loop.
No. This is wrong for two reasons:
Objects in general are not "interned". Interning is an operation on String objects, and even then it only happens automatically for String literals. Non-literal String objects only get interned if your application calls String.intern() explicitly on them.
Even if some kind of interning was performed automatically, this would not cause an infinite loop. You seem to think that interning would somehow cause class initialization to be restarted or repeated. That cannot happen, the JVM goes to considerable lengths to ensure that each class is initialized at most once during its lifetime.
During debugging we can get to know , when first time control comes to the static variable ,
as variable is nothing but an instance of the class , it will call class loading .
then control enters in to the class , and finds a static variable object , but by this time it would be assigned by a memory address value by JVM(as done to other static variables). Control just ignores variable as instance and it assumes purely as static and program continues.
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?
I have the following code:
public class BookLib {
void f() {
final int x = 5; // Line 1
class MyCLass {
void print() {
System.out.println(x);
}
}
}
}
I don't understand why should use final variable in this case (Line 1)?
You've created an inner class here. Since the life-time of objects of this class can potentially be much greater than the runtime of the method invocation (i.e. the object can still exist long after the method has returned), it needs to "preserve" the state of local variables that it can access.
This preserving is done by creating an (invisible, synthetic) copy inside the inner class and automatically replacing all references to the local variable with references to that copy. This could lead to strange effects when the local variable were modified after the inner class object was created.
To avoid this, there is a requirement that all local variables that you access this way are final: this ensures that there is only ever one possible value for the local variable and no inconsistencies are observed.
This specific rule can be found in §8.1.3 Inner Classes and Enclosing Instances of the JLS:
Any local variable, formal method parameter or exception handler parameter used but not declared in an inner class must be declared final. Any local variable, used but not declared in an inner class must be definitely assigned (§16) before the body of the inner class.
Here you create an inner class. In order to access the context of execution, the references to the variables should stay intact, otherwise an error behaviour is observed. In order to guarantee this, you should declare your variable final: thus one can't change it.
See detailed explanation here.
From kathy sierra scjp Book
The local variables of the method live on the stack, and exist only for the lifetime of the method. We already know that the scope of a local variable is limited to the method the variable is declared in. When the method ends, the stack frame is blown away and the variable is history. But even after the method completes, the inner class object created within it might still be alive on the heap if, for example, a reference to it was passed into some other code and then stored in an instance variable. Because the local variables aren't guaranteed to be alive as long as the method-local inner class object, the inner class object can't use them. Unless the local variables are marked final!
So you have a local final variable and method-local inner class. A method-local inner class cannot use non-final variables declared within method (including parameters).
To go more deeply into this:
Method-local inner class can be instantiated only within method where the class is defined. The local variables live on stack for the lifetime of the method. As the method ends, the local variables disappear, however the inner class object created still lives.
It's a matter of lifetime/scope.