想办法让Jvm的各个分区OOM
堆内存溢出主要是一直创建对象,但是又不能被GC回收(可达性分析,GC Root和对象之间有可达路径)就会溢出了。
参数:-Xmx20m -Xms20m -XX:+HeapDumpOnOutOfMemoryError
byte[] a = new byte[21 * 1024 * 1024];
加上HeapDumpOnOutOfMemoryError
可以dump出日志,便于后续分析OOM的问题所在
虚拟机栈里有个局部变量表,通过不断创建局部变量,可以让它爆掉
(这里没成功OOM,不懂是Jvm的原因还是什么)
参数: -Xss1m -XX:+HeapDumpOnOutOfMemoryError
public void StackOOM() {
while (true) {
Thread thread = new Thread(this::job);
thread.start();
}
}
private void job() {
while (true) {
}
}
方法区用于存放类的信息,所以想要溢出方法区,只要动态地生成大量的类就可以了。比较简单地生成类的方法是通过使用Cglib生成。所以说
有使用Cglib的项目是有可能出现方法区溢出异常的,比如Spring的Aop,如果大量的增强类,会产生很多的类,方法区的大小不够就会产生异常。
如果使用-XX:PermSize=1M -XX:MaxPermSize=1M
,要确保jvm版本低于8,因为Java1.8移除了永久代,类信息放在了Meta Space。
控制Meta space用 -XX:MetaspaceSize
和 -XX:MaxMetaspaceSize
参数:-XX:MaxMetaspaceSize=10m -XX:MetaspaceSize=10m -Xmx20m -Xms10m
while (true){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(TestMain.class);
enhancer.setUseCache(false);
enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> methodProxy.invokeSuper(o, objects));
enhancer.create();
}
Exception in thread "main" java.lang.OutOfMemoryError: Metaspace
直接内存溢出通常出现在Nio出现的地方,比如Netty。可以通过unsafe方法直接请求系统内存来模拟直接内存溢出。
参数: -XX:MaxDirectMemorySize=10M -XX:+HeapDumpOnOutOfMemoryError
Field field = Unsafe.class.getDeclaredFields()[0];
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get(null);
while (true) {
unsafe.allocateMemory(1 * 1024 * 1024);
}
Exception in thread "main" java.lang.OutOfMemoryError at sun.misc.Unsafe.allocateMemory(Native Method)