1-报错信息
java.lang.OutOfMemoryError: Java heap space
2-案例模拟
用spring boot创建的案例
package com.atguigu.demo.controller;import com.atguigu.demo.bean.People;import com.atguigu.demo.service.PeopleSevice;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cglib.proxy.*;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.lang.management.ClassLoadingMXBean;import java.lang.management.ManagementFactory;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.List;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;/*** <pre>* @author : shkstart* time : 08:54* desc : 内存测试* version : v1.0* </pre>*/@RestControllerpublic class MemoryTestController {@Autowiredprivate PeopleSevice peopleSevice;/*** 案例1:模拟线上环境OOM*/@RequestMapping("/add")public void addObject(){System.err.println("add"+peopleSevice);ArrayList<People> people = new ArrayList<>();while (true){people.add(new People());}}/*** 案例2:模拟元空间OOM溢出*/@RequestMapping("/metaSpaceOom")public void metaSpaceOom(){ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();while (true){Enhancer enhancer = new Enhancer();enhancer.setSuperclass(People.class);// enhancer.setUseCache(false);enhancer.setUseCache(true);enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {System.out.println("我是加强类,输出print之前的加强方法");return methodProxy.invokeSuper(o,objects);});People people = (People)enhancer.create();people.print();System.out.println(people.getClass());System.out.println("totalClass:" + classLoadingMXBean.getTotalLoadedClassCount());System.out.println("activeClass:" + classLoadingMXBean.getLoadedClassCount());System.out.println("unloadedClass:" + classLoadingMXBean.getUnloadedClassCount());}}/*** 性能优化案例3:合理配置堆内存*/@RequestMapping("/getData")public List<People> getProduct(){List<People> peopleList = peopleSevice.getPeopleList();return peopleList;}}
发送请求:http://localhost:8080/add
3-JVM参数配置
参数配置: 初始-Xms30M  -Xmx30M
 
-XX:+PrintGCDetails -XX:MetaspaceSize=64m -XX:+HeapDumpOnOutOfMemoryError  -XX:HeapDumpPath=heap/heapdump.hprof -XX:+PrintGCDateStamps -Xms200M  -Xmx200M  -Xloggc:log/gc-oomHeap.log
4-运行结果
运行结果:
java.lang.OutOfMemoryError: Java heap space
  at java.util.Arrays.copyOf(Arrays.java:3210) ~[na:1.8.0_131]
  at java.util.Arrays.copyOf(Arrays.java:3181) ~[na:1.8.0_131]
  at java.util.ArrayList.grow(ArrayList.java:261) ~[na:1.8.0_131]
  at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235) ~[na:1.8.0_131]
  at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227) ~[na:1.8.0_131]
 
运行程序得到 heapdump.hprof 文件。如下图所示:
 
 还可以进一步分析log日志。见生成的log日志即可。
5-原因及解决方案
原因
  1、代码中可能存在大对象分配  
  2、可能存在内存泄漏,导致在多次GC之后,还是无法找到一块足够大的内存容纳当前对象。
解决方法
  1、检查是否存在大对象的分配,最有可能的是大数组分配  
  2、通过jmap命令,把堆内存dump下来,使用MAT等工具分析一下,检查是否存在内存泄漏的问题
  3、如果没有找到明显的内存泄漏,使用 -Xmx 加大堆内存  
  4、还有一点容易被忽略,检查是否有大量的自定义的 Finalizable 对象,也有可能是框架内部提供的,考虑其存在的必要性
6-dump文件分析
jvisualvm分析
- 接下来我们使用工具打开该文件,由于我们当前设置的内存比较小,所以该文件比较小,但是正常在线上环境,该文件是比较大的,通常是以G为单位。
 jvisualvm工具分析堆内存文件heapdump.hprof:


通过jvisualvm工具查看,占用最多实例的类是哪个,这样就可以定位到我们的问题所在。
MAT分析
使用MAT工具查看,能找到对应的线程及相应线程中对应实例的位置和代码:
7-gc日志分析

