昆明java培训
达内昆明广州春城路

18487146383

热门课程

java程序:使用Throwable获得栈信息

  • 时间:2016-10-24
  • 发布:昆明Java培训
  • 来源:达内新闻

AOP编程可以很轻松的控制一个方法调用哪些类,也能够控制哪些方法允许被调用,一般来说切面编程(比如AspectJ),只能控制到方法级别,不能实现代码级别的植入(Weave),比如一个方法被类A的m1方法调用时返回1,在类B的m2方法调用时返回0(同参数情况下),这就要求被调用者具有识别调用者的能力。在这种情况下,昆明Java培训机构的老师发现可以使用Throwable获得栈信息,然后鉴别调用者并分别输出,代码如下:

class Foo {

public static boolean method() {

//取得当前栈信息

StackTraceElement[] sts = new Throwable().getStackTrace();

//检查是否是methodA方法调用

for (StackTraceElement st : sts) {

if (st.getMethodName().equals("methodA")) {

return true;

}

}

return false;

}

}

//调用者

class Invoker{

//该方法打印出true

public static void methodA(){

System.out.println(Foo.method());

}

//该方法打印出false

public static void methodB(){

System.out.println(Foo.method());

}

}

注意看Invoker类,两个方法methodA和methodB都调用了Foo的method方法,都是无参调用,返回值却不同,这是我们的Throwable类发挥效能了。JVM在创建一本Throwable类及其子类时会把当前线程的栈信息记录下来,以便在输出异常时准确定位异常原因,我们来看Throwable源代码。

public class Throwable implements Serializable {

private static final StackTraceElement[] UNASSIGNED_STACK = new StackTraceElement[0];

//出现异常记录的栈帧

private StackTraceElement[] stackTrace = UNASSIGNED_STACK;

//默认构造函数

public Throwable() {

//记录栈帧

fillInStackTrace();

}

//本地方法,抓取执行时的栈信息

private native Throwable fillInStackTrace(int dummy);

public synchronized Throwable fillInStackTrace() {

if (stackTrace != null || backtrace != ull /* Out of protocol state */) {

fillInStackTrace(0);

stackTrace = UNASSIGNED_STACK;

}

return this;

}

}

在出现异常时(或主动声明一个Throwable对象时),JVM会通过fillInStackTrace方法记录下栈帧信息,然后生成一个Throwable对象,这样我们就可以知道类间的调用顺序,方法名称及当前行号等了。

获得栈信息可以对调用者进行判断,然后决定不同的输出,比如我们的methodA和methodB方法,同样地输入参数,同样的调用方法,但是输出却不同,这看起来很想是一个bug:方法methodA调用method方法正常显示,而方法methodB调用却会返回错误数据,因此我们虽然可以根据调用者的不同产生不同的逻辑,但这仅局限在对此方法的广泛认知上,更多的时候昆明Java培训机构的老师使用method方法的变形体,代码如下:

class Foo {

public static boolean method() {

//取得当前栈信息

StackTraceElement[] sts = new Throwable().getStackTrace();

//检查是否是methodA方法调用

for (StackTraceElement st : sts) {

if (st.getMethodName().equals("methodA")) {

return true;

}

}

throw new RuntimeException("除了methodA方法外,该方法不允许其它方法调用");

}

}

只是把“return false”替换成了一个运行期异常,除了methodA方法外,其它方法调用都会产生异常,该方法常用作离线注册码校验,让破解者视图暴力破解时,由于执行者不是期望的值,因此会返回一个经过包装和混淆的异常信息,大大增加了破解难度。

上一篇:Java培训:不要在构造函数中抛出异常
下一篇:java程序里面异常只为异常服务

昆明java培训机构:java未来的发展走向

昆明java培训机构:java学完可以干什么!

昆明java培训机构:如何搞定BAT和华为offer?有这份攻略就够了!

昆明java培训机构:学Java别担心枯燥和无聊

选择城市和中心
贵州省

广西省

海南省

扫一扫

了解更多干货