使用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方法外,其他方法調用都會產生異常,該方法常用作離線注冊碼校驗,當破解者試圖暴力破解時,由于主執行者不善期望的值,因此會返回一個經過包裝和混淆的異常信息,大大增加了破解的難度.
?
本文轉自SummerChill博客園博客,原文鏈接:http://www.cnblogs.com/DreamDrive/p/5622976.html,如需轉載請自行聯系原作者
總結
以上是生活随笔為你收集整理的使用Throwable获得栈信息的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【HIMI转载推荐之三】新手教程之如何向
- 下一篇: 正则表达式grep sed awk总结