Static Allocation in Java - Heap, Stack and Permanent Generation

static allocation in java - heap, stack and permanent generation

First, as should be clear to you by now that there are very few people who can confirm these answers from first hand knowledge. Very few people have worked on recent HotSpot JVMs or studied them to the depth needed to really know. Most people here (myself included) are answering based on things they have seen written elsewhere, or what they have inferred. Usually what is written here, or in various articles and web pages, is based on other sources which may or may not be definitive. Often it is simplified, inaccurate or just plain wrong.

If you want definitive confirmation of your answers, you really need to download the OpenJDK sourcecode ... and do your own research by reading and understanding the source code. Asking questions on SO, or trawling through random web articles is not a sound academic research technique.

Having said that ...

... my question is Sun specific.

At the time this question was asked, Sun Microsystems had ceased to exist. The question was therefore Oracle specific. AFAIK, all current (non-research) 3rd-party JVM implementations are either direct ports of an OpenJDK release or descended from another Sun/Oracle release.

The answers below apply to Oracle Hotspot and OpenJDK releases, and probably to most others as well ... including GraalVM.

1) Classes (loaded by the classloaders) go in a special area on heap : Permanent Generation.

Prior to Java 8, yes.

As of Java 8, the PermGen space has been replaced with Metaspace. Loaded and JIT-compiled classes now go there. PermGen no longer exists.

2) All the information related to a class like name of the class, Object arrays associated with the class, internal objects used by JVM (like java/lang/Object) and optimization information goes into the Permanent Generation area.

More or less, yes. I'm not sure what you mean by some of those things. I'm guessing that "internal objects used by JVM (like java/lang/Object)" means JVM-internal class descriptors.

3) All the static member variables are kept on the Permanent Generation area again.

The variables themselves yes. These variables (like all Java variables) will hold either primitive values or object references. However, while the static member variables are in a frame that is allocated in the permgen heap, the objects/arrays referred to by those variables may be allocated in any heap.

4) Objects go on a different heap : Young generation

Not necessarily. Large objects may be allocated directly into the tenured generation.

5) There is only one copy of each method per class, be the method static or non-static. That copy is put in the Permanent Generation area.

Assuming that you are referring to the code of the method, then AFAIK yes. It may be a little more complicated though. For instance that code may exist in bytecode and/or native code forms at different times during the JVM's life.

... For non-static methods, all the parameters and local variables go onto the stack - and whenever there is a concrete invocation of that method, we get a new stack-frame associated with it.

Yes.

... I am not sure where are the local variables of a static method are stored. Are they on the heap of Permanent Generation ? Or just their reference is stored in the Permanent Generation area, and the actual copy is somewhere else (Where ?)

No. They are stored on the stack, just like local variables in non-static methods.

6) I am also unsure where does the return type of a method get stored.

If you mean the value returned by a (non-void) method call, then it is either returned on the stack or in a machine register. If it is returned on the stack, this takes 1 or two words, depending on the return type.

7) If the objects (in the young generation) nees to use a static member (in the permanent generation), they are given a reference to the static member && they are given enough memory space to store the return type of the method,etc.

That is inaccurate (or at least, you are not expressing yourself clearly).

If some method accesses a static member variable, what it gets is either a primitive value or an object reference. This may be assigned to an (existing) local variable or parameter, assigned to an (existing) static or non-static member, assigned to an (existing) element of a previously allocated array, or simply used and discarded.

  • In no case does new storage need to be allocated to hold either a reference or a primitive value.

  • Typically, one word of memory is all that is needed to store an object or array reference, and a primitive value typically occupies one or two words, depending on the hardware architecture.

  • In no case does space need to be allocated by the caller to hold some object / array returned by a method. In Java, objects and arrays are always returned using pass-by-value semantics ... but that value that is is returned is an object or array reference.


For more information, please refer to these resources:

  • Class metadata: a user guide
  • What is the difference between PermGen and Metaspace?
  • Java 8: From PermGen to Metaspace
  • About G1 Garbage Collector, Permanent Generation and Metaspace

Where are static methods and static variables stored in Java?

Static methods (in fact all methods) as well as static variables are stored in the PermGen section of the heap, since they are part of the reflection data (class related data, not instance related). As of Java 8 PermGen has been replaced by MetaSpace and as per JEP 122 it only holds meta-data while static fields are stored in the heap.

Note that this mostly applies to Oracle's Hotspot JVM and others that are based on it. However, not every JVM has PermGen or Metaspace like Eclipse OpenJ9.

Update for clarification:

Note that only the variables and their technical values (primitives or references) are stored in PermGen space.

If your static variable is a reference to an object that object itself is stored in the normal sections of the heap (young/old generation or survivor space). Those objects (unless they are internal objects like classes etc.) are not stored in PermGen space.

Example:

static int i = 1; //the value 1 is stored in the PermGen section
static Object o = new SomeObject(); //the reference(pointer/memory address) is stored in the PermGen section, the object itself is not.
A word on garbage collection:

Do not rely on finalize() as it's not guaranteed to run. It is totally up to the JVM to decide when to run the garbage collector and what to collect, even if an object is eligible for garbage collection.

Of course you can set a static variable to null and thus remove the reference to the object on the heap but that doesn't mean the garbage collector will collect it (even if there are no more references).

Additionally finalize() is run only once, so you have to make sure it doesn't throw exceptions or otherwise prevent the object to be collected. If you halt finalization through some exception, finalize() won't be invoked on the same object a second time.

A final note: how code, runtime data etc. are stored depends on the JVM which is used, i.e. HotSpot might do it differently than JRockit and this might even differ between versions of the same JVM. The above is based on HotSpot for Java 5 and 6 (those are basically the same) since at the time of answering I'd say that most people used those JVMs. Due to major changes in the memory model as of Java 8, the statements above might not be true for Java 8 HotSpot - and I didn't check the changes of Java 7 HotSpot, so I guess the above is still true for that version, but I'm not sure here.

Where does the Static members reside in memory,is it permanent generation?

static members : permanent generation(heap)

local variable : stack memory which is not heap.
refer here http://tutorials.jenkov.com/java-concurrency/java-memory-model.html

Understanding the difference between a static and a non-static method representation on the heap

There's another side of the story that needs to be mentioned. When you have a class, say Bar:

public class Bar {
public static void doSomething() { ... }

public void doSomethingElse() { ... }
}

On the heap the signature for doSomethingElse is not doSomethingElse() but doSomethingElse(Bar this). As opposed to doSomething which is left with no parameters (hence you can't call this from a static method - there is no this to call to).

When you have a call like this:

Bar bar = new Bar();
bar.doSomethingElse();

It's just a syntactic sugar to:

doSomethingElse(bar); // I neglected here for simplification but the name of the method in the compiled code also includes the name of the class.

When you define an extending class Foo:

public class Foo extends Bar {
@Override
public void doSomethingElse() { ... }
}

Another method is created doSomethingElse(Foo this). Next thing to there is a virtual table (read about it if you're not familiar with the term) - Each class holds a virtual table which maps a method signature to a concrete code. When you call a method in runtime there is a search in the class (not the instance) virtual table for the correct implementation according to the dynamic type of the instance.

So the full example would be (and of course that's just a simplification):

Java syntax (syntactic sugar):

Bar b = new Foo();
b.doSomethingElse();

What really happens (simplified):

// Step 1: Get the correct overriden method for Foo class from the virtual table
// Step 2: Invoke the method with the instance "b" as the first parameter (the "this" parameter)
Foo.getMethodFromVirtualTable("doSomethingElse").invoke(b);

That's only a simplification of course but that's sort of the way it happens.

In fact when you come to think of it, all the methods are static in memory (that's why they reside in PermGen). The complier uses the static virtual table for each class in order to call the correct method. This what allows polymorphism.

Where static is stored in java8 above version?

All code is held in metaspace.

All class metadata is held in metaspace.

All static variables are held in the heap.

So:

In conclusion, where static method, static variables, static class is stored in java8?

The answers are 1) metaspace, and 2) heap. For 3) it depends on what you mean. However the metadata is the only aspect of a static class that has a representation, and that is stored in metaspace.


Note that an application cannot get its hands on the actual method code, class metadata or frame containing the static variables.

Also note that class metadata, method code, and static frames not copied when (for example) objects are created.

So it is moot where they are actually stored.



Some article says static variables, static class can't be deleted by Garbage Collector.

Those articles are incorrect ... if that is what they actually say. The reality is that a class may be garbage collected if it becomes unreachable, but it is not easy to create the conditions in which a class becomes unreachable. So, in practice classes are rarely garbage collected.

Likewise, a classes static variables will become unreachable if the class itself is unreachable. But that is rare too; see above.

But anyway, the logical inference you were trying to make is incorrect. Being in the heap is neither necessary or sufficient for something to be reclaimed by one of the JVM's storage management mechanisms.

  • Things allocated in metaspace can be deleted.
  • Things allocated in the heap won't necessarily ever be eligible for deletion.

Java stack and heap memory management

Where are the methods of s stored?

They are stored in the String class object; it is an object loaded by a ClassLoader object when String is first referenced in the program. All the implementations of the JVM that existed when I read about this last never deallocated the memory for a class object once it was loaded. It's on the heap.

Had I created another object of MemoryClass inside myMethod, would JVM allocate memory for the same methods again inside the stack memory?

No, methods and data for objects is kept separately, specifically because the JVM never needs more than one copy of the methods.

Would JVM free the memory allocated to myMethod as soon as it's execution is completed, if so, how would it manage the situation mentioned in question 2(only applicable if JVM allocates memory multiple times to the same method).

No. Java doesn't generally "immediately free memory" of things stored on the heap. It would make things run too slowly. It only frees memory when the garbage collector runs, and it does that only when its algorithm for running the garbage collector decides it is time.

What would have been the case, if I had only declared s and did not initialize it, would JVM still allocate memory to all the methods of java.lang.String class,if so,why?

This depends on the JVM implementation, I think, and maybe the compiler. If you declare a variable and never use it, it is quite possible (and common) for the compiler to notice that there is no use for it and to not put it into the class file. If it isn't in the class file, it is never referenced, and therefore it and its methods are not loaded, etc. If the compiler puts it in anyway but it is never referenced, then the ClassLoader wouldn't have any reason to load it, but I'm a little vague on whether it would get loaded or not. Might depend on the JVM implementation; does it load things because there are variables of the class or only when they are referenced? How many ClassLoader algorithms can dance on the head of a 4-digit PIN?

I encourage you to read about the JVM and ClassLoaders and such; you will gain so much more by reading an explanation of how it works rather than poking at it with examples you can think up.



Related Topics



Leave a reply



Submit