课程咨询 :186 8716 1620      qq:2066486918

昆明Java培训 > 达内新闻 > java程序:使用Throwable获得栈信息
  • java程序:使用Throwable获得栈信息

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

  • 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--零基础全日制班

开班日期:11/30

Java--零基础业余班

Java--零基础业余班

开班日期:11/30

Java--周末提升班

Java--周末提升班

开班日期:11/30

Java--零基础周末班

Java--零基础周末班

开班日期:11/30

  • 网址:http://km .java.tedu.cn      地址:昆明市官渡区春城路62号证券大厦附楼6楼
  • 课程培训电话:186 8716 1620      qq:2066486918    全国服务监督电话:400-827-0010
  • 服务邮箱 ts@tedu.cn
  • 2001-2016 达内国际公司(TARENA INTERNATIONAL,INC.) 版权所有 京ICP证08000853号-56