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

1、堆区

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

 堆的优劣势:

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

缺点是:

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

2、栈区

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

栈分为3部分:

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

栈的优势劣势:

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

3、方法区

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

4、Java中不同的存储数据的地方:

 寄存器(register)

  • 最快的存储区,因为它位于不同于其他存储区的地方——处理器内部

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

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

堆栈(stack)

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

堆(heap)

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

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

5、JVM内存模型

大多数JVM将内存分配为:

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

6、Method Area(方法区)

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

29bf9b965bae0ee904dd7c5e3e2a95d294e.jpg

类型信息

  • 类型的全限定名
  • 超类的全限定名
  • 直接超接口的全限定名
  • 类型标志(该类是类类型还是接口类型)
  • 类的访问描述符(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文件里的一样
  • 边运行边把常量转换成直接链接

转载于:https://my.oschina.net/u/3847203/blog/1839886

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值