(1)基本概念:
jvm是可运行java代码的假想计算机 包括一套字节码指令集 一组寄存器 一个栈 一个垃圾回收 堆 和一个存储方法域 JVM是运行在操作系统之上的,与硬件没有直接的交互字节码指令集 寄存器 栈 垃圾回收 堆 存储方法域
内存模型
!
在这里插入图片描述
栈(stack) 是由基本数据类型 int boolean byte[] 等基本数据类型组成的 而且线程是私有有的
**堆(heap) ** 里面放的是对象 并且 线程公有
程序计时器(pc register) 主要的作用 作为存档来记录 当前线程具体运行到哪个位置
方法区(methed area) 存放一些常量 类 结构字段 方法 等源数据信息 运行时常量区 线程公有
方法区 是jvm抽象的规范
原空间(matespace)jdk1.8之后用 本地内存
永久代(premGen)jdk1.8之前用 堆的内存
本地方法栈(native methed stack)
本地方法就是其他语言编写的 交由java运行的
使用本地方法的栈空间 比如jdk里面使用native x修饰的方法 (Thread.sleep());为java运行其他语言 提供了可能
三 回顾永久代与方法区的关系
如果在HotSpot虚拟机上开发,部署,方法区是规范,永久代是Hotspot针对该规范进行的实现。在Java7及以前的版本中,方法区都是永久代实现的。
为什么会用原空间替换了永久代呢???
可以看到在jdk1.8之前 方法区的内存和堆的物理存储都是连续的
永久代的大小配置
- -XX:PermSize:设置永久代的初始大小。
- -XX:MaxPermSize:设置永久代的最大值,默认是64M。
对于永久代,如果动态生成很多class的时候,很有可能出现java.lang.OutOfMemoryError:PermGen space错误,这是因为永久代空间配置的大小有限。在典型的单一应用中,需要编写和加载很多的jsp页面,就会出现java.lang.OutOfMemoryError。
在JDK1.8版本之后,方法区存在于元空间(Metaspace)。物理内存不再与堆连续,而是直接存在于本地内存中,理论上,机器内存有多大,元空间就有多大。
综上所述,表面上是为了避免OOM异常,因为通常使用PermSize和MaxPermSize设置了永久代的大小上限,但是不是总能设置到刚刚合适的大小,而使用默认值是很容易遇到OOM错误。当使用元空间时,可以加载多少类的元数据就不再由MaxPermSize控制,而是由系统的实际可用空间来控制。