JAVA中栈(堆栈)与堆的数据存储方式

JAVA中栈(堆栈)与堆的数据存储方式


堆区:   堆这块区域是JVM中最大的,应用的对象和数据都是存在这个区域,这块区域也是线程共享的,也是 gc 主要的回收区,一个 JVM 实例只存在一个堆类存,堆内存的大小是可以调节的。类加载器读取了类文件后,需要把类、方法、常变量放到堆内存中,以方便执行器执行,堆内存分为三部分:新生代、年老代、永久代
1.
存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令
2.jvm
只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身 
栈区:   栈也叫栈内存,主管Java程序的运行,是在线程创建时创建,它的生命期是跟随线程的生命期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只要线程一结束该栈就Over,生命周期和线程一致,是线程私有的。基本类型的变量和对象的引用变量都是在函数的栈内存中分配。 ()栈中的数据都是以栈帧(Stack Frame)的格式存在,栈帧是一个内存区块,是一个数据集,是一个有关方法和运行期数据的数据集,当一个方法A被调用时就产生了一个栈帧F1,并被压入到栈中,A方法又调用了B方法,于是产生栈帧F2也被压入栈,B方法又调用了C方法,于是产生栈帧F3也被压入栈…… 依次执行完毕后,先弹出后进......F3栈帧,再弹出F2栈帧,再弹出F1栈帧。
1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中 
2.
每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。 
3.
栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)

方法区:    方法区是被所有线程共享,所有字段和方法字节码,以及一些特殊方法如构造函数,接口代码也在此定义。简单说,所有定义的方法的信息都保存在该区域,此区域属于共享区间。静态变量+常量+类信息+运行时常量池存在方法区中,实例变量存在堆内存中。
1.又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的classstatic变量。 
2.
方法区中包含的都是在整个程序中永远唯一的元素,如classstatic变量。 

简单程序举例分析:

Pulic classSample{     

private String name;//newSample实例化后,name放入栈区,new对象放入堆里

Public Sample(String name){//以下两个方法放入方法区(带参构造方法和普通方法)

    This.name=name;0

}

Publicvoid printName(){

System.out.print(name);

}

}

Public classTest{  //运行时,JVM把Test的信息放入方法区

    Public static void main (String[] args){

       Sample test1=new Sample(“测试1”);

       Sample test2=new Sample(“测试2”);

       //在堆中new创建2个对象,tes1与test2是引用对象,压入栈中,

             test1.printName():

             test2.printName():

}

}

程序执行过程:

    (1)系统收到我们发出的指令时,启动一个Java虚拟机进程,这个进程首先从calsspath中找到Test.class文件,读取这个文件中的字节码数据,然后把Test类的信息存放到运行时数据区的方法中,这一过程,称为Test类的加载;

       接着,Java虚拟机定位到方法区中,执行main中的第一条语句

Sampletest1=new Sample(“测试1”);Java虚拟机首先先到方法区寻找Sample类信息,有就直接访问,没有就加载Sample类的字节码,然后创建一个Sample对象实例,并且,使用引用变量test1引用这个实例对象;

(2)资源准备好了后,开始执行,Java虚拟机做的第一件事情就是在堆区中为一个新的Sample实例分配内存, 这个Sample实例持有着指向方法区的Sample类的类型信息的引用。这里所说的引用,实际上指的是Sample类的类型信息在方法区中的内存地址

(3)在JAVA虚拟机进程中,每个线程都会拥有一个方法调用栈,用来跟踪线程运行中一系列的方法调用过程,栈中的每一个元素就被称为栈帧,每当线程调用一个方法的时候就会向方法栈压入一个新帧。这里的帧用来存储方法的参数、局部变量和运算过程中的临时数据。OK,原理讲完了,就让我们来继续我们的跟踪行动!位于“=”前的Test1是一个在main()方法中定义的变量,可见,它是一个局部变量,因此,它被会添加到了执行main()方法的主线程的JAVA方法调用栈中。而“=”将把这个test1变量指向堆区中的Sample实例,也就是说,它持有指向Sample实例的引用。

OK,到这里为止呢,JAVA虚拟机就完成了这个简单语句的执行任务。

在Java语言里堆(heap)和栈(stack)里的区别

   1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。

  2. 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共享,详见第3点。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢


猜你喜欢

转载自blog.csdn.net/lin542405822/article/details/80338256