Java对象生命周期
一个Java对象从被加载到JVM内存,到最终被垃圾回收器(GC)清除,会经历一个完整的生命周期,主要包含以下几个关键阶段: 一、 类的加载与初始化(发生在对象创建之前) 加载: 当JVM第一次遇到 new 关键字、静态字段访问、静态方法调用、反射调用(如 Class.forName())、子类初始化触发父类初始化等场景时,如果目标类尚未被加载,JVM会通过类加载器查找并加载该类的字节码(.class 文件)到内存中。 验证: 确保被加载的字节码是符合JVM规范的、安全的,不会危害虚拟机自身。检查内容包括文件格式、元数据、字节码语义、符号引用等。 准备: 为类的静态变量分配内存(在方法区)并设置其初始零值(0, null, false 等)。final static 常量如果其值在编译期可知,通常在这个阶段就直接赋值了。 解析: 将常量池内的符号引用(以文本形式表示的引用,如类名、方法名、字段名)替换为直接引用(指向内存中具体位置的指针、偏移量或句柄)。解析可能在初始化之前或之后进行。 初始化: 执行类的初始化方法 <clinit>(),该方法由编译器...
JVM问题排查
一、明确问题现象 常见问题类型: 内存溢出(OutOfMemoryError) CPU占用率飙升(100%) 线程阻塞/死锁(应用无响应) GC频繁(应用卡顿) 类加载异常(ClassNotFoundException/NoClassDefFoundError) 二、基础信息收集1. 查看JVM参数12jps -lvm # 列出所有Java进程及其启动参数jinfo <pid> # 查看指定进程的详细配置 关键参数:堆大小(-Xms, -Xmx)、GC算法(-XX:+UseG1GC)、OOM行为(-XX:+HeapDumpOnOutOfMemoryError) 2. 实时监控1jstat -gcutil <pid> 1000 # 每秒打印一次GC情况 输出关键指标: YGC/YGCT:Young GC次数/耗时 FGC/FGCT:Full GC次数/耗时 O:老年代使用率 M:元空间使用率 三、深度排查工具1. 内存问题排查 堆内存分析: 12jmap -dump:format=b,file=hea...
Java内存模型
Java内存模型(JMM)是Java虚拟机规范中定义的一种抽象内存模型,它规定了多线程环境下,线程如何与主内存及工作内存交互,以及线程间共享变量的可见性、有序性和原子性规则。其核心目标是解决多线程并发中的内存可见性、指令重排序等问题,为开发者提供一套可预测的并发编程语义。 一、JMM的核心组件 主内存(Main Memory) 存储所有共享变量(实例字段、静态字段等)。 所有线程均可访问,但线程不能直接操作主内存中的变量。 工作内存(Working Memory) 每个线程独享的私有内存区域。 存储该线程使用的共享变量的副本。 线程对变量的所有操作(读/写)必须在工作内存中进行,不能直接读写主内存。 二、JMM的关键规则 内存交互操作JMM定义了8种原子操作(已简化,实际由JVM实现): lock:锁定主内存变量,标识为线程独占。 unlock:解锁主内存变量。 read:从主内存读取变量到工作内存。 load:将read得到的值放入工作内存副本。 use:将工作内存变量值传递给执行引擎(如CPU)。 assign:将执行引擎结果赋给工作内存...
JVM内存模型
JVM(Java虚拟机)内存模型(也称为运行时数据区)是Java程序运行时的核心基础,它定义了程序执行过程中数据存储和管理的逻辑结构。这种设计是为了实现平台无关性、内存自动管理(垃圾回收)、线程安全和高性能等目标。 JVM内存模型的核心区域 方法区(Method Area) 存储内容:类信息(Class元数据)、常量池(Constant Pool)、静态变量(Static Variables)、JIT编译后的代码等。 设计原因: 共享性:所有线程共享类元数据,避免重复加载,节省内存。 持久性:类信息在程序启动后长期存在,直到JVM关闭。 演进:在JDK 8之前称为“永久代”(PermGen),后改为元空间(Metaspace)(使用本地内存,避免OutOfMemoryError)。 堆(Heap) 存储内容:所有对象实例和数组。 设计原因: 动态内存分配:对象生命周期不确定,需要灵活的内存管理。 垃圾回收(GC)的核心区域:通过分代设计(年轻代、老年代)优化GC效率。 线程共享:减少对象复制的开销,但需通过同步机制保证线程安全。 虚拟机栈(JVM Stack...
Java双亲委派机制
Java 中的双亲委派机制(Parent Delegation Model) 是类加载器(ClassLoader)加载类的核心机制,其核心思想是:当一个类加载器收到加载类的请求时,它不会立即尝试加载,而是先将请求委派给父类加载器处理。只有在父类加载器无法完成加载时,子加载器才会尝试加载。 类加载器的层级结构Java 类加载器分为三层(实际为四层,包括自定义加载器): 启动类加载器(Bootstrap ClassLoader) 由 C++ 实现,是 JVM 的一部分。 负责加载 JAVA_HOME/lib 下的核心类库(如 rt.jar)。 唯一没有父加载器的加载器(顶级存在)。 扩展类加载器(Extension ClassLoader) Java 实现,继承自 ClassLoader。 负责加载 JAVA_HOME/lib/ext 目录或 java.ext.dirs 指定路径的类。 父加载器是 Bootstrap ClassLoader。 应用程序类加载器(Application ClassLoader) 也称为系统类加载器(AppClassLoader)...
Java非受检异常 VS 受检异常
在业务自定义异常的设计中,优先选择非受检异常(RuntimeException子类)通常是更优方案,但需根据具体场景权衡。以下是深度分析和决策指南: 一、核心对比:非受检异常 vs 受检异常 维度 非受检异常(RuntimeException) 受检异常(Exception) 强制处理 调用方不强制捕获或声明 编译器强制处理(try-catch/throws) 适用场景 业务逻辑错误、不可恢复错误 可恢复错误、需显式处理的场景 代码侵入性 低(不污染方法签名) 高(方法需声明throws,调用链需处理) 设计哲学 “Fail-Fast” 快速暴露问题 “防御式编程” 确保错误被处理 典型案例 IllegalArgumentException IOException 二、优先选择非受检异常的场景(推荐主流方案)1. 不可恢复的业务错误 如订单状态冲突、ID不存在等业务规则违反 示例:1234567891011121314// 非受检业务异常:调用方无法通过代码修复此错误class OrderStateException extends R...
Java异常体系
Java 的异常体系采用层次化设计,以 Throwable 为顶层基类,其下分为 Error 和 Exception 两大分支,而 Exception 又细分为 受检异常(Checked Exception) 和 非受检异常(Unchecked Exception)。以下是体系结构详解: 一、异常体系层次 Throwable(所有异常/错误的超类) 定义异常消息、堆栈跟踪等方法。 直接子类:Error 和 Exception。 Error(系统级错误) 表示 JVM 无法处理的严重问题(如内存耗尽)。 非受检:无需强制捕获(如 OutOfMemoryError)。 Exception(程序可处理的异常) 分为两类: 受检异常(Checked Exception)需显式处理(如 IOException、SQLException)。 非受检异常(Unchecked Exception)即 RuntimeException 及其子类(如 NullPointerException)。 二、设计原因与优势 强制处理可恢复错误(受检异常) ...