JAVA内存管理

JAVA内存管理_第1张图片

  1. 程序计数器:当前线程所执行的字节码的行号指示器。(内存较小,唯一一个有规定任何OutOfMemoryError情况的区域。)
  2. Java虚拟机栈(是Java方法执行的线程内存模型:每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧[1](Stack Frame)用于存储局部变量表、操作数栈、动态连接、方法出口等信息)(常说的栈指虚拟机栈中局部变量表部分)
    2.1 局部变量表:基本数据类型,句柄等
    2.2 StackOverflowError:线程请求的栈深度>虚拟机所允许的深度
    2.3 OutOfMemoryError:若Java虚拟机栈容量可以动态扩展,当栈扩展时无法申请到足够的内存
  3. 本地方法栈:为虚拟机本地方法服务(同上:StackOverflowError和OutOfMemoryError)
  4. 堆(线程共享):虚拟机启动时创建,存放对象实例,垃圾收集器管理的内存区域(参数-Xmx和-Xms设定大小,可能出现OutOfMemoryError)
    4.1新生代
    4.2老年代
    4.3永久代

5.方法区:(线程共享)存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等(OutOfMemoryError)

运行时常量池:(类加载时)用于存放编译期生成的各种字面量与符号引用

6.直接内存:(OutOfMemoryError)

对象分配内存流程如下
JAVA内存管理_第2张图片
对象存储布局如下:

  1. 对象头
    1.1 存储对象自身的运行时数据(哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳)
    1.2 类型指针
    1.3 数组(记录数组长度)
  2. 实例数据:对象真正存储的有效信息(存储顺序会受到虚拟机分配策略参数(-XX:FieldsAllocationStyle参数)和字段在Java源码中定义顺序的影响。)

+XX:CompactFields:子类中较小的会插入父类较大的

  1. 对齐填充

栈:存放引用地址-》堆(对象实例数据和对象类型数据指针)-》方法区(对象类型数据)

出现OOM处理方式如下:(Eclipse Memory Analyzer)
1 首先分析是内存泄漏还是内存溢出
2 若为内存泄漏,则分析GC Roots引用链信息
3 内存溢出(设置-Xmx与-Xms)代码上检查
是否存在某些对象生命周期过长、持有状态时间过长、存储结构设计不合理等情况,尽量减少程序运行期的内存消耗。

栈容量设置:-Xss
JDK1.6 之前:

      -XX:PermSize和-XX:MaxPermSize(永久代(常量池中:本地方法栈中),之后在元空间(堆))

JAVA1.8:

      -XX:MaxMetaspaceSize:元空间最大值
      -XX:MetaspaceSize:元空间的初始空间大小,以字节为单位,达到该值就会触发垃圾收集进行类型卸载,同时收集器会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过-XX:MaxMetaspaceSize(如果设置了的话)的情况下,适当提高该值
      -XX:MinMetaspaceFreeRatio:

直接内存溢出:OOM是内存很小

     -XX:MaxDirectMemorySize(默认java堆的最大值):

你可能感兴趣的:(java)