程序计数器
如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是本地(Native)方法,这个计数器值则应为空(Undefined)。此内存区域是唯 一一个在《Java虚拟机规范》中没有规定任何OutOfMemoryError情况的区域。
特点
- 线程私有
- 不存在内存溢出
虚拟机栈
- 每个线程会产生对应的一个虚拟机栈
- 每个方法被执行的时候,Java虚拟机都 会同步创建一个栈帧[1](Stack Frame)用于存储局部变量表、操作数栈、动态连接、方法出口等信 息。每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
局部变量都是在线程内创建销毁的,因此是线程安全的
栈内存溢出栈帧过多导致栈内存溢出
栈帧过大导致栈内存溢出
设置栈大小-Xss2048kb
用top定位哪个进程对cpu的占用过高
ps H -eo pid,tid,%cpu | grep 进程id (用ps命令进一步定位是哪个线程引起的cpu占用过高)
jstack 进程id
可以根据线程id 找到有问题的线程,进一步定位到问题代码的源码行号
本地方法栈
为调用本地方方法提供内存空间
堆
对于java应用程序来讲,堆是jvm所管理的内存中最大的一块。是被所有线程共享的一块区域,并在虚拟机启动时创建。此区域的唯一目的就是存放对象实例,java程序里“几乎”所有的对象实例都会在这里创建并分配内存。
jvm规范中规定:
堆可以处于物理上不连续的内存空间中,但在逻辑上它应该 被视为连续的,这点就像我们用磁盘空间去存储文件一样,并不要求每个文件都连续存放。
堆既可以被实现成固定大小的,也可以是可扩展的,不过当前主流的Java虚拟机都是按照可扩展来实现的。假如堆中没有内存完成实例分配了,并且也无法进行扩展时 jvm 就会抛出 OutOfMemoryError 异常。
特点
- 是线程共享的,所以堆中对象都需要考虑线程的安全问题。
- 有垃圾回收机制
- 会内存溢出
堆内存溢出
虽然有垃圾回收机制,当对象不会再被使用时就会被当作垃圾回收释放掉。
但是对象不断被产生并且任然有在使用时,这个时候这些对象并不会被当作垃圾回收掉,当对象达到一定的数量时就会使得堆内存被耗尽,从而产生堆内存溢出问题。
设置堆大小-Xmx 和 -Xms
方法区
是各个线程共享的内存区域,它用于存储已被虚拟机加载 的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。用于存储和类的结构相关的信息,比如类的成员变量、方法数据、成员方法和构造器方法代码部分,类的构造器,运行时常量池等。
方法区内存溢出
方法区在申请内存时发现内存不足了,它也会让虚拟机抛一个 OutOfMemoryError 异常。
由于jdk1.8使用的是本地内存,不受jvm内存限制,一般jdk1.8方法区不会内存溢出,如果内存溢出了很大原因是本地内存不够了