JavaEE-05-Java中内存的分配
Java程序为了提高程序的效率,就对数据进行了不同空间的分配,具体如下:
1.栈:存放的是局部变量;---重点
2.堆:存放的是所有new出来的东西;---重点
3.方法区:(面向对象的东西); ---重点
4.本地方法区:存放的是和系统相关的东西,比如Windows、Linux。
5.寄存器:CPU使用的。
以下着重介绍堆和栈!
栈(stack)和堆(heap)都是JAVA在RAM中存放数据的地方。
*与C++不同,JAVA自动管理栈和堆,程序员不能直接的设置栈和堆。
栈内存:
存储的都是局部变量,而且变量所属的作用域一旦结束,该变量就自动释放。
堆内存:
存储的是数组和对象(其实数组也是对象),凡是new建立在堆中。
特点:1.每一个实体都有首地址值;
2.堆内存中的每一个变量都有默认初始化值,根据类型的不同而不同;
栈和堆在内存中的存储方式可参考下图:
举例:int[] arr = new int[3];
步骤:
1,创建变量arr,且这个局部变量在主函数中,故主函数的代码段先进栈;
2,右边用new建立的对象是实体,故放在堆中;
3,给该对象分配一个内存地址,用来存放该对象,比如:0x0045;(堆会对其中的对象进行默认初始化)
4,将对象的地址0x0045赋给栈中的变量arr,而arr就指向堆中的这个地址(也可以作称作引用这个地址),类似于c++中的指针。
栈的优势:存取速度比堆要快,仅次于直接位于CPU中的寄存器。
栈的缺点:1.存在栈中的数据大小和生存期必须是确定的,缺乏灵活性。
2.栈数据在多个线程或者多个栈之间是不可以共享的。(但是,在栈内部多个值相等的变量是可以指向一个地址的)
堆的优势:可以动态的分配内存大小,生存期也不必事先告诉编译器,JAVA的垃圾收集器会自动收走不用的数据。
堆的缺点:由于要在运行时动态分配内存,存取速度较慢。
JAVA中的数据类型有两种:
一.基本类型(byte,short,int,long,float,double,boolean,char)
这种类型定义的变量被称作自动变量,自动变量存的是字面值,不是类的实例(即不是类的引用)。
比如:int a=3,long b=255L 这些字面值的数据,由于大小可知,生存期可知,出于追求速度的原因,就存在于栈中。
二.包装类数据(如Integer,String,Double等将相应的基本数据类型包装起来的类,这些类数据全部存在于堆中)
JAVA用new语句来显式的告诉编译器,在运行时才根据需要动态创建,因此比较灵活,但缺点是要占用更多的时间。
注意:包装类的值不可修改!
--------------------------------------------------------------------------------------------------------------------------------------------
由上图1可知,JVM的基本结构包括:类装载器,内存区域,执行引擎,本地库接口。
下面主要介绍一下内存区:
1.虚拟机栈
每当启动一个新线程的时候,java虚拟机都会为它分配一个java栈,故每个线程包含一个栈区。
每个栈中的数据都是私有的,其它栈不能访问。栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区。
2.堆内存
存储的全部是对象,每个对象包含一个与之对应的class信息-----class的目的是得到操作指令。
jvm只有一个堆区被所有线程共享,堆区中不存放基本类型和对象引用,只存放对象本身。
3.方法区
在方法区中,存储了每个类的信息(包括类的名称、方法、字段)、静态变量、常量以及编译器编译后的代码等。
4.本地方法栈
和虚拟机栈的作用差不多,只不过是为JVM使用到的native方法服务的。
*.在HotSopt虚拟机中直接就把本地方法栈和虚拟机栈合二为一了。
5.程序计数器
用于保存当前线程执行的内存地址。
由于JVM程序是多线程执行的,为了保证线程切换回来后,还能恢复到原先状态,就需要一个独立的计数器,记录之前中断的地方,可见程序计数器也是线程私有的。