JVM,这个东西是我们每个Java程序员都认识、了解的一个知识点,今天捡起这个东西,好好做个总结。要了解JVM之前,我们先来认识一下Java 虚拟机所管理的内存运行模块。
Java 虚拟机所管理的内存运行结构图
1、线程独占区域模块
1.1、程序计数器 程序计数器(Program Counter Register)是每个线程独立占用多一块较小的内存空间,它是当前线程执行字节码的行号指示器。该模块在JAVA虚拟机内存规范中唯一不会有出现OutofMemoryError情况的一个区域。如果该线程在执行JAVA方法,该线程的计数器记录的正在执行虚拟字节码指令的地址,如果是在执行native方法,那么这个计数器的值为undefined。
1.2、虚拟机栈 虚拟机栈是运行java方法的一个动态内存模型。 栈帧:每个执行的方法都会创建一个栈帧,一旦方法执行完毕,则销毁栈帧。栈帧主要用于局部变量表、操作数栈,动态链接、方法的出口等。(该区域如果满了,则StackOverError,栈溢出的情况) 局部变量表——存放编译期可知的各种基本数据类型,引用类型,局部变量在编译期便已经确定,在运行过程中不会发生)
1.3、本地方法栈 本地方法栈为虚拟机执行native方法服务。
1.4、堆 堆是JVM中内存分配最大一块空间,主要由新生代(新生代分为Eden Space和Surivor Space)和老年代组成。堆主要存放对象实例和数组。在该区域会抛出OutOfMemoryError的问题。
1.5、方法区 存储虚拟机加载的类信息(类的版本、字段、方法、接口),运行时常量池,静态变量,即时编译后的代码数据。该区域也会抛出OutOfMemoryError的问题。
1.6、运行时常量池 属于方法区的一部分,用于存放编译期生成的各种字面量和符号引用,在编译过程和运行中都可以将常量放入常量池中,但是内存有限,可能会由于无法申请到内存,抛出OutOfMemoryError的问题。
1.7、直接内存 非虚拟机运行时数据区的部分 在jdk1.4之后引入了NIO类,这个类中是基于Channel和Buffer的IO方式,可以使用Native函数库直接分配堆外内存,然后通过在java堆中一个DirectByteBuffer对象这块内存引用进行操作。避免了Java和Native堆中来回的数据耗时的操作。同时也会引发OutOfMemoryError的问题。