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

 public class Client {
public static void main(String[] args) {
Invoker.m1();
Invoker.m2();
} } class Foo {
public static boolean m() {
// 取得当前栈信息
StackTraceElement[] sts = new Throwable().getStackTrace();
// 检查是否是m1方法调用
for (StackTraceElement st : sts) {
if (st.getMethodName().equals("m1")) {
return true;
}
}
return false;
}
} class Invoker {
// 该方法打印出true
public static void m1() {
System.out.println(Foo.m());
} // 该方法打印出false
public static void m2() {
System.out.println(Foo.m());
}
}

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方法的变形体代码如下:

 public class Client {
public static void main(String[] args) {
Invoker.m1();
Invoker.m2();
} } class Foo {
public static boolean m() {
// 取得当前栈信息
StackTraceElement[] sts = new Throwable().getStackTrace();
// 检查是否是m1方法调用
for (StackTraceElement st : sts) {
if (st.getMethodName().equals("m1")) {
return true;
}
}
throw new RuntimeException("除m1方法外,该方法不允许其他方法调用");
}
} class Invoker {
// 该方法打印出true
public static void m1() {
System.out.println(Foo.m());
} // 该方法打印出false
public static void m2() {
System.out.println(Foo.m());
}
}

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

最新文章

  1. Atom + activate-power-mode震屏插件Windows7下安装
  2. 5.toogleButton以及Switch
  3. [置顶] SSO单点登录系列6:cas单点登录防止登出退出后刷新后退ticket失效报500错
  4. QML开源游戏
  5. 爬虫代码实现五:解析所有分页url并优化解析实现类
  6. springboot+thymeleaf(2)
  7. Java的基本类型和包装类型
  8. vue交互
  9. GRPC单向/双向流
  10. 最长连续子序列(dp,分而治之递归)
  11. JavaScript 函数式编程读书笔记2
  12. CentOS 7 之 Docker 安装及操作命令
  13. Enum,Int,String的互相转换 枚举转换
  14. CentOS 7修改管理员密码
  15. Z-score(Z值)的意义--转载
  16. Index--过滤索引和参数化
  17. SQLServer------查询结果为空的列赋默认值
  18. 让一个表单以post的方式在window.open的窗口中打开
  19. LOJ#6049. 「雅礼集训 2017 Day10」拍苍蝇(计算几何+bitset)
  20. tensorflow c++ API加载.pb模型文件并预测图片

热门文章

  1. maven 控制台乱码
  2. 高版本myeclipse破解以及优化
  3. 浏览器插件-ActiveX
  4. 【转】使用Auto Layout中的VFL(Visual format language)--代码实现自动布局
  5. Gym 100507J Scarily interesting! (贪心)
  6. eclipse svn切换账号登陆问题
  7. ASP.NET forms凭据设置和跳转的几种方法
  8. Error: [$injector:unpr] angular.js
  9. 【转】Android真机抓屏- Android Screen Monitor
  10. 手机调用系统的拍照和裁剪功能,假设界面有输入框EditText,在一些手机会出现点击EditText会弹出输入法,却不能输入的情况。