java虚拟机中的堆(heap)、栈(stack)、方法区(method area)

一、堆区java

  • 存储的所有是对象,每一个对象都包含一个与之对应的class的信息。(class的目的是获得操做指令)
  •  jvm只有一个heap区,被全部线程共享,不存放基本类型和对象引用,只存放对象自己

 堆的优劣势:数组

  • 堆的优点是能够动态的分配内存大小,生存期也没必要事先告诉编译器,java的垃圾收集器会自动收取这些再也不使用的数据

缺点是:数据结构

  • 因为要在运行时动态分配内存,存取速度慢

二、栈区jvm

  • 每个线程包含一个stack区,只保存基本数据类型的对象和自定义对象的引用(不是对象),对象都存放在共享heap中
  • 每一个栈中的数据(基本数据类型和对象引用)都是私有的,其余栈不能访问

栈分为3部分:线程

  • 基本类型变量区
  • 执行环境上下文
  • 操做指令区(存放操做指令)

栈的优点劣势:3d

  • 存取速度比堆要快,仅次于直接位于CPU的寄存器
  • 但必须肯定的是存在stack中的数据大小与生存期必须是肯定的,缺少灵活性
  • 单个stack的数据能够共享
  •  stack:是一个先进后出的数据结构,一般保存方法中的参数,局部变量
  • 在java中,全部基本类型和引用类型都在stack中储存,栈中数据的生存空间通常在当前scopes内

三、方法区指针

  • 又叫静态区,跟堆同样,被全部的线程共享。方法区包含全部的class和static变量
  • 方法区中包含的都是在程序中永远的惟一的元素

四、Java中不一样的存储数据的地方:对象

 寄存器(register)blog

  • 最快的存储区,由于它位于不一样于其余存储区的地方——处理器内部继承

  • 可是寄存器的数量极其有限,因此寄存器由编译器根据需求进行分配

  • 你不能直接控制,也不能在程序中感受到寄存器存在的任何迹象

堆栈(stack)

  • 位于通用RAM中,但经过它的“堆栈指针”能够从处理器哪里得到支持
  • 堆栈指针若向下移动,则分配新的内存;若向上移动,则释放那些 内存
  • 一种快速有效的分配存储方法,仅次于寄存器

堆(heap)

  • 通用性的内存池(也存在于RAM中),用于存放因此的JAVA对象
  • 好处是:编译器不须要知道要从堆里分配多少存储区域,也没必要知道存储的数据在堆里存活多长时间

  • 所以,在堆里分配存储有很大的灵活性

五、JVM内存模型

大多数JVM将内存分配为:

  • Method Area(方法区)
  • Heap(堆)
  • Program Counter Register(程序计数器)
  • JAVA Method Stack(JAVA方法栈)
  • Native Method Stack(本地方法栈)

六、Method Area(方法区)

  • 线程共享,存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等等
  • HotSpot虚拟机上开发部署人员更愿意成为“永久代”,Permanent Generation

类型信息

  • 类型的全限定名
  • 超类的全限定名
  • 直接超接口的全限定名
  • 类型标志(该类是类类型仍是接口类型)
  • 类的访问描述符(public、private、default、abstract、final、static)

类型的常量池

  • 存放该类型所用到的常量的有序集合
  • 包括直接常量(如字符串、整数、浮点数的常量)和对其余类型、字段、方法的符号引用
  • 常量池中每个保存的常量都有一个索引,就像数组中的字段同样
  • 常量池中保存中全部类型使用到的类型、字段、方法的字符引用,因此它也是动态链接的主要对象(在动态连接中起到核心做用)

字段信息(该类声明的全部字段)

  • 字段修饰符(public、protect、private、default)
  • 字段的类型
  • 字段名称

方法信息(包含类的全部方法,每一个方法包含如下信息)

  • 方法修饰符
  • 方法返回类型
  • 方法名
  • 方法参数个数、类型、顺序等
  • 方法字节码
  • 操做数栈和该方法在栈帧中的局部变量区大小
  • 异常表

类变量(静态变量)

  • 该类全部对象共享的变量,即便没有任何实例对象时,也能够访问的类变量。它们与类进行绑定

指向类加载器的引用

  • 每个被JVM加载的类型,都保存这个类加载器的引用,类加载器动态连接时会用到

指向Class实例的引用

  •  类加载的过程当中,虚拟机会建立该类型的Class实例,方法区中必须保存对该对象的引用
  • 经过Class.forName(String className)来查找得到该实例的引用,而后建立该类的对象

方法表

  • 为了提升访问效率,JVM可能会对每一个装载的非抽象类,都建立一个数组
  • 数组的每一个元素是实例可能调用的方法的直接引用,包括父类中继承过来的方法
  • 这个表在抽象类或者接口中是没有的

运行时常量池(Runtime Constant Pool)

  •  Class文件中除了有类的版本、字段、方法、接口等描述信息外
  • 还有一项信息是常量池,用于存放编译器生成的各类字面常量和符号引用
  • 这部份内容被类加载后进入方法区的运行时常量池中存放

运行时常量池相对于Class文件常量池的另一个特征具备动态性

  • 能够在运行期间将新的常量放入池中(典型的如String类的intern()方法)
  • 运行时常量池是把Class文件常量池加载进来,每一个类有一个独立的
  • 刚开始时运行的时候常量池里的连接都是符号连接(只用名字没有实体),跟在Class文件里的同样
  • 边运行边把常量转换成直接连接
相关文章
相关标签/搜索