jvm 内存模型,参数配置,命令解释
1,jvm的组成
java 堆
1,所有系统对象都保存在jvm 堆中
2,所有线程共享java堆
3,堆是分代的,分为eden s0 s1 renured
4, gc 工作的主要空间
java 栈
1,线程私有的
2,栈是由一系列帧组成
3,每次方法调用都会创建一个帧,并压栈
4,每个方法执行,都会创建一个栈帧,伴随着方法从创建到执行完成。用于存储局部变量表,操作数栈,动态链接,方法出口等。
java 方法区
1,保存装载类信息,类型的常量池,字段,方法信息 字节码方法
pc 寄存器
1 每个线程都有一个pc寄存器
2 pc 寄存器都是存储下指令的位置
3当执行本地方法时候,pc寄存器为undefind
4,线程创建的时候创建
对象结构:
1,header(对象头) 自身运行时数据 包含哈希值,gc 分代信息 锁状态标志 线程持有的锁 偏向线程id 偏向时间戳
类型指针
2,实例数据
3,占位数据(对象地址要求要有8个占位符,没有达到使用占位数据填充)
2,参数配置:
Gc 信息打印相关配置
-XX:+PrintGC 打印简要GC信息
-XX:+PrintGCDetails 打印GC的详细信息
-XX:+PrintGCTimeStamps 打印GC的时间戳
-xloggc:log/gc.log 指定GC log的位置,以文件的形式保存
-XX:+PrintHeapAtGC 每次一次GC,都打印堆信息
-XX:+TraceClassLoading 监控类的加载
-XX:+PrintClassHistogram Ctrl+Break 后,打印类的信息
堆的参数分配
-Xmx -Xms 指定最大堆和最小堆 (-Xmx20m -Xms5m) java 会尽力维持在最小堆运行
-Xmn 设置新生代大小
-XX:NewRatio 设置新生代和老年代的比值
-XX:SurvivorRatio 设置两个Survivor(幸存区)和eden(新生代)的比
-XX:+HeapDumpOnOutOfMemoryError oom时导出到文件
-XX:+HeapDumpPath 导出OOM的路径
-XX:onOutOfMemoryError 在OOM时,执行一个脚本
推荐新生代占堆的3/8
幸存代占新生代的1/10
-XX:PermSize 设置永久区的初始空间
-XX:MaxPermSize 设置永久区的最大空间
-Xss 栈大小分配 通常只有几百k 决定了函数调用的深度 每个线程都有独立的栈空间 局部变量,参数分配在栈上
-XX:PretenureSizeThreshold 设置多大对象直接进入老年代
-XX:MaxTenuringThreshold 设置长期存活的年龄进入老年代
-XX:+HandlePromotionFailure 设置空间分配担保
常用实战
// 设置堆内存大小oom时导出堆镜像
-Xmx20m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heapdump.hprof
3,GC算法
GC 主要对堆和老年代进行垃圾回收
1,引用计数算法
根据对象的引用进行计数,当被其他对象进行引用进行加一,消失引用进行减一。
缺点:引用和去引用伴随加法和减法,影响性能且很难处理循环引用问题。
2,标记清除算法
标记清除算法分为两个阶段,一个是标记阶段,一个是清除阶段。在根节点开始寻找引用对象并进行标记,然后把未标记的对象进行清除。
3,标记压缩算法
开始同标记清除算法先根据根节点寻找引用对象并进行标记,移动存活的的对象移动到另一端,然后清空边界以外的内存区域。(适合存活对象较的区域,像老年代)
4,标记复制算法
将内存空间划分为两块空间,一块为存活对象和垃圾对象正在使用的内存空间,一块为未使用的内存空间。在垃圾回收时把存活的对象移动到未使用的那块内存空间,完成后清除当前使用内存空间。然后交换内存角色。
4,GC 收集器
1,串行收集器
即当需要进行GC操作时候,所有程序都暂停调用等待GC操作。优点:效率高,最稳定。缺点:所有线程服务停止等待gc程序运行,会造成服务停滞现象较长。新生代:使用标记复制算法,老年代:使用标记整理算法
设置参数: -XX:+UseSerialGC
2,并行收集器
一,ParNew 收集器
新生代采用并行的垃圾回收,老年代采用串行的垃圾回收。新生代:使用标记复制算法,老年代:使用标记整理算法
设置参数:-XX:+UserParNewGC -XX:ParalleGCThreads 限制线程数量
二,Parallel 收集器
类似于ParNew收集器,新生代:使用标记复制算法,老年代:使用标记压缩算法,但是更加关注吞吐量。
设置参数:-XX:+UseParallelGC 使用Parallel收集器+ 老年代串行 -XX:+UseParallelOldGC 使用Parallel收集器+ 并行老年代
-XX:MaxGCPauseMills 最大停顿时间,单位毫秒 GC尽力保证回收时间不超过设定值
-XX:GCTimeRatio 0-100的取值范围 垃圾收集时间占总时间的比 默认99,即最大允许1%时间做GC
3,CMS收集器
Concurrent Mark Sweep 并发标记清除 。主要是在老年代使用并行的标记清除算法,新生代使用ParNew 。
优点:尽可能降低停顿 缺点:会影响系统整体吞吐量和性能(比如,在用户线程运行过程中,分一半CPU去做GC,系统性能在GC阶段,反应速度就下降一半),清理不够彻底(因为清理的时候还会产生新的垃圾)。
设置参数:-XX:+UseConcMarkSweepGC 设置CMS收集器 -XX:CMSInitiatingOccupancyFraction 设置该值代表老年代堆空间的使用率(比如,value=75意味着第一次CMS垃圾收集会在老年代被占用75%时被触发)。
碎片整理参数
-XX:+ UseCMSCompactAtFullCollection Full GC后,进行一次整理 整理过程是独占的,会引起停顿时间变长
-XX:+CMSFullGCsBeforeCompaction 设置进行几次Full GC后,进行一次碎片整理
-XX:ParallelCMSThreads 设定CMS的线程数量
-XX:CMSInitiatingPermOccupancyFraction:当永久区占用率达到这一百分比时,启动CMS回收
-XX:UseCMSInitiatingOccupancyOnly:表示只在到达阀值的时候,才进行CMS回收
系统性能监控
uptime :显示系统时间,运行时间,系统连接数,系统负载等。
top:第一行和uptime 显示的是一致的;CPU内存;没个进程占用cpu的情况
pidstat:细致观察进程;安装(sudo apt-get install sysstat);监控CPU;监控IO;监控内存;
-t 线程的监控
-d 系统io监控
pidstat -p 26983 -u 1 1000 -t
jps 列出java进程,类似于ps命令
参数-q可以指定jps只输出进程ID ,不输出类的短名称
参数-m可以用于输出传递给Java进程(主函数)的参数
参数-l可以用于输出主函数的完整路径
参数-v可以显示传递给JVM的参数
jstat 类装置,内存,垃圾收集,jit编译的音息
1、jstat –class<pid> : 显示加载class的数量,及所占空间等信息。
显示列名 |
具体描述 |
Loaded |
装载的类的数量 |
Bytes |
装载类所占用的字节数 |
Unloaded |
卸载类的数量 |
Bytes |
卸载类的字节数 |
Time |
装载和卸载类所花费的时间 |
2、jstat -compiler <pid>显示VM实时编译的数量等信息。
显示列名 |
具体描述 |
Compiled |
编译任务执行数量 |
Failed |
编译任务执行失败数量 |
Invalid |
编译任务执行失效数量 |
Time |
编译任务消耗时间 |
FailedType |
最后一个编译失败任务的类型 |
FailedMethod |
最后一个编译失败任务所在的类及方法 |
3、jstat -gc <pid>: 可以显示gc的信息,查看gc的次数,及时间。
显示列名 |
具体描述 |
S0C |
年轻代中第一个survivor(幸存区)的容量 (字节) |
S1C |
年轻代中第二个survivor(幸存区)的容量 (字节) |
S0U |
年轻代中第一个survivor(幸存区)目前已使用空间 (字节) |
S1U |
年轻代中第二个survivor(幸存区)目前已使用空间 (字节) |
EC |
年轻代中Eden(伊甸园)的容量 (字节) |
EU |
年轻代中Eden(伊甸园)目前已使用空间 (字节) |
OC |
Old代的容量 (字节) |
OU |
Old代目前已使用空间 (字节) |
PC |
Perm(持久代)的容量 (字节) |
PU |
Perm(持久代)目前已使用空间 (字节) |
YGC |
从应用程序启动到采样时年轻代中gc次数 |
YGCT |
从应用程序启动到采样时年轻代中gc所用时间(s) |
FGC |
从应用程序启动到采样时old代(全gc)gc次数 |
FGCT |
从应用程序启动到采样时old代(全gc)gc所用时间(s) |
GCT |
从应用程序启动到采样时gc用的总时间(s) |
4、jstat -gccapacity <pid>:可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小
显示列名 |
具体描述 |
NGCMN |
年轻代(young)中初始化(最小)的大小(字节) |
NGCMX |
年轻代(young)的最大容量 (字节) |
NGC |
年轻代(young)中当前的容量 (字节) |
S0C |
年轻代中第一个survivor(幸存区)的容量 (字节) |
S1C |
年轻代中第二个survivor(幸存区)的容量 (字节) |
EC |
年轻代中Eden(伊甸园)的容量 (字节) |
OGCMN |
old代中初始化(最小)的大小 (字节) |
OGCMX |
old代的最大容量(字节) |
OGC |
old代当前新生成的容量 (字节) |
OC |
Old代的容量 (字节) |
PGCMN |
perm代中初始化(最小)的大小 (字节) |
PGCMX |
perm代的最大容量 (字节) |
PGC |
perm代当前新生成的容量 (字节) |
PC |
Perm(持久代)的容量 (字节) |
YGC |
从应用程序启动到采样时年轻代中gc次数 |
FGC |
从应用程序启动到采样时old代(全gc)gc次数 |
5、jstat -gcutil <pid>:统计gc信息
显示列名 |
具体描述 |
S0 |
年轻代中第一个survivor(幸存区)已使用的占当前容量百分比 |
S1 |
年轻代中第二个survivor(幸存区)已使用的占当前容量百分比 |
E |
年轻代中Eden(伊甸园)已使用的占当前容量百分比 |
O |
old代已使用的占当前容量百分比 |
P |
perm代已使用的占当前容量百分比 |
YGC |
从应用程序启动到采样时年轻代中gc次数 |
YGCT |
从应用程序启动到采样时年轻代中gc所用时间(s) |
FGC |
从应用程序启动到采样时old代(全gc)gc次数 |
FGCT |
从应用程序启动到采样时old代(全gc)gc所用时间(s) |
GCT |
从应用程序启动到采样时gc用的总时间(s) |
6、jstat -gcnew <pid>:年轻代对象的信息。
显示列名 |
具体描述 |
S0C |
年轻代中第一个survivor(幸存区)的容量 (字节) |
S1C |
年轻代中第二个survivor(幸存区)的容量 (字节) |
S0U |
年轻代中第一个survivor(幸存区)目前已使用空间 (字节) |
S1U |
年轻代中第二个survivor(幸存区)目前已使用空间 (字节) |
TT |
持有次数限制 |
MTT |
最大持有次数限制 |
EC |
年轻代中Eden(伊甸园)的容量 (字节) |
EU |
年轻代中Eden(伊甸园)目前已使用空间 (字节) |
YGC |
从应用程序启动到采样时年轻代中gc次数 |
YGCT |
从应用程序启动到采样时年轻代中gc所用时间(s) |
7、jstat -gcnewcapacity<pid>: 年轻代对象的信息及其占用量。
显示列名 |
具体描述 |
NGCMN |
年轻代(young)中初始化(最小)的大小(字节) |
NGCMX |
年轻代(young)的最大容量 (字节) |
NGC |
年轻代(young)中当前的容量 (字节) |
S0CMX |
年轻代中第一个survivor(幸存区)的最大容量 (字节) |
S0C |
年轻代中第一个survivor(幸存区)的容量 (字节) |
S1CMX |
年轻代中第二个survivor(幸存区)的最大容量 (字节) |
S1C |
年轻代中第二个survivor(幸存区)的容量 (字节) |
ECMX |
年轻代中Eden(伊甸园)的最大容量 (字节) |
EC |
年轻代中Eden(伊甸园)的容量 (字节) |
YGC |
从应用程序启动到采样时年轻代中gc次数 |
FGC |
从应用程序启动到采样时old代(全gc)gc次数 |
8、jstat -gcold <pid>:old代对象的信息。
显示列名 |
具体描述 |
PC |
Perm(持久代)的容量 (字节) |
PU |
Perm(持久代)目前已使用空间 (字节) |
OC |
Old代的容量 (字节) |
OU |
Old代目前已使用空间 (字节) |
YGC |
从应用程序启动到采样时年轻代中gc次数 |
FGC |
从应用程序启动到采样时old代(全gc)gc次数 |
FGCT |
从应用程序启动到采样时old代(全gc)gc所用时间(s) |
GCT |
从应用程序启动到采样时gc用的总时间(s) |
9、stat -gcoldcapacity <pid>: old代对象的信息及其占用量。
显示列名 |
具体描述 |
OGCMN |
old代中初始化(最小)的大小 (字节) |
OGCMX |
old代的最大容量(字节) |
OGC |
old代当前新生成的容量 (字节) |
OC |
Old代的容量 (字节) |
YGC |
从应用程序启动到采样时年轻代中gc次数 |
FGC |
从应用程序启动到采样时old代(全gc)gc次数 |
FGCT |
从应用程序启动到采样时old代(全gc)gc所用时间(s) |
GCT |
从应用程序启动到采样时gc用的总时间(s) |
10、jstat -gcpermcapacity<pid>: perm对象的信息及其占用量。
显示列名 |
具体描述 |
PGCMN |
perm代中初始化(最小)的大小 (字节) |
PGCMX |
perm代的最大容量 (字节) |
PGC |
perm代当前新生成的容量 (字节) |
PC |
Perm(持久代)的容量 (字节) |
YGC |
从应用程序启动到采样时年轻代中gc次数 |
FGC |
从应用程序启动到采样时old代(全gc)gc次数 |
FGCT |
从应用程序启动到采样时old代(全gc)gc所用时间(s) |
GCT |
从应用程序启动到采样时gc用的总时间(s) |
11、jstat -printcompilation <pid>:当前VM执行的信息。
显示列名 |
具体描述 |
Compiled |
编译任务的数目 |
Size |
方法生成的字节码的大小 |
Type |
编译类型 |
Method |
类名和方法名用来标识编译的方法。类名使用/做为一个命名空间分隔符。方法名是给定类中的方法。上述格式是由-XX:+PrintComplation选项进行设置的 |
jinfo
可以用来查看正在运行的Java应用程序的扩展参数,甚至支持在运行时,修改部分参数
-flag <name>:打印指定JVM的参数值
-flag [+|-]<name>:设置指定JVM参数的布尔值
-flag <name>=<value>:设置指定JVM参数的值
jmap
是一个可以输出所有内存中对象的工具,甚至可以将VM 中的heap,以二进制输出成文本
-dump:[live,]format=b,file=<filename>: 使用hprof二进制形式,输出jvm的heap内容到文件=. live子选项是可选的,假如指定live选项,那么只输出活的对象到文件.
-finalizerinfo :打印正等候回收的对象的信息
-heap: 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况.
-histo[:live] :打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量
-permstat: 打印classload和jvm heap长久层的信息. 包含每个classloader的名字,活泼性,地址,父classloader和加载的class数量. 另外,内部String的数量和占用内存数也会打印出来.
jhat (Java Head Analyse Tool)
是jdk自带的用来分析java堆快照的工具
jhat dump堆内存位置
jstack
用生成当前虚拟机线程快照的工具
-F当'jstack [-l] pid'没有相应的时候强制打印栈信息,如果直接jstack无响应时,用于强制jstack),一般情况不需要使用
-l长列表. 打印关于锁的附加信息,例如属于java.util.concurrent的ownable synchronizers列表,会使得JVM停顿得长久得多(可能会差很多倍,比如普通的jstack可能几毫秒和一次GC没区别,加了-l 就是近一秒的时间),-l 建议不要用。一般情况不需要使用
-m打印java和native c/c++ 框架的所有栈信息.可以打印JVM的堆栈,显示上Native的栈帧,一般应用排查不需要使用
线程状态解释
NEW:未启动的。不会出现在Dump中。
RUNNABLE:在虚拟机内执行的。运行中状态,可能里面还能看到locked字样,表明它获得了某把锁。
BLOCKED:受阻塞并等待监视器锁。被某个锁(synchronizers)給block住了。
WATING:无限期等待另一个线程执行特定操作。等待某个condition或monitor发生,一般停留在park(), wait(), sleep(),join() 等语句里。
TIMED_WATING:有时限的等待另一个线程的特定操作。和WAITING的区别是wait() 等语句加上了时间限制 wait(timeout)。
TERMINATED:已退出的
类加载器
1、串行收集器:暂停所有的线程,属于单线程工作, 新生代 serial
启用:-XX:+UseSerialGC
新生代 Serial 算法 复制算法
老年代 Serial Old 算法 标记整理
2、并行收集器(默认):暂停所有线程,多线程工作,除了多加了线程 几乎跟串行收集器一样 ParNew
启用:-XX:+UseParNewGC 强制使用新生代
新生代: ParNew 复制算法
老年代单独指定
3、G1收集器:这个主要是对堆内存进行分区,并发性回收
启用:-XX:+UseG1GC
老年代和新生代都一样 分区分代算法
4、CMS收集器:多线程扫描,使用的算法是标记清除算法,标记需要回收的对象,进行回收
启动:-XX:+UseConcMarkSweepGC
老年代使用 CMS垃圾收集器 算法 标记清除