【Java】内存分析

程序与内存

  程序要想运行,一般需要以下三个步骤,如图1-1所示:

1、将程序加载到内存区。
2、操作系统代码找到程序的main方法开始执行。
3、执行过程中进行内存管理。

这里写图片描述
图1-1 程序执行过程

一个程序的内存分析

  比如我们写了一个求空间中两点之间距离的程序。很简单,只要一个点对象就可以完成了。代码如下:

class Point {
    double x, y, z;

    Point(double _x, double _y, double _z) {
        x = _x;
        y = _y;
        z = _z;
    }

    void setX(double _x) {
        x = _x;
    }

    double getDistance(Point p) {
        return (x - p.x)*(x - p.x) + (y - p.y)*(y - p.y) + (z - p.z)*(z - p.z);
    }

}

  同样,也需要一个类来使用Point类,我们将这个使用过程写在了main函数中,代码如下:

public class TestPoint {
    public static void main(String[] args) {
        Point p = new Point(1.0, 2.0, 3.0);
        Point p1 = new Point(0.0, 0.0, 0.0);
        //计算点p到原点的距离
        System.out.println(p.getDistance(p1));
        //设置点的x坐标为5
        p.setX(5.0);
        //计算点p到点(1.0,1.0,1.0)的距离
        System.out.println(p.getDistance(new Point(1.0, 1.0, 1.0)));
    }
}

  我们开始看第一句代码:Point p = new Point(1.0, 2.0, 3.0);,分析其执行过程和相应的内存变化。它首先可以分成两个部分:①调用构造方法生成Point对象;②声明Point对象并为其赋值。new Point(1.0, 2.0, 3.0)的过程其实就是在堆内存中新建了一个Point对象,里面有三个成员变量(x = 1.0 ,y = 2.0 ,z = 3.0)。然后再执行声明和赋值,Point p即Point对象的声明过程,在内存的栈空间中分配一块儿内存,通过名字p调用,为其赋值的过程即:将堆中new出来的对象的引用保存到这块栈空间中。内存状态如图2-1所示:

这里写图片描述
图2-1 第一句代码执行完成后内存图

  第二句代码的分析过程同一类似,不再赘述,执行完成后内存空间状态如图2-2所示:
这里写图片描述
图2-2 第二句代码执行完成后内存图

  第三句代码: System.out.println(p.getDistance(p1)),其中println是字符串的打印输出方法,而括号中是点对象方法的调用,它们的过程是一样的,那我们直接分析括号中的方法调用过程,即:p.getDistance(p1)。
  
  我们可以看到 getDistance(Point p)方法中有一个参数Point p,p也叫局部变量。当我们调用这个方法的时候,在栈内存中会分配一直临时变量p,指向p1的引用对象。计算完成后,会有一个返回值,内存中的栈空间会分配一块儿空间来存储这个返回值。这时方法调用完毕,为其局部变量分配的内存空间收回,即局部变量p消失。当System.out.println()执行完毕,将返回值打印在界面上,为返回值分配的内存消失。所以第三句代码执行完成之后,内存空间无变化。(它曾经来过,它现在没了)
  
  第四句代码: p.setX(5.0);,调用setX()方法将p引用的对象的x值修改为5.0,此时内存空间状态如图2-3所示:
这里写图片描述
图2-3 第三句代码执行完成后内存图

  最后一句代码: System.out.println(p.getDistance(new Point(1.0, 1.0, 1.0)));。遇到稍复杂的表达式,我们应从里向外分析。 new Point(1.0, 1.0, 1.0)也就是在堆中新建一个点对象,里面有三个成员变量(x=1.0 , y=1.0 ,z=1.0)。然后调用对象p的 getDistance()方法,新建一个临时变量p(参数),指向刚new出来的这对象,计算结果,返回并打印计算结果,方法执行完毕,为局部变量p和返回值分配的内存空间消失。堆中的点对象(1.0,1.0,1.0)没有引用指向它,等待垃圾收集器回收。此时内存空间状态如图2-4所示:
这里写图片描述
图2-4 最后一句代码执行完成后内存图

  main方法执行完成后,局部变量p和p1也就消失了,其引用的对象等待垃圾收集器回收。

总结

  1. 基本数据类型只在栈中分配一块空间。
  2. 引用类型在栈中和堆中各有一块内存空间。
  3. 方法执行完毕,为其分配的局部变量消失,栈中的返回值如果没有用到也会默默的消失。
  4. 垃圾收集器判断一个对象是否需要回收的标准是:有没有引用指向它。如果没有,则回收。
  5. 字符串常量在DataSegment和栈中分配内存空间,相同字符串常量的引用相同(java优化机制)。
  6. 字符串变量在堆栈中分配内存,相同字符串的引用不同,并重写了equals()方法,以方便比较字符串内容是否一致。
评论 46
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值