当前位置: 首页 > news >正文

[改善Java代码]使用Throwable获得栈信息

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

 1 public class Client {
 2     public static void main(String[] args) {
 3         Invoker.m1();
 4         Invoker.m2();
 5     }
 6 
 7 }
 8 
 9 class Foo {
10     public static boolean m() {
11         // 取得当前栈信息
12         StackTraceElement[] sts = new Throwable().getStackTrace();
13         // 检查是否是m1方法调用
14         for (StackTraceElement st : sts) {
15             if (st.getMethodName().equals("m1")) {
16                 return true;
17             }
18         }
19         return false;
20     }
21 }
22 
23 class Invoker {
24     // 该方法打印出true
25     public static void m1() {
26         System.out.println(Foo.m());
27     }
28 
29     // 该方法打印出false
30     public static void m2() {
31         System.out.println(Foo.m());
32     }
33 }

Invoker类,两个方法m1和m2都调用了Foo的m方法,都是无参调用,返回值却不相同.这是因为Throwable类发挥效能了.

JVM在创建一个Throwable类及其子类时会把当前线程的栈信息记录下来,以便在输出异常时准确定位异常原因,看Throwable的源代码...

public class Throwable implements Serializable {
    //出现异常的栈记录
    private StackTraceElement[] stackTrace;
    //默认的构造函数
    public Throwable() {
        //记录栈帧
        fillInStackTrace();
    }
    //本地方法,抓取执行时的栈信息
    public synchronized native Throwable fillInStackTrace() {}
}

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

获得栈信息可以对调用者进行判断,然后决定不同的输出,比如上面的m1和m2方法,同样是输入参数,同样的调用方法,但是输出却不同,这看起来像一个Bug:方法m1电泳m方法是正常显示,而方法m2调用却返回错误数据.

因此我们虽然可以依据调用者不同产生不同的逻辑,但这仅仅局限在对方法的广泛认知上.

更多的时候我们用m方法的变形体代码如下:

 1 public class Client {
 2     public static void main(String[] args) {
 3         Invoker.m1();
 4         Invoker.m2();
 5     }
 6 
 7 }
 8 
 9 class Foo {
10     public static boolean m() {
11         // 取得当前栈信息
12         StackTraceElement[] sts = new Throwable().getStackTrace();
13         // 检查是否是m1方法调用
14         for (StackTraceElement st : sts) {
15             if (st.getMethodName().equals("m1")) {
16                 return true;
17             }
18         }
19         throw new RuntimeException("除m1方法外,该方法不允许其他方法调用");
20     }
21 }
22 
23 class Invoker {
24     // 该方法打印出true
25     public static void m1() {
26         System.out.println(Foo.m());
27     }
28 
29     // 该方法打印出false
30     public static void m2() {
31         System.out.println(Foo.m());
32     }
33 }

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

 

转载于:https://www.cnblogs.com/DreamDrive/p/5622976.html

相关文章:

  • VMM系列之VMM服务器主机和主机组介绍
  • JavaScript内置对象(二)
  • 私有网盘nextcloud 12的使用介绍
  • win10使用Composer-Setup安装Composer以及使用Composer安装Yii2最新版
  • 面试
  • 深入浅出——float
  • 为Docker配置阿里加速器,系统为Debian8
  • 利用Scikit-Learn和Spark预测Airbnb的listing价格
  • H264中的SPS、PPS提取与作用转
  • 4G VoLTE存在漏洞可导致手机用户地理位置和其它个人信息泄露
  • Java框架搭建-Maven、Mybatis、Spring MVC整合搭建
  • 突破你的想象 OPPO R11s新升级
  • 仓储层到多维数据库
  • linux学习——管道
  • http协议的详解
  • [nginx文档翻译系列] 控制nginx
  • [译]CSS 居中(Center)方法大合集
  • css布局,左右固定中间自适应实现
  • mysql常用命令汇总
  • v-if和v-for连用出现的问题
  • vue-cli3搭建项目
  • 浏览器缓存机制分析
  • 盘点那些不知名却常用的 Git 操作
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • 微信小程序填坑清单
  • 运行时添加log4j2的appender
  • 再次简单明了总结flex布局,一看就懂...
  • 责任链模式的两种实现
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • Java数据解析之JSON
  • 哈罗单车融资几十亿元,蚂蚁金服与春华资本加持 ...
  • 正则表达式-基础知识Review
  • # 数据结构
  • #pragma pack(1)
  • #宝哥教你#查看jquery绑定的事件函数
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • $(function(){})与(function($){....})(jQuery)的区别
  • $.each()与$(selector).each()
  • (4)事件处理——(6)给.ready()回调函数传递一个参数(Passing an argument to the .ready() callback)...
  • (Java)【深基9.例1】选举学生会
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (附源码)springboot码头作业管理系统 毕业设计 341654
  • (免费领源码)Python#MySQL图书馆管理系统071718-计算机毕业设计项目选题推荐
  • (转载)跟我一起学习VIM - The Life Changing Editor
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .Net接口调试与案例
  • .Net语言中的StringBuilder:入门到精通
  • ?php echo ?,?php echo Hello world!;?
  • @Query中countQuery的介绍
  • [ vulhub漏洞复现篇 ] AppWeb认证绕过漏洞(CVE-2018-8715)
  • [2024最新教程]地表最强AGI:Claude 3注册账号/登录账号/访问方法,小白教程包教包会
  • [C#基础]说说lock到底锁谁?
  • [C++]高精度 bign (重载运算符版本)
  • [C++从入门到精通] 14.虚函数、纯虚函数和虚析构(virtual)