本文作者Pierre是一名有10多年经验的高级系统架构师,他的主要专业领域是Java EE、中间件和JVM技术。根据他多年的工作实践经验,他发现许多性能问题都是由Java堆容量不足和调优引起的。下面他将和大家分享非常实用的5个Java堆优化技巧。
1.JVM:对难以理解的东西产生恐惧感
千万不要以为,通过配置,调优,就可以排除那些你所不明白的问题。有些人认为Java程序员不需要知道内部JVM内存管理。毫无疑问,这种观点明显是错误的,如果想拓宽知识面和提升排除故障能力,你就必须要了解和学习一下JVM内存管理。
对于Java或者是Java EE新手来说,Java Heap调优和故障排除是一项非常有挑战的工作。下面会提供一些典型的案例场景:
客户端环境面临着有规律的OutOfMemoryError错误并且对业务造成了很大的影响。
你的开发团队要在如此大的压力下去解决这个问题,通常会怎么做?
用谷歌搜索引擎找到类似的问题并且你会相信(或假设)你也面临同样的问题。
你会抓住JVM-Xms和存在OutOfMemoryError异常这几个关键字的例子,然后希望通过这样的案例来快速解决客户端问题。
最后你会在你环境中使用相同的调优方法。两天后,问题仍然发生(甚至更糟或者稍微好点)……
到底是哪里错了呢?
首先,没有摸清问题根源所在?对开发环境没有正确地进行深层面(规格、负载情况等)理解。网络搜索是一个非常优秀的学习方法和知识分享工具,但是你必须结合自己的实际项目,从根本上进行分析解决。
可能缺乏基本的JVM和JVM内存管理技能,阻止你把所有的点给连接起来。
今天讲的第一条技巧是帮助你理解基本的JVM原则及其与众不同的内存空间。这些知识都是相当重要的,它可以帮助你做出有效的调优策略、更加正确合理的预测将来会产生的影响、提前知道未来需要做哪些调优工作。下面来看一下JVM参考指南:
JVM内存分为3个内存空间
Java Heap:适用于所有的JVM厂商,通常用来拆分YoungGen(幼苗)和OldGen(终身享用)空间。
PermGen(永久代):适用于Sun HotSpot VM((PermGen空间在Java7或者Java8更新中将会被删除)
Native Heap(C-Heap):适用于所有的JVM厂商。
建议把下面的文章都能看一遍,最好把Sun的Java内存管理白皮书和OpenJDKS实现下载下来并仔细阅读。
Sun HotSpot VM
IBM VM
Oracle JRockit VM
Sun(Oracle)–Java memory management white paper
OpenJDK–Open-source Java implementation
正如你所看到的,JVM内存管理比使用Xmx设置最大值更为复杂。你需要查看每个角度,包括本地和PermGen需求以及从主机上查看物理内存可用性(CPU core)。
在较大的Java Heap和较小的本地Heap比赛中,32位虚拟机可能会变得相当棘手。试图在一个32位VM如2.5GB+上设置一个大型堆,根据应用程序占用和线程数量等因素会增加OutOfMemoryError这个异常抛出。64位JVM可以解决这个问题,但物理资源可用性和垃圾回收成本仍然是有限制的(成本主要集中在GC大小收集上)。最大并不表示是最好的,所以请不要假设在一个16GB的64位虚拟机上可以运行20个Java EE应用程序。