Java的内存管理机制
JVM运行时的数据区域:程序计数器,Java虚拟机栈,本地方法栈,Java堆,方法区,运行时常量池,(直接内存)
按照线程共享分类:线程独有
1.程序计数器,占用非常小的空间,用于维护线程切换时执行过程的正确性
2.Java虚拟机栈:Java线程没执行一个方法都会生成一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息,而栈帧就存储在Java虚拟机栈中。使用-Xss 来控制栈的大小。有两种情况会导致虚拟机栈报错:a.栈帧的数量过多,报错SOF!例如无限递归(windows64位我测出来是 6w+报错);b.没创建一个线程都会为他分配一个虚拟机栈,如果新创建线程时,无法分配新的虚拟机栈则报OOM;
3.本地方法栈:和Java虚拟机栈没有什么区别,只不过面向本地Native方法。(Sun Hotspot是将两个栈合并在一起了)
按照线程共享分类:线程共享
1.Java堆:规范描述,所有的对象实例和数组都要在堆上分配。现在流行可扩展大小,使用-Xmx 和-Xms 进行控制,无法再扩展时,就会抛出OOM异常
2.方法区:存储已经被虚拟机加载的类信息、常量、静态变量、即时编译后的代码数据。用-XX:MaxPermSize进行大小控制,当无法满足内存分配是时抛出OOM。(关于-XX:PermSize使用,我在Java8上测试,提示-XX:MaxPermSize无效的,需要研究,查看资料,发现Java8中的永久代没有啦,使用什么元空间。需要学习Java7-Java8的内存模型的变化)
3.运行时常量池:是方法区的一部分,用于存储各种字面变量和符号应用。比如较小的int、调用String的intern()方法。
直接内存:并不在JVM规范里面,不过会被频繁的使用,使用-Xmx进行大小控制,如果没有足够的空间则抛出OOM