Throwable是所有异常的父类
StackOverFlowError
产生原因:
递归的深度调用可能会产生StackOverFlowError
(深度的方法调用出不来)
实例:
package com.example.demo.Throwable;
/**
* 实现堆栈溢出异常
* 深度进行递归
*/
public class StackOverErrorFlowDemo {
public static void shen(){
shen();
}
public static void main(String[] args) {
shen();
}
}
展示结果:
Exception in thread "main" java.lang.StackOverflowError
at com.example.demo.Throwable.StackOverErrorFlowDemo.shen(StackOverErrorFlowDemo.java:9)
at com.example.demo.Throwable.StackOverErrorFlowDemo.shen(StackOverErrorFlowDemo.java:9)
at com.example.demo.Throwable.StackOverErrorFlowDemo.shen(StackOverErrorFlowDemo.java:9)
at com.example.demo.Throwable.StackOverErrorFlowDemo.shen(StackOverErrorFlowDemo.java:9)
at com.example.demo.Throwable.StackOverErrorFlowDemo.shen(StackOverErrorFlowDemo.java:9)
at com.example.demo.Throwable.StackOverErrorFlowDemo.shen(StackOverErrorFlowDemo.java:9)
at com.example.demo.Throwable.StackOverErrorFlowDemo.shen(StackOverErrorFlowDemo.java:9)
at com.example.demo.Throwable.StackOverErrorFlowDemo.shen(StackOverErrorFlowDemo.java:9)
at com.example.demo.Throwable.StackOverErrorFlowDemo.shen(StackOverErrorFlowDemo.java:9)
OOM
OOM之java head space
产生原因:
内存溢出
实例:
package com.example.demo.Throwable;
/**
* OOM(OutOfMemoryError)内存溢出 之 Java Heap Space
* 修改jvm的内存大小
* -Xms8m -Xmx8m
*/
public class JavaHeapSpaceInOOM {
public static void main(String[] args) {
//创建byte数组撑爆内存
byte[] bytes = new byte[10 * 1024 * 1024];
}
}
展示结果:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.example.demo.Throwable.JavaHeapSpaceInOOM.main(JavaHeapSpaceInOOM.java:11)
OOM之 GC overHead limit exceeded
产生原因:
java代码编写的特别诡异,导致java内存急剧的上升
实例:
-XX:MaxDirectMemorySize : 虚拟机外的内存大小
package com.example.demo.Throwable;
import java.util.ArrayList;
/**
* 测试OOM 之 GC OverHead limit exceeded
* 表示98%的时间GC且回收不到2%的内存
* JVM的参数配置
* -Xmx8m -Xms8m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
*/
public class GcOverHeadLimitInOOM {
public static void main(String[] args) {
//初始化添加的int对象
int i = 0 ;
//创建list用来添加数据
ArrayList<String> strings = new ArrayList<>();
try {
while (true){
//一直添加对象
strings.add(String.valueOf(i++).intern());
}
} catch (Throwable e) {
System.out.println("i:============="+i);
e.printStackTrace();
}
}
}
显示效果:
i:=============94936
Heap
PSYoungGen total 2048K, used 203K [0x00000000ffd80000, 0x0000000100000000, 0x0000000100000000)
eden space 1536K, 13% used [0x00000000ffd80000,0x00000000ffdb2d90,0x00000000fff00000)
from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
to space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
ParOldGen total 5632K, used 1557K [0x00000000ff800000, 0x00000000ffd80000, 0x00000000ffd80000)
object space 5632K, 27% used [0x00000000ff800000,0x00000000ff985798,0x00000000ffd80000)
Metaspace used 3729K, capacity 4540K, committed 4864K, reserved 1056768K
class space used 398K, capacity 428K, committed 512K, reserved 1048576K
java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.lang.Integer.toString(Integer.java:403)
at java.lang.String.valueOf(String.java:3099)
at com.example.demo.Throwable.GcOverHeadLimitInOOM.main(GcOverHeadLimitInOOM.java:20)
OOM之Direct Buffer Memory(一般在NIO里面经常出现)
产生原因:
不断分配本地内存,而堆内存很少使用,那么JVM不需要执行GC,directByteBuffer对象不会被回收,这个时候堆内存充足,但是本地内存已经用光,再次尝试就会出现OOM的情况.
实例:
package com.example.demo.Throwable;
import sun.misc.VM;
import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;
/**
* OOM 之 Direct Buffer Memory
* 不断分配本地内存,而堆内存很少使用,那么JVM不需要执行GC
* directByteBuffer对象不会被回收,这个时候堆内存充足,但是本地内存已经用光,再次尝试就会出现OOM的情况.
* JVM参数配置
* -Xmx8m -Xms8m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
*/
public class DirectBufferMemoryInOOM {
public static void main(String[] args) {
//查看本地的direct buffer memory内存
long memory = VM.maxDirectMemory();
System.out.println("配置的maxDirectMemory内存:"+(memory/(double)1024/1024)+"MB");
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
//给堆外空间,本地内存分配大小为6M的字节缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(6 * 1024 * 1024);
}
}
展示结果:
配置的maxDirectMemory内存:5.0MB
Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
at java.nio.Bits.reserveMemory(Bits.java:694)
at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
at com.example.demo.Throwable.DirectBufferMemoryInOOM.main(DirectBufferMemoryInOOM.java:23)
OMM之Unable to create new native Thread
出现场景:
高并发请求超时时,经常出现这个异常。
产生原因:
应用程序创建太多线程,一个应用进程创建多个线程,超过了系统承载极限,服务器不允许应用程序创建这个多线程,linux系统(非root用户)默认允许单个进程可以创建1024个Thread,而root用户没有上线可以一直创建用户,就会报:java.lang.OutOfMemoryError:unable to create new native thread
解决方法:
1.降低应用程序创建的线程数量,分析应用是否真的需要创建这么多线程,如果不是,修改代码把线程数降到最低。
2.如果有的应用,确实需要创建多个线程,而这个线程数远超过linux系统的默认1024个线程的限制,可以修改linux的服务配置,扩大linux的默认配置
3.修改非root用户的上线在 /etc/security/limitsd/90-nproc.conf(服务器级别的调优)
查看90-nproc.conf配置文件
实例:
package com.example.demo.Throwable;
/**
* 测试OOM之 Unable Create Native Thread
* 应用程序创建太多线程,一个应用进程创建多个线程,超过了系统承载极限,服务器不允许应用程序创建这个多线程,
* linux系统默认允许单个进程可以创建1024个,应用创建这个数量,
* 就会报:java.lang.OutOfMemoryError:unable to create new native thread
*/
public class UnableCreateNativeThreadInOOM {
public static void main(String[] args) {
//初始化i i用来线程命名
int i = 0 ;
while(true){
new Thread(()->{
try {
//保证线程一致存在不退出
Thread.sleep(Integer.MAX_VALUE);
} catch (Throwable e) {
System.out.println();
e.printStackTrace();
}
}).start();
}
}
}
OOM之Metaspace
产生原因:
元空间满了
实例:
package com.example.demo.Throwable;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* MetaspaceInOOM
* 配置JVM参数
* -XX:MaxMetaspaceSize=7m -XX:MetaspaceSize=5m -XX:+PrintGCDetails
*
* 元空间存储:
* 虚拟机加载类信息
* 常量池
* 静态变量
* 即时后编译的代码
*/
public class MetaSpaceInOOM {
public static class MetaOom{
}
public static void main(String[] args) {
int i = 0 ;
try {
while (true){
i++;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MetaOom.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
return methodProxy.invokeSuper(o,args);
}
});
enhancer.create();
}
}catch (Throwable throwable){
System.out.println("执行到i="+i+"时抛出异常");
throwable.printStackTrace();
}
}
}
展示结果:
执行到i=179时抛出异常
java.lang.OutOfMemoryError: Metaspace
at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:538)
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:363)
at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:585)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:131)
at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:319)
at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:572)
at org.springframework.cglib.proxy.Enhancer.create(Enhancer.java:387)
at com.example.demo.Throwable.MetaSpaceInOOM.main(MetaSpaceInOOM.java:38)