打字猴:1.700449265e+09
1700449265
1700449266 }
1700449267
1700449268 注意看Invoker类,两个方法m1和m2都调用了Foo的m方法,都是无参调用,返回值却不同,这是我们的Throwable类发挥效能了。JVM在创建一个Throwable类及其子类时会把当前线程的栈信息记录下来,以便在输出异常时准确定位异常原因,我们来看Throwable源代码:
1700449269
1700449270 public class Throwable implements Serializable{
1700449271
1700449272 //出现异常的栈记录
1700449273
1700449274 private StackTraceElement[]stackTrace;
1700449275
1700449276 //默认构造函数
1700449277
1700449278 public Throwable(){
1700449279
1700449280 //记录栈帧
1700449281
1700449282 fllInStackTrace();
1700449283
1700449284 }
1700449285
1700449286 //本地方法,抓取执行时的栈信息
1700449287
1700449288 public synchronized native Throwable fillInStackTrace();
1700449289
1700449290 }
1700449291
1700449292 在出现异常时(或主动声明一个Throwable对象时),JVM会通过fillInStackTrace方法记录下栈帧信息,然后生成一个Throwable对象,这样我们就可以知道类间的调用顺序、方法名称及当前行号等了。
1700449293
1700449294 获得栈信息可以对调用者进行判断,然后决定不同的输出,比如我们的m1和m2方法,同样是输入参数,同样的调用方法,但是输出却不同,这看起来很像是一个Bug:方法m1调用m方法是正常显示,而方法m2调用却会返回“错误”数据。因此我们虽然可以依据调用者不同产生不同的逻辑,但这仅局限在对此方法的广泛认知上。更多的时候我们使用m方法的变形体,代码如下:
1700449295
1700449296 class Foo{
1700449297
1700449298 public static boolean m(){
1700449299
1700449300 //取得当前栈信息
1700449301
1700449302 StackTraceElement[]sts=new Throwable().getStackTrace();
1700449303
1700449304 //检查是否是m1方法调用
1700449305
1700449306 for(StackTraceElement st:sts){
1700449307
1700449308 if(st.getMethodName().equals(“m1”)){
1700449309
1700449310 return true;
1700449311
1700449312 }
1700449313
1700449314 }
[ 上一页 ]  [ :1.700449265e+09 ]  [ 下一页 ]