Java内存分配与管理是Java的核心技术之一,一般Java在内存分配时会涉及到以下区域:
1.栈区:由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2.堆区:由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
3.全局区(静态区):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。
4.文字常量区:常量字符串就是放在这里的,程序结束后由系统释放 。
5.程序代码区 :见名思意:存放代码的区域。
堆栈内存的分配
栈区:局部变量存在栈内存中。函数的参数值也存放着栈区。保存类的实例,即堆区对象的引用(指针)。
堆:用来存放动态产生的数据,比如new出来的对象。注意创建出来的对象只包含属于各自的成员变量,并不包括成员方法。因为同一个类的对象拥有各自的成员变量,存储在各自的堆中,但是他们共享该类的方法,并不是每创建一个对象就把成员方法复制一次。常量池存在于堆内存。
代码:package string;
public class memonry {
/**
* @param args
* a1和a2是局部变量,放在栈区,而new出的对象放在堆区,堆区还有某类的成员变量
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
a a1=new a();
a1.a=1;
a1.b="asd";
a a2=new a();
a2.a=2;
a2.b="a2";
}
}
class a{
int a;
String b;
}
如果另a2=a1;则图就变成如下所示
原因:a2=a1将a1指向堆的地址给了a2,即a2也指向了a1的堆地址。这样原来的那个a2指向的内存就变成Java中所谓的垃圾了,就会被jvm垃圾回收机制所回收。
static的用法:
静态static:静态会在堆内存创建一个静态内存区。静态有:静态属性,静态方法,静态类。而静态方法不能调用非静态数据,
因为静态属性依赖于类,而不是对象。而非静态依赖于对象,静态类一旦创建,只会有一个,并且在该类中是共享的。一但使用
静态属性,那么就会自动赋一个值,比如int型的话默认就为0,boolean的就为false,string就为null。如:某个类中有静态属
性时,不应该new一个对象去操作该属性,而是应该直接使用该类名去操作他。
使用static的优点:
1.一个静态属性在堆内存只能存在一个,即大家可以共享该属性值。
2.如果一个对象数组中其中的某人属性大家都是相同的,即可以使用静态,这样可以节省内存空间。
3.静态一旦创建,生命周期就会从创建开始到该程序结束才会死亡。
4.静态依赖于类,而不是对象。
代码:
public class Static {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
c.number=12;//通过类名直接更改静态属性,
c c1=new c();
//c.number=11;//这样也可以,但会给人错觉,认为是对象去操作该静态类,所以不提倡这种写法。
c1.a();
c.b();
c.c=122;
c.b();
}
}
class c{
public static int c;
static boolean a;
static int number;
String name;
public void a(){
System.out.println(number);
System.out.println(c);
}
public static void b(){
//System.out.println(name);//因为name为非静态属性,而该方法为静态方法,所以无法调用该属性。
System.out.println(a);
System.out.println(c);
}
}