Android中使用ClassLoader修改自定義異常類繼承來使異常捕獲失效來坑害你的同事
原理:使用熱修復的原理,用ClassLoader載入同名替換類。根據類的載入機制,一個類只會被載入一次,所以可以使用ClassLoader載入一個同名的、Throwable子類中的非異常類的類,來使異常捕獲失效
首先,定義一個自定義異常
public class FooledYouException extends Exception {
public FooledYouException() {
super("Surprise!");
}
}
然後,在方法中宣告丟擲和捕獲
可以看到方法中宣告的位所有異常類的父類,不應該有異常被丟擲public class FooledYouTool { public static void fooledYou(int i){ try{ System.out.println("Do something for i "+i); throwExceptionMethod(); }catch (Exception e){ e.printStackTrace(); } } private static void throwExceptionMethod() throws FooledYouException{ throw new FooledYouException(); } }
最後,呼叫方法
public class MainActivity2 extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FooledYouTool.fooledYou(1);
}
}
可以看到控制檯打印出了Do something for i 1和之後的異常棧,程式正常執行。
下面開始搗亂
1.把FooledYouException複製出來,將繼承Exception改為繼承Error,並編譯成類檔案,目錄結構和包保持一致
public class FooledYouException extends Error { public FooledYouException() { super("Surprise!"); } }
2.用jar工具打成jar包
jar cvf FooledYou.jar alpacaplayground/FooledYouException.class
3.用dx工具轉成dex
dx工具在sdk的built-tools目錄中,以mac為例,目錄為
~/Library/Android/sdk/build-tools
會有多個buildtools版本,我選擇了app使用的26版本。
執行命令
~/Library/Android/sdk/build-tools/26.0.2/dx --dex --output=FoolYouDex.jar FooledYou.jar
再將轉好的dex檔案複製到手機裡可被App訪問的地方,比如SD卡中。我為了省事放到了Assets目錄中,在App啟動後複製到App快取目錄下
由於要在其他人第一次使用這個類之前完成替換,將替換程式碼寫在Application類中
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
try {
/*
這裡是將dexjar檔案複製到快取目錄中來給ClassLoader載入
所有的耗時操作都應該放在工作執行緒中進行,這裡是為了演示省事,
直接在主執行緒中進行IO操作,請勿效仿
不要阻塞主執行緒,不要阻塞主執行緒,不要阻塞主執行緒,重要的事情說三遍
*/
InputStream im = getAssets().open("FoolYouDex.jar");
File foolYou = new File(getCacheDir(), "foolYou.jar");
if (foolYou.exists()) {
foolYou.delete();
}
byte[] buf = new byte[4096];
FileOutputStream fos = new FileOutputStream(foolYou);
int length;
while ((length = im.read(buf)) > 0) {
fos.write(buf, 0, length);
}
//獲得預設的ClassLoader
ClassLoader pathClassLoader = getClassLoader();
try {
Field field = ClassLoader.class.getDeclaredField("parent");
field.setAccessible(true);
//建立自定義ClassLoader,並以預設ClassLoader的parent作為自己的parent
DexClassLoader dexClassLoader = new DexClassLoader(foolYou.getAbsolutePath(), getDir("dex", 0).getAbsolutePath(),
null, (ClassLoader) field.get(pathClassLoader));
//將預設ClassLoader的parent設定為自定義ClassLoader
field.set(pathClassLoader, dexClassLoader);
} catch (Throwable e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
修改manifest將Application的name指定為自定義的,再執行
可以看到一呼叫方法立刻就崩潰了。這時你的同事會上FooledYouTool中找問題,然而他會看到一個宣告捕獲Exception公共父類的try-catch語句。
這裡就是利用熱修復的原理,將載入的類替換成了外部dex中的,導致應用行為改變。
為了驗證一下,將異常捕獲地方的宣告改為捕獲對應類,並驗證繼承關係
public static void fooledYou(int i){
try{
System.out.println("Do something for i "+i);
throwExceptionMethod();
}catch (FooledYouException e){
e.printStackTrace();
Log.i("FooledYouException","is Throwable "+(Throwable.class.isInstance(e)));
Log.i("FooledYouException","is Exception "+(Exception.class.isInstance(e)));
Log.i("FooledYouException","is Error "+(Error.class.isInstance(e)));
}
}
執行App,結果如下
可以看到方法正常執行,進入catch塊列印異常棧,根據Log輸出結果可以看出新建的FooledYouException實際為Error的子類,以Exception宣告捕獲自然是會漏掉。
這裡參考的熱修復/類載入方法來自文章
http://blog.csdn.net/sahadev_/article/details/53363052
原文中通過修改預設ClassLoader中的dexElements陣列實現,我在使用時遇到了問題,修改後無法找到入口Activity,一啟動就會丟擲ClassNotFound異常。
根據類載入器的雙親委派機制,子ClassLoader在嘗試載入一個類時,首先會讓父ClassLoader載入,所以嘗試修改預設載入器的parent來實現替換。
原關係為
預設載入器->預設載入器父載入器
修改後變為
預設載入器->我的載入器->預設載入器父載入器
執行結果正常。
相關推薦
Android中使用ClassLoader修改自定義異常類繼承來使異常捕獲失效來坑害你的同事
原理:使用熱修復的原理,用ClassLoader載入同名替換類。根據類的載入機制,一個類只會被載入一次,所以可以使用ClassLoader載入一個同名的、Throwable子類中的非異常類的類,來使異常捕獲失效 首先,定義一個自定義異常 public class Fool
Android中快速實現自定義字體!
sdk true fcm version ttf spa pre ets 怎麽 前言:我們都知道,Android中默認的字體是黑體,而大多數app也都是使用的這種字體,但我們發現,大多數app中,個別地方字體非常好看,例如app的標題欄,菜單欄等地方,那他們是怎麽做到的呢?
Android中Intent傳遞自定義物件型別的資料
Android中Intent是用來實現元件之間的通訊的,可以在元件之間傳遞資料。可以傳遞一些基本型別的資料,也可以傳遞自定義物件型別的資料,但是如果要傳遞自定義型別的物件資料,這個自定義型別的物件必須是實現了Serializable介面或者是實現Parcelab
Android中的Button自定義點選效果
原來聽很多人說Button不能使用自定義的點選或選中效果,所以做下測試 結果顯示Button很強大 完全可以使用這種靈活的方法 方法一 1.放在drawable下的selector.xml檔案 <?xml version="1.0" encoding="utf-8"?
Android中的Button自定義點選效果之改變點選時按鈕的顏色
在Android中定義按鈕的點選效果可以通過自定義selector,通過設定兩張不同的背景圖片來改變點選時和未點選時的狀態,但有時候僅僅只想改變點選時按鈕的顏色,但是在selector中並不能直接定義顏色。下面程式碼實現一個點選按鈕時僅僅改變按鈕顏色。 1.
Android 自定義Dialog類,並在Activity中實現按鈕監聽。
實際開發中,經常會用到Dialog,比如退出時候會彈出是否退出,或者還有一些編輯框也會用Dialog實現,效果圖如下: 開發中遇到的問題無非在於如果在Activity中監聽這個Dialog中實現的按鈕,Dialog類如下,在MyDialog這個類中實現了一個LeaveMyDialogLi
c#(winform)中自定義ListItem類方便ComboBox添加Item項
urn left over string his 定義 return box item 1.定義ListItem類 public class ListItem { private string _key = string.Empty;
Lambda語句中創建自定義類型時,也可指定某種特定類型,方法是在new與{}之間寫上類型名稱
特定 pan sel lambda語句 lam {} where distinct select 如: var fc =...ChildFath = fc.Select(c => new Child_Father { child = c.child, father =
java web項目中後臺控制層對參數進行自定義驗證 類 Pattern
span 快捷方式 pattern 例如 att ice 模式 匹配 ret Pattern pattern = Pattern.compile("/^([1-9]\\d+元*|[0]{0,1})$/");//將給定的正則表達式編譯到模式中 if(!"".equals
Java類載入器( CLassLoader ) 死磕 6: 自定義網路類載入器
【正文】Java類載入器( CLassLoader ) 死磕 6: 自定義網路類載入器 本小節目錄 6.1. 自定義網路類載入器的類設計 6.2. 檔案傳輸Server端的原始碼 6.3. 檔案傳輸Client端的原始碼 6. 4 自定義載入器SocketClassLoader的原始
ByteBuf 一個用於在通訊中的資料解析傳輸組裝的自定義容器類
在做和硬體通訊的專案的時候,通訊的內容一般都是最基本的byte陣列,比如BLE,UART等等方式,傳遞的都是byte陣列。 移動端在接收的時候,就需要去解析byte陣列,然後從中通過拼接和或(|)以及位移等運算來得到想要的資料型別,比如說,unsignedByte,short,int,float
Mybatis需要返回的資料引數中在資料表中沒有對應的欄位,自定義實體類和resultmap作為返回值型別
自定義實體類:因為需要做相關記錄的統計,而表中沒有統計欄位 public class TrafficJeevesDistrictCount { //施工top5+1 按區域 private String districtInfo; private
在Android系統中實現AIDL 自定義物件傳遞
今天要在《在Android系統中實現AIDL介面回撥》這篇文章的基礎上實現AIDL自定義物件的傳遞功能。還是上一篇說到的三個專案: ├── SimpleJar ├── SimpleJarClient └── SimpleJarService 一、在SimpleJar專
spring 中自定義工具類 @Autowired引入service或者mapper為null
在SMM專案中,經常使用@Autowired引入service或者mapper,但是在自定的utils包下引入service或者mapper的時候,會出現null的情況,下面就來解決這個問題。 首先,我們在spring的配置檔案中加上 掃描utils工具類的配置 <context:
android studio引入一個自定義的佈局,自定義控制元件,避免每一個活動中都編寫一樣佈局程式碼的問題
本次演示的是標題欄上建立按鈕,即 引入自定義佈局和自定義控制元件的應用十分的廣泛,它的形成的效果很多的應用程式都有,我們可以自定義標題欄,因為普通的標題欄就是一行文字,但是,我們可以發現,很多手機軟體的標題欄上都有返回,或者 進入的按鈕,尤其是全面屏的手機。而且它還能解
實驗報告:(1)合理定義一個三角形類Triangle,成員屬性包括3條邊,能否構成三角形的標誌;成員方法包括構造方法、修改3條邊、計算面積。 (2)寫一測試類,測試自定義三角形類Triangle是否正
(1)合理定義一個三角形類Triangle,成員屬性包括3條邊,能否構成三角形的標誌;成員方法包括構造方法、修改3條邊、計算面積。(2)寫一測試類,測試自定義三角形類Triangle是否正確。class Triangle_D{ private double f_edge;
c++STL中的hash_map自定義類。
是的,hash_map是一個很方便的容器,有了STL確確實實給了C++developer很大方便,hash_map就是其中一種。他在資料少的時候,作用和基於RB-tree的map差不多,甚至不如,畢竟有hasher。但是在大量資料的時候,就很快捷了。我平時用hash_map
自定義Thread類中run()方法,super().run 的理解
當我們重寫Thread類中的run方法時,經常會看到這樣的程式碼: public void run() { super.run(); System.out.println(Thread.currentThread().getName(
【Android】 XML佈局檔案中,使用自定義屬性不提示和不生效
在XML檔案中使用首先要宣告 xmlns:toolbar=http://schemas.android.com/apk/res/cn.zzm.toolbar 注意,“toolbar”可以換成其他的任何名字,後面的url地址必須最後一部分必須用上自定義元件的包名。自定義屬性了
Android 獲取不到自定義屬性(Android studio 2.2版本中自定義屬性的宣告)
跟著慕課網中鴻洋大神照著寫QQ5.0的側滑選單中遇到的問題。 如果按照鴻洋大神所說書寫格式是 xmlns:arrtss=”http://schemas.android.com/apk/+當前應用包名但