【J2SE快速进阶】——Java内存分析

简介: 要在Java中分析内存,我们先来了解一下程序的执行过程:

       程序的执行过程


       要在Java中分析内存,我们先来了解一下程序的执行过程:


58.png

        正如上图所示,大致分为3个步骤:


        1、最开始,我们的程序是存在于硬盘中的,当启动运行时,程序会被加载(load)到内存中去,这里的内存可以看做我们的内存条;


        2、此时,内存中除了存在刚加载的程序的代码,还存在操作系统本身的代码(好吧,此句可以当做废话→_→),操作系统会找到程序中的Main方法开始执行程序;


        3、第三步就是本文的重点,系统在程序执行过程中对内存的管理。在Java中,内存大致会被分为四块——heap(栈)、stack(堆)、data segment(数据段)、code segment(代码段),分别用来存放程序中的局部变量、new出来的对象或数组等、静态变量、程序代码。


        这里主要讨论heap(栈)和stack(堆)。


        Java的数据类型


        先来复习一下Java的数据类型,Java中数据类型分为两种,基本数据类型和引用数据类型,如下图:


59.png


       基本数据类型就这八种,引用数据类型包括类、数组、接口等。


     (初学者可能会把String、Integer等类型和char、int等基本数据类型混淆,这里说明一下,Integer相当于int的“包装类”,String可以看做是char[]类型的数组,此外,Byte、Float等类似。所以这些类型应当当做引用类型去对待。)



      内存分析

      正如第一张图所示,程序运行时,我们定义的局部变量一般都存放于栈内存中,这些局部变量既可以是基本数据类型的变量(基本数据类型的变量在栈中直接保存它的值),也可以是引用类型的变量(引用类型的变量在栈中保存的是它所指向的堆内存中对象的地址)。


      堆内存中存放的就是引用类型变量的地址所指向的对象。        




      实践出真知,下面具体在代码中分析一下,希望您能抽出10秒钟来仔细看一下这段代码再继续:      


public class MemoryAnalysis {
  public static void main(String[] args) {        
        Person person=new Person("小明",15);
    String newName="小红";
    int newAge=18;
    person.SetName(newName);
    person.SetAge(newAge);
    person.SayHello();
  }
}
public class Person {
  public String name;
  public int age;
  public Person(String name,int age){
    this.name =name;
    this.age=age;
  }
  public void SetName(String name){
    this.name=name;
  }
  public void SetAge(int age){
    this.age=age;
  }
  public void SayHello(){
    System.out.println("我的名字叫"+name+",我"+age+"岁了");
  }
}

      下面对Main方法中的代码逐句分析  :


Person person=new Person("小明",15);


      实例化了Person类后:


      堆内存:堆内存中分配一块内存用来存放Person实例person中的数据,因为person的name属性为String类型,所以在堆内存中会另外分配一块内存用来存放String类型的“小明”,person中的name中存放的只是一个地址(地址3),这个地址指向存放“小明”的内存块;person中age属性为int类型,所以直接在age的内存单元存放int类型的“15”。


       栈内存:因为person为引用类型,所以在栈内存中分配的内存单元person中存放的是一个指向堆内存中person实例的地址(地址1)。如果上面的代码中只是定义了person,而没有new,那么只会在栈内存中分配一个person的内存单元,内才能中的值为空。


60.png

String newName="小红";


61.png


      因为newName类型为String类型,所以newName的实际内容也会存放于堆内存中,栈内存分配的内存单元newName中只是存放指向堆内存中“小红”的地址。

int newAge=18;


62.png

     newAge的类型为int类型,所以直接将值(18)存放在栈内存分配的单元newAge中。

person.SetName(newName);

 

      到了函数这块,会有一点点复杂,因为SetName(String name)函数有一个类型为引用类型参数name,而且传入的实参为newName,这时newName中存储的值(地址2)会赋值给这个name,所以这时newName和name存储的地址相同(即同时指向“小红”)。同理,当执行了SetName(String name)函数中的this.name=name时,会把栈内存中name中存储的值(地址2)赋值给堆内存中person的name,此时person中的name里存储的也是指向“小红”的地址。


63.png


       之后,person原来的name值“小明”会在某个时刻被java的垃圾回收机制所回收。


64.png


       方法执行完毕后,栈内存中变量name所占的内存被回收。

65.png

person.SetAge(newAge);


         跟SetName(String name)一样,执行时也会在栈内存中为形参age分配内存单元,只不过SetAge(int age)函数中的形参age为int类型,所以直接在栈内存分配的单元中直接存储实参的值(18)即可。

66.png


          方法执行完毕后,栈内存中变量age所占的内存被回收。

68.png


        以上就是这几句代码的执行过程。多少懂一些java基础的您肯定已经猜出运行结果了:


        运行结果:            

69.png


相关文章
|
3天前
|
Java 程序员
Java 一个 Scanner.nextInt 造成的奇怪问题及分析解决过程
Java 一个 Scanner.nextInt 造成的奇怪问题及分析解决过程
|
15天前
|
存储 SQL 缓存
揭秘Java并发核心:深度剖析Java内存模型(JMM)与Volatile关键字的魔法底层,让你的多线程应用无懈可击
【8月更文挑战第4天】Java内存模型(JMM)是Java并发的核心,定义了多线程环境中变量的访问规则,确保原子性、可见性和有序性。JMM区分了主内存与工作内存,以提高性能但可能引入可见性问题。Volatile关键字确保变量的可见性和有序性,其作用于读写操作中插入内存屏障,避免缓存一致性问题。例如,在DCL单例模式中使用Volatile确保实例化过程的可见性。Volatile依赖内存屏障和缓存一致性协议,但不保证原子性,需与其他同步机制配合使用以构建安全的并发程序。
46 0
|
10天前
|
存储 Java 程序员
Java中对象几种类型的内存分配(JVM对象储存机制)
Java中对象几种类型的内存分配(JVM对象储存机制)
43 5
Java中对象几种类型的内存分配(JVM对象储存机制)
|
4天前
|
存储 Java 开发者
Java 内存模型与垃圾回收机制的深度剖析
在Java的世界里,理解其内存模型和垃圾回收机制是提升编程效率的关键。本文将通过浅显易懂的语言,带你深入了解Java的内存分配原理和垃圾回收过程,让你对Java的性能调优有更深刻的认识。
|
5天前
|
存储 Java 编译器
刷完一千道java笔试题的常见题目分析
这篇文章是关于刷完一千道Java笔试题后的常见题目分析,涵盖了Java基础知识点,如标识符命名规则、抽象类与接口的区别、String类的equals方法、try-catch-finally块的执行逻辑、类与实例方法的区别、this与super关键字的用法、面向对象的基本概念、重写与重载的原则等,并建议结合JVM内存结构图加深理解。
刷完一千道java笔试题的常见题目分析
|
7天前
|
安全 Java 程序员
深入浅出Java内存模型:探索JMM的奥秘
在Java编程世界中,理解其内存模型(JMM)是提升代码性能和确保线程安全的关键。本文将带你走进Java内存模型的大门,通过浅显易懂的方式揭示其工作原理,并指导你如何在实际开发中有效利用JMM来避免常见的并发问题。
|
12天前
|
算法 Java 开发者
Java 内存管理:深入理解垃圾收集机制
在Java的世界中,内存管理是一块基石,它确保了程序的顺畅运行和资源的合理利用。本文将带你深入探讨Java的垃圾收集机制,揭示其工作原理、常见算法以及调优实践。我们将一起探索如何通过理解这一机制来编写更高效的代码,避免内存泄漏,并提升应用性能。
|
9天前
|
Java 开发者
深入浅出Java内存管理
在Java的世界里,内存管理是支撑程序运行的基石。本文将通过浅显易懂的语言和生动的比喻,带你了解Java是如何巧妙地处理内存分配与回收的。我们将一起探索对象在Java内存模型中的生命周期,以及JVM如何通过垃圾收集机制保持内存的健康状态。无论你是初学者还是有一定经验的开发者,这篇文章都将为你揭开Java内存管理的神秘面纱。
|
14天前
|
安全 Java
Java RMI技术详解与案例分析
在实际的银行系统中,当然还需要考虑安全性、事务性、持久性以及错误处理等多方面的因素,RMI的网络通信也需要在安全的网络环境下进行,以防止数据泄露或被篡改。你在应用中是怎么使用 RMI 的,欢迎关注威哥爱编程,一起交流一下哈。
132 4
|
14天前
|
监控 算法 Java
Java 内存管理:从垃圾收集到性能调优
【8月更文挑战第5天】 本文将深入探讨 Java 的内存管理机制,特别是垃圾收集器(GC)的工作原理及其在性能优化中的关键作用。通过具体案例分析,我们将了解如何选择合适的垃圾收集算法以及调优 JVM 参数来提升应用性能。文章旨在为 Java 开发者提供实用的内存管理和性能调优技巧,帮助他们编写更高效、更稳定的应用程序。
34 3