JVM-da Xotira bilan Tanishuv
Siz allaqachon bilganingizdek, JVM ichida Java dasturlarini ishga tushiradi. Har qanday virtual mashina kabi, u o'zining xotira tashkilot tizimiga ega.
Ichki xotirani tashkil etish sxemasi sizning Java ilovangizning qanday ishlash prinsipini ko'rsatadi. Shu yo'l bilan ilovalar va algoritmlarning tor joylarini aniqlash mumkin. Keling, uning qanday tuzilganligini bilib olaylik.
Ahamiyatli! Java modelining dastlabki ko'rinishi yetarli darajada yaxshi emas edi, shuning uchun u Java 1.5 da qayta ko'rib chiqildi. Bu versiya hozirgi kunda ham (Java 14+) ishlatiladi.
Oqim steki
JVM ichida ishlatiladigan Java xotira modeli xotirani oqim steklari (thread stacks) va kuchaga (heap) bo'ladi. Keling, bloklarga mantiqan bo'lingan Java xotira modeliga nazar tashlaylik:
Barcha oqimlar, JVM-da ishlayotgan, o'z stekiga ega. Stek o'z navbatida oqim qanday metodlarni chaqirganligi haqida ma'lumot saqlaydi. Men buni "chaqiruv steki" deb atayman. Chaqiruv steki oqim o'z kodini bajarishi bilan qayta tiklanadi.
Oqim steki ichida hamma mahalliy o'zgaruvchilar saqlanadi, oqim stekidagi metodlarni amalga oshirish uchun zarur bo'lgan. Oqim faqat o'z stekiga kirish huquqiga ega. Mahalliy o'zgaruvchilar boshqa oqimlarga ko'rinmaydi, faqat ularni yaratgan oqimga. Ikki oqim bir xil kodni bajarayotgan holatda, ularning ikkalasi ham o'z mahalliy o'zgaruvchilarini yaratadi. Shunday qilib, har bir oqim har bir mahalliy o'zgaruvchining o'z versiyasiga ega.
Hamma primitiv turlarga tegishli barcha mahalliy o'zgaruvchilar (boolean, byte, short, char, int, long, float, double) to'liq oqim stekida saqlanadi va boshqa oqimlarga ko'rinmaydi. Bitta oqim bir primitiv o'zgaruvchining nusxasini boshqa oqimga o'tkazishi mumkin, lekin u primitiv mahalliy o'zgaruvchini qo'shma foydalanishga olib kelolmaydi.
Kucha (heap)
Kucha ilovangizda yaratilgan barcha ob'ektlarni o'z ichiga oladi, qaysi oqim ob'ektni yaratganligini hisobga olmasdan. Bunga primitiv turlarning o'rash moslamalari ham kiradi (masalan, Byte, Integer, Long va hokazo). Ob'ekt mahalliy o'zgaruvchi sifatida yaratilgan yoki boshqa ob'ektning a'zovari sifatida yaratilganmi, muhim emas, u kuchada saqlanadi.
Quyida chaqiruv steki va mahalliy o'zgaruvchilarni (ular steklarda saqlanadi), shuningdek, ob'ektlar (ular kuchada saqlanadi) iltimos qiluvchi diagramma:
Agar mahalliy o'zgaruvchi primitiv turga ega bo'lsa, u oqim stekida saqlanadi.
Mahalliy o'zgaruvchi, shuningdek, ob'ektga ishora qilishi mumkin. Bu holatda ishora (mahalliy o'zgaruvchi) oqim stekida saqlanadi, lekin ob'ektning o'zi kuchada saqlanadi.
Ob'ekt metodlarni o'z ichiga oladi, bu metodlar esa mahalliy o'zgaruvchilarni o'z ichiga oladi. Ushbu mahalliy o'zgaruvchilar ham oqim stekida, hatto metodning ob'ekti kuchada saqlanayotgan bo'lsa ham, saqlanadi.
Ob'ektning a'zo o'zgaruvchilari ob'ektning o'ziga qo'shib kuchada saqlanadi. Bu, agar a'zo o'zgaruvchi primitiv turga ega bo'lsa ham, ob'ektga ishora qiluvchi bo'lsa ham, to'g'ri.
Sinfning statik o'zgaruvchilari ham sinfni aniqlash bilan birga kuchada saqlanadi.
Ob'ektlar bilan o'zaro ta'sir
Kuchadagi ob'ektlarga ularga ishora qiladigan barcha oqimlar murojaat qilishi mumkin. Agar oqim ob'ektga kirish imkoniga ega bo'lsa, u ob'ektning o'zgaruvchilariga ham kirish imkoniga ega. Agar ikki oqim bir vaqtning o'zida bir xil ob'ekt uchun metodni chaqirsa, ularning ikkalasi ham ob'ektning a'zo o'zgaruvchilariga kirish imkoniga ega bo'ladi, lekin har bir oqim o'z mahalliy o'zgaruvchilar nusxasiga ega bo'ladi.
Ikki oqim mahalliy o'zgaruvchilar to'plamiga ega. Local Variable 2 kuchada umumiy ob'ektga (Object 3) ishora qiladi. Har bir oqim o'z isora nusxasiga ega. Ularning ishoralari mahalliy o'zgaruvchilar sifatida steklarda saqlanadi. Shunga qaramay, ikki xil ishora kuchadagi bir xil ob'ektga ishora qiladi.
E'tibor bering, umumiy Object 3 o'zining a'zo o'zgaruvchilari sifatida Object 2 va Object 4 ga ishora qiladi (strelkalar orqali ko'rsatilgan). Bu ishoralar orqali ikki oqim Object 2 va Object 4 ga kirish imkoniga ega bo'lishi mumkin.
Diagrammada shuningdek, lokal o'zgaruvchi (Local variable 1 ichida methodTwo) ko'rsatilgan. Uning har bir nusxasi turli ishoralarni o'z ichiga oladi, bu esa ikki xil ob'ektga (Object 1 va Object 5) ishora qiladi, bir xil emas. Nazariy jihatdan, ikki oqim ham Object 1 va Object 5 ga ishora qiluvchi ishoralarga ega bo'lsa, har ikkala ob'ektga ham kirish imkoniga ega bo'lishi mumkin. Ammo yuqoridagi diagrammada har bir oqim faqat ikki ob'ektdan biriga ishora qiladi.
Ob'ektlar bilan o'zaro ta'sirning misoli
Kodda qanday qilib ishlashni ko'rsatishimiz mumkinligini ko'rib chiqaylik:
public class MySomeRunnable implements Runnable() {
public void run() {
one();
}
public void one() {
int localOne = 1;
Shared localTwo = Shared.instance;
//… mahalliy o'zgaruvchilar bilan nimadir qilamiz
two();
}
public void two() {
Integer localOne = 2;
//… mahalliy o'zgaruvchilar bilan nimadir qilamiz
}
}
public class Shared {
// ob'ektimizga instansni saqlaymiz
public static final Shared instance = new Shared();
// kuchada ikki ob'ektga ishora qiluvchi a'zo o'zgaruvchilar
public Integer object2 = new Integer(22);
public Integer object4 = new Integer(44);
}
run() metodi one() metodni chaqiradi va one() o'z navbatida two() ni chaqiradi.
one() metodi primitiv mahalliy o'zgaruvchi (localOne) turidagi int va mahalliy o'zgaruvchi (localTwo) ni, ob'ektga ishora qiladi, e'lon qiladi.
Metodni bajarayotgan har bir oqim o'z stekida localOne va localTwo ning o'z nusxasini yaratadi. localOne o'zgaruvchilari bir-biridan to'liq ajratilgan bo'ladi, ular har bir oqimning stekida bo'lganligi sababli. Bir oqim boshqa oqimning localOne nusxasida qanday o'zgarishlar qilishini ko'ra olmaydi.
Metodni bajarayotgan har bir oqim shuningdek, localTwo ning o'z nusxasini yaratadi. Ammo, oxir-oqibat ikki xil localTwo nusxasi bir xil ob'ektga kuchada ishora qiladi. Buning sababi, localTwo statik o'zgaruvchiga ishora qiladi instance. Statik o'zgaruvchining faqat bitta nusxasi mavjud va bu nusxa kuchada saqlanadi.
Shunday qilib, oxir-oqibat ikkala localTwo nusxasi bir xil Shared instansiga ishora qiladi. Shared instans ham kuchada saqlanadi. Bu yuqoridagi diagrammada Object 3 ga mos keladi.
Shuni e'tiborga olingki, Shared sinfi ikki a'zo o'zgaruvchilarni ham o'z ichiga oladi. A'zo o'zgaruvchilarni o'zlari ob'ekt bilan birga kuchada saqlanadi. Ikki a'zo o'zgaruvchilar ikki boshqa Integer ob'ektga ishora qiladi. Bu butun sonli ob'ektlar yuqoridagi diagrammada Object 2 va Object 4 ga mos keladi.
Shuni ham e'tiborga olingki, two() metodi localOne nomli mahalliy o'zgaruvchini yaratadi. Ushbu mahalliy o'zgaruvchi Integer turidagi ob'ektga ishora qiladi. Metod localOne ishorasini yangi Integer nusxasiga ko'rsatishga o'rnatadi. Ishora har bir oqimning localOne nusxasida saqlanadi. Ikki Integer nusxasi kuchada saqlanadi va metod har safar yangi Integer ob'ektini yaratadiganligi sababli, ushbu metodni bajarayotgan ikki oqim alohida Integer nusxalarini yaratadi. Bu yuqoridagi diagrammada Object 1 va Object 5 ga mos keladi.
Shuningdek, Shared sinfida Integer turidagi uchta a'zo o'zgaruvchilarning ikkitasiga e'tibor bering, bu primitiv turga ega. Ushbu o'zgaruvchilar a'zo o'zgaruvchilar bo'lganligi sababli, ular hali ham ob'ekt bilan birga kuchada saqlanadi. Faqat mahalliy o'zgaruvchilar oqim stekida saqlanadi.
GO TO FULL VERSION