浅析Java内存分配机制

        今日看了网易公开课关于java内存的课程,觉得受益匪浅,虽然算是比较浅显的理论知识,但对于写程序来说还是帮助挺大的,毕竟只有掌握了内存的分配,才可以更好的写出性能高的java程序应用。所以还是决定写出来和各位分享这课程~~

      长话短说,首先来看下整个内存总体模型(直接用笔画方便,不过字不好看= =):

      浅析Java内存分配机制_第1张图片

简单说一下,最上方低地址的是一个特殊区域,一般存储静态变量、常量等。往下是堆(heap),主要存储在程序中动态创建和释放的实例,即对象。它是从低地址向高地址增长的。最下方高地址的是栈,存储像局部变量这样编译器自动分配的内存。有个问题,一个往上增长,一个往下,那它们会不会“相撞”呢?答案是“嗯,会的,一旦发生则会出现互相修改数据的情况= =”,但是这种事件发生的概率很小,暂时不做讨论。

   那么java程序运行的时候内存的分配是什么样子的呢?咱举个例子看一看,以小见大,一目了然~~

        上代码~~首先是Point类:

 

public class Point {
	private int x;
	private int y;
	
	
	
	public Point(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}


	public void move(int dx,int dy){
		x+=dx;
		y+=dy;
	}
很简单,一个点,横纵坐标两个属性。move方法是堆点位置的移动。现在执行下面的方法:

public void run(){
		Point p1 = new Point(2,3);
		Point p2 = new Point(4,5);
		p1.move(1, 2);
	}
接下来就详细给大家说说内存是如何分配运作的~~

首先执行前两行语句,Point p1 = new Point(2,3);、Point p2 = new Point(4,5);,创建一个Point对象,此时内存是这样子滴:

浅析Java内存分配机制_第2张图片

左边堆存储对象,每个对象首先是一份额外的内存,然后是各个成员变量的内存空间,右边的栈是局部变量即对象引用p1、p2的内存空间(p1、p2为方法run的局部变量),同样起始也有一段额外内存空间,p1、p2的值为对应的对象在堆上的地址值,即引用指向对应的对象。

然后看看p1.move(1, 2);的执行,执行方法,首先在栈上开辟参数dx、dy变量的内存,还有一个this的内存,它是一个引用,指向被调用方法的对象(不然不知道哪个对象被调用= =),同样起始位置有一段额外空间:

浅析Java内存分配机制_第3张图片

然后x+=dx;y+=dy;被执行,内存变成:

浅析Java内存分配机制_第4张图片

堆上x,y的值被修改。注意move方法执行完毕后,栈上的对应的局部变量将出栈,即被释放。

加入现在有个线的类Line,代码如下:

public class Line {
	private Point beg;
	private Point end;
	public Line(Point beg, Point end) {
		
		this.beg = beg;
		this.end = end;
	}
	
	
}
run方法最后加一句Line line = new Line(p1, p2);,如下:

public void run(){
		Point p1 = new Point(2,3);
		Point p2 = new Point(4,5);
		p1.move(1, 2);
		Line line = new Line(p1, p2);
	}
执行这一句的时候,首先在栈上开辟Line的引用line,因为构造方法是方法,拥有局部p1、p2,故先在栈上开辟这两个参数的内存,然后在堆上开辟Line对象内存,两个成员变量是两个Point的引用,然后将栈上局部变量p1、p2的值赋给beg、end。如下图:

浅析Java内存分配机制_第5张图片

这样beg、end指向p1、p2指向的两个对象,随着构造方法执行完毕,Line的引用line也会指向Line对象,而局部变量p1、p2也会出栈,如下图:

浅析Java内存分配机制_第6张图片

整个run方法执行完毕后,栈上的局部变量将全部出栈,堆上的对象仍然存在,直到垃圾回收器将其自动回收。

以上就是一个简单java程序执行对应的内存分配过程,希望大家看了有所收获,能起到抛砖引玉的效果就心满意足了。欢迎大家提出疑问或者指出里面有误的地方~~

你可能感兴趣的:(java,内存分配)