JVM 内存区域划分与垃圾回收机制详解

简介: 本文深入解析JVM内存区域划分与垃圾回收机制,涵盖程序计数器、虚拟机栈、堆、方法区等核心结构,详解对象生命周期、分代收集、GC算法及主流收集器(如G1、ZGC、Shenandoah),并提供调优实践建议,助力开发者掌握Java性能优化核心技能。

JVM 内存区域划分与垃圾回收机制详解

引言

Java虚拟机(JVM)是Java程序运行的核心环境,其内存管理和垃圾回收机制直接影响着应用程序的性能和稳定性。深入理解JVM内存区域划分和垃圾回收机制,对于编写高性能Java程序、进行内存调优、解决内存泄漏问题具有重要意义。

JVM内存区域划分

程序计数器(Program Counter Register)

程序计数器是JVM内存中最小的内存区域,用于记录当前线程执行的字节码指令地址。

// 程序计数器相关概念演示
public class ProgramCounterExample {
   

    // 模拟字节码执行过程
    public static void executeBytecode() {
   
        int a = 1;  // 程序计数器指向这行指令
        int b = 2;  // 程序计数器递增,指向下一行
        int c = a + b;  // 程序计数器继续递增
        System.out.println(c);
    }

    // 线程切换时程序计数器的保存与恢复
    public static void threadSwitching() {
   
        Thread thread1 = new Thread(() -> {
   
            // 每个线程都有独立的程序计数器
            for (int i = 0; i < 100; i++) {
   
                System.out.println("Thread 1: " + i);
                try {
   
                    Thread.sleep(10);
                } catch (InterruptedException e) {
   
                    Thread.currentThread().interrupt();
                }
            }
        });

        Thread thread2 = new Thread(() -> {
   
            // 每个线程的程序计数器独立记录执行位置
            for (int i = 0; i < 100; i++) {
   
                System.out.println("Thread 2: " + i);
                try {
   
                    Thread.sleep(10);
                } catch (InterruptedException e) {
   
                    Thread.currentThread().interrupt();
                }
            }
        });

        thread1.start();
        thread2.start();
    }

    // 程序计数器的唯一无内存溢出区域
    public static void noOutOfMemory() {
   
        // 程序计数器不会发生OutOfMemoryError
        // 因为它只存储当前线程执行的字节码地址
        // 每个线程的程序计数器大小固定
    }
}

虚拟机栈(Java Virtual Machine Stacks)

虚拟机栈描述的是Java方法执行的内存模型,每个方法执行时都会创建一个栈帧。

// 虚拟机栈深度测试
public class VirtualMachineStackExample {
   

    private static int stackDepth = 0;

    // 递归调用测试栈深度
    public static void recursiveCall() {
   
        stackDepth++;
        try {
   
            recursiveCall();
        } catch (StackOverflowError e) {
   
            System.out.println("Maximum stack depth: " + stackDepth);
            System.out.println("Stack overflow occurred: " + e.getMessage());
            throw e;
        }
    }

    // 栈帧结构演示
    public static int calculateSum(int n) {
   
        if (n <= 1) {
   
            return 1; // 栈帧1:返回1
        }
        int result = n + calculateSum(n - 1); // 栈帧2,3,4...
        return result; // 每个栈帧返回计算结果
    }

    // 局部变量表演示
    public static void localVarTable() {
   
        int localVar1 = 10;        // 局部变量表slot 0
        String localVar2 = "test"; // 局部变量表slot 1
        double localVar3 = 3.14;   // 局部变量表slot 2,3 (double占2个slot)

        // 每个方法都有独立的局部变量表
        // 存储方法参数、局部变量等
    }

    // 操作数栈演示
    public static int operationStackDemo() {
   
        int a = 10;    // 加载到操作数栈
        int b = 20;    // 加载到操作数栈
        int c = a + b; // 从操作数栈弹出a,b,计算结果压入栈
        return c;      // 返回值压入操作数栈
    }

    // 动态链接演示
    public static void dynamicLinking() {
   
        // 每个栈帧都包含一个指向运行时常量池的引用
        // 用于支持方法调用过程中的动态链接
        String str = "Hello"; // 常量池引用
        System.out.println(str); // 动态链接到String类的toString方法
    }

    // 方法返回地址
    public static int methodReturnAddress() {
   
        int result = calculateSum(5); // 调用方法
        // 方法执行完毕后,返回到调用处的下一条指令
        return result;
    }
}

本地方法栈(Native Method Stacks)

本地方法栈为虚拟机使用到的Native方法服务。

// 本地方法栈相关概念
public class NativeMethodStackExample {
   

    // 声明本地方法
    public native void nativeMethod();

    // 本地方法调用示例
    public void callNativeMethod() {
   
        // 调用本地方法时,JVM会在本地方法栈中创建栈帧
        nativeMethod();
    }

    // 本地方法栈溢出示例(理论演示)
    public static void nativeStackOverflow() {
   
        // 在实际使用中,本地方法栈也可能出现栈溢出
        // 但这种情况相对较少见
    }

    static {
   
        // 加载本地库
        System.loadLibrary("nativeLibrary");
    }
}

Java堆(Java Heap)

Java堆是JVM管理的内存中最大的一块,所有线程共享,用于存放对象实例。

// Java堆内存管理演示
public class JavaHeapExample {
   

    // 对象分配演示
    public static void objectAllocation() {
   
        // 对象在堆中分配
        String str = new String("Hello World"); // 字符串对象在堆中
        User user = new User("Alice", 25);       // User对象在堆中
        int[] array = new int[1000];             // 数组对象在堆中
    }

    // 堆内存溢出示例
    public static void heapOutOfMemory() {
   
        List<byte[]> list = new ArrayList<>();
        int count = 0;
        try {
   
            while (true) {
   
                // 持续分配大对象,直到堆内存不足
                list.add(new byte[1024 * 1024]); // 每次分配1MB
                count++;
                if (count % 100 == 0) {
   
                    System.out.println("Allocated " + count + " MB");
                }
            }
        } catch (OutOfMemoryError e) {
   
            System.out.println("Heap OutOfMemoryError occurred: " + e.getMessage());
            System.out.println("Allocated approximately: " + count + " MB");
        }
    }

    // 堆内存区域划分
    public static class HeapRegionDemo {
   
        // 新生代(Young Generation)
        // - Eden区:新对象分配区域
        // - Survivor区:Survivor From和Survivor To

        // 老年代(Old Generation)
        // - 存放经过多次GC后仍然存活的对象

        // 永久代/元空间(Permanent Generation/Metaspace)
        // - 存放类信息、常量、静态变量等

        public static void generationalDemo() {
   
            // 大多数对象在Eden区分配
            Object obj1 = new Object(); // 分配在Eden区

            // 经过一次Minor GC后,存活对象进入Survivor区
            // 经过多次GC后,进入老年代
        }
    }

    // 大对象直接进入老年代
    public static void largeObjectAllocation() {
   
        // 大对象(如大数组)可能直接分配到老年代
        // 以避免在新生代之间频繁复制
        byte[] largeArray = new byte[2 * 1024 * 1024]; // 2MB大数组
    }

    // 对象年龄计数器
    public static void objectAgeCounter() {
   
        // 每次Minor GC后,对象年龄+1
        // 当年龄达到阈值(默认15)时,进入老年代
        Object obj = new Object();
        // 经过15次GC后,obj可能进入老年代
    }
}

// 示例用户类
class User {
   
    private String name;
    private int age;

    public User(String name, int age) {
   
        this.name = name;
        this.age = age;
    }

    public String getName() {
    return name; }
    public int getAge() {
    return age; }
}

方法区(Method Area)

方法区用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

// 方法区相关概念演示
public class MethodAreaExample {
   

    // 静态变量存储在方法区
    private static String staticVar = "Static Variable";
    private static final String CONSTANT = "Constant Value";

    // 类信息存储在方法区
    public static class InnerClass {
   
        private String innerField;

        public InnerClass(String innerField) {
   
            this.innerField = innerField;
        }
    }

    // 方法区溢出示例
    public static void methodAreaOutOfMemory() {
   
        // 在JDK 8之前,方法区是永久代,容易出现内存溢出
        // 在JDK 8及以后,方法区被元空间替代

        // 动态生成大量类来测试方法区溢出(需要特殊工具)
        // 例如使用CGLIB动态生成类
    }

    // 运行时常量池演示
    public static void runtimeConstantPool() {
   
        String str1 = "Hello";
        String str2 = "Hello";
        // str1和str2指向常量池中的同一个对象

        String str3 = new String("Hello");
        // str3指向堆中的新对象

        System.out.println(str1 == str2); // true
        System.out.println(str1 == str3); // false
    }

    // 字符串常量池
    public static void stringConstantPool() {
   
        // 字符串常量池是方法区的一部分
        String s1 = "test";
        String s2 = "test";
        String s3 = new String("test");
        String s4 = s3.intern();

        System.out.println(s1 == s2); // true
        System.out.println(s1 == s3); // false
        System.out.println(s1 == s4); // true
    }
}

垃圾回收算法

标记-清除算法(Mark-Sweep)

标记-清除算法是最基础的垃圾收集算法,分为标记和清除两个阶段。

// 标记-清除算法实现
public class MarkSweepGC {
   

    // 模拟对象标记过程
    static class MockObject {
   
        private boolean marked = false;
        private MockObject next;

        public MockObject(MockObject next) {
   
            this.next = next;
        }

        public boolean isMarked() {
    return marked; }
        public void mark() {
    this.marked = true; }
        public void unmark() {
    this.marked = false; }
        public MockObject getNext() {
    return next; }
    }

    private MockObject root; // GC Root

    // 标记阶段
    public void markPhase() {
   
        if (root != null) {
   
            markObject(root);
        }
    }

    private void markObject(MockObject obj) {
   
        if (obj != null && !obj.isMarked()) {
   
            obj.mark();
            // 递归标记引用的对象
            markObject(obj.getNext());
        }
    }

    // 清除阶段
    public void sweepPhase() {
   
        // 遍历堆中的所有对象,清除未标记的对象
        // 实际JVM中会有更复杂的实现
        System.out.println("Sweeping unmarked objects...");
    }

    // 算法特点分析
    public void algorithmCharacteristics() {
   
        System.out.println("标记-清除算法特点:");
        System.out.println("1. 简单易实现");
        System.out.println("2. 效率不高(需要遍历所有对象)");
        System.out.println("3. 会产生内存碎片");
        System.out.println("4. 标记和清除过程都需要暂停程序");
    }
}

复制算法(Copying)

复制算法将内存按容量划分为大小相等的两块,每次只使用其中一块。

// 复制算法实现
public class CopyingGC {
   

    static class MockObject {
   
        private int id;
        private MockObject next;
        private boolean copied = false;

        public MockObject(int id, MockObject next) {
   
            this.id = id;
            this.next = next;
        }

        public int getId() {
    return id; }
        public MockObject getNext() {
    return next; }
        public boolean isCopied() {
    return copied; }
        public void setCopied(boolean copied) {
    this.copied = copied; }
    }

    // 模拟Eden区和Survivor区
    private MockObject[] fromSpace = new MockObject[1000];
    private MockObject[] toSpace = new MockObject[1000];
    private int fromIndex = 0;
    private int toIndex = 0;

    // 复制过程
    public void copyLiveObjects() {
   
        // 从fromSpace复制存活对象到toSpace
        for (int i = 0; i < fromIndex; i++) {
   
            MockObject obj = fromSpace[i];
            if (obj != null && isLiveObject(obj)) {
    // 假设isLiveObject判断对象是否存活
                toSpace[toIndex++] = obj;
                obj.setCopied(true);
            }
        }

        // 交换fromSpace和toSpace
        MockObject[] temp = fromSpace;
        fromSpace = toSpace;
        toSpace = temp;
        fromIndex = toIndex;
        toIndex = 0;

        System.out.println("Copying completed, fromIndex: " + fromIndex);
    }

    // 判断对象是否存活(简化实现)
    private boolean isLiveObject(MockObject obj) {
   
        // 在实际GC中,会通过GC Root可达性分析判断
        return obj.getId() % 2 == 0; // 假设偶数ID的对象存活
    }

    // 算法特点分析
    public void algorithmCharacteristics() {
   
        System.out.println("复制算法特点:");
        System.out.println("1. 实现简单,运行高效");
        System.out.println("2. 不会产生内存碎片");
        System.out.println("3. 需要浪费一半内存空间");
        System.out.println("4. 适合新生代(存活对象少)");
    }

    // 对象分配
    public void allocateObject(int id) {
   
        if (fromIndex < fromSpace.length) {
   
            fromSpace[fromIndex++] = new MockObject(id, null);
        } else {
   
            System.out.println("Eden space full, triggering GC");
            copyLiveObjects();
        }
    }
}

标记-整理算法(Mark-Compact)

标记-整理算法结合了标记-清除和复制算法的优点。

// 标记-整理算法实现
public class MarkCompactGC {
   

    static class MockObject {
   
        private int id;
        private MockObject next;
        private boolean marked = false;
        private int newAddress = -1;

        public MockObject(int id, MockObject next) {
   
            this.id = id;
            this.next = next;
        }

        public int getId() {
    return id; }
        public MockObject getNext() {
    return next; }
        public boolean isMarked() {
    return marked; }
        public void mark() {
    this.marked = true; }
        public int getNewAddress() {
    return newAddress; }
        public void setNewAddress(int address) {
    this.newAddress = address; }
    }

    private MockObject[] heap = new MockObject[1000];
    private int heapSize = 0;

    // 标记阶段
    public void markPhase() {
   
        // 从GC Roots开始标记可达对象
        for (int i = 0; i < heapSize; i++) {
   
            if (heap[i] != null) {
   
                markReachable(heap[i]);
            }
        }
    }

    private void markReachable(MockObject obj) {
   
        if (obj != null && !obj.isMarked()) {
   
            obj.mark();
            // 标记引用的对象
            markReachable(obj.getNext());
        }
    }

    // 整理阶段
    public void compactPhase() {
   
        int toIndex = 0;

        // 将存活对象移动到内存的一端
        for (int i = 0; i < heapSize; i++) {
   
            if (heap[i] != null && heap[i].isMarked()) {
   
                if (toIndex != i) {
   
                    heap[toIndex] = heap[i];
                    heap[i] = null; // 清除原位置
                }
                heap[toIndex].setNewAddress(toIndex);
                toIndex++;
            } else if (heap[i] != null) {
   
                heap[i] = null; // 清除死亡对象
            }
        }

        heapSize = toIndex;
        System.out.println("Compaction completed, heapSize: " + heapSize);
    }

    // 算法特点分析
    public void algorithmCharacteristics() {
   
        System.out.println("标记-整理算法特点:");
        System.out.println("1. 不会产生内存碎片");
        System.out.println("2. 不需要额外的内存空间");
        System.out.println("3. 移动对象需要更新引用");
        System.out.println("4. 适合老年代(存活对象多)");
    }

    // 对象分配
    public void allocateObject(int id) {
   
        if (heapSize < heap.length) {
   
            heap[heapSize++] = new MockObject(id, null);
        }
    }
}

分代收集算法(Generational Collection)

分代收集算法基于对象的存活周期将内存划分为几块,不同区域采用不同的收集算法。

// 分代收集算法实现
public class GenerationalGC {
   

    static class MockObject {
   
        private int id;
        private int age = 0;
        private MockObject next;
        private boolean marked = false;

        public MockObject(int id, MockObject next) {
   
            this.id = id;
            this.next = next;
        }

        public int getId() {
    return id; }
        public int getAge() {
    return age; }
        public void incrementAge() {
    this.age++; }
        public MockObject getNext() {
    return next; }
        public boolean isMarked() {
    return marked; }
        public void mark() {
    this.marked = true; }
    }

    // 新生代:Eden + 2个Survivor
    private MockObject[] eden = new MockObject[100];
    private MockObject[] survivorFrom = new MockObject[50];
    private MockObject[] survivorTo = new MockObject[50];

    // 老年代
    private MockObject[] oldGen = new MockObject[1000];

    private int edenIndex = 0;
    private int survivorFromIndex = 0;
    private int survivorToIndex = 0;
    private int oldGenIndex = 0;

    // Minor GC:新生代收集
    public void minorGC() {
   
        System.out.println("Starting Minor GC...");

        // 1. 标记新生代中的存活对象
        markYoungGeneration();

        // 2. 复制存活对象到Survivor区或晋升到老年代
        int toPromoteCount = 0;
        survivorToIndex = 0;

        // 从Eden复制存活对象
        for (int i = 0; i < edenIndex; i++) {
   
            if (eden[i] != null && eden[i].isMarked()) {
   
                if (eden[i].getAge() >= 15) {
   
                    // 年龄达到阈值,晋升到老年代
                    oldGen[oldGenIndex++] = eden[i];
                    toPromoteCount++;
                } else {
   
                    // 复制到Survivor To区
                    survivorTo[survivorToIndex++] = eden[i];
                    eden[i].incrementAge();
                }
            }
            eden[i] = null; // 清空Eden
        }

        // 从Survivor From复制存活对象
        for (int i = 0; i < survivorFromIndex; i++) {
   
            if (survivorFrom[i] != null && survivorFrom[i].isMarked()) {
   
                if (survivorFrom[i].getAge() >= 15) {
   
                    oldGen[oldGenIndex++] = survivorFrom[i];
                    toPromoteCount++;
                } else {
   
                    survivorTo[survivorToIndex++] = survivorFrom[i];
                    survivorFrom[i].incrementAge();
                }
            }
            survivorFrom[i] = null; // 清空Survivor From
        }

        // 交换Survivor区
        MockObject[] temp = survivorFrom;
        survivorFrom = survivorTo;
        survivorTo = temp;
        survivorFromIndex = survivorToIndex;
        survivorToIndex = 0;

        System.out.println("Minor GC completed. Promoted " + toPromoteCount + " objects to old gen.");
    }

    // Major GC:老年代收集
    public void majorGC() {
   
        System.out.println("Starting Major GC...");

        // 老年代使用标记-整理算法
        markOldGeneration();
        compactOldGeneration();

        System.out.println("Major GC completed.");
    }

    // 标记新生代
    private void markYoungGeneration() {
   
        // 从GC Roots开始标记
        // 这里简化为标记所有对象(实际会更复杂)
        for (int i = 0; i < edenIndex; i++) {
   
            if (eden[i] != null) {
   
                eden[i].mark();
            }
        }
        for (int i = 0; i < survivorFromIndex; i++) {
   
            if (survivorFrom[i] != null) {
   
                survivorFrom[i].mark();
            }
        }
    }

    // 标记老年代
    private void markOldGeneration() {
   
        for (int i = 0; i < oldGenIndex; i++) {
   
            if (oldGen[i] != null) {
   
                oldGen[i].mark();
            }
        }
    }

    // 整理老年代
    private void compactOldGeneration() {
   
        int toIndex = 0;
        for (int i = 0; i < oldGenIndex; i++) {
   
            if (oldGen[i] != null && oldGen[i].isMarked()) {
   
                if (toIndex != i) {
   
                    oldGen[toIndex] = oldGen[i];
                    oldGen[i] = null;
                }
                toIndex++;
            } else if (oldGen[i] != null) {
   
                oldGen[i] = null;
            }
        }
        oldGenIndex = toIndex;
    }

    // 对象分配
    public void allocateObject(int id) {
   
        if (edenIndex < eden.length) {
   
            eden[edenIndex++] = new MockObject(id, null);
        } else {
   
            System.out.println("Eden full, triggering Minor GC");
            minorGC();
            // 重新尝试分配
            if (edenIndex < eden.length) {
   
                eden[edenIndex++] = new MockObject(id, null);
            } else {
   
                System.out.println("Still no space after GC, promoting to old gen");
                oldGen[oldGenIndex++] = new MockObject(id, null);
            }
        }
    }

    // 模拟对象年龄增长
    public void simulateAging() {
   
        for (int i = 0; i < survivorFromIndex; i++) {
   
            if (survivorFrom[i] != null) {
   
                survivorFrom[i].incrementAge();
            }
        }
    }
}

垃圾收集器

Serial收集器

Serial收集器是最基本的垃圾收集器,使用单线程进行垃圾收集。

// Serial收集器概念演示
public class SerialGCConcept {
   

    // 模拟单线程GC过程
    public static class MockSerialGC {
   
        private MockObject[] heap = new MockObject[1000];
        private int heapSize = 0;

        public void collect() {
   
            System.out.println("Serial GC started - STW (Stop The World)");

            // 1. 标记阶段(单线程)
            long startTime = System.currentTimeMillis();
            markLiveObjects();
            long markTime = System.currentTimeMillis() - startTime;

            // 2. 清除阶段(单线程)
            startTime = System.currentTimeMillis();
            sweepDeadObjects();
            long sweepTime = System.currentTimeMillis() - startTime;

            System.out.println("Serial GC completed. Mark time: " + markTime + "ms, Sweep time: " + sweepTime + "ms");
            System.out.println("STW ended");
        }

        private void markLiveObjects() {
   
            // 从GC Roots开始标记
            for (int i = 0; i < heapSize; i++) {
   
                if (heap[i] != null && isLive(heap[i])) {
   
                    heap[i].mark();
                }
            }
        }

        private void sweepDeadObjects() {
   
            int newHeapSize = 0;
            for (int i = 0; i < heapSize; i++) {
   
                if (heap[i] != null && heap[i].isMarked()) {
   
                    heap[newHeapSize++] = heap[i];
                    heap[i].unmark(); // 清除标记
                } else if (heap[i] != null) {
   
                    heap[i] = null; // 回收死亡对象
                }
            }
            heapSize = newHeapSize;
        }

        private boolean isLive(MockObject obj) {
   
            // 简化的存活判断
            return obj.getId() % 3 != 0; // 假设id不是3的倍数的对象存活
        }
    }

    // Serial收集器特点
    public void characteristics() {
   
        System.out.println("Serial收集器特点:");
        System.out.println("1. 单线程收集");
        System.out.println("2. 简单高效");
        System.out.println("3. 适用于客户端模式");
        System.out.println("4. 新生代采用复制算法");
        System.out.println("5. 老年代采用标记-整理算法");
    }
}

ParNew收集器

ParNew收集器是Serial收集器的多线程版本。

// ParNew收集器概念演示
public class ParNewGCConcept {
   

    public static class MockParNewGC {
   
        private MockObject[] heap = new MockObject[1000];
        private int heapSize = 0;
        private int threadCount = 4;

        public void collect() {
   
            System.out.println("ParNew GC started - STW");

            // 分区并行处理
            int objectsPerThread = heapSize / threadCount;
            List<CompletableFuture<Void>> futures = new ArrayList<>();

            long startTime = System.currentTimeMillis();

            // 并行标记
            for (int i = 0; i < threadCount; i++) {
   
                final int start = i * objectsPerThread;
                final int end = (i == threadCount - 1) ? heapSize : (i + 1) * objectsPerThread;

                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
   
                    for (int j = start; j < end; j++) {
   
                        if (heap[j] != null && isLive(heap[j])) {
   
                            heap[j].mark();
                        }
                    }
                });
                futures.add(future);
            }

            // 等待所有线程完成标记
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();

            long markTime = System.currentTimeMillis() - startTime;

            // 串行清理(为简单起见,实际可能并行)
            startTime = System.currentTimeMillis();
            sweepDeadObjects();
            long sweepTime = System.currentTimeMillis() - startTime;

            System.out.println("ParNew GC completed. Mark time: " + markTime + "ms, Sweep time: " + sweepTime + "ms");
        }

        private void sweepDeadObjects() {
   
            int newHeapSize = 0;
            for (int i = 0; i < heapSize; i++) {
   
                if (heap[i] != null && heap[i].isMarked()) {
   
                    heap[newHeapSize++] = heap[i];
                    heap[i].unmark();
                } else if (heap[i] != null) {
   
                    heap[i] = null;
                }
            }
            heapSize = newHeapSize;
        }

        private boolean isLive(MockObject obj) {
   
            return obj.getId() % 3 != 0;
        }
    }

    // ParNew收集器特点
    public void characteristics() {
   
        System.out.println("ParNew收集器特点:");
        System.out.println("1. 多线程并行收集");
        System.out.println("2. 仅作用于新生代");
        System.out.println("3. 配合CMS收集器使用");
        System.out.println("4. 默认线程数等于CPU核心数");
    }
}

Parallel Scavenge收集器

Parallel Scavenge收集器关注吞吐量。

// Parallel Scavenge收集器概念演示
public class ParallelScavengeGCConcept {
   

    public static class MockParallelScavengeGC {
   
        private MockObject[] heap = new MockObject[1000];
        private int heapSize = 0;
        private int threadCount = Runtime.getRuntime().availableProcessors();

        // 关注吞吐量的参数
        private double targetGCTimeRatio = 0.01; // GC时间占比目标
        private int maxGCPauseMillis = 200;      // 最大暂停时间目标

        public void collect() {
   
            System.out.println("Parallel Scavenge GC started");

            long startTime = System.currentTimeMillis();

            // 并行标记
            parallelMark();

            // 并行复制
            parallelCopy();

            long gcTime = System.currentTimeMillis() - startTime;
            long totalTime = getRunningTime();

            double gcRatio = (double) gcTime / totalTime;
            System.out.println("GC ratio: " + gcRatio + ", Target: " + targetGCTimeRatio);

            // 根据GC时间比例调整参数
            if (gcRatio > targetGCTimeRatio) {
   
                adjustParametersForThroughput();
            }
        }

        private void parallelMark() {
   
            int objectsPerThread = heapSize / threadCount;
            List<CompletableFuture<Void>> futures = new ArrayList<>();

            for (int i = 0; i < threadCount; i++) {
   
                final int start = i * objectsPerThread;
                final int end = (i == threadCount - 1) ? heapSize : (i + 1) * objectsPerThread;

                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
   
                    for (int j = start; j < end; j++) {
   
                        if (heap[j] != null && isLive(heap[j])) {
   
                            heap[j].mark();
                        }
                    }
                });
                futures.add(future);
            }

            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        }

        private void parallelCopy() {
   
            // 并行复制存活对象
            List<MockObject> liveObjects = new ArrayList<>();
            for (int i = 0; i < heapSize; i++) {
   
                if (heap[i] != null && heap[i].isMarked()) {
   
                    liveObjects.add(heap[i]);
                    heap[i].unmark();
                } else if (heap[i] != null) {
   
                    heap[i] = null;
                }
            }

            // 重新分配
            heapSize = 0;
            for (MockObject obj : liveObjects) {
   
                heap[heapSize++] = obj;
            }
        }

        private long getRunningTime() {
   
            // 模拟获取程序运行总时间
            return System.currentTimeMillis();
        }

        private void adjustParametersForThroughput() {
   
            // 根据吞吐量目标调整GC参数
            System.out.println("Adjusting parameters for better throughput");
        }

        private boolean isLive(MockObject obj) {
   
            return obj.getId() % 2 == 0; // 假设偶数ID的对象存活
        }
    }

    // Parallel Scavenge收集器特点
    public void characteristics() {
   
        System.out.println("Parallel Scavenge收集器特点:");
        System.out.println("1. 关注吞吐量");
        System.out.println("2. 自适应调节策略");
        System.out.println("3. 新生代并行收集");
        System.out.println("4. 适合后台计算服务");
    }
}

CMS收集器

CMS(Concurrent Mark Sweep)收集器关注最短回收停顿时间。

// CMS收集器概念演示
public class CMSGCConcept {
   

    public static class MockCMSGC {
   
        private MockObject[] heap = new MockObject[1000];
        private int heapSize = 0;
        private volatile boolean concurrentMarking = false;

        public void collect() {
   
            System.out.println("CMS GC started");

            // 1. 初始标记(STW)
            long startTime = System.currentTimeMillis();
            initialMark();
            long initialMarkTime = System.currentTimeMillis() - startTime;
            System.out.println("Initial mark completed - STW: " + initialMarkTime + "ms");

            // 2. 并发标记(与用户线程并发)
            startTime = System.currentTimeMillis();
            concurrentMark();
            long concurrentMarkTime = System.currentTimeMillis() - startTime;
            System.out.println("Concurrent mark completed: " + concurrentMarkTime + "ms");

            // 3. 重新标记(STW)
            startTime = System.currentTimeMillis();
            remark();
            long remarkTime = System.currentTimeMillis() - startTime;
            System.out.println("Remark completed - STW: " + remarkTime + "ms");

            // 4. 并发清除(与用户线程并发)
            startTime = System.currentTimeMillis();
            concurrentSweep();
            long concurrentSweepTime = System.currentTimeMillis() - startTime;
            System.out.println("Concurrent sweep completed: " + concurrentSweepTime + "ms");
        }

        private void initialMark() {
   
            // 仅标记GC Roots直接关联的对象
            for (int i = 0; i < heapSize; i++) {
   
                if (heap[i] != null && isGcRoot(heap[i])) {
   
                    heap[i].mark();
                }
            }
        }

        private void concurrentMark() {
   
            concurrentMarking = true;
            // 启动并发标记线程
            Thread markThread = new Thread(() -> {
   
                for (int i = 0; i < heapSize && concurrentMarking; i++) {
   
                    if (heap[i] != null && !heap[i].isMarked()) {
   
                        markReachable(heap[i]);
                    }
                }
            });
            markThread.start();

            // 模拟用户线程继续运行
            simulateUserThreads();

            try {
   
                markThread.join();
            } catch (InterruptedException e) {
   
                Thread.currentThread().interrupt();
            }
            concurrentMarking = false;
        }

        private void remark() {
   
            // 修正并发标记期间对象引用关系变化
            for (int i = 0; i < heapSize; i++) {
   
                if (heap[i] != null && hasReferenceChanged(heap[i])) {
   
                    markReachable(heap[i]);
                }
            }
        }

        private void concurrentSweep() {
   
            // 并发清除死亡对象
            Thread sweepThread = new Thread(() -> {
   
                for (int i = 0; i < heapSize; i++) {
   
                    if (heap[i] != null && !heap[i].isMarked()) {
   
                        heap[i] = null; // 清除死亡对象
                    } else if (heap[i] != null) {
   
                        heap[i].unmark(); // 清除标记
                    }
                }
            });
            sweepThread.start();

            // 用户线程继续运行
            simulateUserThreads();

            try {
   
                sweepThread.join();
            } catch (InterruptedException e) {
   
                Thread.currentThread().interrupt();
            }
        }

        private void markReachable(MockObject obj) {
   
            if (obj != null && !obj.isMarked()) {
   
                obj.mark();
                // 标记引用的对象
                if (obj.getNext() != null) {
   
                    markReachable(obj.getNext());
                }
            }
        }

        private boolean isGcRoot(MockObject obj) {
   
            // 简化的GC Root判断
            return obj.getId() < 10; // 假设ID小于10的是GC Root
        }

        private boolean hasReferenceChanged(MockObject obj) {
   
            // 模拟并发标记期间引用关系变化
            return Math.random() > 0.9; // 10%概率引用关系变化
        }

        private void simulateUserThreads() {
   
            // 模拟用户线程在GC期间继续运行
            try {
   
                Thread.sleep(100); // 模拟用户线程工作
            } catch (InterruptedException e) {
   
                Thread.currentThread().interrupt();
            }
        }
    }

    // CMS收集器特点
    public void characteristics() {
   
        System.out.println("CMS收集器特点:");
        System.out.println("1. 关注最短停顿时间");
        System.out.println("2. 基于标记-清除算法");
        System.out.println("3. 并发收集,低停顿");
        System.out.println("4. 会产生内存碎片");
        System.out.println("5. 对CPU资源敏感");
    }
}

G1收集器

G1(Garbage-First)收集器面向服务端应用。

// G1收集器概念演示
public class G1GCConcept {
   

    // G1将堆划分为多个Region
    public static class Region {
   
        private MockObject[] objects = new MockObject[100];
        private int objectCount = 0;
        private boolean isHumongous = false; // 是否是大对象Region
        private boolean isOld = false;       // 是否是老年代Region

        public void addObject(MockObject obj) {
   
            if (objectCount < objects.length) {
   
                objects[objectCount++] = obj;
            }
        }

        public int getLiveObjectCount() {
   
            int count = 0;
            for (int i = 0; i < objectCount; i++) {
   
                if (objects[i] != null && objects[i].isMarked()) {
   
                    count++;
                }
            }
            return count;
        }

        public boolean isEmpty() {
   
            return objectCount == 0;
        }
    }

    public static class MockG1GC {
   
        private Region[] regions = new Region[200]; // 200个Region
        private PriorityQueue<Region> collectionSet = new PriorityQueue<>((r1, r2) -> 
            Integer.compare(r2.getLiveObjectCount(), r1.getLiveObjectCount())); // 按垃圾量排序

        public MockG1GC() {
   
            for (int i = 0; i < regions.length; i++) {
   
                regions[i] = new Region();
            }
        }

        public void collect() {
   
            System.out.println("G1 GC started");

            // 1. 全局并发标记
            concurrentMarking();

            // 2. 选择回收价值最大的Region集合
            selectCollectionSet();

            // 3. 并行回收选定的Region
            parallelEvacuation();
        }

        private void concurrentMarking() {
   
            System.out.println("Concurrent marking phase");
            // 并发标记整个堆
            for (Region region : regions) {
   
                markRegion(region);
            }
        }

        private void markRegion(Region region) {
   
            // 标记Region中的存活对象
            for (int i = 0; i < region.objectCount; i++) {
   
                if (region.objects[i] != null && isLive(region.objects[i])) {
   
                    region.objects[i].mark();
                }
            }
        }

        private void selectCollectionSet() {
   
            // 选择垃圾最多的Region进行回收
            collectionSet.clear();
            for (Region region : regions) {
   
                if (!region.isEmpty() && region.getLiveObjectCount() < region.objectCount * 0.8) {
   
                    collectionSet.offer(region);
                }
            }
        }

        private void parallelEvacuation() {
   
            System.out.println("Parallel evacuation phase");
            // 并行回收选中的Region
            while (!collectionSet.isEmpty()) {
   
                Region region = collectionSet.poll();
                evacuateRegion(region);
            }
        }

        private void evacuateRegion(Region region) {
   
            // 将Region中的存活对象复制到其他Region
            List<MockObject> liveObjects = new ArrayList<>();

            for (int i = 0; i < region.objectCount; i++) {
   
                if (region.objects[i] != null && region.objects[i].isMarked()) {
   
                    liveObjects.add(region.objects[i]);
                    region.objects[i].unmark();
                }
            }

            // 清空原Region
            region.objectCount = 0;

            // 将存活对象分配到新的Region
            allocateLiveObjects(liveObjects);
        }

        private void allocateLiveObjects(List<MockObject> liveObjects) {
   
            // 将存活对象分配到合适的Region
            for (MockObject obj : liveObjects) {
   
                // 简化的分配逻辑
                for (Region region : regions) {
   
                    if (region.objectCount < region.objects.length) {
   
                        region.addObject(obj);
                        break;
                    }
                }
            }
        }

        private boolean isLive(MockObject obj) {
   
            return obj.getId() % 3 != 0;
        }
    }

    // G1收集器特点
    public void characteristics() {
   
        System.out.println("G1收集器特点:");
        System.out.println("1. 面向服务端应用");
        System.out.println("2. 并行与并发");
        System.out.println("3. 分代收集");
        System.out.println("4. 空间整合(类似标记-整理)");
        System.out.println("5. 可预测的停顿");
    }
}

ZGC收集器

ZGC是JDK 11引入的低延迟垃圾收集器。

// ZGC概念演示(简化版)
public class ZGCConcept {
   

    // ZGC的内存布局概念
    public static class ZGCHeap {
   
        // ZGC使用Colored Pointers技术
        private static final int MAPPABLE = 0x01;      // 可映射
        private static final int REMAPPED = 0x02;      // 已重映射
        private static final int MARKED0 = 0x04;       // 标记0
        private static final int MARKED1 = 0x08;       // 标记1

        // 并发标记阶段
        public void concurrentMark() {
   
            System.out.println("ZGC Concurrent Mark Phase");
            // 使用Colored Pointers进行并发标记
            // 不需要STW,用户线程可以继续运行
        }

        // 并发重映射阶段
        public void concurrentRemap() {
   
            System.out.println("ZGC Concurrent Remap Phase");
            // 重映射阶段,修正指针
        }

        // 并发转移阶段
        public void concurrentRelocate() {
   
            System.out.println("ZGC Concurrent Relocate Phase");
            // 并发转移存活对象到新区域
        }
    }

    // ZGC特点
    public void characteristics() {
   
        System.out.println("ZGC收集器特点:");
        System.out.println("1. 超低延迟(<10ms)");
        System.out.println("2. 并发执行,几乎无停顿");
        System.out.println("3. 支持大堆内存(TB级别)");
        System.out.println("4. 使用Colored Pointers技术");
        System.out.println("5. Region-based内存管理");
    }
}

内存调优与监控

内存参数配置

JVM提供了丰富的参数来配置内存区域大小和垃圾收集器。

// 内存参数配置示例
public class MemoryTuningExample {
   

    // 常用JVM参数说明
    public void commonJVMParameters() {
   
        System.out.println("常用JVM内存参数:");
        System.out.println("-Xms<size>          初始堆大小");
        System.out.println("-Xmx<size>          最大堆大小");
        System.out.println("-Xmn<size>          新生代大小");
        System.out.println("-XX:NewRatio=<ratio> 新生代与老年代比例");
        System.out.println("-XX:SurvivorRatio=<ratio> Eden区与Survivor区比例");
        System.out.println("-XX:MaxTenuringThreshold=<n> 最大年龄阈值");
        System.out.println("-XX:+UseSerialGC     使用Serial收集器");
        System.out.println("-XX:+UseParNewGC     使用ParNew收集器");
        System.out.println("-XX:+UseParallelGC   使用Parallel收集器");
        System.out.println("-XX:+UseConcMarkSweepGC 使用CMS收集器");
        System.out.println("-XX:+UseG1GC         使用G1收集器");
    }

    // 内存配置策略
    public void memoryConfigurationStrategy() {
   
        System.out.println("内存配置策略:");
        System.out.println("1. 根据应用特点选择合适的收集器");
        System.out.println("2. 合理设置堆大小,避免频繁GC");
        System.out.println("3. 调整新生代大小,平衡Minor GC频率");
        System.out.println("4. 监控GC日志,分析性能瓶颈");
    }

    // GC日志分析
    public void gcLogAnalysis() {
   
        System.out.println("GC日志分析要点:");
        System.out.println("1. GC频率:Minor GC和Major GC的频率");
        System.out.println("2. GC时间:每次GC的停顿时间");
        System.out.println("3. 内存使用:各代内存的使用情况");
        System.out.println("4. 晋升速率:对象从新生代到老年代的速率");
    }
}

内存监控工具

JVM提供了多种工具来监控内存使用情况。

// 内存监控示例
public class MemoryMonitoring {
   

    // 使用ManagementFactory监控内存
    public void monitorMemoryUsage() {
   
        MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
        MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
        MemoryUsage nonHeapUsage = memoryBean.getNonHeapMemoryUsage();

        System.out.println("Heap Memory Usage:");
        System.out.println("  Used: " + heapUsage.getUsed() / (1024 * 1024) + " MB");
        System.out.println("  Max: " + heapUsage.getMax() / (1024 * 1024) + " MB");
        System.out.println("  Committed: " + heapUsage.getCommitted() / (1024 * 1024) + " MB");

        System.out.println("Non-Heap Memory Usage:");
        System.out.println("  Used: " + nonHeapUsage.getUsed() / (1024 * 1024) + " MB");
        System.out.println("  Max: " + nonHeapUsage.getMax() / (1024 * 1024) + " MB");
        System.out.println("  Committed: " + nonHeapUsage.getCommitted() / (1024 * 1024) + " MB");
    }

    // 监控垃圾收集器信息
    public void monitorGarbageCollectors() {
   
        List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();

        for (GarbageCollectorMXBean gcBean : gcBeans) {
   
            System.out.println("GC Name: " + gcBean.getName());
            System.out.println("  Collection Count: " + gcBean.getCollectionCount());
            System.out.println("  Collection Time: " + gcBean.getCollectionTime() + " ms");

            String[] memoryPoolNames = gcBean.getMemoryPoolNames();
            System.out.println("  Associated Memory Pools: " + String.join(", ", memoryPoolNames));
        }
    }

    // 监控内存池
    public void monitorMemoryPools() {
   
        List<MemoryPoolMXBean> memoryPoolBeans = ManagementFactory.getMemoryPoolMXBeans();

        for (MemoryPoolMXBean poolBean : memoryPoolBeans) {
   
            System.out.println("Memory Pool: " + poolBean.getName());
            System.out.println("  Type: " + poolBean.getType());
            System.out.println("  Usage: " + poolBean.getUsage());

            if (poolBean.getPeakUsage() != null) {
   
                System.out.println("  Peak Usage: " + poolBean.getPeakUsage());
            }
        }
    }

    // 模拟内存使用监控
    public void simulateMemoryMonitoring() {
   
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

        scheduler.scheduleAtFixedRate(() -> {
   
            monitorMemoryUsage();
            System.out.println("---");
        }, 0, 5, TimeUnit.SECONDS);

        // 模拟内存分配
        List<byte[]> memoryHog = new ArrayList<>();
        ScheduledExecutorService allocationScheduler = Executors.newScheduledThreadPool(1);

        allocationScheduler.scheduleAtFixedRate(() -> {
   
            if (memoryHog.size() < 100) {
   
                memoryHog.add(new byte[1024 * 1024]); // 每次分配1MB
            }
        }, 0, 100, TimeUnit.MILLISECONDS);
    }
}

常见内存问题诊断

了解常见的内存问题及其诊断方法。

// 内存问题诊断示例
public class MemoryProblemDiagnosis {
   

    // 内存泄漏示例
    public static class MemoryLeakExample {
   
        private List<String> cache = new ArrayList<>();

        public void addToCache(String data) {
   
            // 没有清理机制,可能导致内存泄漏
            cache.add(data);
        }

        // 正确的清理方法
        public void clearCache() {
   
            cache.clear();
        }

        // 使用WeakReference避免内存泄漏
        private Map<String, WeakReference<Object>> weakCache = new HashMap<>();

        public void addToWeakCache(String key, Object value) {
   
            weakCache.put(key, new WeakReference<>(value));
        }
    }

    // 内存溢出示例
    public void demonstrateOutOfMemory() {
   
        List<byte[]> list = new ArrayList<>();
        try {
   
            while (true) {
   
                list.add(new byte[1024 * 1024]); // 每次分配1MB
            }
        } catch (OutOfMemoryError e) {
   
            System.out.println("OutOfMemoryError caught: " + e.getMessage());
            list.clear(); // 清理内存
        }
    }

    // 栈溢出示例
    public void demonstrateStackOverflow() {
   
        try {
   
            recursiveMethod();
        } catch (StackOverflowError e) {
   
            System.out.println("StackOverflowError caught: " + e.getMessage());
        }
    }

    private int recursiveMethod() {
   
        return recursiveMethod() + 1; // 无限递归导致栈溢出
    }

    // GC开销限制超出示例
    public void demonstrateGCOverheadLimit() {
   
        List<byte[]> list = new ArrayList<>();
        try {
   
            while (true) {
   
                // 创建大量短生命周期对象
                for (int i = 0; i < 1000; i++) {
   
                    list.add(new byte[1024]); // 1KB对象
                }
                // 立即丢弃大部分对象
                list.subList(0, 900).clear();
            }
        } catch (OutOfMemoryError e) {
   
            System.out.println("GC overhead limit exceeded: " + e.getMessage());
        }
    }

    // 内存诊断工具使用
    public void diagnosticTools() {
   
        System.out.println("常用内存诊断工具:");
        System.out.println("1. jstat - 监控JVM统计信息");
        System.out.println("2. jmap - 生成堆转储快照");
        System.out.println("3. jhat - 分析堆转储快照");
        System.out.println("4. jconsole - 图形化监控工具");
        System.out.println("5. VisualVM - 综合性能分析工具");
        System.out.println("6. JProfiler - 商业性能分析工具");
        System.out.println("7. YourKit - 商业性能分析工具");
    }
}

性能调优实践

实际的性能调优案例和最佳实践。

// 性能调优实践示例
public class PerformanceTuningPractice {
   

    // 对象池模式减少GC压力
    public static class ObjectPool<T> {
   
        private final Queue<T> pool = new ConcurrentLinkedQueue<>();
        private final Supplier<T> factory;
        private final Consumer<T> resetter;

        public ObjectPool(Supplier<T> factory, Consumer<T> resetter) {
   
            this.factory = factory;
            this.resetter = resetter;
        }

        public T acquire() {
   
            T object = pool.poll();
            if (object == null) {
   
                object = factory.get();
            }
            return object;
        }

        public void release(T object) {
   
            resetter.accept(object);
            pool.offer(object);
        }
    }

    // 字符串池优化
    public static class StringPoolOptimization {
   
        private final Map<String, String> stringPool = new ConcurrentHashMap<>();

        public String internString(String str) {
   
            return stringPool.computeIfAbsent(str, s -> s);
        }

        // 使用String.intern()优化内存
        public String useIntern(String str) {
   
            return str.intern(); // 将字符串放入常量池
        }
    }

    // 大对象处理策略
    public static class LargeObjectHandling {
   

        // 使用直接内存避免堆内存压力
        public ByteBuffer allocateDirectMemory(int size) {
   
            return ByteBuffer.allocateDirect(size); // 直接内存,不受堆大小限制
        }

        // 分块处理大对象
        public void processLargeData(byte[] largeData) {
   
            int chunkSize = 1024 * 1024; // 1MB chunks
            for (int i = 0; i < largeData.length; i += chunkSize) {
   
                int end = Math.min(i + chunkSize, largeData.length);
                byte[] chunk = Arrays.copyOfRange(largeData, i, end);
                processChunk(chunk);
            }
        }

        private void processChunk(byte[] chunk) {
   
            // 处理数据块
        }
    }

    // 引用类型选择
    public static class ReferenceTypeSelection {
   
        private Map<String, Object> strongCache = new HashMap<>();
        private Map<String, WeakReference<Object>> weakCache = new HashMap<>();
        private Map<String, SoftReference<Object>> softCache = new HashMap<>();

        // 强引用:对象不会被回收
        public void useStrongReference(String key, Object value) {
   
            strongCache.put(key, value);
        }

        // 软引用:内存不足时会被回收
        public void useSoftReference(String key, Object value) {
   
            softCache.put(key, new SoftReference<>(value));
        }

        // 弱引用:GC时会被回收
        public void useWeakReference(String key, Object value) {
   
            weakCache.put(key, new WeakReference<>(value));
        }
    }

    // 性能调优检查清单
    public void tuningChecklist() {
   
        System.out.println("JVM性能调优检查清单:");
        System.out.println("1. 分析GC日志,确定GC频率和停顿时间");
        System.out.println("2. 检查内存使用情况,避免内存泄漏");
        System.out.println("3. 选择合适的垃圾收集器");
        System.out.println("4. 调整堆大小和各代比例");
        System.out.println("5. 优化对象分配和生命周期管理");
        System.out.println("6. 使用对象池减少GC压力");
        System.out.println("7. 合理使用不同类型的引用");
        System.out.println("8. 监控和调优JVM参数");
    }
}

JVM内存区域划分和垃圾回收机制是Java程序性能优化的核心。通过深入理解各内存区域的特点、垃圾回收算法的原理和各种收集器的特性,开发者可以更好地进行内存调优,构建高性能的Java应用程序。



关于作者



🌟 我是suxiaoxiang,一位热爱技术的开发者

💡 专注于Java生态和前沿技术分享

🚀 持续输出高质量技术内容



如果这篇文章对你有帮助,请支持一下:




👍 点赞


收藏


👀 关注



您的支持是我持续创作的动力!感谢每一位读者的关注与认可!


目录
相关文章
|
2月前
|
Java 开发者
Java高级技术深度解析:性能优化与架构设计
本文深入解析Java高级技术,涵盖JVM性能调优、并发编程、内存模型与架构设计。从G1/ZGC垃圾回收到CompletableFuture异步处理,剖析底层机制与实战优化策略,助力构建高性能、高可用的Java系统。
266 47
|
负载均衡 Java 微服务
OpenFeign:让微服务调用像本地方法一样简单
OpenFeign是Spring Cloud中声明式微服务调用组件,通过接口注解简化远程调用,支持负载均衡、服务发现、熔断降级、自定义拦截器与编解码,提升微服务间通信开发效率与系统稳定性。
646 156
|
Nacos 微服务 监控
Nacos:微服务架构中的“服务管家”与“配置中心”
Nacos是阿里巴巴开源的微服务“服务管家”与“配置中心”,集服务注册发现、动态配置管理、健康检查、DNS发现等功能于一体,支持多语言、多协议接入,助力构建高可用、易运维的云原生应用体系。
727 155
|
数据可视化 Java Nacos
OpenFeign + Sentinel 实现微服务熔断限流实战
本文介绍如何在Spring Cloud微服务架构中,结合OpenFeign与阿里巴巴开源组件Sentinel,实现服务调用的熔断、降级与限流。通过实战步骤搭建user-service与order-service,集成Nacos注册中心与Sentinel Dashboard,演示服务异常熔断、QPS限流控制,并支持自定义限流响应。借助Fallback降级机制与可视化规则配置,提升系统稳定性与高可用性,助力构建健壮的分布式应用。
623 155
|
SQL 关系型数据库 数据库
学习分布式事务Seata看这一篇就够了,建议收藏
学习分布式事务Seata看这一篇就够了,建议收藏
21382 2
|
2月前
|
缓存 监控 Java
用 Spring Boot 3 构建高性能 RESTful API 的 10 个关键技巧
本文介绍使用 Spring Boot 3 构建高性能 RESTful API 的 10 大关键技巧,涵盖启动优化、数据库连接池、缓存策略、异步处理、分页查询、限流熔断、日志监控等方面。通过合理配置与代码优化,显著提升响应速度、并发能力与系统稳定性,助力打造高效云原生应用。
500 3
|
2月前
|
Java Nacos Sentinel
Spring Cloud Alibaba 深度实战:Nacos + Sentinel + Gateway 整合指南
本指南深入整合Spring Cloud Alibaba核心组件:Nacos实现服务注册与配置管理,Sentinel提供流量控制与熔断降级,Gateway构建统一API网关。涵盖环境搭建、动态配置、服务调用与监控,助你打造高可用微服务架构。(238字)
952 10
|
消息中间件 缓存 监控
缓存与数据库一致性问题的解决策略
本文系统探讨了缓存与数据库一致性问题的根源及解决方案,涵盖Cache-Aside、Read/Write-Through等主流策略,结合分布式锁、消息队列、布隆过滤器等技术应对缓存穿透、击穿与雪崩,并提出版本控制、事件驱动等高级保障机制,辅以监控告警与最佳实践,助力构建高性能、高一致性的分布式系统。
352 0
|
存储 关系型数据库 MySQL
MySQL 数据库详解与实践指南
本文全面解析MySQL数据库核心概念、存储引擎、数据类型及高级特性,涵盖索引优化、查询性能提升、安全配置、备份恢复与主从复制等实战技巧,助你掌握MySQL高效应用与运维最佳实践。
308 1
|
监控 Java Spring
Spring Boot 拦截器(Interceptor)详解
本文介绍Spring Boot拦截器的原理与使用,涵盖自定义拦截器创建、注册配置、执行顺序及典型应用场景,助力提升系统安全性与可维护性。(238字)
1061 0