Простите за добавление ответа на такой старый вопрос - текущий ответ великолепен, но пропускает пару крайних случаев из-за статического кода и обновлений Java 8.
Обзор
- Stack
- Выделено на тему
- Хранит локальные ссылки и примитивы
- Это объем памяти - Когда метод или поток заканчивается, все их данные в стеке теряются
- Имеет самый быстрый доступ, поэтому локальный примитив быстрее в использовании, чем локальный объект
- Heap
- Здесь есть все выделенные экземпляры объектов
- Разделенный на поколения, первое место на котором смотрит GC
- Доступно для всех потоков, поэтому распределения и освобождения должны быть синхронизированы
- Эта память может стать фрагментированной (, но вы обычно сами не управляете этим )
- PermGen
- Хранит загруженную информацию о классе
- Хранит неизменную информацию (Приматы, интернированные строки)
- Хранит статический класс членов
Пример кода
public class SimpleVal { //The Class (loaded by a classloader) is in the PermGen
private static final int MAGIC_CONSTANT = 42; //Static fields are stored in PermGen
private static final SimpleVal INSTANCE = new SimpleVal(1); //Static field objects are created in the heap normally, with the reference in the PermGen ('class statics' moved to the heap from Java 7+)
private static SimpleVal previousInstance; //Mutable static fields also have their reference in PermGen so they can easily cause memory leaks
private int value; //Member variables will be part of the heap
public SimpleVal(int realValue) {
value = realValue;
...
}
public static int subtract(SimpleVal val1, SimpleVal val2) {
....
}
public int add(SimpleVal other) { //Only one copy of any method (static or not) exists - in PermGen
int sum = value + other.value; //Local values in methods are placed in the Stack memory
return sum;
}
}
public static void main(String[] args) {
SimpleVal val1 = null;
SimpleVal val2 = new SimpleVal(3); //Both of these variables (references) are stored in the Stack
val1 = new SimpleVal(14); //The actual objects we create and add to the variables are placed in the Heap (app global memory, initially in the Young Gen space and later moved to old generation, unless they are very large they can immediately go old gen)
int prim = val1.add(val2); //primitive value is stored directly in the Stack memory
Integer boxed = new Integer(prim); //but the boxed object will be in the heap (with a reference (variable) in the Stack)
String message = "The output is: "; //In Java 7+ the string is created in the heap, in 6 and below it is created in the PermGen
System.out.println(message + prim);
}
Java 8 Примечание: Пространство PermGen было заменено на то, что называется Metaspace. Это все еще работает так же, но может быть изменено автоматически - по умолчанию Metaspace auto увеличивает свой размер в собственной памяти до максимума (указанного в параметрах JVM), но PermGen всегда имеет фиксированный максимальный размер, смежный с кучей памяти.
Примечание для Android: Начиная с Android 4.0 (из практики 3.0) Android должен соблюдать описанные контракты с памятью, но в более старых версиях реализация была нарушена . Память «Stack» в Android-Davlik фактически основана на регистре (размеры команд и их количество различаются, но для разработчика функциональность остается неизменной).
Наконец, для получения дополнительной информации, лучший ответ, который я когда-либо видел на эту тему в StackOverflow: здесь