JVM规范1.7

一、JVM体系结构

类装载器:Classload,状态class文件;
执行引擎:执行字节码或本地方法;
运行时数据区:方法区、堆区、Java虚拟机栈、本地方法栈、程序计数器;

二、JVM内存区域

运行时数据区

方法区 

属共享区域,存储已被JVM加载的类信息、常量、静态变量、即时编译后的代码等。《Java虚拟机规范》只规定有方法区概念和作用,并没有规定如何去实现。故在不同的JVM上实现是不同的,Sun公司的HotSpot上把垃圾分代搜集扩展至方法区,或者说使用永久代来实现方法区,即:永久代是HotSpot的概念,方法区是Java虚拟机规范中的定义,是一种规范。 

JDK8中,HotSpot取消了永久代,是不是就没有方法区了?当然不是,方法区是一个规范,规范没变就会一直都在。取代永久代的是元空间,区别:

存储位置:永久代是堆的一部分,和新生代、老年代地址是连续的,而元空间属于本地内存; 
存储内容:元空间存储类的元信息,静态变量和常量池等并入堆中。相当于原永久代的数据被分到堆和元空间中; 

堆区 

属共享区域,主要存放对象实例和数组。在其上进行对象内存的分配需要加锁,这也导致new对象开销比较大。JVM中的堆栈和数据结构中的堆栈是两码事。

Sun HotSpot JVM为了提升对象内存分配的效率,对所创建的线程分配独立的空间TLAB(Thread Local Allocation Buffer)缓冲区。可位于物理上不连续的空间,但逻辑上要连续,大小由JVM运行时动态决定,在TLAB上分配对象不需要加锁,保证效率,因此JVM在给线程的对象分配内存时尽量在TLAB上,但如果对象过大仍需直接使用堆空间分配。 

JVM内存分为:堆内存和非堆内存,非堆内存指的是永久代。

  堆内存分为:年轻代(YoungGen)、老年代(OldGen);默认比例是1:2;图1 

  年轻代又分为:Eden(生成区)和Survivor(幸存区);Survivor区由From Space(S0)和To Space(S1)组成;三者默认比例是8:1:1; 


Java虚拟机栈 

属线程私有,生命周期和线程一致。主要存放对象实例和数组。内部会划分出多个线程私有的分分配缓冲区(Thread Local Allocation Buffer,TLAB)。可位于物理上不连续的空间,单逻辑上要连续。 


本地方法栈 

属线程私有,生命周期和线程一致。调用非Java语言实现的方法,作用域Java虚拟机栈类似,会存放对应的局部变量、返回结果等。 


程序计数器 

属线程私有,生命周期和线程一致。空间小存放当前线程所执行方法的地址。 

内存溢出

三、JVM垃圾回收

四、JVM类加载

概念 

JVM把描述类数据的字节码.class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型。 


五、图例

图1JVM规范1.7