![1263bea30c9ea29ea0933a6096d57486.png](https://img-blog.csdnimg.cn/img_convert/1263bea30c9ea29ea0933a6096d57486.png)
案例介绍
异常处理是java语言非常重要的一个语法,本章主要实现如何处理抛出的异常。
在Java语言中,异常可以分为两类:Checked异常和Unchecked异常。Unchecked异常包括java.lang.RuntimeException、java.lang.Error以及它们的子类,提前异常都是Checked异常。所有异常都最终继承自java.lang.Throwable。如果一个方法有可能导致Checked异常抛出,则该方法要么需要捕获该异常并妥善处理,要么必须把该异常列在自己的throws子句中,否则无法通过编译。Unchanged异常没有这个限制。请注意,Java虚拟机规范并没有这个规定,这只是Java语言的语法规则。
异常可以由Java虚拟机抛出,也可以由Java代码抛出。当Java虚拟机在运行过程中遇到比较严重的问题时,会抛出java.lang.Error的某个子类,如StackOverflowError、OutOfMemoryError等。程序一般无法从这种异常里恢复,所以在代码中通常也不必关心这类异常。
一部分执行在执行过程中会导致Java虚拟机抛出java.lang.RuntimeException的某个子类,如NullPointerException、IndexOutOfBoundsException等。这类异常一般是代码中的bug导致的,需要格外注意。在代码中抛出和处理异常是由athrow指令和方法的异常处理表配合完成的。
环境准备
1、jdk 1.8.0
2、IntelliJ IDEA Community Edition 2018.3.1 x64
配置信息
1、调试配置
2.1、配置位置:Run/Debug Configurations -> program arguments
2.2、配置内容:-Xjre "C:Program FilesJavajdk1.8.0_161jre" E:itstackgitistack-demoitstack-demo-jvmitstack-demo-jvm-10argetest-classesorgitstackdemoestHelloWorld
代码示例
itstack-demo-jvm-10├── pom.xml└── src └── main │ └── java │ └── org.itstack.demo.jvm │ ├── _native │ │ ├── java │ │ │ ├── _Class.java │ │ │ ├── _Double.java │ │ │ ├── _Float.java │ │ │ ├── _Object.java │ │ │ ├── _String.java │ │ │ ├── _System.java │ │ │ └── _Throwable.java │ │ └── sun │ ├── NativeMethod.java │ └── Registry.java │ ├── classfile │ │ ├── attributes │ │ ├── constantpool │ │ ├── ClassFile.java │ │ ├── ClassReader.java │ │ └── MemberInfo.java │ ├── classpath │ │ ├── impl │ │ │ ├── CompositeEntry.java │ │ │ ├── DirEntry.java │ │ │ ├── WildcardEntry.java │ │ │ └── ZipEntry.java │ │ ├── Classpath.java │ │ └── Entry.java │ ├── classpath │ │ ├── base │ │ │ ├── BytecodeReader.java │ │ │ ├── ClassInitLogic.java │ │ │ ├── Instruction.java │ │ │ ├── InstructionBranch.java │ │ │ ├── InstructionIndex8.java │ │ │ ├── InstructionIndex16.java │ │ │ ├── InstructionNoOperands.java │ │ │ └── MethodInvokeLogic.java │ │ ├── comparisons │ │ ├── constants │ │ ├── control │ │ ├── conversions │ │ ├── extended │ │ ├── loads │ │ ├── math │ │ ├── references │ │ │ ├── ANEW_ARRAY.java │ │ │ ├── ARRAY_LENGTH.java │ │ │ ├── ATHROW.java │ │ │ ├── CHECK_CAST.java │ │ │ ├── GET_FIELD.java │ │ │ ├── GET_STATIC.java │ │ │ ├── INSTANCE_OF.java │ │ │ ├── INVOKE_INTERFACE.java │ │ │ ├── INVOKE_SPECIAL.java │ │ │ ├── INVOKE_STATIC.java │ │ │ ├── INVOKE_VIRTUAL.java │ │ │ ├── MULTI_ANEW_ARRAY.java │ │ │ ├── NEW.java │ │ │ ├── NEW_ARRAY.java │ │ │ ├── PUT_FIELD.java │ │ │ └── PUT_STATIC.java │ │ ├── reserved │ │ │ └── INVOKE_NATIVE.java │ │ ├── stack │ │ ├── store │ │ │ └── xastore │ │ │ ├── AASTORE.java │ │ │ ├── BASTORE.java │ │ │ ├── CASTORE.java │ │ │ ├── DASTORE.java │ │ │ ├── FASTORE.java │ │ │ ├── IASTORE.java │ │ │ ├── LASTORE.java │ │ │ └── SASTORE.java │ │ └── Factory │ ├── rtda │ │ ├── heap │ │ │ ├── constantpool │ │ │ ├── methodarea │ │ │ │ ├── Class.java │ │ │ │ ├── ClassMember.java │ │ │ │ ├── ExceptionTable.java │ │ │ │ ├── Field.java │ │ │ │ ├── Method.java │ │ │ │ ├── MethodDescriptor.java │ │ │ │ ├── MethodDescriptorParser.java │ │ │ │ ├── MethodLookup.java │ │ │ │ ├── Object.java │ │ │ │ ├── Slots.java │ │ │ │ └── StringPool.java │ │ │ └── ClassLoader.java │ │ ├── Frame.java │ │ ├── JvmStack.java │ │ ├── LocalVars.java │ │ ├── OperandStack.java │ │ ├── Slot.java │ │ └── Thread.java │ ├── Cmd.java │ ├── Interpret.java │ └── Main.java └── test └── java └── org.itstack.demo.test └── HelloWorld.java
如下为新增代码:
ClassReader.java (优化)
/** * http://www.itstack.org * create by fuzhengwei on 2019/5/12 *
* java虚拟机定义了u1、u2、u4三种数据类型来表示;1字节、2字节、4字节,无符号整数。 * 在如下实现中,用增位方式表示无符号类型: * u1、u2可以用int类型存储,因为int类型是4字节 * u4 需要用long类型存储,因为long类型是8字节 */public class ClassReader { private byte[] data; public ClassReader(byte[] data) { this.data = data; } //u1 public int readUint8() { byte[] val = readByte(1); return byte2int(val); } //u2 public int readUint16() { byte[] val = readByte(2); return byte2int(val); } //u4 public long readUint32() { byte[] val = readByte(4); String str_hex = new BigInteger(1, val).toString(16); return Long.parseLong(str_hex, 16); } public int readUint32TInteger(){ byte[] val = readByte(4); return new BigInteger(1, val).intValue(); } public float readUint64TFloat() { byte[] val = readByte(8); return new BigInteger(1, val).floatValue(); } public long readUint64TLong() { byte[] val = readByte(8); return new BigInteger(1, val).longValue(); } public double readUint64TDouble() { byte[] val = readByte(8); return new BigInteger(1, val).doubleValue(); } public int[] readUint16s() { int n = this.readUint16(); int[] s = new int[n]; for (int i = 0; i < n; i++) { s[i] = this.readUint16(); } return s; } public byte[] readBytes(int n) { return readByte(n); } private byte[] readByte(int length) { byte[] copy = new byte[length]; System.arraycopy(data, 0, copy, 0, length); System.arraycopy(data, length, data, 0, data.length - length); return copy; } private int byte2int(byte[] val) { String str_hex = new BigInteger(1, val).toString(16); return Integer.parseInt(str_hex, 16); }}
_Throwable.java
public class _Throwable { private StackTraceElement stackTraceElement; private final String jlThrowable = "java/lang/Throwable"; public _Throwable() { Registry.register(jlThrowable, "fillInStackTrace