程序技术器:
是当前线程所执行的字节码的行号指示器,每个线程都有一个独立的程序技术器。
正在执行的是Java的方法的时候,技术器记录的是虚拟机字节码指令的地址,如果是Native方法,则为空。
唯一一个没有规定任何OutOfMemoryError情况的区域。
线程私有。
Java虚拟机栈:
是描述Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧,栈帧存储局部变量表,操作数等信息。
每一个方法的调用直到执行完成的过程,都对应这栈帧在虚拟机栈中从入栈到出栈。
栈帧随着方法调用而创建,随着方法结束而销毁。
线程私有。
本地方法栈:
与Java虚拟机栈类似,区别是一个是在java方法服务,一个在本地方法服务。
线程私有。
Java堆:
是java虚拟机所管理的内存中最大的一块。
创建的对象和数组都保存在Java堆内存中,也是垃圾收集器进行垃圾收集最重要的内存区域。因为分代收集,所以从gc的角度还 可以分为新生代和年老代。
线程共享。
方法区:
用于存储已被虚拟机加载的类信息,常量,静态变量等数据。java虚拟机把它规范为堆的一个逻辑部分。
运行时常量池:
是方法区的一个部分
Java堆栈溢出:
发生java.lang.OutOfMemoryError,要解决这个异常,一般手段都是先通过内存映像分析工具Dump出来的堆转储快照进行分析, 重点是分析内存中的对象是否还有必要继续存在,换句话说,就是要高明白是内存泄漏还是内存溢出。
如果是内存泄漏,则通过工具进一步分析泄漏对象和GC Roots链之间的引用关系,这样就可以弄明白是什么导致垃圾回收机制无 法回收他们的。
如果是内存溢出,则需要分析的是虚拟机的堆参数和机器物理内存对比看是否还可以调大,从代码上检测是否存在对象周期过 长,持有状态过长的情况,尝试减少程序运行期的内存消耗。
虚拟机栈和本地方法栈溢出:
关于虚拟机栈和本地方法栈两种异常:
线程请求栈深大于虚拟机所允许的最大栈深:StackOverflowError异常。
如果虚拟机在扩展栈的时候无法申请到足够的空间:OutOfMemoryError异常。
实验结果表明,当单个线程的时候,无论是栈帧太大还是虚拟机栈太小,在无法分配内存的时候都会报StackOverflowError.如果不限制单线程,通过不断创建线程可以造成内存溢出的情况。但是这样的内存溢出和栈的空间大小有一定关系,这样当栈的分配的内存越大,越容易发生内存溢出。原因是每个进程的内存有限,出去堆和方法区的最大值,程序技术器以及虚拟机运行需要的内存外,就被虚拟机的栈和本地方法栈给瓜分了,当栈内存过大的时候可以建立的进程数就很少,建立线程就容易把剩下的内存耗尽。如果是建立过多的线程造成了内存溢出,就只能通过减少栈的容量和最大堆来实现了。
方法区和运行时常量池溢出:
本机直接内存溢出: