JVM 调优主要是减少GC的频繁调用, GC调用是为了回收空间, 但是频繁调用会带来: STW(Stop-The-World), 顾名思义 STW :使得世界停止, 只不过这里的世界是JVM 的世界, 即STW会使用户线程暂停, 时间过长的话会影响性能和用户体验.
那么为了达到减少GC频繁调用, 有哪些方法呢?
一, 栈上分配技术.
说这个问题之前问个问题: 堆是分配对象存储的唯一选择吗?
我们都知道, 对象主要是在堆空间中被创建的, 也是主要在堆空间中被销毁的, 其中新生代的Minor GC(又叫young GC) 效率比较高, 老年代的 Major GC(又叫 old GC) 效率比较低, 此时为了减少堆中的GC调用, 我们会通过逃逸分析(Escape analysis) 的方式分析哪些对象有没有发生逃逸, 如果没有发生逃逸, 我们就可以把这一部分对象分配到栈上. 相比较堆而言, 栈的特点是:每个线程独有的, 不会出现安全问题, 每个方法对应一个栈帧, 栈帧先进后出, 说白了只有出栈进栈, 方法需要执行了就进栈, 执行完了就出栈, 自动回收空间的机制使得栈中不需要GC, 那么我们把没有发生逃逸的对象分配在栈中的话, 就会减少堆中GC的调用, 达到调高JVM 性能的目的. 到这里你可能会问, 逃逸分析怎么分析, 其实在JDK6以后, Hotspot已经默认开启逃逸分析了, 而怎么避免对象发生逃逸呢? 很简单-----创建对象的时候尽量使用局部变量, 能在方法内声明的, 就不要在方法外声明, 另外在方法内声明的对象的实体还要避免被其他方法使用, 此时, 我们就可以说这个对象是没有发生逃逸的, 就会被分配到栈上.
最后也就回答了我一开始的问题: 堆是分配对象存储的唯一选择吗?, 大家都知道答案了, 堆并不是分配对象存储的唯一选择.
二, 堆外存储技术.
这里说的堆外存储技术主要指taobaoVM虚拟机为代表的GCIH(GC-Invisible Heap) 技术, 淘宝团队在JVM深度定制的过程中, 把一些大的对象存储在GCIH中, 也就是堆外的空间里, 此时的GC就完全不用管GCIH中的对象了, 大大的减少了GC 的调用频率, 达到了提升性能的目的.
未完待续.........
浙公网安备 33010602011771号