案例1
情况:选用64位的JDK,堆大小固定12GB
问题:网站经常是定期,长时间失去响应,GC太长,回收12GB的堆,一次Full GC停顿14秒
解决方式:1.通过64位JDK使用大内存。2.使用若干32位虚拟机建立集群使用资源。
第一种:控制Full GC频率,则需要大多数对象的生存时间不应该太长。大部分对象都是 朝生夕灭,才能保证超大堆能正常使用而没有Full GC
第二种:在一台物理机上,启动多个服务应用,通过nginx负载均衡处理请求,每台服务平均分配12GB大内存。
案例2
情况:电子考试系统,客户端实时从服务器接受考试数据,4GB内存,1.6GB给java,Window32系统
问题:服务端不定时抛出内存溢出异常,Window32,限制2GB内存,划分1.6GB给java堆(在32位windows的机器上,堆最大可以达到1.4G至1.6G),其他只有0.4GB,垃圾收集时,虚拟机虽然会对
Direct Memory进行回收,但是它不会发现空间不足就通知收集器进行垃圾回收,它要等到老年代满了后
Full GC才会清理这些内存,否则就要等到内存溢出抛出异常。
解决方式:调整-XX:MaxDirectMemorySize
案例3
情况:业务每10分钟加载一个80MB的数据文件到内存进行分析,100万个HashMap<Long,Long>
问题:分析,一个HashMap:Long(24B)*2+Entry(32B)+HashMap Ret(8B)=88B。
Long:8BMarkWord+8B的Klass指针+8B数据=24B
MapEntry:16B对象头+8Bnext字段+4B的int类型hash字段=32B
对齐:4B
但其实他只要两个Long16B就行。
解决方式:1.去掉Survivor空间(-XX:SurvivorRatio=65536,-XX:MaxTenuringThreshold=0),让新生代的对象第一次Minor GC就进入老年代,治标不治本。
2.修改这个数据结构