物理内存模型
线程:分为八种原子性操作,作用于不同的区域
工作内存:,load、use、assign、store,线程私有
主内存:lock、unlock、read、write,线程共享
volatile关键字修饰的变量
变量线程安全,变量值的修改会立刻同步到主内存,使用的变量必须从主内存重新获取
变量的修改对所有线程可见,
禁止了指令重排序
JVM类加载
装载:通过全限定名获取类的二进制字节流
将字节流所代表的静态存储结构转化为方法区的运行时数据结构
生成代表这个类的class对象,作为对方法区中这些数据的访问入口
ClassLoader
链接
验证
文件格式、元数据、字节码、符号引用
准备
为静态变量分配内存并初始化默认值
解析
把变量中的符号引用转换为直接引用
初始化
初始化静态变量,静态代码块
运行时数据区
方法区(no-heap)
线程共享区,存放类信息、常量、静态变量、即时编译器编译后的代码(常量池)内存不够抛出OOM
JDK8 称为Metaspace
JDK 6\7称为PermSpace
堆(heap)
线程共享,存放java对象
虚拟机栈:线程私有,存放当前线程中方法的调用状态,通过栈帧方式,调用一个方法压入一个栈帧,调用完成弹出一个栈帧,即先进后出
程序计数器
线程私有,记录当前线程执行的位置、字节码指令的地址
本地方法栈
线程私有,执行native类型方法
堆内存区域划分
堆内存模型
Eden
Young区的一部分,默认Eden:s0:s1=8:1:1,一般对象默认创建后进入Eden区,内存不足进行Minor GC ,将存活对象复制到S0后清理Eden
S0/S1
Young区的一部分,存放Eden经过GC后存活的对象,若对象年龄达到阈值,进入Old区,否则复制到To区,并清空from区,s0、s1互换角色,直到to区填满或者年龄大于16,在gc时,将to区复制到old区,清空to区
设置两块s区的作用:1、减少full gc次数 2、避免minor gc时对象空间存储的碎片化,浪费内存空间
Old
存放年龄较大的对象,或者占用内存较大的对象,GC称为Major GC
对象的创建过程及生命周期
分代收集机制
Young区:复制算法,对象生命周期短,复制率高
Old区:标记清除或者标记整理,对象生命周期长,复制效率低
垃圾收集器标准:
停顿时间:垃圾收集器进行垃圾回收时终端应用执行相应的时间
吞吐量:运行用户代码时间/(运行用户代码时间+垃圾回收时间)
Garbage Collect
确认垃圾对象标准:引用计数法、可达性分析
垃圾收集算法
1、标记-清除:耗时,产生内存碎片
2、复制算法:空间利用率低
3、标记-整理:同标记清除但不会产生内存碎片
垃圾收集器
Seriall:单线程收集器,使用一个cpu或者线程去完成垃圾收集工作,进行时会暂停其他线程
优点:简单高效,拥有很高的单线程收集效率
缺点:收集过程需要暂停所有线程
算法:复制算法
适用范围:新生代
应用:Client模式下的默认新生代收集器
老年代版本:Serial Old 采用标记整理算法
ParNew:seriall的多线程版本
优点:在多CPU时,比Serial效率高。
缺点:收集过程暂停所有应用程序线程,单CPU时比Serial效率差。
算法:复制算法
适用范围:新生代
应用:运行在Server模式下的虚拟机中首选的新生代收集器
Parallel Scavenge
复制算法
关注吞吐量 = 运行用户代码时间/(运行用户代码时间+垃圾收集时间)
老年代版本:Parallel Old 标记整理算法
CMS:Concurrent Mark Sweep 以最短回收停顿时间为目标的收集器,收集器线程和用户线程一起工作,总体上来说Cms收集器内存回收是与用户一起并发执行的
标记-清除算法
优点:并发收集、低停顿
缺点:产生大量空间碎片、并发阶段会降低吞吐量
G First:比CMS更先进的地方在于能让使用者明确指定一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒,使用G1收集器时,Java堆的内存布局与就与其他收集器有很大差别,它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,它们都是一部分Region(不需要连续)的集合。
标记-整理算法
选择合适的垃圾收集器
1、优先调整堆的大小,让服务器自己选择
2、如果内存小于100M,采用串行收集器
3、如果是单核并且没有停顿时间要求,采用串行收集或者jvm自己选择
4、如果允许停顿时间超过1秒,选择并行或者jvm自己选择
5、如果相应时间最重要并且不能超过1s,使用并发收集器
诊断分析工具
JDK内置工具
控制台命令工具:
jps: 查看java进程
jinfo:查看jvm配置参数,jinfo -flags PID
jstat: 查看虚拟机栈统计信息,jstat -class PID 1000 10 ,每1000毫秒输出一次,共输出10次;jstat -gc PID 1000 10 ,查看垃圾收集信息
jstack:查看线程堆栈信息,jstack PID
jmap:打印堆内存相关信息,jmap -heap PID ;jmap -dump:format=b,file=heap.hprof PID ---dump出堆内存相关信息
可视化工具:
jconsole:查看程序运行概况、监控堆信息、永久区使用情况、类加载信息等
jvisualvm:监控本地或者远程java程序CPU、类、线程等信息
第三方工具
arthas:阿里的一个jvm监控开源工具,提供命令行交互式的方式查看java程序运行过程中的一系列参数信息,功能全面,方便问题的定位和诊断,http://github.com/alibaba/arthas
MAT:java堆分析器,用于查找内存泄露
GC分析工具:GCViewer\http://gceasy.io; 参数-xloggc:gc.log 生成gc文件