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程序是多线程执行的,为了保证线程切换回来后,还能恢复到原先状态,就需要一个独立的计数器,记录之前中断的地方,可见程序计数器也是线程私有的。

 

posted @ 2019-03-30 13:48  benon  阅读(1287)  评论(0编辑  收藏  举报