一、JVM内存区域
1、方法区
用于存储虚拟机加载的类信息、常量、静态变量、以及在类中声明的各种方法、方法字段等等,是各个线程共享的内存区域。在该区域进行内存回收的主要目的是对常量池的回收和对内存数据的卸载。
-
默认最小值为16MB,最大值为64MB,可以通过-XX:PermSize 和 -XX:MaxPermSize 参数限制方法区的大小。
-
当方法区无法满足内存需求时,将抛出 OutOfMemoryError 异常。
- 运行时常量池:是方法区的一部分,存储 Java 类文件常量池中的符号信息,用于存放编译器生成的各种符号引用。
2、虚拟机栈
java方法执行的内存模型,每个方法被执行的时候都会创建一个“栈帧”用于存储局部变量表(包括参数)、操作数栈、帧数据区、方法出口等信息。生命周期与线程相同,是线程私有的。
- 对象可能分配于此(判断是否逃逸):
详细
hollis博客 - 当栈空间无法满足内存需求时,将抛出 StackOverFlowError异常。
- 局部变量表:局部变量表存放了编译器可知的各种基本数据类型、对象引用(引用指针,并非对象本身),其中long和double类型的数据会占用2个局部变量的空间,其余数据类型只占1个。局部变量表所需的内存空间在编译期间完成分配,在运行期间栈帧不会改变局部变量表的大小空间。
- 操作数栈:是一个临时数据存储区域,它是通过入栈和出栈来进行操作的。
- 帧数据区:java栈帧还需要一些数据来支持常量池解析、正常方法返回以及异常派发机制。这些数据都保存在java栈帧的帧数据区中。
3、本地方法栈
与虚拟机栈基本类似,区别在于虚拟机栈为虚拟机执行的java方法服务,而本地方法栈则是为Native方法服务。
4、JAVA堆
java虚拟机所管理的内存中最大的一块内存区域,也是被各个线程共享的内存区域,在JVM启动时创建。
-
大小通过-Xms(最小值)和-Xmx(最大值)参数设置,-Xms为JVM启动时申请的最小内存,-Xmx为JVM可申请的最大内存。为避免在运行时频繁调整Heap的大小,通常-Xms与-Xmx的值设成一样。
例:-Xmx256m来设置堆内存最大的大小为256MB。
-
当堆空间无法满足内存需求时,将抛出 OutOfMemoryError 异常。
-
常见的垃圾回收算法主要有:引用计数器法、标记清除法、复制算法、标记压缩法、分代算法、分区算法。
- 采用分代收集算法,堆被划分为新生代和老年代。
- 可以用JConsole或者 Runtime.maxMemory(), Runtime.totalMemory(),Runtime.freeMemory()来查看Java中堆内存的大小。
5、程序计数器
最小的一块内存区域,它的作用是当前线程所执行的字节码的行号指示器,在虚拟机的模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。
二、直接内存
1、概要
不是虚拟机内存的一部分,也不是Java虚拟机规范中定义的内存区域。
- jdk1.4中新加入的NIO,引入了通道与缓冲区的IO方式,它可以调用Native方法直接分配堆外内存,这个堆外内存就是本机内存,不会影响到堆内存的大小。
三、 参考资料
链接:Java虚拟机的内存组成以及堆内存介绍-HollisChuang's Blog
链接:Java堆和栈看这篇就够 - Johnny-Zhuang's Technology Blog
网友评论