异常处理学习

1 异常概述

  • 异常:程序执行过程中,产出的问题,因为异常的问题程序的正常的逻辑中断

  • Java程序在执行过程中所发生的异常事件可分为两类:异常最顶层的类Throwable

    • Error: Java虚拟机无法解决的严重问题。 如: JVM系统内部错误、 资源耗尽等严重情况。

      • StackOverflowError:栈深度溢出异常,比如递归方法,没有退出条件
      • -Xss128k
      • java.lang.OutOfMemoryError:OOM内存溢出异常,栈,堆,方法区,程序计数器不会发生
      • Xms4g
      • Xmx4g
      • xx:MaxMetespaceSize=512M
    • Exception: 其它因编程错误或偶然的外在因素导致的一般性问题, 可以使用针对性的代码进行处

      • RuntimeException:运行期异常,编译是不需要处理

        • ClassCastException
        • ArrayIndexOutOfBoundsException
        • ArithmeticException
        • NullPointerException
      • 非RuntimeException:编译期需要处理(try catche 或者throws)

        • FileNotFoundException
        • IOException
        • SQLException

1.1 堆内存OOM

  • xms10m:初始堆内存10m
  • xmx20m:最大堆内存20m

测试代码:

public class Test1 {

    static class OOM{
        // int i = 0;
    }

    /**
     * xms:初始化堆内存
     * xmx:最大堆内存
     * 360146 10m
     * 810326 20m
     * 1215488 40m
     * @param args
     */
    public static void main(String[] args) {
        System.out.println("前面代码");
        List<OOM> list = new ArrayList<>();
        int i=0;
        try {
            while (true) {
                i++;
                list.add(new OOM());
            }
        } catch (Throwable e) {
            System.out.println("=================多少次后发生异常:"+i);
            e.printStackTrace();
        }
    }

}

设置jvm参数:

  • xmx40m:最大堆内存大小40m
  • xms10m:初始堆内存大小10m

在这里插入图片描述
执行结果:

前面代码
=================多少次后发生异常:1215488
java.lang.OutOfMemoryError: Java heap space
	at java.util.Arrays.copyOf(Arrays.java:3210)
	at java.util.Arrays.copyOf(Arrays.java:3181)
	at java.util.ArrayList.grow(ArrayList.java:265)
	at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
	at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
	at java.util.ArrayList.add(ArrayList.java:462)
	at a_basic.Test1.main(Test1.java:27)

1.2 方法区(元空间)OOM

public class MetaspaceDemo {

    static class OOM{}

    public static void main(String[] args) {
        int i = 0;//模拟计数多少次以后发生异常
        try {
            while (true){
                i++;
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(OOM.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 e) {
            System.out.println("=================多少次后发生异常:"+i);
            e.printStackTrace();
        }
    }

}

设置最大方法区(元空间大小)

-XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m

在这里插入图片描述

=================多少次后发生异常:540
org.springframework.cglib.core.CodeGenerationException: java.lang.OutOfMemoryError-->Metaspace
	at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:557)

1.3 StackOverflowError栈深度溢出异常

StackOverflowError:栈深度⼤于虚拟机所允许的深度

    static void f1() {
        int i = 1;
        f1();
    }

    /**
     * StackOverflowError:栈寻址深度溢出异常,递归没有退出条件
     */
    @Test
    public void f2() {
        System.out.println("前面代码");
        f1();
        System.out.println("后续代码");
    }

结果:

前面代码

java.lang.StackOverflowError
	at a_basic.Test1.f1(Test1.java:38)
	at a_basic.Test1.f1(Test1.java:38)

1.4 其他异常

1. 拷贝junit的jar包到项目

#创建lib目录
#拷贝junit的jar文件到目录

在这里插入图片描述
2. 配置使用junit依赖
在这里插入图片描述

public class Test1 {

    /**
     * 空指针异常
     */
    @Test
    public void f3() {
        System.out.println("前面代码");

        String s = null;
        s.trim();

        System.out.println("后续代码");
    }

    /**
     * java.lang.ArithmeticException: / by zero:0作为除数异常
     */
    @Test
    public void f4() {
        System.out.println("前面代码");

        int i = 1/0;

        System.out.println("后续代码");
    }


}

2 异常处理

2.1 try catch finally

例1:

    /**
     * ClassCastException
     * 类型转换异常
     */
    static void fn1() {
        Object o = "abc";
        Integer i = (Integer) o;

        int a = 1/0;

        String s = null;
        s.trim();


    }

    @Test
    public void test6() {
        System.out.println("步骤1");

        try {
            fn1(); //共享单车车胎坏了
        } catch (ClassCastException e) {
            System.out.println("ClassCastException");
            //换了一个车
            e.printStackTrace(); //test6在调用fn1的时候123行异常
        } catch (NullPointerException e) {
            //轱辘没了...
            e.printStackTrace();
        } catch (Exception e) { //兜底,捕获除了上面2个异常的所有异常
            e.printStackTrace();
        } finally {
            System.out.println("还共享单车"); //释放资源,必须执行的代码
        }

        System.out.println("步骤3");
        //运行期异常RuntimeException的子类,不需要处理,编译也不报错
    }

例2:

public class Test2 {

    public static void fn1() {
        DataOutputStream out = null;
        try {
            out = new DataOutputStream(new FileOutputStream("d:\\a.txt"));
            out.writeChar(97);
            out.writeInt(1);
            out.writeChar(98);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static void main(String[] args) {
        fn1();
    }


}

2.2 throws

throws:声明异常,当前方法不捕获(catch)异常,而是由调用这个方法的方法catch异常
注意RuntimeException不需要catch异常

    public static void fn1() throws IOException {
            DataOutputStream out = new DataOutputStream(new FileOutputStream("d:\\c.txt"));
            out.writeChar(97); //发生异常
            out.writeInt(1);
            out.writeChar(98);
            out.close(); //有可能执行不到
    }

    public static void main(String[] args) {
        //alt+enter:解决一切问题
        try {
            fn1();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2.3 throw和自定义异常

throw:抛出一个异常,可以是一个自定义异常,语法

throw new MyException(); //抛出自定义异常
throw new RuntimeException(e);//抛出运行期异常

自定义异常:

public class MyException extends Exception {

    public MyException() {
    }

    public MyException(String message) {
        super(message);
    }
}

student:

public class Student {

    private int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        if (id > 0) {
            this.id = id;
        } else {
//            throw new RuntimeException("学员编号不能为负数"); //抛出运行期异常
            //抛出自定义异常
            throw new RuntimeException(new MyException("学员编号不能为负数")) ;
        }


    }
}

测试:

public class Test1 {

    public static void main(String[] args) {
        Student s = new Student();
        s.setId(-1001);

        System.out.println(s.getId());
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值