一、堆区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)
五、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文件里的同样
- 边运行边把常量转换成直接连接