Купчина срещу стек срещу пермско пространство

  • Какви са разликите между пространствата на паметта на Java (Perm Space, Space Stack, Heap Space)?
  • Кога JVM използва едно или друго?
  • Ако използвам Scala/Groovy/и т.н., има ли разлики?

person caarlos0    schedule 23.07.2011    source източник
comment
Стекът е детайл за изпълнение. Може да не е толкова важно за Java, тъй като липсва дефинирани от потребителя типове стойности, но все пак е важно четиво за всеки, който работи на език за събиране на отпадъци.   -  person    schedule 23.07.2011
comment
други JVM езици използват същия стандарт?   -  person caarlos0    schedule 23.07.2011
comment
Също така трябва да се отбележи, че не всички JVM използват PermSpace.   -  person Ian McLaird    schedule 25.07.2011
comment
Всички JVM езици използват един и същ стандарт, няма нищо общо с езика, той е teh JVM!!, който е разделен на купчина и стеково пространство, а купчината е разделена на по-млади и по-стари поколения и perm ген.   -  person Angel O'Sphere    schedule 28.07.2011


Отговори (2)


Просто

  • Хийп пространство: Всички живи обекти се разпределят тук.
  • Стеково пространство: Съхранява препратки към обекта за променлива в извикване на метод или инстанциране на променлива.
  • Perm space: Съхранява информация за заредени класове

Например:

Student std = new Student();

след изпълнение на реда по-горе състоянието на паметта ще бъде такова.

  • Купчина: съхранява "new Student()"
  • Стек: съхранява информация за "std"
  • Perm Space: съхранява информация за ученическия клас
person Kowser    schedule 23.07.2011
comment
Стекът също съхранява примитивни литерали. - person Daniel C. Sobral; 27.07.2011
comment
@Daniel: Благодаря за информацията. Не знаех това и ще проуча повече за това. - person Kowser; 27.07.2011
comment
@Daniel: Стекът също съхранява примитивни литерали. Какво искаш да кажеш с това? Строго казано, стекът не съхранява нищо В стека има само параметри за извиквания на методи и стойности, които се използват при изчисляване на изрази. - person Angel O'Sphere; 28.07.2011
comment
@Kowser: нормалните Java обекти, особено интернираните низове, също се скитат през различни gc фази в perm gen. Колкото по-стар е обектът, толкова повече се движи към perm gen и накрая се намира в perm gen. - person Angel O'Sphere; 28.07.2011
comment
@Angel Стекът, по дефиниция, е структура от данни, която съхранява неща, със свойството, че когато изваждате неща, го правите в обратен ред на момента, в който ги поставяте. Така че, стриктно погледнато, стекът съхранява неща. Нещата, които JVM поставя в персонала, са препратки към обекти и примитивни литерали. Тоест, всеки параметър или променлива, който е от примитивен тип, не се поставя в стека като препратки, а като литерали. Между другото, нищо, което видях, не ми подсказа, че даден обект може да мигрира към perm gen, имате ли препратка към това? - person Daniel C. Sobral; 28.07.2011
comment
@Angel: redstack.wordpress.com/ 2011/01/06/ Досега това е статията, която намерих за много лесна и добре обяснена относно Събирането на боклука. Просто го добавих като справка, което може да е полезно. - person Kowser; 28.07.2011
comment
@Daniel: Вие също може да се интересувате. Моля, вижте връзката по-горе. - person Kowser; 28.07.2011
comment
@Kowser Благодаря. Почти това, което си спомних. - person Daniel C. Sobral; 29.07.2011
comment
@Daniel, съжалявам, че се заяждам, но Satastructure Stack като в java.util.Stack няма абсолютно нищо общо със стека в JVM или как стекът работи в истински компютър, освен че е LIFO структура. Така че ОТНОВО: в стека в JVM не се съхранява НИЩО. Стекът е за предаване на параметри към извиканите методи, това е всичко. Може би разглеждането на това как работят байт кодовете и как се специфицира JVM или разглеждането на истински асемблер за истински процесор може да помогне да се разбере това. Kowser: благодаря за връзката ;D Знам как работят GCs, сам добавих няколко, когато бях по-млад. Хубав линк обаче - person Angel O'Sphere; 29.07.2011
comment
@Angel Не говорех за java.util.Stack, говорех за стек. Ако нещата не се съхраняват в стека, как бихте могли да ги извлечете от стека? Ако искате да говорите за асемблер вместо концепция за стека, кодът за операция push на i386 съхранява данни в стека -- той коригира регистър и след това записва данните на позицията в паметта, посочена от него. Самият този акт на запис в паметта се нарича в някои асемблерни езици (като 6502) store. Започвам да си мисля, че имате някакво специално определение за думата магазин. - person Daniel C. Sobral; 29.07.2011
comment
@Angel Обратно към JVM, какво мислите, че се случва, когато изпълни кода на операцията iconst_1? - person Daniel C. Sobral; 29.07.2011
comment
И на двама ви: точно това исках да отбележа. Първоначалният въпрос вече е грешен. Въпросът трябваше да бъде: за какво VM използва купчината и за какво стека. Обърнете внимание на думата използване. Затова казах: строго погледнато! Даниел все още смята, че процесорният стек е същото като структурата на данните, което не е така. И да, iconst_1 е код за операция, който зарежда стойността 1 в горната част на стека! Следователно: това е в смисъла на думата: не съхранява нищо. Стекът е част от паметта, необходима за изпълнение. Не е склад. Но може би съм твърде академичен за вас. - person Angel O'Sphere; 29.07.2011

Извинете ме, че добавих отговор към толкова стар въпрос - Текущият отговор е страхотен, но пропуска няколко крайни случая поради статичен код и актуализации на Java 8.

Общ преглед

  • Stack
    • Allocated per Thread
    • Съхранява локални препратки и примитиви
    • Това е памет с обхват - Когато метод или нишка приключи, всичките им данни в стека се губят
    • Има най-бърз достъп, така че локалният примитив е по-бърз за използване от локалния обект
  • Heap
    • All allocated object instances exist here
    • Разделени на поколения, като най-младото поколение е първото място, където GC изглежда
    • Достъпно за всички нишки, така че разпределенията и освобождаванията трябва да бъдат синхронизирани
    • Тази памет може да стане фрагментирана (но обикновено не управлявате това сами)
  • PermGen
    • Stores loaded class information
    • Съхранява неизменна информация (примативи, интернирани низове)
    • Съхранява статичен клас членове

Примерен код

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 автоматично увеличава размера си в основната памет до максимум (посочен в параметрите на JVM), но PermGen винаги има фиксиран максимален размер, съседен на паметта на стека.

Забележка за Android: От Android 4.0 (от 3.0 на практика) Android трябва да спазва описаните договори за памет - но в по-стари версии внедряването беше повредено. Паметта „Stack“ в Android-Davlik всъщност е базирана на регистър (размерите и броят на инструкциите варират между двете, но за разработчика функционалността остава същата).

И накрая, за повече информация най-добрият отговор, който някога съм виждал на тази тема в StackOverflow, е тук

person Nick Cardoso    schedule 09.09.2017