java内存分配中的栈:
在函数中定义的一些基本类型的变量数据和对象的引用变量都在函数的栈内存中分配。当在一段代码块定义一个变量时,java就在栈中为这个变量分配内存空间,当该变量退出该作用域的时候,java就会自动释放掉为该变量分配的内存。
java内存分配中的堆:
当用new关键字创建的对象或者数组时候,就会在堆内存中分配内存空间。而此时栈中就可以定义特殊的变量,此变量的取值就是数组或者对象在内存中的首地址,栈中的变量称为数组或对象的引用变量,也就是一个名字。当程序运行到使用new关键字创建的对象或者数组代码块之外时候,数组和对象在堆中的内存空间不会自动释放,而会在以后某个时间被垃圾回收器收走。这就是java比较占内存的原因。而自动垃圾回收器是jvm管理的。
常量池:
常量池是在编译时期被确定并保存在已编译的.class文件的一些数据。包括代码中定义的的各种基本类型(如:int,long)和对象型(如string及数组)的常量值还包含一些文本形式出现的符号引用,比如:类和接口的全限定名;字段的名称和描述符;方法的名称和描述符。
虚拟机会为每个被装在的类型保持一个常量池。
堆和栈各自的优缺点:
堆:可以动态的分配内存大小,生存期也不必事先告诉编译器,因为他是在运行时动态分配内存的。但缺点是要在运行时动态分配内存,存取的速度较慢。
栈:存取速度比堆快,仅次于寄存器。栈中的数据可以共享。
例:int a=3;int b=3;
编译器在处理int b=3;时会在栈中创建一个b的引用,之后会在栈中查找是否有3这个值,栈中已经有3这个值,便将b直接指向3.这样就出现a,b同时指向3。这时如果再令a=4;那么编译器会重新搜索栈中是否有这个值,如果没有,则将4存放进来,并令a指向4。如果已经有了,就直接将a指向这个地址。
需要注意的地方:
这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况修改a不会影响到b,他是有编译器完成的,有利于节省内存空间。而一个对象引用变量修改了内部的数据和函数的状态,会影响到另一个对象引用此对象变量。
栈的缺点是:存放在栈中的数据的大小和生存期必须是确定的,缺乏灵活性。
java中的静态域:
存放在对象中用static修饰的静态成员。
|