JVM 内存泄漏
内存分配在 JVM 中,内存泄漏(Memory Leak)的核心定义是:存在一些对象,它们已经不再被程序使用(没有任何业务意义),但由于仍然被 GC Roots(根对象)直接或间接引用,导致 GC(垃圾回收器)无法回收它们,最终占用的内存越来越多,直至引发 OOM(内存溢出)。 内存泄漏是 “缓慢积累” 的过程,而 OOM 是泄漏的最终结果之一 堆内存泄漏堆内存用于存储对象实例,当对象 “无用但可达” 时,就会发生泄漏 静态集合(如 static List/Map)的生命周期与 JVM 一致。如果向静态集合中添加对象后,未在使用完后移除,这些对象会一直被集合引用,导致无法回收。 文件流(FileInputStream)、数据库连接(Connection)、网络连接(Socket)等资源对象,不仅占用堆内存,还关联底层系统资源。如果未调用 close()释放,这些对象会被 JVM 持有引用(如通过 finalize 机制等待回收),但回收周期长,且可能因资源句柄耗尽导致泄漏。 非静态内部类(成员内部类)会隐式持有外部类的实例引用。如果内部类对象被长期引用(如放入静态集合),会导致...
分段锁学习记录
分段锁概述分段锁是一种通过缩小锁粒度来提高并发性能的锁设计策略,核心思想是将共享数据分割成多个独立的 “段(Segment)”,每个段单独配备一把锁。当线程操作某一段数据时,只需获取该段的锁,不会影响其他段的访问,从而允许多个线程同时操作不同的段,大幅降低锁竞争。 经典应用ConcurrentHashMapJDK7 及之前版本的 ConcurrentHashMap,之后版本已废除,采用红黑树+synchronized 设计结构:JDK7 的 ConcurrentHashMap 由 多个 Segment 组成,每个 Segment 本质上是一个 “小 HashMap”(内部包含数组和链表),且每个 Segment 都继承了 ReentrantLock(可重入锁),因此每个 Segment 自身就是一把独立的锁。关于 ReentrantLock 请查阅我关于锁的详细介绍的相关文档,这里就不多解释了 核心操作:当往 ConcurrentHashMap 中插入数据时,步骤如下: 根据 key 的哈希值计算出对应的 Segment 索引(确定要操作的段); 获取该 Segment 的...
JVM 垃圾回收
JVM 的内存结构JVM 的内存区域按功能分为多个部分,其中堆(Heap) 和方法区(Method Area,JDK8 后为元空间 Metaspace) 是垃圾回收的主要目标(因为这两个区域的内存分配和释放是动态的)。其他区域(如程序计数器、虚拟机栈、本地方法栈)是线程私有且生命周期与线程一致,无需 GC(GC 就是垃圾回收)。 堆:存储对象实例(几乎存储所有对象都在这里分配),是 GC 最核心的区域。堆按对象存活周期可分为: 年轻代:分为 Eden 区和两个 Survivoe 区,用于存储新创建的对象,对象存活率低,回收频繁 老年代:存储存活时间较长的对象(多次年轻代回收仍然存活的对象就会被存储到老年代),存活率高,回收频率低 方法区:存储类信息,常量、静态变量,也会发生垃圾回收 垃圾回收垃圾回收的本质是自动释放不再被使用地内存,解决手动管理内存容易出现的内存泄漏、内存溢出问题。我们需要考虑两个问题:哪些对象是垃圾?如何高效地回收这些垃圾。 STW:在垃圾回收的过程中,用户所有线程暂停执行 内存分配策略:对象优先在 Eden 区分配;Eden 区满时触发 Minor...
java中的并发编程
基本概念Java 是支持多线程的开发语言,意思就是可以在多 CPU 核心的机子上同时处理不同的任务,优化资源的使用率,提升程序的效率。 并发编程三要素 原子性:指一个操作或一系列操作要么全部执行完成,要么全部不执行(synchronized,CAS) 有序性:指程序执行的顺序按照代码的逻辑顺序进行(volatile,锁机制) 可见性:指当一个线程修改了共享变量的值后,其他线程能立即看到这个修改。 volatile核心作用是通过 JVM 的底层机制解决多线程通信中的可见性和有序性问题。volatile 是 Java 提供的一种轻量级同步机制,被 volatile 修饰的变量具有两个核心特性: 可见性:一个线程对变量的修改,其他线程能立即看到 有序性:禁止特定类型的指令重排序 Java 内存模型(JMM)是 JVM 定义的一套抽象规范,它规定了线程如何通过内存进行交互,目的是解决多线程通过共享内存通信时的三大问题:可见性、原子性、有序性。 JMM主内存:所有线程共享的内存区域,存储共享变量(实例变量、静态变量等)。工作内存:每个线程独有的内存区域,存储主内存中共享变量的副本()...
淘汰算法
缓存淘汰算法FIFO 先进先出 思想:最先进来的数据,被认为在未来被访问的概率也是最低的,因此,当规定空间用尽且需要放入新数据的时候,会优先淘汰最早进来的数据 优点:公平,逻辑简单,容易实现 缺点:命中率极低 LRU 思想:如果一个数据最近很少被访问到,那么被认为在未来被访问的概率也是最低的,当规定空间用尽且需要放入新数据的时候,会优先淘汰最久未被访问的数据 优点:LRU 可以有效的对访问比较频繁的数据进行保护,也就是针对热点数据的命中率提高有明显的效果。 缺点:对于周期性、偶发性的访问数据,有大概率可能造成缓存污染,也就是置换出去了热点数据,把这些偶发性数据留下了,从而导致 LRU 的数据命中率急剧下降。 LFU 思想:如果一个数据在一定时间内被访问的次数很低,那么被认为在未来被访问的概率也是最低的,当规定空间用尽且需要放入新数据的时候,会优先淘汰时间段内访问次数最低的数据 优点:LFU 也可以有效的保护缓存,相对场景来讲,比 LRU 有更好的缓存命中率。 缺点:因为 LFU 需要记录数据的访问频率,因此需要额外的空间;当访问模式改变的时候,算法命中率会急剧下降,...
雪花算法
概述雪花算法(Snowflake)是一种分布式唯一 ID 生成算法,由 Twitter 公司设计,用于解决分布式系统中生成全局唯一 ID 的需求。它能在高并发场景下高效生成不重复的 ID,且生成的 ID 具备有序性,便于数据库索引优化。 结构雪花算法生成的 ID 是一个 64 为长整型 long 数字: 符号位(1 位):二进制中最高位为符号位,默认为 0,表示生成的 ID 为正 时间戳(41 位):记录当前时间戳-算法指定的起始时间戳这个相对时间 工作节点(10 位):用于区分分布式系统中的不同节点(机器或进程),确保不同节点生成的 ID 不冲突。10 位最多支持 1024 个节点,可根据实际需求拆分(如 5 位数据中心 ID + 5 位机器 ID,支持 32 个数据中心,每个中心 32 台机器)。 序列号(12 位):用于解决同一节点在同一毫秒内生成多个 ID 的冲突问题。 应用场景 分布式数据库表的主键 ID,常用于分库分表 分布式系统中的订单号、流水号等唯一标识 日志追踪、消息队列等需要唯一 ID 的场景 优势 全局唯一:通过时间戳、节点 ID 和序列号的组合,确保...