jvm内存

121 阅读5分钟
jvm内存划分哪几块?
  • 方法区
  • 虚拟机栈
  • 本地方法栈
  • 程序计数器
哪些是线程共享、哪些是线程私有?
  • 堆、方法区 为线程共享
  • 虚拟机栈、本地方法栈、程序计数器 为线程私有
每一块内存存放的那些东西?
  • 堆【对象实例、数组等动态分配的内存】
  • 方法区【类信息、常量、静态变量、即时编译后的代码】
  • 虚拟机栈【栈桢】
  • 本地方法栈【本地方法的native栈桢】
  • 程序计数器【当前线程执行的指令地址】
栈桢的具体介绍?
  • 局部变量表【变量的存储】
  • 操作数栈【从局部变量表获取变量计算后结果写回变量表】
  • 动态链接【方法调用的符号引用到直接引用】
  • 返回指令【处理return】
  • 附加信息
堆内存的详细划分?

年轻代

  • 2块 s区
  • 1块 e区
  • 默认比例 8e:1s:1s 老年代
  • 默认比例 老年代:年轻代 = 2:1
方法区在jdk1.6、1.7、1.8中的变化?
版本方法区位置静态变量字符串常量池
1.6jvm内存方法区方法区
1.7jvm内存
1.8本地内存
垃圾判定算法?

引用计数器

  • 每个对象添加个引用计数器,每当被引用时+1,引用失效的时候-1,为0时代表可以回收的垃圾对象;
  • 简单高效,很难处理循环引用的问题。

可达性分析算法

  • 从一系列GC Roots出发,找出可以到达的对象称之为 可达对象或者说存活对象,其余的为垃圾对象。
java语言中那些对象可以作为GC Roots
  • 虚拟栈中局部变量表中的对象
  • 本地方法栈中JNI中的对象
  • 方法区中的静态变量
  • 方法区中的常量

总结: 其实就是方法运行时要使用的对象比如虚拟机栈、本地方法栈;应用运行中共享的对象比如方法区中的常量、静态属性变量

垃圾回收算法

标记-清理

  • 利用可达性分析算法,标记出 存活、垃圾对象
  • 把垃圾对象占用的空间清空
  • 产生很多碎片化内存
  • 适合垃圾少、存活多的场景

标记-整理

  • 利用可达性分析算法,标记出 存活、垃圾对象
  • 存活对象移动整理
  • 适合垃圾少、存活多的场景

复制

  • 利用可达性分析算法,标记出 存活、垃圾对象
  • 将存活对象顺序移动到另外一块干净的内存,清空之前那一半内存
  • 适合垃圾多、存活少的场景
老年代为什么使用标记整理、年轻代使用复制算法?
  • 老年代对象 存活多、垃圾少
  • 新生代对象 存活少、垃圾多
常用的垃圾收集器?

新生代

  • Serial 单线程
  • ParNew 多线程
  • Parallel Scavenge 多线程、可控吞吐量、自适应调整新生代和老年代的比例 以达到停顿和吞吐量的平衡策略

老年代

  • SerialOld(带整理)单线程
  • ParallelOld(带整理)多线程
  • CMS(带整理UseCMSCompactAtFullCollection(默认开启)、CMSFullGCsBeforeCompaction) 【初始标记STW、并发标记、重新标记STW、并发清理】

G1

什么情况下会发生young GC、什么情况下会发生full GC
  • Eden 区无法容纳新产生的对象时发生young GC
  • 老年代中的空间不足以存放新产生的对象,大对象会更容易引发fullGC,没有足够的连续空间容纳一个大对象
内存模型中不会发生oom的是?为什么?
  • 程序计数器
  • 每个线程私有的程序计数器内存 因为其大小固定、存储简单,所以不会oom
其他几块内存发生oom的场景?
  • 堆中 产生对象的所占用的堆内存大于GC后剩余的堆内存产生oom
  • 方法区 类信息 等数据大于方法区的内存时,理论上1.8之后,除非超出的机器的剩余物理内存oom
  • 虚拟机栈 方法调用层次太深大于虚拟机允许的深度 soe;递归调用,不停产生的栈桢占用空间大于虚拟机栈内存oom
  • 本地方法栈 本地方法调用层次太深大于允许的深度 soe;递归调用,不停产生的栈桢占用空间大于本地方法栈内存oom
java对象的内存分布
  • 对象头 8byte
  • classpointer 4byte
  • instancedata 具体数据类型
  • padding 对齐填充 8byte的倍数
栈桢
  • 局部变量表 变量存储
  • 操作数栈 从局部变量表拿数据计算并写回局部变量表
  • 动态连接 方法的调用链这种符号引用转道直接引用
  • 返回指令
  • 附加信息
如何排查oom?

获取堆转储 Heap Dump文件

  • 方式1:jmap
  • 方式2:jcmd
  • 方式3: -XX:+HeapDumpOnOutOfMemoryError

分析 HeapDump 文件

  • VisualVM
如何排查soe
  • 发生soe时,分析java打印的异常堆栈信息
  • 从异常堆栈信息中找到引发异常方法调用链路的末尾,通常是递归调用导致超出栈深度
  • 解决:-Xss调整栈大小、使用迭代代替递归
如何排查cpu 飙高?
  • jps 查看java进程pid
  • top -Hp pid 查看进程中线程详细信息
  • 找出较高栈用的线程tid
  • 通过 【printf "%x\n" tid】 将16进制转10进制 tid16
  • jstack | grep tid16