您的位置:首页 > 编程语言 > Java开发

简单的java代码在内存加载过程(详解)

2016-06-18 05:05 435 查看

内存

(1) 寄存器(Registers)。这是速度最快的存储场所,因为寄存器其他所有存储媒介都不同:它位于处理器内部。不过,寄存器的数量十分有限,所以寄存器是根据需要由编译器适当地分配。作为一个程序员,我们对此没有直接的控制权,也没办法在程序里头感觉到寄存器的任何存在迹象。

(2) Stack(栈)。位于一般的RAM(random-access memory,随机访问内存)中。处理器通过其指针(“栈指针”,stack pointer)获得处理的直接支持。栈指针若向下(后)移,会分配新的内存;若向上(前)移,则会释放那些内存。这是一种特别快、特别有效率的数据存储方式,速度仅次于寄存器。由于Java编译器有责任产生“将stack指针前后移动”的程序代码,所以它必须能够完全掌握它所编译的程序中“存在stack里头的所有数据的实际大小和存活时间”。如此一来便会限制程序的弹性。由于这个限制,尽管有些Java数据要存储在栈里——特别是对象句柄,但Java对象并不放到其中。

(3) Heap(堆)。Heap是一种通用性质的内存存储空间(也存在于RAM中),用来置放所有Java对象。“内存堆”或“堆”(Heap)胜过stack之处在于,编译器不需知道究竟得从堆里分配多少存储空间,也不需知道从堆上分配的空间究竟要存活多长的时间。因此,用堆存储数据时会得到更大的灵活性。要求创建一个对象时,只需用new即可。执行这些代码时,会在堆里分配空间。当然,为达到这种灵活性,必然会付出一定的代价:在堆里分配存储空间时会比从栈里分配花掉更长的时间(假设你真的可以在Java中像C++一样地从stack上产生对象的话)!

(4) 静态存储空间(Static storage)。这儿的“静态”(Static)是指“位于固定位置”(也在RAM里头)。静态存储空间存放着“程序运行期间”一直存在的数据。可用static关键字将某个对象内的特定成员设为静态,但Java对象本身永远都不会置入静态存储空间。

(5) 常量存储空间(Constant storage)。常量值通常被直接置于程序代码里头。因为它们永远都不会改变,所以也是安全的。有的常数需要严格地保护,所以可考虑将它们置入只读存储器(read-only memory,ROM)中。

(6) 非RAM存储空间(Non-RAM storage)。若数据完全存活于程序之外,则程序不运行时数据仍继续存在,脱离了程序的控制范围。

* 本节我们将重点看2,3,4*

new Classname的加载到内存方式

class Car{

String color;

String number;

public void run(){

System.out.println(color+”:”+number);

}

public void method(){

int x=0;

}

}

class CarDemo{

public static void main(String[] args){

//测试:Car类中的run方法

//1.创建Car的对象,给对象起个名字。

Car c = new Car();

//c是类型的变
4000
量。C指向了一个具体的Car类型的对象

c.color=”red”;

c.number=4;

//2.通过已有的对象调用该对象的功能。

c.run();

}

}

在内存加载的过程

1. 在栈中加载主方法(main)

2. 然后执行到new Car();在堆中创建一片连续的地址,并在栈中的Main方法会有Car C这个变量。而堆中的这片地址会有成员变量。例如:头地址0x22

3. Car c = new Car();所以将该地址值赋给了C = 0x22,而C是引用变量(此处省略部分)

4. c.color=”red”,c.number=4;则c指向的地址0x22, 然后逗号作用和C语言一样

5. 运行到c.run(),然后将该方法压栈(略略略).

方法体进栈的过程

请参考以上代码Car类里method()方法

Car c = new Car();

c.method();

若运行到第二个语句时,将在内存进行这样操作

将Method()方法压进栈,同时创建了int类型的X变量。

当方法执行完时,将弹栈。

变量的加载到内存的方式

变量的域范围有两种,一种是成员变量,另外一种则是局部变量。

成员变量也称之为类属性,所以在堆中创建对象的时候,对象中就已经包含了成员变量了。

而局部变量 是在方法体里,或者能说是在代码块里

成员变量和局部变量的区别:

区别一:定义的位置不痛。

成员变量定义在类中

局部变量定义在方法中以及语句里。

**区别二:内存位置不同

成员变量存储在堆内存中对象中。

局部变量存储在栈内存中方法中。

区别三:生命周期不同。

成员变量随着对象的出现而出现,随着对象的消失而消失。

局部变量随着方法运行而出现,当方法运行完弹栈而消失。

区别四:初始化不同。

成员变量因为在堆内存中,所以有默认初始化值(有关构造方法)。

局部变量没有默认初始化值,必须初始化后才可以使用。

调用构造器的加载到内存方式

class Person{

private String name;

private int age;

Person(String n ){

name = n;

}

public void speak(){

System.out.println(“name=”+name+”,age=”+age);

}

}

class PersionDemo2{

public static void main(String[] args){

Person p = new Person(“lisi”);

p.speak();

}

}

1. main 方法 进栈

2. 读到Person p = new Person(“lisi”);

new 的时候开辟了一个空间,

开始创建成员变量 name 、age ,然后取他们的默认值

String name = null int age = 0 ;

然后才调取他们的构造函数(该方法进栈),因为这里是Person(String n )

所以构造函数只初始化name。

This 原理

讲到这里,大家肯定有疑问,为什么方法进栈会知道自己是哪个对象调用的方法呢,毕竟一个类有千万个实例化后的对象。

原因就是方法在入栈的时候不止是创建局部变量还会创建一个this来装被哪个对象调用的对象地址。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: