Related
I know the concept of a constants pool and the String constant pool used by JVMs to handle String literals. But I don't know which type of memory is used by the JVM to store String constant literals. The stack or the heap? Since its a literal which is not associated with any instance I would assume that it will be stored in stack. But if it's not referred by any instance the literal has to be collected by GC run (correct me if I am wrong), so how is that handled if it is stored in the stack?
The answer is technically neither. According to the Java Virtual Machine Specification, the area for storing string literals is in the runtime constant pool. The runtime constant pool memory area is allocated on a per-class or per-interface basis, so it's not tied to any object instances at all. The runtime constant pool is a subset of the method area which "stores per-class structures such as the runtime constant pool, field and method data, and the code for methods and constructors, including the special methods used in class and instance initialization and interface type initialization". The VM spec says that although the method area is logically part of the heap, it doesn't dictate that memory allocated in the method area be subject to garbage collection or other behaviors that would be associated with normal data structures allocated to the heap.
As explained by this answer, the exact location of the string pool is not specified and can vary from one JVM implementation to another.
It is interesting to note that until Java 7, the pool was in the permgen space of the heap on hotspot JVM but it has been moved to the main part of the heap since Java 7:
Area: HotSpot
Synopsis: In JDK 7, interned strings are no longer allocated in the permanent generation of the Java heap, but are instead allocated in the main part of the Java heap (known as the young and old generations), along with the other objects created by the application. This change will result in more data residing in the main Java heap, and less data in the permanent generation, and thus may require heap sizes to be adjusted. Most applications will see only relatively small differences in heap usage due to this change, but larger applications that load many classes or make heavy use of the String.intern() method will see more significant differences.
RFE: 6962931
And in Java 8 Hotspot, Permanent Generation has been completely removed.
String literals are not stored on the stack. Never. In fact, no objects are stored on the stack.
String literals (or more accurately, the String objects that represent them) are were historically stored in a Heap called the "permgen" heap. (Permgen is short for permanent generation.)
Under normal circumstances, String literals and much of the other stuff in the permgen heap are "permanently" reachable, and are not garbage collected. (For instance, String literals are always reachable from the code objects that use them.) However, you can configure a JVM to attempt to find and collect dynamically loaded classes that are no longer needed, and this may cause String literals to be garbage collected.
CLARIFICATION #1 - I'm not saying that Permgen doesn't get GC'ed. It does, typically when the JVM decides to run a Full GC. My point is that String literals will be reachable as long as the code that uses them is reachable, and the code will be reachable as long as the code's classloader is reachable, and for the default classloaders, that means "for ever".
CLARIFICATION #2 - In fact, Java 7 and later uses the regular heap to hold the string pool. Thus, String objects that represent String literals and intern'd strings are actually in the regular heap. (See #assylias's Answer for details.)
But I am still trying to find out thin line between storage of string literal and string created with new.
There is no "thin line". It is really very simple:
String objects that represent / correspond to string literals are held in the string pool.
String objects that were created by a String::intern call are held in the string pool.
All other String objects are NOT held in the string pool.
Then there is the separate question of where the string pool is "stored". Prior to Java 7 it was the permgen heap. From Java 7 onwards it is the main heap.
String pooling
String pooling (sometimes also called as string canonicalisation) is a
process of replacing several String objects with equal value but
different identity with a single shared String object. You can achieve
this goal by keeping your own Map (with possibly soft
or weak references depending on your requirements) and using map
values as canonicalised values. Or you can use String.intern() method
which is provided to you by JDK.
At times of Java 6 using String.intern() was forbidden by many
standards due to a high possibility to get an OutOfMemoryException if
pooling went out of control. Oracle Java 7 implementation of string
pooling was changed considerably. You can look for details in
http://bugs.sun.com/view_bug.do?bug_id=6962931 and
http://bugs.sun.com/view_bug.do?bug_id=6962930.
String.intern() in Java 6
In those good old days all interned strings were stored in the PermGen
– the fixed size part of heap mainly used for storing loaded classes
and string pool. Besides explicitly interned strings, PermGen string
pool also contained all literal strings earlier used in your program
(the important word here is used – if a class or method was never
loaded/called, any constants defined in it will not be loaded).
The biggest issue with such string pool in Java 6 was its location –
the PermGen. PermGen has a fixed size and can not be expanded at
runtime. You can set it using -XX:MaxPermSize=96m option. As far as I
know, the default PermGen size varies between 32M and 96M depending on
the platform. You can increase its size, but its size will still be
fixed. Such limitation required very careful usage of String.intern –
you’d better not intern any uncontrolled user input using this method.
That’s why string pooling at times of Java 6 was mostly implemented in
the manually managed maps.
String.intern() in Java 7
Oracle engineers made an extremely important change to the string
pooling logic in Java 7 – the string pool was relocated to the heap.
It means that you are no longer limited by a separate fixed size
memory area. All strings are now located in the heap, as most of other
ordinary objects, which allows you to manage only the heap size while
tuning your application. Technically, this alone could be a sufficient
reason to reconsider using String.intern() in your Java 7 programs.
But there are other reasons.
String pool values are garbage collected
Yes, all strings in the JVM string pool are eligible for garbage
collection if there are no references to them from your program roots.
It applies to all discussed versions of Java. It means that if your
interned string went out of scope and there are no other references to
it – it will be garbage collected from the JVM string pool.
Being eligible for garbage collection and residing in the heap, a JVM
string pool seems to be a right place for all your strings, isn’t it?
In theory it is true – non-used strings will be garbage collected from
the pool, used strings will allow you to save memory in case then you
get an equal string from the input. Seems to be a perfect memory
saving strategy? Nearly so. You must know how the string pool is
implemented before making any decisions.
source.
As other answers explain Memory in Java is divided into two portions
1. Stack: One stack is created per thread and it stores stack frames which again stores local variables and if a variable is a reference type then that variable refers to a memory location in heap for the actual object.
2. Heap: All kinds of objects will be created in heap only.
Heap memory is again divided into 3 portions
1. Young Generation: Stores objects which have a short life, Young Generation itself can be divided into two categories Eden Space and Survivor Space.
2. Old Generation: Store objects which have survived many garbage collection cycles and still being referenced.
3. Permanent Generation: Stores metadata about the program e.g. runtime constant pool.
String constant pool belongs to the permanent generation area of Heap memory.
We can see the runtime constant pool for our code in the bytecode by using javap -verbose class_name which will show us method references (#Methodref), Class objects ( #Class ), string literals ( #String )
You can read more about it on my article How Does JVM Handle Method Overloading and Overriding Internally.
To the great answers that already included here I want to add something that missing in my perspective - an illustration.
As you already JVM divides the allocated memory to a Java program into two parts. one is stack and another one is heap. Stack is used for execution purpose and heap is used for storage purpose. In that heap memory, JVM allocates some memory specially meant for string literals. This part of the heap memory is called string constants pool.
So for example, if you init the following objects:
String s1 = "abc";
String s2 = "123";
String obj1 = new String("abc");
String obj2 = new String("def");
String obj3 = new String("456);
String literals s1 and s2 will go to string constant pool, objects obj1, obj2, obj3 to the heap. All of them, will be referenced from the Stack.
Also, please note that "abc" will appear in heap and in string constant pool. Why is String s1 = "abc" and String obj1 = new String("abc") will be created this way? It's because String obj1 = new String("abc") explicitly creates a new and referentially distinct instance of a String object and String s1 = "abc" may reuse an instance from the string constant pool if one is available. For a more elaborate explanation: https://stackoverflow.com/a/3298542/2811258
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Explain the difference between contiguous allocation (memory held in a heap in the stack) vs. memory in a heap.
I'm new at this and not entirely sure.
The question isn't contiguous versus heap, but automatic versus heap.
Automatic storage is set up on entry to a block of code -- traditionally on entry to a function or method -- and discarded when that function returns, so its memory space on the stack can be reused by the next function call. That's how most local variables are handled. Obviously this isn't useful for anything which is intended to persist past the end of that function call.
In Java, objects are never allocated from automatic storage. Instead, they are allocated from the heap, on demands, when the new operation is performed. There are several reasons for this which, frankly, unless you're designing a programming language you don't really need to know about and it's too large a topic to cover here. The important thing is that since they were obtained from the heap, their lifetime is independent of the stack frame. Since Java is a garbage-collected language, their memory will be automatically recovered for reuse sometime after that last reference to them goes away -- again, the details are too large a topic to cover here, but basically you can trust that the GC comes through periodically to pick up the clothes we dropped on the floor and toss them into the laundry.
A stack frame only exists for the life of a method call, which means that memory is allocated to provide storage for all your local variables and method parameters that are used in some way that assist helping the method achieve its goals of whatever task it set out to achieve.
Examples of memory storage in a stack frame are temporary pointers that are used to keep track of an index position in an array which you are iterating through. Once the loop is finished, the stack frame would be popped off the stack, which means all the temporary memory allocated for the local variables and method parameters that existed are released back into the system.
The heap is different because it is where objects live, not "pointers" to objects.
When I was learning I found it hard to work out the difference between the two.
The key point that helped me was that, a pointer to an object is kept in a stack frame, it has a little bit of temporary memory allocated that exists for the life time of the method call. Thus, you can only access an object when the method is in "scope".
The pointer contains a memory address that leads to the location of the object stored on the heap. This allows you to reference the object to change the objects state at a later time.
public static void main(String[] args)
{
Person person = new Person("Steven", 30);
}
When you run this program:
new keyword means java will allocate memory on the heap for the space required to store the Person objects instance variables.
The important part to understand is, no memory is required to store an objects methods. When a method is called, a new stack frame is created which allocates temporary memory for the duration of the method call. Using the example above, a Person has 2 instance variables, a String name and int age. This means that the memory required for this Person object is the required memory to store a reference variable of type String (bit pattern of the memory address of a String object on the heap) and memory to hold the bit pattern of an int.
Lastly, the main method is a stack frame too, so when main finishes, you no longer have a reference to a Person object or access to any temporary variables that may have existed in main.
This is true for any method, if you have a method that creates an object but doesn't return the reference to that object, then you can never access the object and the java garbage collector comes along at a later time and cleans up all the objects on the heap that don't have references pointing to them.
If you are starting out, I highly recommend head first java. It is a great book IMO and covers these topics in easy to understand ways.
When we talk about memory or disc allocation, the word "contiguous" simply means "without any gaps".
A single stack or heap memory allocation is always contiguous ... in every programming language runtime I've ever encountered where it makes sense to talk about allocations at all.
A sequence of allocations is contiguous if there is no gap between the individual allocations.
This is orthogonal to stack versus heap. Both stack allocations and heap allocations can be contiguous ... or non-contiguous.
Well ... not quite orthogonal.
If you are talking about strictly contiguous memory addresses (physical or virtual), a typical heap node consists of the area of memory that the application can use, plus a small node header. So, if you look at the available memory for two consecutive heap nodes, there is a gap ... comprising the node header ... that prevents the two regions being used by the application as a single contiguous region. (And you'd better not try 'cos if you overwrite the node header, bad things could happen.)
However, when we are talking about Java this is not relevant. Java does not allow an application to join objects or arrays together. (That would be a fundamental violation of runtime type safety.) So the notional gap in the address ranges doesn't matter. In the Java context, we would say that two objects are contiguous, ignoring the heap node / object header.
Besides, in Java you can't explicitly allocate things on the heap either. In a classical JVM, only local variables comprising primitive types and references go on the stack. There is no way to say "allocate this array on the stack". (The JVM might do the latter under certain circumstances, but it is entirely transparent to the application, and certainly not something that you could make use of.)
This question already has answers here:
Is the garbage collector guaranteed to run before Out of Memory Error?
(5 answers)
Closed 9 years ago.
This is a theoretical question. I am just curios that if Java has a mechanism for garbage collection to free the memory, then why does still OutOfMemoryError occur?
I searched SO for this but could get these links
Is the garbage collector guaranteed to run before Out of Memory Error?
Garbage collection before OutOfMemoryError
These do not answer my question specifically. If Java allows memory so well by using garbage collection, then why does OutOfMemoryError occur?
An OutOfMemoryError can occur if none of the objects in memory is eligible for garbage collection. For example:
List<MyClass> hellos = new ArrayList<>();
for (;;) {
hellos.add(new MyClass());
}
This creates a list and keeps adding MyClass objects to it until memory runs out. None of the objects is eligible for garbage collection because there are references to all of them.
It is also possible to sequester memory in ways you don't expect. Consider the following string example.
char[] chars = new char[10_000_000]; // May need to adjust.
String string = new String(chars);
chars = null;
String substring = string.substring(5_000_000);
string = null;
The chars array may be collected. The array inside string may not be collected, because substring contains a reference to the internal array followed by an offset and range into it. So, 107 characters remain allocated, even though only 5 * 106 are used and accessible.
Java 1.7.0_06
It seems that String.substring no longer has this behavior. In an article in the Java Performance Tuning Guide web site, Mikhail Vorontsov reports that in Java 1.7.0_06 and higher, String.substring always creates a new String independent of the old one. The String class no longer has offset and range instance variables. Creating a large string, taking substrings, and throwing away the original will not leave the old string's char[] sequestered.
// Java 1.7.0_06 and up
char[] chars = new char[10_000_000]; // May need to adjust.
String string = new String(chars);
chars = null;
String substring = string.substring(5_000_000);
// Copies a portion of string's array to a new array.
string = null;
// string's array is no longer reachable, and may be garbage collected.
Because not all memory is garbage.
Garbage collector works on memory that is not going to be used.
However, if you allocate memory, and that memory is in scope, that means, garbage collector can't really clean that memory.
When the memory allocated is too high above the allowed for the VM, you get that exception.
An object that's still has a reference to it from running code can't be collected. So if there's a way to even theoretically access an object, it's stuck in memory.
Just so it's said, Java doesn't eliminate the need to care about memory; it just automates a whole lot of the memory management stuff. You still have to do your part to ensure that you aren't squirreling away objects after their useful life is over...cause as long as they can be reached (however indirectly), they are taking up memory that can't be reclaimed.
It is better to nullify your objects once your work has been completed with them, so you make sure the objects to be available to the garbage collector in order to avoid the problems regarding out of memory or memory leak.
If you run out of memory and there is no variable or object eligible for removing, the except will be raised.
So best way to use GC(Garbage collection) is:
Explicitly assign the variable to null value if it is no used any more.
This might seem a lot of questions but they are all interrelated.I'm little confused as in where is the heap space allocated and where is the stack memory located ? If both are present in main memory then why it is said that stack memory is easier to access and why can't we allocate objects in stack memory ? Since classes are stored in PermGen where is this space allocated and how does it differ from heap space and where are constant strings stored ?
"Where are the heap and stack allocated?" The accepted answer to this question covers this. Each thread gets its own stack and they all share one heap. The operating system controls the exact memory locations of the stacks and heap items and it varies.
"Why is stack memory easier to access" Each thread has its own stack, so there are fewer concurrency issues. The stack and heap are both eligible for caching in the L1, L2, and L3 portions of the memory hierarchy, so I disagree with Daniel's answer here. Really I would not say that one kind of memory is particularly easier to access than the other.
"Why can't we allocated objects in stack memory?" This is a design decision taken by the JVM. In other languages like C/C++ you can allocate objects on the stack. Once you return from the function that allocated that stack frame such objects are lost. A common source of errors in C/C++ programs is sharing a pointer to such a stack allocated object. I bet that's why the JVM designers made this choice, though I am not sure.
The PermGen is another piece of the heap. Constant strings are stored here for the lifetime of the JVM. It is garbage collected just like the rest of the heap.
If both are present in main memory then why it is said that stack memory is easier to access
There's speed of access and speed of allocation. Stack allocation (as in alloca) is fast because there's no need to search for an unused block of memory. But Java doesn't allow stack allocation, unless you count the allocation of new stack frames.
Accessing stack memory is fast because it tends to be cached. Not only are locals near one another, they are also stored very compactly.
and why can't we allocate objects in stack memory ?
This would be useful, but dangerous. A user could allocate an object on the stack, create references to it from permanent objects, and then try to access the object after the associated stack frame is gone.
It's safe to store primitives on the stack because we can't create references to them from elsewhere.
Since classes are stored in PermGen where is this space allocated and how does it differ from heap space and where are constant strings stored ?
PermGen is just another heap space. String literals are stored in the literal pool, which is just a table in memory which is allocated when a class is loaded.
I know the concept of a constants pool and the String constant pool used by JVMs to handle String literals. But I don't know which type of memory is used by the JVM to store String constant literals. The stack or the heap? Since its a literal which is not associated with any instance I would assume that it will be stored in stack. But if it's not referred by any instance the literal has to be collected by GC run (correct me if I am wrong), so how is that handled if it is stored in the stack?
The answer is technically neither. According to the Java Virtual Machine Specification, the area for storing string literals is in the runtime constant pool. The runtime constant pool memory area is allocated on a per-class or per-interface basis, so it's not tied to any object instances at all. The runtime constant pool is a subset of the method area which "stores per-class structures such as the runtime constant pool, field and method data, and the code for methods and constructors, including the special methods used in class and instance initialization and interface type initialization". The VM spec says that although the method area is logically part of the heap, it doesn't dictate that memory allocated in the method area be subject to garbage collection or other behaviors that would be associated with normal data structures allocated to the heap.
As explained by this answer, the exact location of the string pool is not specified and can vary from one JVM implementation to another.
It is interesting to note that until Java 7, the pool was in the permgen space of the heap on hotspot JVM but it has been moved to the main part of the heap since Java 7:
Area: HotSpot
Synopsis: In JDK 7, interned strings are no longer allocated in the permanent generation of the Java heap, but are instead allocated in the main part of the Java heap (known as the young and old generations), along with the other objects created by the application. This change will result in more data residing in the main Java heap, and less data in the permanent generation, and thus may require heap sizes to be adjusted. Most applications will see only relatively small differences in heap usage due to this change, but larger applications that load many classes or make heavy use of the String.intern() method will see more significant differences.
RFE: 6962931
And in Java 8 Hotspot, Permanent Generation has been completely removed.
String literals are not stored on the stack. Never. In fact, no objects are stored on the stack.
String literals (or more accurately, the String objects that represent them) are were historically stored in a Heap called the "permgen" heap. (Permgen is short for permanent generation.)
Under normal circumstances, String literals and much of the other stuff in the permgen heap are "permanently" reachable, and are not garbage collected. (For instance, String literals are always reachable from the code objects that use them.) However, you can configure a JVM to attempt to find and collect dynamically loaded classes that are no longer needed, and this may cause String literals to be garbage collected.
CLARIFICATION #1 - I'm not saying that Permgen doesn't get GC'ed. It does, typically when the JVM decides to run a Full GC. My point is that String literals will be reachable as long as the code that uses them is reachable, and the code will be reachable as long as the code's classloader is reachable, and for the default classloaders, that means "for ever".
CLARIFICATION #2 - In fact, Java 7 and later uses the regular heap to hold the string pool. Thus, String objects that represent String literals and intern'd strings are actually in the regular heap. (See #assylias's Answer for details.)
But I am still trying to find out thin line between storage of string literal and string created with new.
There is no "thin line". It is really very simple:
String objects that represent / correspond to string literals are held in the string pool.
String objects that were created by a String::intern call are held in the string pool.
All other String objects are NOT held in the string pool.
Then there is the separate question of where the string pool is "stored". Prior to Java 7 it was the permgen heap. From Java 7 onwards it is the main heap.
String pooling
String pooling (sometimes also called as string canonicalisation) is a
process of replacing several String objects with equal value but
different identity with a single shared String object. You can achieve
this goal by keeping your own Map (with possibly soft
or weak references depending on your requirements) and using map
values as canonicalised values. Or you can use String.intern() method
which is provided to you by JDK.
At times of Java 6 using String.intern() was forbidden by many
standards due to a high possibility to get an OutOfMemoryException if
pooling went out of control. Oracle Java 7 implementation of string
pooling was changed considerably. You can look for details in
http://bugs.sun.com/view_bug.do?bug_id=6962931 and
http://bugs.sun.com/view_bug.do?bug_id=6962930.
String.intern() in Java 6
In those good old days all interned strings were stored in the PermGen
– the fixed size part of heap mainly used for storing loaded classes
and string pool. Besides explicitly interned strings, PermGen string
pool also contained all literal strings earlier used in your program
(the important word here is used – if a class or method was never
loaded/called, any constants defined in it will not be loaded).
The biggest issue with such string pool in Java 6 was its location –
the PermGen. PermGen has a fixed size and can not be expanded at
runtime. You can set it using -XX:MaxPermSize=96m option. As far as I
know, the default PermGen size varies between 32M and 96M depending on
the platform. You can increase its size, but its size will still be
fixed. Such limitation required very careful usage of String.intern –
you’d better not intern any uncontrolled user input using this method.
That’s why string pooling at times of Java 6 was mostly implemented in
the manually managed maps.
String.intern() in Java 7
Oracle engineers made an extremely important change to the string
pooling logic in Java 7 – the string pool was relocated to the heap.
It means that you are no longer limited by a separate fixed size
memory area. All strings are now located in the heap, as most of other
ordinary objects, which allows you to manage only the heap size while
tuning your application. Technically, this alone could be a sufficient
reason to reconsider using String.intern() in your Java 7 programs.
But there are other reasons.
String pool values are garbage collected
Yes, all strings in the JVM string pool are eligible for garbage
collection if there are no references to them from your program roots.
It applies to all discussed versions of Java. It means that if your
interned string went out of scope and there are no other references to
it – it will be garbage collected from the JVM string pool.
Being eligible for garbage collection and residing in the heap, a JVM
string pool seems to be a right place for all your strings, isn’t it?
In theory it is true – non-used strings will be garbage collected from
the pool, used strings will allow you to save memory in case then you
get an equal string from the input. Seems to be a perfect memory
saving strategy? Nearly so. You must know how the string pool is
implemented before making any decisions.
source.
As other answers explain Memory in Java is divided into two portions
1. Stack: One stack is created per thread and it stores stack frames which again stores local variables and if a variable is a reference type then that variable refers to a memory location in heap for the actual object.
2. Heap: All kinds of objects will be created in heap only.
Heap memory is again divided into 3 portions
1. Young Generation: Stores objects which have a short life, Young Generation itself can be divided into two categories Eden Space and Survivor Space.
2. Old Generation: Store objects which have survived many garbage collection cycles and still being referenced.
3. Permanent Generation: Stores metadata about the program e.g. runtime constant pool.
String constant pool belongs to the permanent generation area of Heap memory.
We can see the runtime constant pool for our code in the bytecode by using javap -verbose class_name which will show us method references (#Methodref), Class objects ( #Class ), string literals ( #String )
You can read more about it on my article How Does JVM Handle Method Overloading and Overriding Internally.
To the great answers that already included here I want to add something that missing in my perspective - an illustration.
As you already JVM divides the allocated memory to a Java program into two parts. one is stack and another one is heap. Stack is used for execution purpose and heap is used for storage purpose. In that heap memory, JVM allocates some memory specially meant for string literals. This part of the heap memory is called string constants pool.
So for example, if you init the following objects:
String s1 = "abc";
String s2 = "123";
String obj1 = new String("abc");
String obj2 = new String("def");
String obj3 = new String("456);
String literals s1 and s2 will go to string constant pool, objects obj1, obj2, obj3 to the heap. All of them, will be referenced from the Stack.
Also, please note that "abc" will appear in heap and in string constant pool. Why is String s1 = "abc" and String obj1 = new String("abc") will be created this way? It's because String obj1 = new String("abc") explicitly creates a new and referentially distinct instance of a String object and String s1 = "abc" may reuse an instance from the string constant pool if one is available. For a more elaborate explanation: https://stackoverflow.com/a/3298542/2811258