高薪程序员必修课-JVM的内存区域以及对象创建过程

发布于:2024-07-06 ⋅ 阅读:(16) ⋅ 点赞:(0)

JVM内存区域

        在Java虚拟机(JVM)中,内存区域(Memory Areas)是对内存空间的逻辑划分,用于存储不同类型的数据和执行不同的操作。理解JVM的内存区域有助于优化程序性能、调优内存使用和排查内存相关的问题。下面是Java中主要的JVM内存区域及其作用:

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

程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。每个线程都有一个独立的程序计数器,它的作用包括:

  • 线程私有:每个线程都有自己的程序计数器。
  • 线程切换时保存当前执行位置:确保线程恢复执行时能够知道继续执行的位置。
  • 执行Java方法时记录字节码地址:用于支持基于线程的轮转和异常处理。

2. Java虚拟机栈(JVM Stack)

Java虚拟机栈用于存储方法的局部变量、部分方法返回值和操作数栈等数据。每个方法被执行时,都会同时创建一个栈帧(Stack Frame),用于存储方法的局部变量表、操作数栈、动态链接、方法出口等信息。JVM栈具有以下特点:

  • 线程私有:每个线程都有自己的JVM栈。
  • 方法调用:用于存储方法的局部变量和操作数栈。
  • 动态扩展和收缩:根据方法的调用深度动态分配和回收内存。

3. 本地方法栈(Native Method Stack)

本地方法栈与JVM栈类似,但是它为执行本地(Native)方法服务。本地方法是由JNI(Java Native Interface)调用的本地代码,本地方法栈用于支持这些本地方法的执行。

4. Java堆(Java Heap)

Java堆是JVM中最大的一块内存区域,用于存储对象实例和数组。Java堆是所有线程共享的内存区域,主要用于存放:

  • 对象实例:通过new关键字创建的对象。
  • 数组:Java中的数组,包括基本类型数组和对象数组。

Java堆具有以下特点:

  • 垃圾回收:Java堆中的对象不再被引用时,会由垃圾回收器自动进行垃圾回收和内存释放。
  • 分代策略:Java堆通常被划分为新生代(Young Generation)、老年代(Old Generation)和永久代(PermGen,已废弃,Java 8后改为元空间Metaspace)等不同的区域,以支持不同的垃圾回收算法。

5. 方法区(Metaspace)

方法区(Metaspace)用于存储类的结构信息、运行时常量池、静态变量、即时编译器编译后的代码等数据。Java 8及之前的版本称为永久代(PermGen),Java 8之后改为元空间(Metaspace),其特点包括:

  • 动态扩展:根据应用程序的需要动态分配内存空间。
  • 垃圾回收:元空间中的类数据和常量池通常不会被垃圾回收器回收。

6. 运行时常量池(Runtime Constant Pool)

运行时常量池是方法区的一部分,用于存放编译期生成的各种字面量和符号引用。与Class文件中的常量池(Constant Pool)不同,运行时常量池是动态生成的,并且具有一定的动态性。


JAVA对象创建过程

        Java中对象的创建过程涉及类加载、内存分配、初始化等多个步骤。下面详细讲解Java中对象创建的过程,从类加载到实例化的整个流程:

1. 类加载

在Java中,对象的创建首先要加载类的定义信息,即将类的.class文件加载到内存中并生成对应的Class对象。类加载由类加载器(ClassLoader)完成,主要包括以下几个步骤:

  • 加载(Loading):查找并加载类的二进制数据(.class文件)到内存中。
  • 链接(Linking)
    • 验证(Verification):确保加载的类符合JVM规范,如字节码验证。
    • 准备(Preparation):为类的静态变量分配内存,并设置默认初始值(零值)。
    • 解析(Resolution):将符号引用转换为直接引用。

2. 内存分配

一旦类加载完成,JVM需要为对象分配内存。Java堆(Heap)是存放对象实例的主要内存区域。内存分配的方式通常有两种:

  • 指针碰撞(Bump the Pointer):在堆内存中,用一个指针来指示已使用和未使用的内存分界线,分配内存时向未使用的内存段移动指针即可。这种方式要求堆中的内存是连续的,且堆空间必须是规整的。

  • 空闲列表(Free List):在堆内存中维护一个列表,记录上哪些内存块是可用的。分配内存时从列表中找到合适大小的块,标记为已使用,并更新列表。这种方式适用于堆空间不规整的情况。

3. 对象初始化

对象内存分配完成后,JVM会对对象进行初始化。对象初始化主要包括:

  • 设置对象头:包括对象的哈希码、GC分代年龄、锁状态标志等。
  • 执行构造方法:调用对象的构造方法进行初始化。构造方法会按照定义顺序初始化成员变量和执行构造代码块。

示例

以下是一个简单的Java类及其对象创建过程的示例:

public class MyClass {
    private int value;
    
    // 构造方法
    public MyClass(int v) {
        this.value = v;
    }
    
    // 实例方法
    public void printValue() {
        System.out.println("Value: " + value);
    }
    
    public static void main(String[] args) {
        // 第一步:加载类信息
        // MyClass类会被ClassLoader加载到JVM中
        
        // 第二步:内存分配
        // 在Java堆中分配内存空间给MyClass对象
        
        // 第三步:对象初始化
        // 调用构造方法进行初始化
        MyClass obj = new MyClass(10);
        
        // 调用对象的实例方法
        obj.printValue();
    }
}

输出结果

Value: 10

总结

        理解Java虚拟机的内存区域对于优化Java程序、排查内存泄漏和性能调优至关重要。Java中对象的创建过程涉及类加载、内存分配和对象初始化等多个步骤。不同的内存区域具有各自的作用和特点,理解其工作原理和使用方法可以帮助开发人员更好地设计和编写Java应用程序,优化代码结构和性能,同时也有助于排查对象相关的内存问题。


⭐️⭐️ ⭐️ ⭐️ ⭐️ 好书推荐
《Java项目开发全程实录》(第4版)

【内容简介】

        《Java项目开发全程实录(第4版)》以企业QQ、蓝宇快递打印系统、开发计划管理系统、酒店管理系统、图书馆管理系统、学生成绩管理系统、进销存管理系统、神奇Book—图书商城、企业门户网站、棋牌游戏系统之网络五子棋10个实际项目开发程序为案例,从软件工程的角度出发,按照项目的开发顺序,系统、全面地介绍了J2SE和J2EE项目的开发流程。从开发背景、需求分析、系统功能分析、数据库分析、数据库建模、网站开发和网站发布或者程序打包与运行方面进行讲解,每一过程都进行了详细的介绍。

📚 京东购买链接:《Java项目开发全程实录》


网站公告

今日签到

点亮在社区的每一天
去签到