27-Linux学习之旅之Java概念
发布时间:2026/8/25 4:35:26 作者:尧图编辑部 阅读量:1,286

Linux学习之旅之Java概念一、认识Java1、代码是怎么运行起来的编辑 → 编译 → 类加载 → 字节码执行 → 程序结束阶段工具 / 组件输入输出核心工作编辑阶段文本编辑器 / IDEA程序员编写代码.java源文件编写 Java 源代码纯文本文件计算机无法直接执行编译阶段javacJDK 前端编译器.java源文件.class字节码文件语法检查、泛型擦除把源码编译为 JVM 可识别的字节码不是机器码类加载阶段JVM 类加载子系统.class字节码加载到 JVM 内存加载→验证→准备→解析→初始化将字节码读入内存处理静态变量、符号引用完成类初始化字节码执行阶段JVM 执行引擎解释器 JIT 即时编译器内存中的字节码CPU 机器指令1. 解释器逐条翻译字节码执行启动快2.JIT热点代码编译成本地机器码缓存提升运行速度GC 后台回收堆内存程序结束JVM运行中进程JVM 进程退出main 线程执行完毕 /System.exit()调用虚拟机退出程序终止2、为什么java需要jvm不同操作系统Windows、Linux、macOS的底层指令集和系统调用接口不同。JVM 在中间加了一层抽象Java 程序编译为平台无关的字节码JVM 负责在具体平台上将字节码转换为对应的机器码。这就是一次编写到处运行的实现原理。核心角度说明1. 实现跨平台一次编写到处运行javac把 Java 源码编译成字节码.class不是 CPU 机器码。不同操作系统 CPU 指令集不一样同一机器码不能跨系统直接跑。JVM 把字节码翻译成本地平台的机器指令Windows/Linux/macOS 安装对应版本 JVM同一套 class 就可以运行。2. 屏蔽底层操作系统硬件差异Java 代码不需要调用操作系统底层 API。文件读写、内存、线程调用全部交给 JVM 封装开发者不用适配 Windows、Linux 的系统 API 差异。3. 提供完整运行时环境JVM 不只是翻译代码提供运行时数据区内存管理、垃圾回收 GC、类加载机制、安全校验、异常处理、线程调度。Java 不用手动 malloc/free 管理内存由 JVM 的 GC 自动回收。4. 安全隔离类加载时做字节码验证校验 class 合法性防止恶意字节码破坏系统提供沙箱安全机制。5. 兼顾启动速度与运行性能JVM 采用解释器 JIT 即时编译器解释器快速启动热点代码 JIT 编译成本地机器码兼顾启动快和运行速度。二、JDK、JRE、JVM的关系JDK 是 Java 开发工具包包含 JRE 和各类开发编译调试工具JRE 是 Java 运行环境包含 JVM 和 Java 核心类库用于运行 Java 程序JVM 是 Java 虚拟机负责执行字节码实现跨平台。三者包含关系JDK 包含 JREJRE 包含 JVM。 包含关系JDK ⊃ JRE ⊃ JVM JDKJRE 开发工具javac、java、jar 等 JREJVM Java 类库核心类库 rt.jar 等 JVMJava 虚拟机只负责运行字节码 JDK开发工具包 ├── JRE运行环境 │ ├── JVM虚拟机真正执行字节码 │ └── Java核心类库String、集合等 └── 开发工具javac编译器、调试工具、打包工具名称全称组成作用使用人群JVMJava Virtual MachineJava 虚拟机执行引擎、类加载器、运行时内存区执行.class字节码内存管理、GC实现跨平台所有运行 Java 程序JRE 必须包含 JVMJREJava Runtime EnvironmentJava 运行时环境JVM Java 标准类库Java 程序运行环境能跑 class但不能编译 java 源码运行 Java 软件的普通用户JDKJava Development KitJava 开发工具包JRE 开发工具集 (javac、java 等)开发 编译 运行 Java 程序有编译器 javacJava 开发人员三、JVM内存结构认知1、认识JVM内存JVM 内存就是Java 虚拟机在运行 Java 程序时向操作系统申请的内存空间程序跑起来之后字节码加载进来数据、对象、局部变量就存放在这块内存。 注意JVM 内存 ≠ 物理内存是虚拟机划分出来的逻辑区域。 JVM 运行时数据区分为3大核心区域栈、堆、元空间区域线程属性存什么什么时候创建销毁常见异常堆 (Heap)线程共享new出来的对象、数组实例变量JVM 启动创建JVM 关闭销毁GC 回收无用对象OOM 内存溢出虚拟机栈Java 栈简称栈线程私有栈帧局部变量、方法信息线程创建就分配栈线程结束栈直接释放StackOverflowError、OOM元空间 Metaspace (方法区实现)线程共享类的结构信息、静态变量、常量池类被加载时存入类卸载释放OOM2、认识堆内存结构新生代与老年代堆是 GC 垃圾回收的主要区域JVM 把堆划分为新生代和老年代 目的是优化垃圾回收效率。#晋升机制新对象优先分配在 Eden 区 new出来的对象放到 Eden。Eden 满了触发 Minor GC新生代 GC。 Minor GC 执行过程 Eden 区垃圾全部清除 Eden 中存活的对象复制到其中一块 SurvivorS0 S0 中存活的对象年龄 1 S0、S1 总有一块是空的作为复制的目标两块不能同时使用。 Survivor 两块来回拷贝复制算法。 对象晋升老年代3 种情况 ① 对象年龄达到阈值默认15每熬过一次 MinorGC对象 age1age15晋升到老年代。-XX:MaxTenuringThreshold15② Survivor 放不下存活对象直接晋升老年代。 ③ 大对象直接进老年代超过 Eden 大小的大对象不经过新生代直接分配到老年代避免大量复制开销。 老年代满 → 触发 Full GC 老年代空间不足触发Full GC回收整个堆新生代 老年代开销很大STW 时间长。四、认识GCMinor GC只回收新生代。频繁发生速度快会 STW暂停用户线程。 Major GC只回收老年代很少发生。 Full GC回收整个堆新生代 老年代 元空间STW 时间很长尽量避免。1、GC回收什么GC 回收堆内存中不再被任何引用指向的对象垃圾对象✔回收堆中没有引用的对象、数组实例❌不回收栈、程序计数器、本地方法栈线程销毁自动释放元空间类信息栈里的局部变量引用。2、怎么回收回收类型触发条件回收范围特点Young GCEden 类型的 Region 全部被占满全部 Eden Survivor RegionSTW只回收新生代存活对象拷贝到 Survivor符合条件晋升老年代Mixed GC堆总使用率达到参数‑XX:InitiatingHeapOccupancyPercent默认45%完成并发标记后触发新生代 部分垃圾最多的老年代 RegionG1 核心优先回收垃圾最多 Region受‑XX:MaxGCPauseMillis目标停顿时间约束避免 Full GCFull GCMixed GC 回收速度跟不上对象分配、没有空闲 Region、手动System.gc()整个堆新生代 老年代 元空间单线程 STW停顿时间很长性能差生产环境尽量避免算法适用区域原理优点缺点复制算法新生代把存活对象复制到另一块内存清空原内存无内存碎片需要预留一块内存占用额外空间标记‑清除老年代先标记垃圾之后直接清除垃圾不需要额外内存产生大量内存碎片标记‑整理老年代标记垃圾清除后把存活对象向一端移动整理压缩无内存碎片移动对象效率低分代收集算法整个堆新生代用复制老年代用标记清除 / 标记整理针对不同生命周期对象整体效率高没有明显缺点现在 JVM 默认3、常见GC回收器回收器版本作用特点Serial 收集器JDK1.3单线程回收单线程回收时暂停所有线程客户端、小程序使用ParallelParallel ScavengeJDK8 默认多线程吞吐量优先多核 CPU追求高吞吐量后台默认CMS 并发标记清除JDK1.5~JDK14老年代低停顿并发降低 STW 时间会内存碎片JDK14 废弃G1(Garbage‑First)JDK9默认分块可预测停顿把堆划分为多个 Region兼顾吞吐量和低停顿服务端首选ZGCJDK11 开始提供JDK17 默认极低停顿几乎不 STW超大堆毫秒级停顿4、常见命令# 使用G1回收器java-XX:UseG1GC-Xms512m-Xmx1024mDemo# 使用CMSJDK14之后已废弃java-XX:UseConcMarkSweepGCDemo# 使用Parallel吞吐量收集器(JDK8默认)java-XX:UseParallelGCDemo# ZGC JDK17java-XX:UseZGCDemo