堆分析
- 浅堆 一个对象结构所占用内存的大小
- 深堆 一个对象被GC回收后真是释放的内存大小,对象的保留集(该对象独立持有的其他对象)中所有对象的浅堆之和
OOM
堆溢出
直接内存溢出
过多线程导致OOM
永久区溢出
GC效率低下引起OOM
String
jdk1.6中字符串常量池的位置位于
PermGen
区域,而jdk1.7中字符串常量池位置位于Java堆
中
锁在Java虚拟机中的实现和优化
偏向锁
如果程序没有竞争,则取消之前已经取得锁的线程同步操作。若某一锁被线程获取后,便进入偏向模式,当线程再次请求这个锁时,无需再进行相关的同步操作,如果在此期间有其他线程进行请求了这个锁,则锁退出偏向模式
-XX:+UseBiasedLocking
启用偏向锁,-XX:BiasedLockingStartupDelay=0
虚拟机启动立即启用偏向锁,默认4秒后启用
偏向在竞争激烈的场合不适用,反而会导致效率降低。
轻量级锁
如果偏向锁失败,虚拟机会让线程申请轻量级锁,如果加锁失败,则轻量级锁有可能被膨胀
锁膨胀
当轻量级锁失败时,锁会被膨胀为重量级锁
自旋锁
当线程没有取得锁时,不被挂起转而去执行一个空循环,若干个空循环后,线程获得锁,则执行,否则被挂起
jdk1.6
时通过参数-XX:+UseSpining
启用自旋锁,JDK1.7
不支持配置,自旋锁总是会执行
锁消除
虚拟机通过JIT编译时,通过对上下文扫描,取消不可能存在竞争的锁(基于逃逸分析技术)。
-XX:+DoEscapeAnalysis -XX:+EliminateLocks
启用逃逸分析和锁消除
锁在应用层面的优化
- 减少锁持有时间,减小锁的持有时间有助于降低锁冲突的可能性,进而提升系统的并发能力
- 减小锁粒度,缩小锁定对象的范围,从而减少锁冲突的可能性,比如
ConcurrentHashMap
,分段加锁- 锁分离,将一个独占锁分为多个锁,比如
LinkedBlockingQueue
使用了takeLock和putLock- 锁粗化,如果频繁的获取释放
同一个锁
,则将锁合并为一次请求,减少对锁的氢气同步次数,比如循环中的锁是否可以考虑提升到循环外边- CAS(Compare And Swap,无锁化),包含三个参数
cas(v,e,n)
,v代表需要更新的变量,e代表预期的值,n代表新的值,只有当v和e相等时,才会将v的值设置为e. Java的java.util.concurrent.atomic
包中使用了无锁算法实现原子操作类
分析工具
后续补充