一个简单的例子教会您使用 javap
javap 是 JDK 自带的工具:
这篇文章使用下面这段简单的 Java 代码作为例子进行讲解。
使用下面的命令行对 NullableTest 进行反编译,以 java 编译器生成的字节码:
javap -v NullableTest >c:\code\1.txt
查看方法 way1()对应的字节码:
下面这个 wiki 包含了 java 字节码里每个指令的具体说明:
https://en.wikipedia.org/wiki/Java_bytecode_instruction_listings
下面对 NullableTest 反编译得到的字节码做一些说明:
0: invokestatic #42 // Method getInitializedOuter:()Ljava8/Outer;
代表静态方法 getInitializedOuter 的调用, Ljava8/Outer 意思是该方法的返回类型是 Outer
3: astore_0
将上述静态方法调用返回的 outer 引用存储到局部变量中,局部变量的 id 为 0.
4: aload_0
因为在我前面的 Java 源代码中,我将静态方法返回的对象引用同 null 做了比较,因此使用指令 aload_0 将存储在代号为 0 的局部变量中的对象引用重新加载到栈上,此后才能和 null 做比较。
5: ifnull 41
这就是我在 Java 源代码里书写的 IF 分支。如果 IF 分支里检测的 outer 引用为 null,则直接返回了。体现在字节码就是,如果 ifnull 为 true,则跳转到第 41 行字节码,即直接返回。
如果 ifnull 不为 true,则继续执行下去。又将 outer 引用加载到栈上。
从字节码的分析可以观察到一个有趣的现象,再次看看我们的 IF 语句。
Java 编译时,编译器实际将其转换成了下面的写法:
这个事实可以通过下图得到确认。
javap 生成的字节码里的 LineNumberTable 也很有用。这张表里每行的 line 后面的数字代表 Java 源代码的序号,line XX 冒号后面的数字代表字节码里每行指令的序号。看看下图中 Java 源代码和对应的字节指令在 LineNumberTable 中的映射关系。
LineNumberTable 维护了 Java 源代码同字节指令的映射关系,确保了 Java 代码调试的顺利进行。
不知道大家对千篇一律的 404 Not Found 的错误页面是否感到腻歪了?其实通过很简单的配置就能够让 Spring MVC 显示您自定义的 404 Not Found 错误页面。
在 WEB-INF 的 web.xml 里添加一个新的区域:
意思是一旦有 404 错误发生时,显示 resouces 文件夹下的 404.jsp 页面。
现在可以随意开发您喜欢的个性化 404 错误页面了。
完毕之后,随便访问一个不存在的 url,故意造成 404 错误,就能看到我们刚才配置的自定义 404 Not Found 页面了。
如果想在 Spring MVC 里实现一个通用的异常处理逻辑(Exception handler), 能够捕捉所有类型的异常,比如通过下面这种方式抛出的异常,可以按照下面介绍的步骤来做。
1. 新建一个类,继承自 SimpleMappingExceptionResolver:
2. 在 Spring MVC 的 Servlet 配置文件里,将刚才创建的类作为一个 Bean 配置进去:
Bean 的 ID 设置为 simpleMappingExceptionResolver,class 设置为步骤一创建的类的包含 namespace 的全名。创建一个名为 defaultErrorView 的 property,其 value 为 generic_error, 指向一个 JSP view:generic_error.jsp。
generic_error.jsp 的源代码:
现在可以做测试了。我之前通过下列语句抛了一个异常:
throw new Exception("Generic Exception raised by Jerry");
这个异常成功地被我自己实现的异常处理类捕捉到,并显示出我自定义的异常显示页面:
要获取更多 Jerry 的原创技术文章,请关注公众号"汪子熙"。
版权声明: 本文为 InfoQ 作者【Jerry Wang】的原创文章。
原文链接:【http://xie.infoq.cn/article/222bc6615a87658a590a37923】。文章转载请联系作者。
评论