如何排查线上问题
Created|Updated
|Word Count:30|Reading Time:1mins|Post Views:
cpu 偏高问题排查
数据库问题排查
Author: magicliang
Copyright Notice: All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.
Related Articles

2026-01-12
Java 并发编程笔记
juc.xmind 写在前面的话 并发编程最早的实践都在操作系统里。高层语言的并发模型都要基于底层系统对硬件抽象和并发的设计来设计和实现,不能超出操作系统允许的范围。所谓的高级抽象总体上是简化对 OS 底层机制的复杂调用。 并发与异步 本文聚焦并发(Concurrency),即多任务在同一时间段内的交替或并行执行,核心问题是资源共享、线程同步与协作。 **异步(Asynchronous)**是另一维度:调用方发起操作后不等结果返回即继续执行,通过回调、Future或事件机制获取结果。异步可通过单线程事件循环实现,也可依托多线程并发实现。 二者关系:并发关注"多任务如何执行与协调",异步关注"调用是否阻塞等待"。并发编程常涉及异步,但本文不展开异步编程模式(如响应式流、协程),相关内容请参阅《Java 线程池笔记》。 管程 理论和实践之间是有鸿沟的,要弥合这种鸿沟,通常需要我们去学习别人的实践。比如并发的标准设计思想来自于操作系统里的管程(monitor),我们应当学习管程,进而了解标准的并发模型-管理共享变量和线程(并发任务)间通信的基本...

2026-01-19
线程安全与锁优化
版本说明:本文主要基于 JDK 6 ~ JDK 14 的 HotSpot 虚拟机实现。需要注意的是,从 JDK 15 开始,偏向锁已被默认关闭并标记为废弃(JEP 374)。如果你使用的是 JDK 15+,文中关于偏向锁的内容仅作为历史参考。 线程安全 什么是线程安全 “当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方法进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那么这个对象就是线程安全的。” 相对的线程安全,可以分成五个等级。但在深入讨论线程安全的分类之前,我们需要先理解 Java 内存模型——它是理解线程安全问题的理论基础。 Java 内存模型基础 Java 内存模型(Java Memory Model,JMM)是 Java 语言规范的一部分,定义了多线程程序中共享变量的访问规则。理解 JMM 是理解线程安全问题的基础。 为什么需要内存模型? 现代计算机系统中,CPU 与主内存之间存在巨大的速度差异。为了弥补这一差距,硬件层面引入了多级缓存(L1、L2、L3 Cache)。这带来了一个问...

2026-02-07
G1/ZGC/Shenandoah 垃圾收集器对比
垃圾收集的核心挑战 垃圾收集器的设计始终面临三个核心指标的权衡:吞吐量、延迟和内存占用。这三个指标构成了一个不可能三角,优化其中一个指标往往需要牺牲其他指标。 吞吐量指单位时间内完成的工作量,通常用应用程序运行时间占总时间的比例来衡量。对于批处理任务、科学计算等场景,高吞吐量是首要目标。 延迟指垃圾收集造成的应用停顿时间。对于交互式应用、金融交易系统等对响应时间敏感的场景,低延迟至关重要。延迟通常关注最大停顿时间和停顿时间分布。 内存占用指垃圾收集器为了完成收集工作所需的额外内存空间。内存受限的环境下,收集器自身的内存开销成为关键约束。 传统垃圾收集器在三者之间做出明确取舍:Serial 和 Parallel GC 追求高吞吐量,但停顿时间较长;CMS GC 降低停顿时间,但牺牲吞吐量并占用更多内存。现代收集器试图在三者之间找到更优的平衡点。 G1(Garbage First)收集器 G1 收集器在 JDK 7u4 版本正式推出,是 JDK 9 之后的默认垃圾收集器。G1 的核心思想是打破传统分代收集的物理隔离,将堆内存划分为多个大小相等的 Region。 Region 化堆内存...

2017-10-27
基于栈的虚拟机
基于栈的虚拟机 全景导图 mindmap root((基于栈的虚拟机)) 核心架构 操作数栈 局部变量表 栈帧 执行机制 字节码指令 基于栈的运算 指令集简洁性 设计优势 可移植性 代码紧凑 实现简单 典型应用 JVM Python虚拟机 .NET CLR 模式总览 # 模式名称 一句话口诀 覆盖场景 1 栈式计算 数据流与控制流分离,操作数隐式传递 JVM字节码执行、表达式求值、递归调用 2 栈帧隔离 每个方法调用独立的执行上下文 方法调用、异常处理、线程隔离 3 指令紧凑 操作数位置编码在指令中,减少指令长度 字节码压缩、跨平台分发 问题定义 为什么选择基于栈的虚拟机架构,而非基于寄存器的架构?这种设计如何影响字节码的生成、执行效率以及跨平台可移植性? 核心概念 虚拟机架构分类 虚拟机按照指令集架构主要分为两类: 基于栈的虚拟机:指令不指定操作数的位置,操作数从栈顶弹出...

2021-10-09
JDK 的广泛分支
Oracle Hospot JDK java 8 特定版本以后就不再免费了。 现有的JDK8,2019.1之前的更新都可以免费获取正常使用。 Oracle JDK11是一个长期支持的版本,用于商业环境需要付费。 Azul Zulu builds of OpenJDK Zulu 是Azul公司基于OpenJDK发布的Java SE产品,它没有Oracle JDK对使用场景上的诸多限制,可以放心免费下载和使用。它的核心部分就是原汁原味的OpenJDK,没有任何额外的改动——Azul有时候也会对OpenJDK做bug fix,但这些都是通过提交回到OpenJDK去然后再进入到Zulu Java SE产品中的。它与“自己下载OpenJDK源码,自己build”的最大区别是:Azul会在每次发布Zulu产品之前进行充分的测试,build出来的二进制版本符合Java的兼容性测试;同时,Azul有与Oracle签订合作协议,在critical security fix的方面会比公开发布的OpenJDK源码要更早获得补丁,提前做好build与测试工作,基本上可以跟Oracle在同一时...

2018-10-13
卡表和 RSet
卡表和 RSet 问题定义:为什么需要跨区域引用记录 JVM 垃圾收集器的核心工作之一是确定 live set——哪些对象仍然存活、不可回收。确定 live set 的标准做法是从 GC Roots(栈帧中的局部变量、静态字段等)出发,沿引用链遍历所有可达对象。 问题在于:当堆被划分为多个区域(代、Region)并且只回收其中一部分时,如何高效地找到从"不回收区域"指向"回收区域"的引用? 以 Young GC 为例:只回收新生代,但老年代中可能持有指向新生代对象的引用。如果不处理这些跨代引用,就会错误地回收仍被老年代引用的新生代对象。最朴素的做法是扫描整个老年代来找出这些引用——但老年代通常远大于新生代,这样做的代价过高,违背了分代收集"只回收一部分堆"的初衷。 卡表(Card Table)和 RSet(Remembered Set)正是为解决这个问题而设计的辅助数据结构。二者的关系并非互相替代,而是层次不同、协作互补:卡表是底层的脏标记机制,RSet 是建立在卡表之上的更高层索引结构。 核心概念速览 在深入细节之前,...
Contents

