开始改变第一天 JVM的原理到调优 1

JVM核心原理学习笔记

一、Java程序执行流程

text
复制代码
Person.java → javac编译 → Person.class → java命令 → JVM加载执行

二、Class文件格式

java
复制代码
ClassFile { u4 magic; // 魔数 u2 minor_version; // 次版本 u2 major_version; // 主版本 u2 constant_pool_count; // 常量池数量 cp_info constant_pool[constant_pool_count-1]; // 常量池 u2 access_flags; // 访问标志 u2 this_class; // 当前类 u2 super_class; // 父类 u2 interfaces_count; // 接口数量 u2 interfaces[interfaces_count]; // 接口表 u2 fields_count; // 字段数量 field_info fields[fields_count]; // 字段表 u2 methods_count; // 方法数量 method_info methods[methods_count]; // 方法表 u2 attributes_count; // 属性数量 attribute_info attributes[attributes_count]; // 属性表 }

三、类加载机制

1. 装载 (Loading)

  • 定位: 通过类加载器 findClass(String name) 找到类文件位置
  • 加载: 类文件字节码 → 方法区
  • 创建: 生成对应的Class对象 → 堆内存

2. 链接 (Linking)

  • 验证:
    • 文件格式验证
    • 元数据验证
    • 字节码验证
    • 符号引用验证
  • 准备: 为静态变量分配内存并设置默认值
    • static int a = 10; → 此阶段a=0
  • 解析: 将符号引用转换为直接引用
    • 将类名、方法名等符号转换为具体内存地址

3. 初始化 (Initialization)

  • 执行静态变量赋值和静态代码块
    • static int a = 10; → 此阶段a=10

四、类加载器与双亲委派机制

类加载器层次:

text
复制代码
Bootstrap ClassLoader (启动类加载器) ↓ Extension ClassLoader (扩展类加载器) ↓ App ClassLoader (应用程序类加载器) ↓ Custom ClassLoader (自定义类加载器)

双亲委派机制:

java
复制代码
protected Class<?> loadClass(String name, boolean resolve) { synchronized (getClassLoadingLock(name)) { // 1. 检查是否已加载 Class<?> c = findLoadedClass(name); if (c == null) { try { // 2. 委托父加载器加载 if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) {} // 3. 父加载器无法加载时,自己加载 if (c == null) { c = findClass(name); } } return c; } }

职责划分:

  • Bootstrap: 加载$JAVA_HOME/jre/lib/rt.jar-Xbootclasspath指定的包
  • Extension: 加载$JAVA_HOME/jre/lib/ext/*.jar-Djava.ext.dirs指定的包
  • App: 加载classpath指定的类和jar包
  • Custom: 应用程序自定义的类加载器(如Tomcat、JBoss等)

五、运行时数据区

线程共享区域:

1. 堆 (Heap)

  • 特点: 唯一,线程共享,生命周期与JVM相同
  • 存储: 对象实例和数组
  • 问题: OutOfMemoryError

2. 方法区 (Method Area) - JDK8+称为元空间(Metaspace)

  • 特点: 唯一,线程共享,生命周期与JVM相同
  • 存储: 类信息、常量、静态变量、即时编译器编译后的代码
  • 注意: JDK8+使用本地内存,不再使用JVM内存
  • GC: 会进行垃圾回收(主要回收不再使用的类和常量)

线程私有区域:

3. Java虚拟机栈 (Java Virtual Machine Stacks)

  • 特点: 每个线程一个栈
  • 组成: 栈帧(每个方法对应一个栈帧)
  • 栈帧包含:
    • 局部变量表
    • 操作数栈
    • 动态链接
    • 方法返回地址
  • 问题: StackOverflowError(如无限递归)

4. 本地方法栈 (Native Method Stacks)

  • 为Native方法服务

5. 程序计数器 (Program Counter Register)

  • 当前线程执行的字节码行号指示器

六、方法执行过程示例

java
复制代码
public static int calc(int op1, int op2) { op1 = 3; int result = op1 + op2; return result; }

执行过程:

  1. 创建栈帧,包含局部变量表(op1, op2, result)
  2. 操作数栈进行运算
  3. 通过javap -c可查看字节码指令
  4. 方法执行完毕,栈帧出栈

七、重要概念区分

JVM内存结构 (运行时数据区)

  • 物理上的内存划分
  • 包含:堆、方法区、栈、程序计数器等

JMM内存模型 (Java Memory Model)

  • 多线程环境下的内存访问规范
  • 保证:可见性、原子性、有序性
  • 解决线程安全问题

八、总结

  • JVM是Java程序的运行环境,理解JVM有助于写出高性能代码
  • 类加载机制确保类的正确加载和初始化
  • 双亲委派机制保证类的唯一性和安全性
  • 运行时数据区管理程序运行时的内存分配
  • 栈帧结构体现了方法调用的底层实现

学习建议: 结合javap工具分析字节码,使用JVM参数监控内存使用,深入理解每个环节的实际表现。

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
下载 APP