JVM 内存模型
Java虚拟机
目前有三大Java虚拟机:HotSpot,Oracle JRockit,IBM J9。JRockit是Oracle发明的,用于其WebLogic服务器,IBM JVM是IBM发明的,用于其Websphere服务器。JRockit和J9不存在永久代这种说法,这里只讨论HotSpot虚拟机,这也是目前使用的最多的JVM。
JVM内存模型(JDK 1.8)
这里介绍的是JDK1.8 JVM内存模型。1.8同1.7比,最大的差别就是:元数据区取代了永久代。元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元数据空间并不在虚拟机中,而是使用本地内存。
参考: JVM内存区域划分
内存模型简介
1、程序计数器(Program Counter Register)
程序计数器是一块较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖计数器完成。
2、虚拟机栈(Java Virtual Machine Stacks)
虚拟机栈中存储了方法执行时相关信息,每个方法在执行的同时都会创建一个栈帧(Stack Frame),用于存储 局部变量、操作数栈、动态链接、方法出口等信息。每一个方法从调用到执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。虚拟机栈也是线程私有的,生命周期于线程相同。
3、本地方法栈(Method Native Stack)
本地方法栈与虚拟机栈的作用非常相似,区别是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则为虚拟机使用到的Native方法服务。
Native方法:指的就是Java程序调用了非Java代码,算是一种引入其它语言程序的接口
4、堆(Java Heap)
堆唯一的作用就是用来存放对象实例,几乎所有的对象实例都在这里分配内存。堆是Java虚拟机管理的内存中最大的一块,被所有线程共享。由于堆是垃圾收集器管理的主要区域,所以也被称为GC堆。由于现代收集器基本都采用分代收集算法,所以Java堆中还可以细分为新生代,老年代。新生代又细分为Edan区、From Survivor区(S0)、To Survivor区(S1)。
5、元空间(Metaspace)
HotSpot虚拟机在1.8之后已经取消了永久代,改为元空间,元空间存储已被虚拟机加载的类信息。元空间没有使用堆内存,而是与堆不相连的本地内存区域。即理论上系统可以使用的内存有多大,元空间就有多大,所以不会出现永久代存在时的内存溢出问题。
元空间和永久代本质上都是方法区的实现。方法区存放虚拟机加载的类信息,静态变量,常量等数据。原方法区存储的信息被分成两部分:1、虚拟机加载的类信息 2、运行时常量池,分别被移动到了元空间和堆中。
方法区与永久代的区别?
《Java虚拟机规范》只是规定了有方法区这么个概念和它的作用,并没有规定如何去实现它。在不同的 JVM 上方法区的实现肯定是不同的,同时大多数用的JVM都是Sun公司的HotSpot。在HotSpot上把GC分代收集扩展至方法区,或者说使用永久代来实现方法区。因此,永久代是HotSpot的概念,方法区是Java虚拟机规范中的定义,是一种规范,其他的虚拟机实现并没有永久代这一说法。在JDK 1.8中,元空间也是方法区的一种实现。
Java方法区和永久代
为什么废除永久代?
- 1、官方文档:移除永久代是为融合HotSpot JVM与 JRockit VM而做出的努力,因为JRockit没有永久代,不需要配置永久代
- 2、PermGen很难调整,PermGen中类的元数据信息在每次FullGC的时候可能被收集,但成绩很难令人满意。而且应该为PermGen分配多大的空间很难确定,因为PermSize的大小依赖于很多因素,比如JVM加载的Class总数,常量池的大小,方法的大小等
- 3、永久代内存经常不够用而发生内存泄露,爆出异常
java.lang.OutOfMemoryError: PermGen
- 4、永久代会为 GC 带来不必要的复杂度,并且回收效率偏低
还没有评论,来说两句吧...