Hello everyone,


I have heard that static variable will make the program consume very much memory. It is because garbage collector (GC) will not work on static variable. Is that correct?

I am also wondering when does the memory space of a static variable is allocated, during compile or during runtime?


thanks in advance,
George

a static variable, by definition, is a variable, declared at the start of the program, that does not change its value throught the execution of the program.

it's memory is allocated at the start of the program, in regular memory, instead of the stack (memory set aside specifically for the program). the advantage of this is that it makes your variable or procedure totally constant, and you can't accidentally change the value. the disadvantage of this is that the memory is not deallocated until the program is terminated. I have never heard anything that static values take any more memory than if they are declared regularly, but thier memory use is constant throught.

Hello everyone,


I have heard that static variable will make the program consume very much memory. It is because garbage collector (GC) will not work on static variable. Is that correct?

I am also wondering when does the memory space of a static variable is allocated, during compile or during runtime?


thanks in advance,
George

Actually, static variables should take the same amount of space as an instance variable. However, this only applies if you only create one instance of your class. Once more then one instance of your class is created then the static variable will take up less space.

Regards,

Nate

a static variable, by definition, is a variable, declared at the start of the program, that does not change its value throught the execution of the program.

Wrong. You're referring to a final member.
A static member is allocated one instance per Class Object rather than one instance per class instance.
It is initialised at class loading time which can be at any point after JVM startup, and after that can be altered as required (depending on access control of course).
It can also be made final in which case it cannot be changed once initialised to a value.

It will take up the same space as an instance member of the same data type would, but whereas instance member are declared once per instance static members are declared only once per classloader.

As I understand it the garbage collector will remove a static variable if all references to it have been lost. This can happen if there are no objects of that class.

Thanks jwenting,

Wrong. You're referring to a final member.
A static member is allocated one instance per Class Object rather than one instance per class instance.
It is initialised at class loading time which can be at any point after JVM startup, and after that can be altered as required (depending on access control of course).
It can also be made final in which case it cannot be changed once initialised to a value.

It will take up the same space as an instance member of the same data type would, but whereas instance member are declared once per instance static members are declared only once per classloader.

Thank you very much! So you mean the memory of a static member is allocated during runtime other than compiling time?

Another question is that, will Garbage Collector work on static members?


regards,
George

Thanks hooknc,

Actually, static variables should take the same amount of space as an instance variable. However, this only applies if you only create one instance of your class. Once more then one instance of your class is created then the static variable will take up less space.

Regards,

Nate

I want to know whether memory of a static member is allocated during runtime or compiling time?

Another question is that, will Garbage Collector work on static members?


regards,
George

Thanks Dortz,

a static variable, by definition, is a variable, declared at the start of the program, that does not change its value throught the execution of the program.

it's memory is allocated at the start of the program, in regular memory, instead of the stack (memory set aside specifically for the program). the advantage of this is that it makes your variable or procedure totally constant, and you can't accidentally change the value. the disadvantage of this is that the memory is not deallocated until the program is terminated. I have never heard anything that static values take any more memory than if they are declared regularly, but thier memory use is constant throught.

I am wondering whether the memory space of a static variable is allocated during compiling time or runtime.


regards,
George

Thanks Gargol,

As I understand it the garbage collector will remove a static variable if all references to it have been lost. This can happen if there are no objects of that class.

I am not quite sure about your points. Could you provide any additional related resources from the Internet? Since it seems that Dortz has a different point of view (you can find his thread above -- thread just below my question).


regards,
George

Memory is never allocated at compile time!
At most a default value to be used during initialisation is set if that value is different from the default the language dictates.

So the memory for your static member is allocated during class initialisation by the classloader.
When the class is unloaded (which can happen, but is not guaranteed to, when there are no more references to it) that memory also is freed (which could lead to more memory being freed if the static member contains a reference to another object).

Remember that it is possible to have more than one instance of a static member in a single application!
While most people will never encounter this, it bears remembering just in case.
Static members are unique per Class instance. Each classloader loading a class will have its own Class instance for that class and thus its own set of static class members.
Unless you're working with distributed applications, some web applications, or custom classloaders, you're unlikely to have to bother about that though.

You said Dotz had a different point of view but my point was complementary really. Others have explained that Dotz was talking about a final. You didn't ask about a final so I returned to your question about a static.

Memory for a static is allocated each time the class is instantiated. Each of these exists until it cannot be referenced any more and then a bit longer until the garbage collector makes the memory free again.

I hope you got your issue sorted anyway.

Check your sources. There's no guarantee that a Class object for a specific class will get garbage collected when there are no more references to instances of the class.
That means that a static member could survive during times when no class instances exist.

public class Tester1 {
    public static void main(String[] args) throws Exception{
	    Inner i = new Inner();
	    i.x = 1;
	    i = null;
	    Thread.sleep(1000);
	    System.gc();
	    i = new Inner();
	    System.out.println(i.x);
    }
}

    class Inner {
	    public static int x;
    }

will print 1 for example, had the static member disappeared because the Class object had disappeared with the last instance of the class it would have printed 0.
This is of course not quite conclusive as there's no guarantee the gc will run when called, but it's a good indication of why you should never rely on static members having their initial value.

Your'e right, but I didn't say there WAS a gaurantee. You used the word.

I accept and for the sake of all other readers of this thread. A peice of memory may never be garbage collected. EVEN if it has been marked as unused and can be detected as such.

A few comments on your garbage collection code...

Looks like your Inner class isn't an inner class. This may confuse some readers.

I see the point you are making but your example uses two instances of Inner so the second one may not use the same part of memory as the first EVEN if the first has been garbage collected.

As you say certainty is something you don't get with gc.

In my comments I did add in the words "and a bit longer" which I think you would have preffered in CAPITALS !? ie. Maybe never.

Thanks Gargol,

I see the point you are making but your example uses two instances of Inner so the second one may not use the same part of memory as the first EVEN if the first has been garbage collected.

I do not understand your points here. Why you stress the point that "the second one may not use the same part of memory as the first EVEN if the first has been garbage collected"? Could you provide more description please?

In my comments I did add in the words "and a bit longer" which I think you would have preffered in CAPITALS !? ie. Maybe never.

What means "and a bit longer" and in CAPITALS in your reply?


regards,
George

An excellent sample, jwenting!

Check your sources. There's no guarantee that a Class object for a specific class will get garbage collected when there are no more references to instances of the class.
That means that a static member could survive during times when no class instances exist.

public class Tester1 {
    public static void main(String[] args) throws Exception{
	    Inner i = new Inner();
	    i.x = 1;
	    i = null;
	    Thread.sleep(1000);
	    System.gc();
	    i = new Inner();
	    System.out.println(i.x);
    }
}

    class Inner {
	    public static int x;
    }

will print 1 for example, had the static member disappeared because the Class object had disappeared with the last instance of the class it would have printed 0.
This is of course not quite conclusive as there's no guarantee the gc will run when called, but it's a good indication of why you should never rely on static members having their initial value.

regards,
George

Gargol,

Memory for a static is allocated each time the class is instantiated. Each of these exists until it cannot be referenced any more and then a bit longer until the garbage collector makes the memory free again.

I am wondering how to write a sample to verify your idea -- "Each of these exists until it cannot be referenced any more and then a bit longer until the garbage collector makes the memory free again". Do you have any good ideas?


regards,
George

jwenting,

So the memory for your static member is allocated during class initialisation by the classloader.
When the class is unloaded (which can happen, but is not guaranteed to, when there are no more references to it) that memory also is freed (which could lead to more memory being freed if the static member contains a reference to another object).

How could "could lead to more memory being freed if the static member contains a reference to another object"? Could you show an example please?

Remember that it is possible to have more than one instance of a static member in a single application!
While most people will never encounter this, it bears remembering just in case.

How could it be possible " have more than one instance of a static member in a single application"?? Could you show an example please? I think this situation violates Java Language.

Static members are unique per Class instance. Each classloader loading a class will have its own Class instance for that class and thus its own set of static class members.

Not quite understand your points here. I think all instances of the same class share the same static members of that specific class, not necessarily having their own individual copies.


regards,
George

Say a static member references a List.
That List contains references to several objects, which have no other references left.

In that case, when the reference to the List disappears because the Class object gets garbage collected, the objects referenced in that List get themselves garbage collected as well so more memory is freed than just the memory footprint of an empty List.

Thanks Gargol,


I do not understand your points here. Why you stress the point that "the second one may not use the same part of memory as the first EVEN if the first has been garbage collected"? Could you provide more description please?

What means "and a bit longer" and in CAPITALS in your reply?


regards,
George

When a new object is created from a class an unused part of memory is used for it.

The unused part of memory MAY have been used before or it MAY NOT. All you can be sure of is that it is marked as unused.

If the garbage collector releases memory after it has been used it MAY be used for a new version of the same object but this is unlikely in complicated applications. If your code only creates one object it is more likely, but even then the way memory is reused is not guaranteed in Java.

When the second object in the test code above is created if it uses the same memory as the old one it may have the old value. This will only work if the variable is not initialised which is often (always?) prevented by the compiler. When writing your programmes you should certainly initialise all your variables before you use them.

The main point you should remember is that a call to gc() is not guaranteed to realease memory even if there is some unused memory available. This may be difficult to accept, I know, but it doesn't mean that calling gc() is a good idea sometimes.

I added the words "and a bit longer" above because even if the gc has found and marked memory for release it may be a long while, or NEVER, before it actually releases it.

Hope that helps you understand my point now.

jwenting, understand!

Say a static member references a List.
That List contains references to several objects, which have no other references left.

In that case, when the reference to the List disappears because the Class object gets garbage collected, the objects referenced in that List get themselves garbage collected as well so more memory is freed than just the memory footprint of an empty List.

regards,
George

Gargol,

When a new object is created from a class an unused part of memory is used for it.

The unused part of memory MAY have been used before or it MAY NOT. All you can be sure of is that it is marked as unused.

If the garbage collector releases memory after it has been used it MAY be used for a new version of the same object but this is unlikely in complicated applications. If your code only creates one object it is more likely, but even then the way memory is reused is not guaranteed in Java.

When the second object in the test code above is created if it uses the same memory as the old one it may have the old value. This will only work if the variable is not initialised which is often (always?) prevented by the compiler. When writing your programmes you should certainly initialise all your variables before you use them.

The main point you should remember is that a call to gc() is not guaranteed to realease memory even if there is some unused memory available. This may be difficult to accept, I know, but it doesn't mean that calling gc() is a good idea sometimes.

I added the words "and a bit longer" above because even if the gc has found and marked memory for release it may be a long while, or NEVER, before it actually releases it.

Hope that helps you understand my point now.

I understand your points. In your opinion, when gc marks a memory space as unused (release/free memory), it will not reset them as zero (or other default value), so the memory may still contain the original information of last time. Is that correct?

I have found that you are using the following comments to say why jwenting's sample has issues to prove his idea,

I see the point you are making but your example uses two instances of Inner so the second one may not use the same part of memory as the first EVEN if the first has been garbage collected.

But I can not find why based on your points, jwenting's sample has issues to prove his idea. Could you help to describe please?


regards,
George

OK. I will try to find a documentation reference for you to read.

If you look in the test code you will see that a new Inner object does not initialise the value of i. This means that when it is printed the value is strictly speaking undefined and I think some compilers would not compile the code for this reason.

The code creates two Inner objects. It sets the value of i for the first object but not the second.

Do you see? If it prints 1 then it may (perhaps) have been the value set for the first Inner object before it was thrown away by the gc.

The point is that in Java the value is NOT undefined as long as the garbage collector has not removed the Class object for class Inner.

According to the JLS:

If a field is declared static, there exists exactly one incarnation of the field, no matter how many instances (possibly zero) of the class may eventually be created. A static field, sometimes called a class variable, is incarnated when the class is initialized (§12.4).

12.4 Initialization of Classes and Interfaces
Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class. Initialization of an interface consists of executing the initializers for fields (constants) declared there.
Before a class is initialized, its superclass must be initialized, but interfaces implemented by the class are not initialized. Similarly, the superinterfaces of an interface are not initialized before the interface is initialized.

So it doesn't matter whether instances of the class exist at any time, the field will exist as long as the Class itself has been loaded.

An implementation of the Java programming language may unload classes. A class or interface may be unloaded if and only if its defining class loader may be reclaimed by the garbage collector as discussed in §12.6. Classes and interfaces loaded by the bootstrap loader may not be unloaded.

Makes clear that that Class object will indeed never be unloaded if created by most classloaders.
Only if the application creates its own classloader and that gets unloaded (gc'd) may Class objects created by that classloader also be unloaded.

JLS chapters 8 and 12.

Gargol,

OK. I will try to find a documentation reference for you to read.

If you look in the test code you will see that a new Inner object does not initialise the value of i. This means that when it is printed the value is strictly speaking undefined and I think some compilers would not compile the code for this reason.

The code creates two Inner objects. It sets the value of i for the first object but not the second.

Do you see? If it prints 1 then it may (perhaps) have been the value set for the first Inner object before it was thrown away by the gc.

Thanks for your reply. I think the sample is just to prove that 1 should be printed out (the value set for the first Inner object is used for the second Inner object before it was thrown away by the gc). Why do you say there is problem?


regards,
George

jwenting,

The point is that in Java the value is NOT undefined as long as the garbage collector has not removed the Class object for class Inner.

According to the JLS:


So it doesn't matter whether instances of the class exist at any time, the field will exist as long as the Class itself has been loaded.

Makes clear that that Class object will indeed never be unloaded if created by most classloaders.
Only if the application creates its own classloader and that gets unloaded (gc'd) may Class objects created by that classloader also be unloaded.

JLS chapters 8 and 12.

Your reply is great! I have two questions from your reply,

1. From what point have you made the conclusion that "The point is that in Java the value is NOT undefined as long as the garbage collector has not removed the Class object for class Inner".

2. How to define a customized ClassLoader which can unload a Class object? Do you know where can I find a simple sample?


regards,
George

I'm sure there are books about it, but I don't have any references at hand (I've never had a need to do that, or I would have).

In general you don't need to worry about such things. Just never assume that a static field has the value you set in it a minute ago and you should be fine :)

jwenting

Firstly my apology. I mis-understood the real point of your test example. I also think this has led me to make some in-correct statements. Sorry. The mixture of static, final and gc issues has been a bit tricky! My statements about gc collecting a static are garbage! Please delete!

I don't really want to continue discussing gc and classloaders. For me this insn't an important part of development with Java anyway, so I'm going to withdraw here.

Just to say that section 16.15.1 (p438) in The Java Programming Language Fourth Edition covers The ClassLoader Class. Also in section 17.4 (p453) details of an agressive garbage collection application method fullGC are also given together with a warning NOT TO USE IT for most purposes!

If Gosling recommends something there must be a good reason!

No problem, we all have our blonde moments :)

garbage collection is indeed a tricky issue even without having to look at what happens when there are multiple classloaders, static members, maybe finals, inner classes, etc. etc. involved.

jwenting, anyway, I think your sample is great and it is just what I want!

No problem, we all have our blonde moments :)

garbage collection is indeed a tricky issue even without having to look at what happens when there are multiple classloaders, static members, maybe finals, inner classes, etc. etc. involved.

regards,
George

This article has been dead for over six months. Start a new discussion instead.