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类型。