一、jvm参数
1)内存
-Xms
-Xmx
-Xss
-Xloggc:file
-Xprof
-XX:+DisabledExplicitGC
-XX:PreBlockSpin
-XX:CompileThreshold
2)Parallel
-XX:SurvivorRatio
-XX:PreTenureSizeThreshold
-XX:MaxTenuringThreshold
-XX:+ParallelGCThreads
-XX:+UseAdaptiveSizePolicy
3)CMS
-XX:+UseConcMarkSweepGC
-XX:MaxTenuringThreshold
-XX:ParallelCMSThreads
-XX:CMSInitiatingOccupancyFraction
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction
-XX:+CMSClassUnloadingEnabled
-XX:CMSInitiatingPermOccupancyFraction
-XX:GCTimeRatio
-XX:MaxGCPauseMillis
4)G1
-XX:+UseG1GC
-XX:MaxGCPauseMillis
-XX:GCPauseIntervalMillis
-XX:+G1HeapRegionSize
-XX:G1NewSizePercent
-XX:G1MaxNewSizePercent
-XX:GCTimeRatio
-XX:ConcGCThreads
-XX:InitiatingHeapOccupancyPercent
二、内存模型
(1)运行时数据区
程序计数器
Java 虚拟机栈
本地方法栈
Java 堆
方法区
(2)对象内存分配
1)内存分配方式
指针碰撞、空闲列表
2)内存分配策略
优先在 Eden 区分配、大对象直接进入老年代、长期存活对象将进入老年代
3)内存分配空间
1.栈分配
技术:逃逸分析、标量替换
缺点:无法栈上分配共享的对象
2.TLAB
优点:尽量避免从堆上直接分配内存从而避免频繁的锁争用
缺点:有内存孔隙问题,影响 gc 扫描性能
3.Eden
4.年老代
4)内存分配并发安全问题
同步处理(采用 CAS + 失败重试)
TLAB 上分配
5)对象的创建方式
new、Class.newInstance、Constructor.newInstance、clone、反序列化
6)对象的访问定位
句柄 、直接指针(HotSpot)
7)引用类型
强引用、软引用、弱引用、虚引用(幽灵引用/幻影引用)PhantomReference
8)对象拷贝克隆
深拷贝和浅拷贝
拷贝有两种方式:
实现 Cloneable 接口并重写 Object 类中的 clone()方法;
实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真
正的深度克隆
9)内存使用
1.内存溢出
OOM错误:stackoverflow错误,permgen space错误
2.内存泄漏
类的静态变量
各种连接,如数据库连接、网络连接和IO连接等
变量不合理的作用域
内部类持有外部类
改变哈希值
单例模式
监听器
ThreadLocal的误用
三、GC
(1)判断垃圾
1)算法
引用计数(缺点:不能解决循环引用)、根可达性分析
2)GC roots
1.虚拟机栈(JVM stack)中引用的对象
2.方法区中类静态属性引用的对象
3.本地方法栈(Native Stack)引用的对象
(2)垃圾回收算法
复制、标记清除、标记整理、分代回收、分块回收
(3)hopspot垃圾回收器
1)GC类型
Minor GC
Major GC
Full GC(Major GC对老年代/永久代的stop the world的GC)
Mixed GC(G1)
1)新生代回收器
serial、parNew、parallelScavenge
2)老年代回收器
CMS、serialOld、parallelOld
3)整堆回收器
G1
关系:(serial和parNew)搭配(CMS和serialOld)、parallelScavenge搭配(serialOld和parallelOld)、CMS并发模式失败后以serialOld做备份
4)CMS
1、运作步骤
初始标记(stop the world)、并发标记、重新标记(stop the world)、并发清除
2、优点
并发收集、低停顿
3、缺点
CMS收集器对CPU资源非常敏感
CMS收集器无法处理浮动垃圾(Concurrent Mode Failure)
CMS收集器会产生大量空间碎片
5)G1
1、特点
并行于并发、空间整合、可预测的停顿、分代收集
2、运作步骤
初始标记、并发标记、最终标记、筛选回收
(4)垃圾回收机制
1)GC触发的条件
Minor GC触发条件:当Eden区满时,触发Minor GC
Full GC触发条件:
1、调用System.gc时,系统建议执行Full GC,但是不必然执行
2、老年代空间不足
3、方法去空间不足
4、通过Minor GC后进入老年代的平均大小大于老年代的可用内存
5、由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小
6、 CMS GC时出现promotion failed和concurrent mode failure
2)年轻代到年老代的晋升过程的判断条件
1、长期存活的对象进入老年代(15次MinorGC,JVM参数-XX:MaxTenuringThreshold)
2、动态对象年龄判定(大于等于某个年龄的对象超过了survivor空间一半)
3、如果对象的大小大于Eden的二分之一会直接分配在old,如果old也分配不下,会做一次majorGC。如果小于eden的一半但是没有足够的空间,就进行minor gc也就是新生代GC,minor gc后,survivor仍然放不下,则放到老年代
3)一次完整的 GC 流程
1.大对象直接进入到老年代
2.小对象先在eden区分配内存,当eden满了后,触发一次Minor GC,清理eden区域
3.存活下来的对象进入到survivor区域,年龄+1
4.当年龄>15(默认)时进入到老年代,当老年代满了后触发一次Full GC
4)fullGC 很频繁,线上排查问题
查看gc.log
jmap -histo:live pid
-XX:+HeapDumpBeforeFullGC
jstat -gcutil pid
四、jvm分析
(1)jvm命令工具
jstack
jmap
jhat
jstat
jinfo
jps
jconsole, jvisualvm
(2)线程堆栈
1)线程堆栈信息
线程的名字、线程的优先级、线程 id、线程的状态、线程占用的内存地址、线程的调用栈
2)线程状态
NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED
3)分析性能问题
1、系统无缘无故的cpu过高
2、系统挂起,无响应
3、系统运行越来越慢
4、性能瓶颈(如无法充分利用cpu等)
5、线程死锁,死循环等
6、由于线程数量太多导致的内存溢出(如无法创建线程等)
五、类加载
(1)双亲委派模型
类加载器:Bootstrap、Extension、Application
(2)打破双亲加载
JNDI、JDBC、Tomcat
(3)类加载过程
装载、链接(验证、准备、解析)、初始化、使用、卸载
(4)类的实例化顺序
父类静态变量->父类静态代码块->子类静态变量->子类的静态代码块->父类成员变量->父类代码块->父类构造方法->子类成员变量->子类代码块->子类构造方法
(5)类装载方式
1)隐式装载
创建类对象、使用类的静态域、创建子类对象、使用子类的静态域。
其他特殊的隐式加载:
在JVM启动时,BootStrapLoader会加载一些JVM自身运行所需的class
在JVM启动时,ExtClassLoader会加载指定目录下一些特殊的class
在JVM启动时,AppClassLoader会加载classpath路径下的class,以及main函数所在的类的class文件
2)显式装载
ClassLoader.loadClass(className) :只执行装载过程。
Class.forName(className):执行类的装载、链接、初始化过程
注:1、Class.forName(className)是初始化类,newInstance()是实例化类。new是初始化加实例化类。2、new关键字和Class类的newInstance()的区别