总结回顾JVM

目录

  • 引言
  • JVM的作用
  • 类加载机制
    • 类加载器
      • 层级关系
      • 类加载顺序:自上而下
  • 运行时数据区
  • JVM内存模型
  • 垃圾回收机制
    • 判断对象是否GC
    • 垃圾回收机制
    • 垃圾回收算法
    • 垃圾回收器
    • GC日志
    • GC对象
  • JDK自带的监控工具
  • JVM参数:

引言

该文章为自我复习,之后会出详细的模块化文章

JVM的作用

  1. 翻译:把java代码翻译成机器可识别的010101串
  2. 内存管理:相比C++需要申请内存和释放内存操作,java封装好了,只需要new,其他操作自动进行

类加载机制

.class文件加载到jvm的过程:装载-链接(验证-准备-解析)-初始化-使用-卸载

类加载器

总结回顾JVM_第1张图片

层级关系

  1. 引导类加载器 Bootstrap ClassLoader
  2. 拓展类加载器 Extension ClassLoader
  3. 系统类加载器 Application ClassLoader
  4. 用户自定义类加载器 Custom ClassLoader

类加载顺序:自上而下

自定义实现类加载器:重写loadClass方法
双亲委派的破坏方式:通过自定义类加载器方式,包名java开头的无法自定义加载

  • 双亲委派模式的优势:防止篡改

运行时数据区

  1. 计数器:指向当前线程正在执行的字节码指令的地址 行号
  2. 虚拟机栈:存储当前线程运行方法所需要的数据、指令和返回地址
    a. 栈帧:
    i. 局部变量表:存储8大基本类型+1引用类型,若是引用类型,存储的是指向堆的地址,定长32位的块存储,超过则多块存储
    ii. 操作数栈:FILO,如int a=i+j 则存i和j的存入过程
    iii. 动态链接:指向真正的实例,如注入@autowire的时候
    iv. 出口:返回地址
  3. 本地方法栈:类似虚拟机栈 native修饰的
  4. 方法区:类信息(创建时间,创建方法等)、常量(1.7)、静态变量、JIT
  5. Heap 堆:存储对象实例

JVM内存模型

  1. jdk<1.8 分为新生代 老年代 永久代(方法区)
  2. jdk1.8 分为新生代 老年代 meta space(存在本地内存当中)
  3. 新生代-老年代 大概是1:2 具体大小根据活跃数的平均数按比例分配
  4. eden s1 s2划分的原因:其中一个service为空减少空间碎片

垃圾回收机制

判断对象是否GC

  1. 引用计数法:循环引用可能会导致无法回收
  2. 可达性分析:从GCRoot判断是否有达到对象的路线,没有则回收
    a. GCRoot(运行时不会被回收):
    i. 虚拟机栈种本地变量表中引用的对象
    ii. 方法区:静态变量引用的对象、常量引用的对象
    iii. 本地方法栈中JNI引用的对象
    iv. 不可达的对象会进行finalize判断

垃圾回收机制

  1. GC:新生代回收算法 age默认15 当相同年龄大小达到servivor一半也放入老年代
  2. Major GC:老年代回收算法
  3. Full GC:两个加起来

垃圾回收算法

  1. 标记-清除算法:可能会产生空间碎片
  2. 复制回收算法:空间利用率低 适用于少量对象存活
  3. 标记整理算法:类似1.先标记 整理 在回收

垃圾回收器

总结回顾JVM_第2张图片

  1. 新生代(复制回收算法)不用标记整理的原因:大量清除对象,移动时间复杂度高
    a. Serial:单个GC线程工作时,其他线程暂停(安全点控制)适用于client模式的jvm
    b. ParNew:多个GC线程 -XX:paralleGCThreads 控制GC线程数(根据cpu内核调优)
    c. ParrallelScavenge:关注吞吐量=运行代码时间/(运行代码+回收时间) 减少回收时间
    i. 控制GC停顿时间 -XX:MaxGCPauseMillis
    ii. -XX:GCRatio 吞吐量大小
    iii. -XX:UseAdaptiveSizePolicy:自动调节参数
  2. 老年代 不用复制回收算法的原因:存活对象多,存在大量移动
    总结回顾JVM_第3张图片
    a. CMS:标记清除算法 原因:减少回收停顿时间 并发执行(gc线程和用户线程并行执行)
    i. -XX:+UserCMSCompactAtfFullCollection:是否压缩
    ii. -XX:CMSFullGCsBeforeCompaction 执行多少次后压缩
    b. Serial Old:标记整理算法 CMS备用预案:触发FullGC时 单线程
    c. Parrallel Old:标记整理算法 多线程 配合ParrallelScavenge
  • -XX:+UseConcMarkSweep 指定回收器
  • G1回收:新生老年都分块存储在G1 并行和并发
    新生代和老年代分为多个region区域
    存在的问题:老年代引用了新生代,则需要扫描整个堆保证准确性
    与cms的区别:cms最后过程是并发清除,g1是筛选回收
    jdk1.9默认回收器
  • CMS导致cpu占用高的原因:当出发新生代和老年代都满了的时候,CMS会不断触发GC,而改GC与用户线程是并发执行的 因此会导致cpu变高

GC日志

总结回顾JVM_第4张图片

  1. -Xloggc:/usr/local/gc.log 输出日志到指定文件
  2. -XX:+printGCTimeStamps 按时间输出
  3. -XX:+PrintGCDetails 输出详细GC日志
  4. -XX:-UseGCLogFileRotation
  5. -XX:-GCLogFileSize=8K 日志文件大小

GC对象

  1. 强引用:Object o=new Object()
  2. 软引用:SoftReference 图片、缓存:在GC后仍不够就会回收软引用对象
  3. 弱引用:GC时一定被回收 WeakReference
  4. 虚引用:PhantomReference 回收前通知对象

JDK自带的监控工具

  1. jmap -heap pid 堆的使用情况
  2. jstat -gcutil pid 3000 输出GC实时信息
  3. jstack 线程dump
  4. jvisualvm 查看线程信息
  5. jconsole 工具
  6. MAT(内存分析):eclipse memory analyzer
    -XX:+HeapDumpOnOutOfMemoryError
    -XX:HeapDumpPath=/usr/local/error.hprof

JVM参数:

  1. -Xms starting 堆的初始大小
  2. -Xmx max 堆的最大大小
  3. -Xmn new 新生代初始大小
  4. -Xss 设置栈大小
  • jvm参数参考地址:https://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#Options
  • new对象的时候(内存规整的时候) 线程可开启TLAB (分配堆的时候产生指针碰撞 cas机制,会存入TLAB中)thread local allocation buffer 只在压缩算法中存在

你可能感兴趣的:(java)