JVM internals — Java dastur ichkarida qanday ishlashini tushunish. Java developer uchun bu mavzu juda muhim, chunki production’da muammolar ko‘pincha shulardan chiqadi:
memory ko‘payib ketadi;
GC ko‘p ishlaydi;
app sekinlashadi;
OutOfMemoryErrorchiqadi;threadlar qotib qoladi;
CPU oshib ketadi;
class loading yoki dependency muammolari bo‘ladi.
Maqolada JVM internals ichida quyidagilar bor: Heap structure, GC algorithms, ClassLoader, JIT compilation, Java Memory Model, Stack vs Heap allocation.
1. JVM nima?
JVM — Java Virtual Machine.
Java kodi to‘g‘ridan-to‘g‘ri kompyuter processorida ishlamaydi. Avval .java fayl .class bytecode’ga compile bo‘ladi.
Main.java -> Main.class -> JVM -> Machine codeMasalan:
public class Main {
public static void main(String[] args) {
System.out.println("Hello JVM");
}
}Compile qilinganda:
javac Main.javaNatija:
Main.classKeyin:
java MainJVM shu .class faylni o‘qib ishga tushiradi.
2. JVM ichida asosiy qismlar
JVMni soddalashtirib shunday tasavvur qil:
Java Code
↓
Bytecode
↓
ClassLoader
↓
Runtime Data Areas
↓
Execution Engine
↓
Garbage CollectorAsosiy qismlar:
Qism | Vazifasi |
|---|---|
ClassLoader |
|
Runtime Data Areas | Memory joylari |
Execution Engine | Bytecode’ni bajaradi |
JIT Compiler | Tez-tez ishlatiladigan kodni optimizatsiya qiladi |
Garbage Collector | Keraksiz objectlarni tozalaydi |
3. Stack va Heap
Bu JVM internals’ning eng asosiy joyi.
Stack nima?
Stack — method chaqiruvlari va local variable’lar saqlanadigan joy.
Har bir thread’ning o‘z stack’i bo‘ladi.
public void test() {
int age = 25;
String name = "Ali";
}Bu yerda:
int age = 25;age stack’da turadi.
Lekin:
String name = "Ali";name reference stack’da, "Ali" object/string pool tarafda bo‘ladi.
Heap nima?
Heap — objectlar saqlanadigan umumiy memory joyi.
User user = new User("Ali");Bu yerda:
user reference -> Stack
new User("Ali") object -> HeapSodda ko‘rinish:
Stack:
user ─────────────┐
↓
Heap:
User{name="Ali"}4. Stack vs Heap farqi
Stack | Heap |
|---|---|
Har bir thread uchun alohida | Barcha threadlar uchun umumiy |
Method chaqiruvlari saqlanadi | Objectlar saqlanadi |
Tez ishlaydi | Nisbatan murakkabroq |
Method tugasa tozalanadi | GC tozalaydi |
StackOverflowError chiqishi mumkin | OutOfMemoryError chiqishi mumkin |
5. StackOverflowError
Agar method o‘zini tinmasdan chaqirsa, stack to‘lib ketadi.
public class Main {
public static void main(String[] args) {
call();
}
static void call() {
call();
}
}Natija:
StackOverflowErrorSabab: har bir call() uchun stack’da yangi frame ochiladi. U hech qachon tugamaydi.
6. OutOfMemoryError
Heap to‘lib ketsa, OutOfMemoryError chiqadi.
List<byte[]> list = new ArrayList<>();
while (true) {
list.add(new byte[1024 * 1024]);
}Bu kod har safar 1 MB array yaratadi va list ichida saqlaydi. GC ularni tozalay olmaydi, chunki list hali ham reference ushlab turibdi.
Natija:
java.lang.OutOfMemoryError: Java heap space7. Heap Structure
Heap odatda bir nechta qismga bo‘linadi:
Heap
├── Young Generation
│ ├── Eden
│ ├── Survivor S0
│ └── Survivor S1
│
└── Old GenerationYoung Generation
Yangi objectlar avval Young Generation’ga tushadi.
User user = new User();Bu object odatda avval Eden ga joylashadi.
Eden Space
Yangi objectlarning boshlang‘ich joyi.
new Object() -> EdenKo‘p objectlar qisqa yashaydi. Masalan:
public String buildMessage(String name) {
return "Hello " + name;
}Bu yerda vaqtinchalik objectlar yaratilishi mumkin. Ular method tugagach kerak bo‘lmaydi.
Survivor Space
GC’dan omon qolgan objectlar Survivor joyiga o‘tadi.
Eden -> Survivor S0 -> Survivor S1Object bir nechta GC’dan keyin ham yashasa, Old Generation’ga o‘tadi.
Old Generation
Uzoq yashaydigan objectlar shu yerda saqlanadi.
Masalan:
Spring singleton beanlar;
cache objectlar;
connection pool objectlari;
application config;
uzoq yashaydigan collectionlar.
@Service
public class UserService {
}Spring bean odatda application ishlagancha yashaydi.
8. Garbage Collector nima?
Garbage Collector — ishlatilmayotgan objectlarni heap’dan tozalaydigan mexanizm.
Java’da biz odatda memory’ni qo‘lda o‘chirmaymiz.
C/C++ da:
free(pointer);Java’da esa:
user = null;Lekin null qilishning o‘zi objectni darhol o‘chirmaydi. Faqat objectga reference qolmasa, GC keyinroq uni tozalashi mumkin.
9. Object qachon garbage bo‘ladi?
Agar objectga hech qanday reachable reference bo‘lmasa.
User user = new User("Ali");
user = null;Endi new User("Ali") objectiga reference yo‘q. U GC uchun candidate bo‘ladi.
Reachability tushunchasi
GC rootlardan boshlab objectlarni tekshiradi.
GC roots:
thread stackdagi local variable’lar;
static fieldlar;
JNI reference’lar;
active threadlar;
system classlar.
Agar object GC rootdan yetib boriladigan bo‘lsa, u tirik hisoblanadi.
10. Minor GC va Major GC
Minor GC
Young Generation tozalanadi.
Eden to‘ldi -> Minor GCOdatda tezroq ishlaydi.
Major GC / Full GC
Old Generation ham tekshiriladi.
Old Generation to‘ldi -> Major/Full GCBu og‘irroq bo‘lishi mumkin. Ba’zida application pause seziladi.
11. Stop-The-World nima?
GC ishlaganda ba’zi bosqichlarda application threadlari to‘xtatiladi.
Bunga Stop-The-World pause deyiladi.
App ishlayapti
↓
GC boshlandi
↓
App threadlari vaqtincha to‘xtadi
↓
GC tugadi
↓
App davom etdiAgar pause uzun bo‘lsa, foydalanuvchi requesti sekinlashadi.
12. GC algoritmlari
Java developer hech bo‘lmasa asosiy GC turlarini tanishi kerak.
Serial GC
Bitta thread bilan GC qiladi. Kichik app yoki test uchun.
-XX:+UseSerialGCParallel GC
Bir nechta thread bilan GC qiladi. Throughput muhim bo‘lgan joylarda ishlatiladi.
-XX:+UseParallelGCG1 GC
Ko‘p server applicationlarda default va keng ishlatiladigan GC.
G1 heap’ni regionlarga bo‘ladi:
Heap:
[Region][Region][Region][Region]Maqsad: pause vaqtini nazorat qilish va katta heap bilan yaxshiroq ishlash.
-XX:+UseG1GCZGC
Past latency uchun. Katta heaplarda ham pause vaqtini kichik ushlashga harakat qiladi.
-XX:+UseZGCShenandoah
Past pause time maqsad qilgan GC. ZGCga o‘xshash yo‘nalish.
-XX:+UseShenandoahGC13. Qaysi GC qachon?
Vaziyat | GC |
|---|---|
Kichik CLI app | Serial GC |
Throughput muhim batch job | Parallel GC |
Oddiy Spring Boot backend | G1 GC |
Past latency muhim service | ZGC yoki Shenandoah |
Katta heap, kam pause kerak | ZGC |
Ko‘p Spring Boot backendlar uchun default GC yetarli bo‘ladi. Avval profiling qilmasdan GC flaglarni ko‘r-ko‘rona o‘zgartirish yaxshi emas.
14. Memory leak Java’da bo‘ladimi?
Ha, Java’da ham memory leak bo‘ladi.
Memory leak — kerak bo‘lmagan objectga hali ham reference bor, shuning uchun GC uni tozalay olmaydi.
Misol: static list
public class MemoryLeakExample {
private static final List<byte[]> cache = new ArrayList<>();
public void add() {
cache.add(new byte[1024 * 1024]);
}
}Bu list tozalanmasa, heap to‘lib boradi.
Misol: noto‘g‘ri cache
Map<Long, User> cache = new HashMap<>();Agar cache’da TTL, limit, eviction bo‘lmasa, u memory leakga aylanadi.
Yaxshiroq:
Caffeine;
Redis;
Ehcache;
TTL;
max size;
eviction policy.
Misol: ThreadLocal leak
threadLocal.set(user);Agar thread pool ishlatilsa va remove() qilinmasa, eski data thread ichida qolib ketishi mumkin.
Yaxshi:
try {
threadLocal.set(user);
// logic
} finally {
threadLocal.remove();
}15. ClassLoader nima?
ClassLoader — .class fayllarni JVM ichiga yuklaydigan mexanizm.
Masalan:
UserService.class
OrderController.class
PaymentClient.classJVM bu classlarni kerak bo‘lganda yuklaydi.
ClassLoader turlari
ClassLoader | Vazifasi |
|---|---|
Bootstrap ClassLoader | Java core classlari |
Platform ClassLoader | Platform librarylar |
Application ClassLoader | App classpath’dagi classlar |
Custom ClassLoader | Framework yoki container ishlatishi mumkin |
Parent Delegation Model
Class yuklashda avval parentdan so‘raladi.
Application ClassLoader
↓ asks parent
Platform ClassLoader
↓ asks parent
Bootstrap ClassLoaderAgar parent topmasa, child o‘zi yuklaydi.
Bu xavfsizlik va class conflictlarni kamaytirish uchun kerak.
16. ClassNotFoundException vs NoClassDefFoundError
Bu interview’da ko‘p so‘raladi.
ClassNotFoundException
Class runtime’da qidirildi, lekin topilmadi.
Masalan:
Class.forName("com.example.User");Agar class yo‘q bo‘lsa:
ClassNotFoundExceptionNoClassDefFoundError
Compile vaqtida class bor edi, lekin runtime’da yo‘q.
Masalan, dependency build vaqtida bor, serverda esa yo‘q.
NoClassDefFoundErrorFarqi:
Xato | Ma’nosi |
|---|---|
ClassNotFoundException | Dynamic loading paytida class topilmadi |
NoClassDefFoundError | Class avval bor deb hisoblangan, runtime’da yo‘q |
17. Execution Engine
JVM bytecode’ni bajaradi.
Bunda ikki asosiy yo‘l bor:
Interpreter
JIT Compiler
Interpreter
Bytecode’ni qatorma-qator o‘qib bajaradi.
Afzalligi:
tez start bo‘ladi;
kodni darhol bajaradi.
Kamchiligi:
uzoq ishlaydigan kod uchun sekinroq.
JIT Compiler
JIT — Just-In-Time compiler.
Tez-tez ishlatiladigan bytecode’ni machine code’ga aylantiradi.
Bytecode -> Hot code detected -> Native machine codeShuning uchun Java app ba’zida ishga tushgandan keyin asta-sekin tezlashadi. JVM hot methodlarni aniqlab optimizatsiya qiladi.
18. HotSpot nima?
HotSpot — JVM implementation nomi. U tez-tez ishlatiladigan kodni topib, optimizatsiya qiladi.
Masalan, bir method million marta chaqirilsa, JVM uni “hot method” deb hisoblaydi.
for (int i = 0; i < 1_000_000; i++) {
calculate(i);
}calculate() hot bo‘lishi mumkin.
19. JIT optimizatsiyalari
JIT ko‘p optimizatsiya qiladi.
Method inlining
Kichik methodlarni chaqirish o‘rniga ichiga joylashtiradi.
int sum(int a, int b) {
return a + b;
}Ko‘p chaqirilsa, JVM uni inline qilishi mumkin.
Dead code elimination
Keraksiz kodni olib tashlaydi.
int x = 10;
int y = 20;Agar x va y ishlatilmasa, JVM optimizatsiya qilishi mumkin.
Escape analysis
Agar object methoddan tashqariga chiqmasa, JVM uni heapga qo‘ymasligi ham mumkin.
public int calculate() {
Point p = new Point(1, 2);
return p.x() + p.y();
}Agar p tashqariga chiqmasa, JVM allocationni optimizatsiya qilishi mumkin.
20. Java Memory Model
Java Memory Model — threadlar memory bilan qanday ishlashini belgilaydigan qoida.
Bu ayniqsa concurrency uchun kerak.
Asosiy tushunchalar:
visibility;
atomicity;
ordering;
happens-before.
Visibility
Bir thread yozgan qiymatni boshqa thread ko‘rishi kerak.
Muammo:
class Worker {
private boolean running = true;
void stop() {
running = false;
}
void work() {
while (running) {
// ishlayveradi
}
}
}Bitta thread stop() qilsa ham, boshqa thread running eski qiymatini ko‘rib turishi mumkin.
Yechim:
private volatile boolean running = true;Atomicity
Bitta operation bo‘linmas bajarilishi.
Bu atomic emas:
count++;Aslida:
1. count o‘qiladi
2. 1 qo‘shiladi
3. qayta yoziladiYechim:
AtomicInteger counter = new AtomicInteger();
counter.incrementAndGet();Ordering
JVM va CPU performance uchun instruction tartibini o‘zgartirishi mumkin.
Masalan, koddagi tartib:
a = 1;
b = 2;Ichkarida optimizatsiya sabab boshqa tartibda bajarilishi mumkin, agar natija bitta thread uchun o‘zgarmasa.
Concurrency’da bu muammo berishi mumkin.
Happens-before
Bir operation boshqasidan oldin ko‘rinishi kafolatlanadi.
Masalan:
synchronized
volatile write/read
Thread.start()
Thread.join()bular happens-before relation yaratishi mumkin.
21. String Pool
Stringlar Java’da alohida e’tiborli.
String a = "hello";
String b = "hello";
System.out.println(a == b); // trueSabab: string literal’lar String Pool’da saqlanadi.
Lekin:
String c = new String("hello");
System.out.println(a == c); // falseBu yangi object yaratadi.
intern()
String c = new String("hello").intern();
System.out.println(a == c); // trueintern() string pool’dagi versiyani qaytaradi.
Real loyihada intern()ni ehtiyotkorlik bilan ishlatish kerak.
22. Metaspace
Oldin Java 8’dan avval PermGen bor edi. Hozir Metaspace ishlatiladi.
Metaspace’da class metadata saqlanadi:
class nomi;
method metadata;
field metadata;
annotation metadata;
runtime class information.
Agar juda ko‘p class yuklansa yoki ClassLoader leak bo‘lsa:
OutOfMemoryError: Metaspacechiqishi mumkin.
23. JVM monitoring uchun kerakli toollar
Java developer kamida nomlarini va qachon ishlatilishini bilishi kerak.
Tool | Vazifasi |
|---|---|
| Java processlarni ko‘rish |
| Thread dump olish |
| Heap dump olish |
| JVM diagnostic komandalar |
VisualVM | GUI orqali monitoring |
Java Flight Recorder | Production profiling |
Mission Control | JFR analiz |
Async Profiler | CPU/allocation profiling |
24. Thread dump nima?
Thread dump — JVM ichidagi barcha threadlarning hozirgi holati.
Qachon kerak?
app qotib qoldi;
CPU oshib ketdi;
deadlock bor;
requestlar javob bermayapti.
Command:
jstack <pid>Yoki:
jcmd <pid> Thread.print25. Heap dump nima?
Heap dump — memorydagi objectlarning snapshot’i.
Qachon kerak?
memory leak;
OutOfMemoryError;
heap doim o‘sib boryapti;
cache haddan tashqari kattalashgan.
Command:
jmap -dump:live,format=b,file=heap.hprof <pid>Keyin analiz qilish uchun:
Eclipse MAT;
VisualVM;
IntelliJ profiler;
YourKit.
26. GC log nima?
GC log — Garbage Collector qachon, qancha ishlaganini ko‘rsatadi.
Java 9+:
-Xlog:gc*:file=gc.log:time,uptime,level,tagsBu orqali bilamiz:
GC tez-tez ishlayaptimi;
pause qancha;
heap tozalanayaptimi;
old gen to‘lib boryaptimi.
27. JVM flags
Spring Boot app ishga tushirishda JVM flaglar berish mumkin.
java -Xms512m -Xmx1024m -jar app.jarMuhim flaglar
Flag | Ma’nosi |
|---|---|
| Boshlang‘ich heap size |
| Maksimal heap size |
| G1 GC ishlatish |
| ZGC ishlatish |
| GC log yoqish |
| OOM bo‘lsa heap dump olish |
Misol:
java \
-Xms512m \
-Xmx1024m \
-XX:+UseG1GC \
-XX:+HeapDumpOnOutOfMemoryError \
-Xlog:gc*:file=gc.log \
-jar app.jar28. Spring Boot va JVM
Spring Boot app ishga tushganda juda ko‘p class yuklanadi:
Controllerlar;
Servicelar;
Repositorylar;
Configuration classlar;
Annotation metadata;
Proxy classlar;
Hibernate entitylar;
Validation classlar;
Security filterlar.
Shuning uchun Spring Boot app’da:
startup time;
memory usage;
class loading;
proxy creation;
reflection;
annotation scanning;
JVM bilan bog‘liq bo‘ladi.
29. Real production muammo misoli
Tasavvur qil:
@GetMapping("/users")
public List<User> getUsers() {
return userRepository.findAll();
}Agar jadvalda 1 million user bo‘lsa, bu katta muammo.
Nima bo‘ladi?
DB juda ko‘p data qaytaradi.
Hibernate juda ko‘p entity yaratadi.
Heap to‘ladi.
GC tez-tez ishlaydi.
Response sekinlashadi.
Oxiri
OutOfMemoryErrorchiqishi mumkin.
Yaxshi yechim:
@GetMapping("/users")
public Page<UserDto> getUsers(Pageable pageable) {
return userRepository.findAll(pageable)
.map(UserDto::from);
}Yana yaxshiroq:
DTO projection;
pagination;
limit;
index;
streaming ehtiyotkorlik bilan;
keyset pagination.
30. Real production muammo: memory leak cache
Yomon:
@Component
public class ProductCache {
private final Map<Long, Product> cache = new HashMap<>();
public Product get(Long id) {
return cache.computeIfAbsent(id, this::loadFromDb);
}
}Bu cache hech qachon tozalanmaydi.
Yaxshiroq:
Cache<Long, Product> cache = Caffeine.newBuilder()
.maximumSize(10_000)
.expireAfterWrite(Duration.ofMinutes(30))
.build();Cache’da doim:
maximum size;
TTL;
invalidation;
monitoring;
bo‘lishi kerak.
31. JVM Internals bo‘yicha interview savollari
JVM, JRE, JDK farqi nima?
Tushuncha | Ma’nosi |
|---|---|
JVM | Java bytecode’ni ishlatadi |
JRE | JVM + runtime library |
JDK | JRE + compiler + dev tools |
Stack va Heap farqi?
Stack method call va local variable uchun.
Heap objectlar uchun.
Object qachon GC bo‘ladi?
Agar unga GC roots orqali yetib bo‘lmasa.
Minor GC nima?
Young Generation tozalanganda Minor GC deyiladi.
Full GC nima?
Heapning katta qismi, jumladan Old Generation tekshirilganda Full GC deyiladi.
JIT nima?
Tez-tez ishlatiladigan bytecode’ni native machine code’ga compile qiladigan mexanizm.
ClassLoader nima qiladi?
.class fayllarni JVM ichiga yuklaydi.
Memory leak Java’da qanday bo‘ladi?
Object kerak emas, lekin unga reference hali ham bor. Shuning uchun GC uni tozalay olmaydi.
OutOfMemoryError va StackOverflowError farqi?
Xato | Sabab |
|---|---|
OutOfMemoryError | Heap yoki boshqa memory joyi to‘ldi |
StackOverflowError | Stack chuqur method call bilan to‘ldi |
volatile JVM bilan qanday bog‘liq?
volatile Java Memory Model’da visibility va ordering kafolatlarini beradi.
32. Java Developer uchun minimal checklist
JVM internals bo‘yicha biz quyidagilarni bilishing kerak:
StackvaHeapfarqi;object heap’da qanday yashashi;
GC objectni qanday aniqlashi;
Young/Old generation;
Minor GC va Full GC;
G1 GC nima;
OutOfMemoryErrorsabablarini;memory leak misollarini;
ClassLoader ishlashini;
JIT nima qilishini;
Java Memory Model asoslarini;
jstack,jmap,jcmd, VisualVM, JFR nima uchun kerakligini;Spring Boot app memory bilan qanday ishlashini.
33. Amaliy mashqlar
1-mashq: StackOverflowError chiqarib ko‘ring
public class StackOverflowDemo {
public static void main(String[] args) {
recursive();
}
static void recursive() {
recursive();
}
}2-mashq: OutOfMemoryError chiqarib ko‘ring
import java.util.ArrayList;
import java.util.List;
public class OomDemo {
public static void main(String[] args) {
List<byte[]> list = new ArrayList<>();
while (true) {
list.add(new byte[1024 * 1024]);
}
}
}Kichik heap bilan ishga tushiring:
java -Xmx64m OomDemo3-mashq: GC log yoqib ko‘r
java -Xmx128m -Xlog:gc* OomDemoGC qanday ishlayotganini terminalda ko‘ramiz.
4-mashq: Thread dump olish
Java app ishlayotganda process ID top:
jpsKeyin:
jstack <pid>5-mashq: Heap dump olish
jmap -dump:live,format=b,file=heap.hprof <pid>Keyin VisualVM yoki Eclipse MAT bilan ochib ko‘ring.
Qisqa xulosa
JVM internals — Java’ni “ichidan tushunish” degani.
Eng muhim joylari:
Stack vs Heap
GC
JIT
ClassLoader
Java Memory Model
Memory leak
JVM monitoring toolsBu mavzuni yaxshi bilsak, production’da sekinlik, memory leak, GC pause, OutOfMemoryError, thread qotishi kabi muammolarni ancha yaxshi tahlil qila olamiz.