欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java的内存分配理解

程序员文章站 2022-06-01 11:54:10
...

本篇文章为本人学习笔记,如有错误,希望指正。

Java 程序在运行时,需要在内存中分配空间。
为了提高运算效率,就对空间进行了不同区域的划分每一片区域都有特定的处理数据方式和内存管理方式。

区域名称 作用
栈内存 方法运行时,进入的内存,局部变量都存放于这块内存当中
堆内存 new出来的内容都会进入堆内存,并且会存在地址值
方法区 字节码文件(.class文件)加载时进入的内存
本地方法栈 调用操作系统相关资源
寄存器 给CPU使用
  • 注意:
    • JDK7 : 方法区 ( 永久代 ) 在堆内存的
    • JDK8 : 方法区成为了一块独立的内存空间 ( 元空间 )

我们通常直接以 【类型 变量名 = 常量;】定义出来的变量都是在栈内存中。

1. 数组中的内存分配

1.1 单个数组

Java的内存分配理解

如图所示,数组变量的声明都在栈中,但是它的地址和对应值都再堆内存中,并且每个格子都有索引和值。

1.2 多个数组

Java的内存分配理解

以此类推,两个不同的数组分配了两个空间来存放索引和对应值。

1.3 多个数组指向相同内存

Java的内存分配理解

要注意的是,如果存在A,B数组,且数组A被赋值给数组B,那么两个数组将在堆中将共用一个内存空间。

2.方法中的内存分配

  • 方法没有被调用的时候,都在方法区中的字节码文件(.class)中存储;
  • 方法被调用的时候,需要进入到栈内存中运行。

Java的内存分配理解

  • 栈就像弹夹,最先压入的子弹,最后才打出。

记忆:栈 —— 先进后出

Java的内存分配理解

  • 如图所示,我们在定义一个方法并在main方法里调用时,栈内存和方法区是这样分配的。

3. 方法参数传递的内存分配

3.1 方法参数传递基本类型

public class ArgsDemo01 {
    public static void main(String[] args) {
        int number = 100;
        System.out.println("调用change方法前:" + number);
        change(number);
        System.out.println("调用change方法后:" + number);
    }

    public static void change(int number) {
        number = 200;
    }
}

运行结果:
调用change方法前:100
调用change方法后:100

  • 结论:
    基本数据类型的参数,形式参数的改变,不影响实际参数。
  • 结论依据:
    每个方法在栈内存中,都会有独立的栈空间,方法运行结束后就会弹栈消失。

Java的内存分配理解

3.1 方法参数传递引用类型

public class ArgsDemo02 {
    public static void main(String[] args) {
        int[] arr = {10, 20, 30};
        System.out.println("调用change方法前:" + arr[1]);
        change(arr);
        System.out.println("调用change方法后:" + arr[1]);
    }

    public static void change(int[] arr) {
        arr[1] = 200;
    }
}

运行结果:
调用change方法前:20
调用change方法后:200

  • 结论:
    对于引用类型的参数,形式参数的改变,影响实际参数的值。
  • 结论依据:
    引用数据类型的传参,传入的是地址值,内存中会造成两个引用指向同一个内存的效果,所以即使方法弹栈,堆内存中的数据也已经是改变后的结果。
    Java的内存分配理解