java内存相关及程序初始化顺序

来源:互联网 发布:石家庄以岭药业 知乎 编辑:程序博客网 时间:2024/05/22 00:22

1、heap和stack的区别

什么时候使用heap和stack不取决于变量类型,而是取决于要变量的生存空间(内存生存期??)。例如:全局变量定义在heap中,动态局部变量定义在stack中。Heap的使用代价要比stack高,而且要慢。

Heap速度慢的原因有:
  (1)分配操作:特别是空闲列表没有块时;

  (2)释放操作:释放内存时的收集操作;

  (3)堆竞争:多线程时;

总之,heap速度慢是因为频繁的分配和重分配。

stack的空间大小有限定,vc的缺省是2M。栈不够用的情况一般是程序中分配了大量数组和递归函数层次太深。有一点必须知道,当一个函数调用完返回后它会释放该函数中所有的栈空间。栈是由编译器自动管理的,不用用户操心。

heap是动态分配内存的,并且你可以分配使用很大的内存。但是用不好会产生内存泄漏。并且频繁地malloc和free会产生内存碎片(有点类似磁盘碎片),因为c分配动态内存时是寻找匹配的内存的。而用栈则不会产生碎片。

heap:堆,在程序中,使用堆来动态的分配和释放对象,也就是用户new出来的内存,必须用delete释放。当new了对象但没有释放时,就会造成内存泄漏。Java的垃圾回收机解决了这个问题,它会帮你释放这部分内存。

下列情况下调用堆操作:事先不知道程序所需对象的数量和大小;对象太大而不适合堆栈分配程序。另外,全局变量、静态变量都是创建在heap上的。注:java这中,没有全局变量,只有静态变量。

stack:栈,其上内容是编系统分配给进程的,只要进程结束就会自动回收。函数体内定义的变量会保存在stack中。因此在GC(没有指针的语言)中,全部分配在heap中,就没有stack这样的说法了。栈是先入后出的,一般是由高地址向低地址生长。

例1:

int a = 0; 全局初始化区

char *p1; 全局未初始化区


main()

{

int b; 栈

char s[] = “abc”;栈

char *p2; 栈

char *p3 = “123456″; 123456在常量区,p3在栈上。

static int c =0; 全局(静态)初始化区

 

p1 = (char *)malloc(10);

p2 = (char *)malloc(20);

分配得来得10和20字节的区域就在堆区。

strcpy(p1, “123456″); 123456放在常量区,编译器可能会将它与p3所指向的”123456″优化成一块。 

}

例2:
char s1[] = “aaaaaaaaaaaaaaa”;
char *s2 = “bbbbbbbbbbbbbbbbb”;
aaaaaaaaaaa是在运行时刻符值的,而bbbbbbbbbbb是在编译时就确定的

但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。

在C++中,指针长度为四字节,并且都是变量或者参数形式存在的,所以都存贮在栈中;而指针所指向的对象是new在堆中的。

2、java中的static

从某种程度上可以说java中的static函数和变量类似于C语言中的全局函数和全局变量。

(1)、static变量

整个程序中,只有一份,即只分配一块存储空间,而且所有此类的方法都可以操作修改该空间。Static变量或者static程序段在第一次装载时就进行初始化,涉及继承时,先初始化父类的static变量,然后是子类的static变量。

(2)、static方法

不需要创建对象就可使用,因此静态方法常用来为应用程序提供一些使用的方法。静态方法的调用方式为“类名.方法名”。

(3)、static类

通常一个普通类不允许声明为静态的,只有一个内部类才可以。这时这个声明为static的内部类可以直接作为一个普通类来使用,而不需实例一个外部类。

3、变量的初始化顺序

装载时初始化static变量及static程序段内的变量:先父类,后子类;

装载完毕,初始化main()内的变量―>创建对象,先初始化此类的变量,再调用构造函数:先父类构造函数,再子类构造函数。

原创粉丝点击