异常处理
1 异常概述
- 异常:程序执行过程中,产出的问题,因为异常的问题程序的正常的逻辑中断
- Java程序在执行过程中所发生的异常事件可分为两类:异常最顶层的类Throwable
- Error: Java虚拟机无法解决的严重问题。 如: JVM系统内部错误、 资源耗尽等严重情况。
- StackOverflowError:栈深度溢出异常,比如递归方法,没有退出条件
- java.lang.OutOfMemoryError:OOM内存溢出异常,栈,堆,方法区,程序计数器不会发生
- Exception: 其它因编程错误或偶然的外在因素导致的一般性问题, 可以使用针对性的代码进行处
- RuntimeException:运行期异常,编译是不需要处理
- ClassCastException
- ArrayIndexOutOfBoundsException
- ArithmeticException
- NullPointerException
- 非RuntimeException:编译期需要处理(try catche 或者throws)
- FileNotFoundException
- IOException
- SQLException
- RuntimeException:运行期异常,编译是不需要处理
- Error: Java虚拟机无法解决的严重问题。 如: JVM系统内部错误、 资源耗尽等严重情况。
1.1堆内存OOM
- xms10m:初始堆内存10m
- xmx20m:最大堆内存20m
测试代码
public class Test1 {
static class OOM{
// int i = 0;
}
/**
* xms:初始化堆内存
* xmx:最大堆内存
* @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
点击Edit Configurations
点击Modify options
点击Add VM options
当然也可以点Alt+V
然后就可以出来VM options
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();
}
}
}
设置最大方法区(元空间大小)(设置VM options)
-XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m
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.3 其他异常
一. 不是maven项目拷贝junit的jar包到项目,是maven的话就在pom里添加依赖.
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>compile</scope>
</dependency>
这里说一下拷贝
#创建lib目录
#拷贝junit的jar文件到目录
就可以写个test测试一下了
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
/**
* 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();
} catch (NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("finally");
System.out.println("步骤3");
}
案例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异常
案例3:
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());
}
}