Java之内存分配(图解)

文章详细解释了Java中的内存分配,包括栈、堆以及数组的内存使用。通过示例代码展示了如何在栈中分配变量和在堆中分配数组,以及当两个数组引用同一块堆内存时的操作影响。重点强调了new操作符在内存分配中的作用,以及栈和堆的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Javaの五大内存分配地:

  • 方法区
  • 本地方法栈
  • 寄存器

我们主要掌握栈和堆的分配规则。

举个例子:

public static void main(String[] args) {
    int a = 5;
    int b = 10;
    int c = a + b;

    sout(c);
}

 现在分析栈和堆中的内存分配。(由于没有new什么东西,所以不需要考虑堆内存)

 栈中的内存分配情况为:

【说明】

1. 首先main函数先入栈

2. int a 表示在栈中分配一块int大小的内存,名字叫a。a=5表示内存中存放的值为5。

3. b同理。

4. int c = a+b; 首先分别要到a、b内存中去取出数字5和数字10,将其相加,相加后的结果存放在内存c中。

二、数组的内存图

1.代码


    public static void main(String[] args) {
        int[] arr1 = new int[2];
        System.out.println(arr1);
        System.out.println(arr1[0]);
        System.out.println(arr1[1]);

        arr1[0]=11;
        arr1[1]=12;
        System.out.println(arr1[0]);
        System.out.println(arr1[1]);

        System.out.println("----------------------");

        int[] arr2 ={33,44,55};
        System.out.println(arr2);
        System.out.println(arr2[0]);
        System.out.println(arr2[1]);
    }

2.栈和堆中内存分配情况:

【说明】

1. int[ ] arr1在栈里面定义了一个变量,变量的名字叫arr,类型int。

2. new int[2];在堆里面开辟了一个小空间,长度为2,索引为0、1。

3. 通过 “=” 将这个小空间的地址值赋值给arr,而arr通过地址值也能找到该小空间。

4. arr1[0] 通过arr1定位地址值找到堆中的空间,再通过0索引找到了里面所对应的空间。

5. arr2数组同理。

 总结:

        1. 只要是new出来的一定是在堆中开辟了一个小空间。

        2. 如果new出现了很多次,那么堆里面有很多个小空间,每个小空间中彼此独立。

三、两个数组指向同一个空间的内存图

1.代码

psvm(){
    int[] arr1 = {11,22};
    int[] arr2 = arr1;

    sout(arr1[0]);
    sout(arr2[0]);
    
    arr2[0] = 33;
    
    sout(arr1[0]);
    sout(arr2[0]);
}

2.运行结果:

3.栈和堆的内存分配情况:

 【说明】

1. main方法进栈。

2. 在栈中定义arr1,在堆中开辟一个空间,里面存储11,22。再把空间的地址赋值给arr1,arr1可以通过地址找到该空间。

3. 在栈中定义arr2,把arr1所记录的内容赋值给了arr2,即把arr1的堆空间的地址赋给了arr2。所以arr1和arr2指向同一个堆空间。

4. arr2[0]=33;  将该地址空间的数组中索引为0的元素赋值为33。

5. arr1[0]和arr2[0]的值都变成了33。

 总结:当两个数组指向同一个堆空间时,如果其中一个数组对空间内的值进行赋值,那么另一个数组再次访问该空间,就是赋值后的结果了。

 制作不易,请多多支持哦(*/ω\*)

### Java JVM 内存区域分布详解 #### 1. 堆内存(Heap Memory) 堆内存是JVM管理的主要内存部分之一,主要用于存储对象实例。当`java.lang.OutOfMemoryError: Java heap space`发生时,意味着在创建新的对象时,堆内存中的空间不足以存放新创建的对象[^1]。 - **年轻代(Young Generation)** - 年轻代分为Eden区和两个Survivor区(S0和S1)。大多数情况下,新对象会在Eden区中分配。一旦Eden区满,则会触发一次Minor GC来清理该区域内的无用对象并移动存活对象到其中一个Survivor区。随着新生代空间占用率升高,Minor GC频率也会增加[^2]。 - **老年代(Old Generation)** - 经过多次Minor GC仍然存活下来的对象会被晋升至老年代。这里发生的GC称为Major GC或Full GC,通常涉及整个堆空间的扫描与整理,耗时较长。 #### 2. 方法区(Method Area) 方法区用来保存已被虚拟机加载的类信息、常量池、静态变量以及即时编译器编译后的代码等数据。自Java 8起,永久代被移除而由元空间替代;后者位于原生内存而非堆内,并且其容量仅受限于操作系统所能提供的最大可用内存范围[^3]。 - **永久代(Permanent Generation,在Java 7及更早版本存在)** - **元空间(Metaspace,从Java 8开始引入)** #### 3. 运行时常量池(Runtime Constant Pool) 这是方法区内的一部分特殊区域,用于存放编译期间产生的各类字面量和符号引用。对于字符串而言,还特别设有一个名为“字符串常量池”的子集,旨在优化相同内容字符串之间的共享机制以节省资源开销[^4]。 ```java // 字符串常量池示例 String str1 = "hello"; String str2 = "hello"; // 实际上str1 和 str2指向同一个地址 ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值