JVM internals

30.06.2026 | Muallif: Jaxongir a.k.a | Kategoriya: JVM & Performance | 27 daqiqa o'qish

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;

  • OutOfMemoryError chiqadi;

  • 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 code

Masalan:

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello JVM");
    }
}

Compile qilinganda:

javac Main.java

Natija:

Main.class

Keyin:

java Main

JVM 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 Collector

Asosiy qismlar:

Qism

Vazifasi

ClassLoader

.class fayllarni yuklaydi

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 -> Heap

Sodda 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:

StackOverflowError

Sabab: 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 space

7. Heap Structure

Heap odatda bir nechta qismga bo‘linadi:

Heap
 ├── Young Generation
 │    ├── Eden
 │    ├── Survivor S0
 │    └── Survivor S1
 │
 └── Old Generation

Young 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() -> Eden

Ko‘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 S1

Object 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 GC

Odatda tezroq ishlaydi.


Major GC / Full GC

Old Generation ham tekshiriladi.

Old Generation to‘ldi -> Major/Full GC

Bu 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 etdi

Agar 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:+UseSerialGC

Parallel GC

Bir nechta thread bilan GC qiladi. Throughput muhim bo‘lgan joylarda ishlatiladi.

-XX:+UseParallelGC

G1 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:+UseG1GC

ZGC

Past latency uchun. Katta heaplarda ham pause vaqtini kichik ushlashga harakat qiladi.

-XX:+UseZGC

Shenandoah

Past pause time maqsad qilgan GC. ZGCga o‘xshash yo‘nalish.

-XX:+UseShenandoahGC

13. 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.class

JVM 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 ClassLoader

Agar 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:

ClassNotFoundException

NoClassDefFoundError

Compile vaqtida class bor edi, lekin runtime’da yo‘q.

Masalan, dependency build vaqtida bor, serverda esa yo‘q.

NoClassDefFoundError

Farqi:

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:

  1. Interpreter

  2. 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 code

Shuning 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 yoziladi

Yechim:

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); // true

Sabab: string literal’lar String Pool’da saqlanadi.

Lekin:

String c = new String("hello");

System.out.println(a == c); // false

Bu yangi object yaratadi.


intern()

String c = new String("hello").intern();

System.out.println(a == c); // true

intern() 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: Metaspace

chiqishi mumkin.


23. JVM monitoring uchun kerakli toollar

Java developer kamida nomlarini va qachon ishlatilishini bilishi kerak.

Tool

Vazifasi

jps

Java processlarni ko‘rish

jstack

Thread dump olish

jmap

Heap dump olish

jcmd

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.print

25. 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,tags

Bu 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.jar

Muhim flaglar

Flag

Ma’nosi

-Xms

Boshlang‘ich heap size

-Xmx

Maksimal heap size

-XX:+UseG1GC

G1 GC ishlatish

-XX:+UseZGC

ZGC ishlatish

-Xlog:gc*

GC log yoqish

-XX:+HeapDumpOnOutOfMemoryError

OOM bo‘lsa heap dump olish

Misol:

java \
  -Xms512m \
  -Xmx1024m \
  -XX:+UseG1GC \
  -XX:+HeapDumpOnOutOfMemoryError \
  -Xlog:gc*:file=gc.log \
  -jar app.jar

28. 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?

  1. DB juda ko‘p data qaytaradi.

  2. Hibernate juda ko‘p entity yaratadi.

  3. Heap to‘ladi.

  4. GC tez-tez ishlaydi.

  5. Response sekinlashadi.

  6. Oxiri OutOfMemoryError chiqishi 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:

  • Stack va Heap farqi;

  • object heap’da qanday yashashi;

  • GC objectni qanday aniqlashi;

  • Young/Old generation;

  • Minor GC va Full GC;

  • G1 GC nima;

  • OutOfMemoryError sabablarini;

  • 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 OomDemo

3-mashq: GC log yoqib ko‘r

java -Xmx128m -Xlog:gc* OomDemo

GC qanday ishlayotganini terminalda ko‘ramiz.


4-mashq: Thread dump olish

Java app ishlayotganda process ID top:

jps

Keyin:

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 tools

Bu mavzuni yaxshi bilsak, production’da sekinlik, memory leak, GC pause, OutOfMemoryError, thread qotishi kabi muammolarni ancha yaxshi tahlil qila olamiz.