目录
引言
该文章为自我复习,之后会出详细的模块化文章
JVM的作用
- 翻译:把java代码翻译成机器可识别的010101串
- 内存管理:相比C++需要申请内存和释放内存操作,java封装好了,只需要new,其他操作自动进行
类加载机制
.class文件加载到jvm的过程:装载-链接(验证-准备-解析)-初始化-使用-卸载
类加载器
层级关系
- 引导类加载器 Bootstrap ClassLoader
- 拓展类加载器 Extension ClassLoader
- 系统类加载器 Application ClassLoader
- 用户自定义类加载器 Custom ClassLoader
类加载顺序:自上而下
自定义实现类加载器:重写loadClass方法
双亲委派的破坏方式:通过自定义类加载器方式,包名java开头的无法自定义加载
- 双亲委派模式的优势:防止篡改
运行时数据区
- 计数器:指向当前线程正在执行的字节码指令的地址 行号
- 虚拟机栈:存储当前线程运行方法所需要的数据、指令和返回地址
a. 栈帧:
i. 局部变量表:存储8大基本类型+1引用类型,若是引用类型,存储的是指向堆的地址,定长32位的块存储,超过则多块存储
ii. 操作数栈:FILO,如int a=i+j 则存i和j的存入过程
iii. 动态链接:指向真正的实例,如注入@autowire的时候
iv. 出口:返回地址 - 本地方法栈:类似虚拟机栈 native修饰的
- 方法区:类信息(创建时间,创建方法等)、常量(1.7)、静态变量、JIT
- Heap 堆:存储对象实例
JVM内存模型
- jdk<1.8 分为新生代 老年代 永久代(方法区)
- jdk1.8 分为新生代 老年代 meta space(存在本地内存当中)
- 新生代-老年代 大概是1:2 具体大小根据活跃数的平均数按比例分配
- eden s1 s2划分的原因:其中一个service为空减少空间碎片
垃圾回收机制
判断对象是否GC
- 引用计数法:循环引用可能会导致无法回收
- 可达性分析:从GCRoot判断是否有达到对象的路线,没有则回收
a. GCRoot(运行时不会被回收):
i. 虚拟机栈种本地变量表中引用的对象
ii. 方法区:静态变量引用的对象、常量引用的对象
iii. 本地方法栈中JNI引用的对象
iv. 不可达的对象会进行finalize判断
垃圾回收机制
- GC:新生代回收算法 age默认15 当相同年龄大小达到servivor一半也放入老年代
- Major GC:老年代回收算法
- Full GC:两个加起来
垃圾回收算法
- 标记-清除算法:可能会产生空间碎片
- 复制回收算法:空间利用率低 适用于少量对象存活
- 标记整理算法:类似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:自动调节参数 - 老年代 不用复制回收算法的原因:存活对象多,存在大量移动
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日志
- -Xloggc:/usr/local/gc.log 输出日志到指定文件
- -XX:+printGCTimeStamps 按时间输出
- -XX:+PrintGCDetails 输出详细GC日志
- -XX:-UseGCLogFileRotation
- -XX:-GCLogFileSize=8K 日志文件大小
GC对象
- 强引用:Object o=new Object()
- 软引用:SoftReference 图片、缓存:在GC后仍不够就会回收软引用对象
- 弱引用:GC时一定被回收 WeakReference
- 虚引用:PhantomReference 回收前通知对象
JDK自带的监控工具
- jmap -heap pid 堆的使用情况
- jstat -gcutil pid 3000 输出GC实时信息
- jstack 线程dump
- jvisualvm 查看线程信息
- jconsole 工具
- MAT(内存分析):eclipse memory analyzer
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/usr/local/error.hprof
JVM参数:
- -Xms starting 堆的初始大小
- -Xmx max 堆的最大大小
- -Xmn new 新生代初始大小
- -Xss 设置栈大小
- jvm参数参考地址:https://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#Options
- new对象的时候(内存规整的时候) 线程可开启TLAB (分配堆的时候产生指针碰撞 cas机制,会存入TLAB中)thread local allocation buffer 只在压缩算法中存在