个人博客:https://suveng.github.io/blog/
2004.9 jdk1.5 tiger 自动装箱拆箱,泛型,,注解,枚举,变长参数,增强for循环 spring2.x spring4.x
2006 jdk1.6 javaee Javase Javame jdk6
2009 jdk1.7 收购sun 74亿
2014 jdk1.8
2017 jdk1.9
2018 jdk10
Java程序设计语言
java 虚拟机
class 类文件格式
Java API
第三方Java类库
jconsole.exe
在jdk/bin目录下,双击打开可运行,监控吗某个Java程序的状态
编写测试类观察jvm内存
JconsoleTest.java
package jconsole;
import java.util.ArrayList;
import java.util.List;
/**
* @author Veng Su [email protected]
* @date 2018/4/29 11:28
*/
public class JconsoleTest {
public static void main(String[] args) throws InterruptedException {
Thread.sleep(5000);
fill(1000);
}
private static void fill(int n) throws InterruptedException {
List jconsoleTests =new ArrayList();
for (int i=0;i
import java.util.ArrayList;
import java.util.List;
/**
* @author Veng Su [email protected]
* @date 2018/4/29 10:39
*/
public class Main {
public static void main(String[] args) {
// 测试堆内存溢出
List demoList=new ArrayList();
while (true){
demoList.add(new Demo());
}
}
}
import java.util.ArrayList;
import java.util.List;
/**
* @author Veng Su [email protected]
* @date 2018/4/29 10:39
*/
public class Main {
public static void main(String[] args) {
// 测试堆内存溢出
List demoList=new ArrayList();
while (true){
demoList.add(new Demo());
}
}
}
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:265)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
at java.util.ArrayList.add(ArrayList.java:462)
at Main.main(Main.java:13)
-XX:+HeapDumpOnOutOfMemoryError -Xms20m -Xmx20m
运行时常量池
存放方法运行时所需的数据,称为栈帧
为jvm调用到的native,即本地方法服务
记录当前线程执行到字节码的行号
这个描述的是Java方法执行的动态内存模型
栈帧:每个方法执行都会创建一个栈帧,伴随方法从创建到执行完成,用于存储局部变量表,操作数栈,动态链接,方法出口等
局部变量表:存放编译期已知的各种基本数据类型,引用类型,returnAddress类型
局部变量表的内存空间在编译期完成分配,在进入一个方法时,这个方法需要在帧分配多少内存是固定的,在方法运行期间是不会改变的
虚拟机栈的大小
可能存在StackOverFlowError
OutOfMemoryError内存不足,申请不到内存空间了
Java虚拟机栈为虚拟机执行Java方法服务
本地方法栈为虚拟机执行native方法服务
存放对象实例
垃圾搜集器管理的主要区域
新生代,老年代,Eden空间
申请不到空间同样抛出outofmemoryerror
存储虚拟机加载的类信息,常量,静态变量,及时编译器编译后的代码等数据
类信息:
类的版本
字段
方法
接口
方法区和永久代 Hotspot使用永久代实现方法区,两者不等价
垃圾回收在方法区的行为
异常的定义
申请空间失败抛出outofmemoryerror
常量池相当于一个hashset存放这写常量,
而new 出来的实例肯定是放到堆内存中去
运行时常量和字节码常量的区别,运行时创建的常量和编译期创建的常量的区别
给对象分配内存的方法
可能会出现线程安全性问题
如何解决
线程同步 缺点:效率低
本地分配缓冲
header (对象头)
自身运行时数据(MarkWord)
哈希值 GC分代年龄 锁状态标志 线程持有的锁 偏向线程ID 偏向时间戳
类型指针、
instanceData
Padding
占位符填充8的整数倍的作用
其他虚拟机
Sun hotshot
Bea JRockit
IBM J9
hotspot vm
kvm(kilobyte)
JRocket
BEA
世界上最快的虚拟机
专注服务器端的应用
优势
垃圾搜集器
MissionControll服务套件 寻找运行时的内存泄露的问题
J9
IBM Technology for Java virtual machine
Azul vm
Liquid vm
Dalvik vm
不是Java虚拟机
寄存器架构,非栈架构
Google的
Microsoft jvm
只能运行在windows平台下
taobaovm
深度定制
回收策略
标记-清除算法
效率问题
空间问题
复制算法
堆
虚拟机栈
本地方法栈
程序计数器
标记-整理-清除算法
针对老年代
分代收集算法
垃圾回收器
Serial
单线程
Parnew
parallel scanvenge收集器
-XX:MaxGFPauseMillis 垃圾收集器停顿时间1
-XX:CGTimeRatio 吞吐量大小
复制算法(新生代收集器)
多线程收集器
达到可控吞吐量
吞吐量:CPU运行代码的时间与CPU消耗的总时间的比值
CMS收集器 current Mark sweep
G1
只要电脑运行内存大于2g,CPU核心是多核, 默认是ServerVM
可以看到我们的虚拟机是HotSpot
优先分配到新生代的Eden区
VM option
-verbose:gc -XX:+PrintGCDetails -XX:+UseSerialGC -Xms20m -Xmx20m -Xmn10m -XX:SurvivorRatio=8
大对象直接进入到老年代
指定进入老年代的对象的内存大小
-XX:PretenureSizeThreshold
长期存活的对象分配到老年代
-XX:MaxTenuringThreshold
具有年龄计数器。每次回收时存活,年龄加1.到达阈值就进入老年代中
空间分配担保
如果内存空间不足,向担保借;
-XX:(+/-)HandlePromotionFailure
逃逸分析和栈上分配
通过逃逸分析,分析出没有逃逸的对象,直接在栈上分配空间。
什么是逃逸分析?
分析对象的作用域。如果对象只有在方法体内有效,则判定为没有逃逸。否则,为逃逸对象
动态对象年龄判断
JPS
JAVA PROCESS STATUS
JPS 名称: jps - Java Virtual Machine Process Status Tool
命令用法: jps options hostid
options:命令选项,用来对输出格式进行控制
hostid:指定特定主机,可以是ip地址和域名, 也可以指定具体协议,端口。
功能描述: jps是用于查看有权访问的hotspot虚拟机的进程. 当未指定hostid时,默认查看本机jvm进程,否者查看指定的hostid机器上的jvm进程,此时hostid所指机器必须开启jstatd服务。 jps可以列出jvm进程lvmid,主类类名,main函数参数, jvm参数,jar名称等信息。
JSTAT
jstat命令可以类装载,内存,垃圾收集,jit编译。命令的格式如下:
jstat [-命令选项] [vmid] [间隔时间/毫秒] [查询次数]
类加载统计
jstat -class
Loaded:加载class的数量
Bytes:所占用空间大小
Unloaded:未加载数量
Bytes:未加载占用空间
Time:时间
编译统计
jstat -compiler
Compiled:编译数量。
Failed:失败数量
Invalid:不可用数量
Time:时间
FailedType:失败类型
FailedMethod:失败的方法
垃圾回收统计
jstat -gccapacity
S0C:第一个幸存区的大小
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
EC:伊甸园区的大小
EU:伊甸园区的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法区大小
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
新生代垃圾回收统计
jstat -gcnew
S0C:第一个幸存区大小
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
TT:对象在新生代存活的次数
MTT:对象在新生代存活的最大次数
DSS:期望的幸存区大小
EC:伊甸园区的大小
EU:伊甸园区的使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
新生代内存统计
jstat -gcnewcapacity
NGCMN:新生代最小容量
NGCMX:新生代最大容量
NGC:当前新生代容量
S0CMX:最大幸存1区大小
S0C:当前幸存1区大小
S1CMX:最大幸存2区大小
S1C:当前幸存2区大小
ECMX:最大伊甸园区大小
EC:当前伊甸园区大小
YGC:年轻代垃圾回收次数
FGC:老年代回收次数
老年代垃圾回收统计
jstat -gcold
MC:方法区大小
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
OC:老年代大小
OU:老年代使用大小
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
老年代内存统计
jstat -gcoldcapacity
OGCMN:老年代最小容量
OGCMX:老年代最大容量
OGC:当前老年代大小
OC:老年代大小
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
元数据空间统计
jstat -gcmetacapacity
MCMN:最小元数据容量
MCMX:最大元数据容量
MC:当前元数据空间大小
CCSMN:最小压缩类空间大小
CCSMX:最大压缩类空间大小
CCSC:当前压缩类空间大小
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
总结垃圾回收统计
jstat -gcutil
S0:幸存1区当前使用比例
S1:幸存2区当前使用比例
E:伊甸园区使用比例
O:老年代使用比例
M:元数据区使用比例
CCS:压缩使用比例
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
JVM编译方法统计
jstat -printcompilation
Compiled:最近编译方法的数量
Size:最近编译方法的字节码数量
Type:最近编译方法的编译类型。
Method:方法名标识。
JINFO
jinfo是jdk自带的命令,用来查看jvm的配置参数。通常会先使用jps查看java进程的id,然后使用jinfo查看指定pid的jvm信息
查看jvm的参数
jinfo -flags process_id
查看java系统参数
jinfo -sysprops process_id
JMAP
JVM Memory Map命令用于生成heap dump文件,如果不使用这个命令,还可以使用-XX:+HeapDumpOnOutOfMemoryError
参数来让虚拟机出现OOM的时候自动生成dump文件。
参数
option:选项参数,不可同时使用多个选项参数
pid:java进程id,命令ps -ef | grep java获取
executable:产生核心dump的java可执行文件
core:需要打印配置信息的核心文件
remote-hostname-or-ip:远程调试的主机名或ip
server-id:可选的唯一id,如果相同的远程主机上运行了多台调试服务器,用此选项参数标识服务器
options参数
heap : 显示Java堆详细信息
histo : 显示堆中对象的统计信息
permstat :Java堆内存的永久保存区域的类加载器的统计信息
finalizerinfo : 显示在F-Queue队列等待Finalizer线程执行finalizer方法的对象
dump : 生成堆转储快照
F : 当-dump没有响应时,强制生成dump快照
-dump
dump堆到文件,format指定输出格式,live指明是活着的对象,file指定文件名
-heap
打印heap的概要信息,GC使用的算法,heap的配置及使用情况,可以用此来判断内存目前的使用情况以及垃圾回收情况
-finalizerinfo
打印等待回收的对象信息,
-histo
打印堆的对象统计,包括对象数、内存大小等等。jmap -histo:live 这个命令执行,JVM会先触发gc,然后再统计信息
jmap -histo:live 24971 | grep com.yuhuo 查询类名包含com.yuhuo的信息
jmap -histo:live 24971 | grep com.yuhuo > histo.txt 保存信息到histo.txt文件
-permstat
打印Java堆内存的永久区的类加载器的智能统计信息。对于每个类加载器而言,它的名称、活跃度、地址、父类加载器、它所加载的类的数量和大小都会被打印。此外,包含的字符串数量和大小也会被打印。
-F
强制模式。如果指定的pid没有响应,请使用jmap -dump或jmap -histo选项。此模式下,不支持live子选项。
JHAT
JVM Heap Analysis Tool命令是与jmap搭配使用,用来分析jmap生成的dump,jhat内置了一个微型的HTTP/HTML服务器,生成dump的分析结果后,可以在浏览器中查看。在此要注意,一般不会直接在服务器上进行分析,因为jhat是一个耗时并且耗费硬件资源的过程,一般把服务器生成的dump文件复制到本地或其他机器上进行分析。【内存分析】
参数
-J< flag >
因为 jhat 命令实际上会启动一个JVM来执行, 通过 -J 可以在启动JVM时传入一些启动参数. 例如, -J-Xmx512m 则指定运行 jhat 的Java虚拟机使用的最大堆内存为 512 MB. 如果需要使用多个JVM启动参数,则传入多个 -Jxxxxxx.
-stack false|true
关闭对象分配调用栈跟踪(tracking object allocation call stack)。 如果分配位置信息在堆转储中不可用. 则必须将此标志设置为 false. 默认值为 true.
-refs false|true
关闭对象引用跟踪(tracking of references to objects)。 默认值为 true. 默认情况下, 返回的指针是指向其他特定对象的对象,如反向链接或输入引用(referrers or incoming references), 会统计/计算堆中的所有对象。
-port port-number
设置 jhat HTTP server 的端口号. 默认值 7000。
-exclude exclude-file
指定对象查询时需要排除的数据成员列表文件(a file that lists data members that should be excluded from the reachable objects query)。 例如, 如果文件列列出了 java.lang.String.value , 那么当从某个特定对象 Object o 计算可达的对象列表时, 引用路径涉及 java.lang.String.value 的都会被排除。
-baseline exclude-file
指定一个基准堆转储(baseline heap dump)。 在两个 heap dumps 中有相同 object ID 的对象会被标记为不是新的(marked as not being new). 其他对象被标记为新的(new). 在比较两个不同的堆转储时很有用。
-debug int
设置 debug 级别. 0 表示不输出调试信息。 值越大则表示输出更详细的 debug 信息。
-version
启动后只显示版本信息就退出。
JSTACK
JCONSOLE
常用思路
优化sql
监控CPU
监控内存
FULL GC 垃圾收集时间过长
解决方案
问题:
处理思路: