ASM(初探使用)

ASM

背景

寫文章特別喜歡寫背景蚓胸,感覺如果不寫背景就沒法回憶出來當(dāng)時(shí)為什么要搞這個(gè)東西。好了马昨,因?yàn)橹皡⑴c的一個(gè)項(xiàng)目的故障演練模塊覺得做的只是基于spring的Bean的代理做的病蛉,這樣對業(yè)務(wù)的侵入性比較強(qiáng),如果業(yè)務(wù)沒有依賴于spring腫么辦呢窟哺?現(xiàn)在我們來看看ASM是怎么做的

ASM可以干什么

大名鼎鼎的CGLIB其實(shí)底層就是ASM泻轰。通過ASM的字節(jié)碼操作,可以動(dòng)態(tài)創(chuàng)建新的類型且轨,可以為類增加新的功能呢浮声。雖然可以使用CGLIB這些高級的庫也可以完成大量的工作,但是如果直接使用ASM還是有很多好處的旋奢,例如ASM的性能是最好的泳挥,靈活度是最好的,功能也是最為強(qiáng)大的黄绩,可以將操作粒度控制到每一條指令羡洁。

簡單的進(jìn)行字節(jié)碼織入操作

例如我們只有一個(gè)簡單的Account類,該類也只有一個(gè)方法operation方法爽丹。

public class Account {
    public void operation() {
        System.out.println("operation ...");
    }
}

現(xiàn)在我們要在這個(gè)操作之前進(jìn)行一定的驗(yàn)證筑煮,例如加入一些檢查權(quán)限的操作checkSecurity()辛蚊。我們將添加一個(gè)名稱為SecurityChecker的類。這個(gè)類中的方法可以幫助我們進(jìn)行一些權(quán)限校驗(yàn)真仲。

public class SecurityChecker {
    public static boolean checkSecurity() {
        System.out.println("SecurityChecker.checkSecurity ...");
        if ((System.currentTimeMillis() & 0x1) == 0) {
            return false;
        } else {
            return true;
        }
    }
}

我們在不修改原來Account的代碼的前提下袋马,如何增加校驗(yàn)操作呢?我們可以直接修改類的字節(jié)碼進(jìn)行代碼織入操作秸应,從而改變Account代碼的執(zhí)行狀態(tài)虑凛。

我們先看一下單獨(dú)運(yùn)行Account類的執(zhí)行效果把~

image.png

可以看到只是打印出來了operation ...

進(jìn)行改寫字節(jié)碼

通過如下代碼我們可以將代碼的字節(jié)碼進(jìn)行修改,并且覆蓋掉原來的編譯好的字節(jié)碼软啼,從而改變類的執(zhí)行狀態(tài)桑谍。

首先我們需要幾個(gè)類對象,第一個(gè)

  • 負(fù)責(zé)Class改寫的適配器類AddSecurityCheckClassAdapter繼承自ClassVisitor

  • 負(fù)責(zé)Method改寫的適配器類AddSecurityCheckMethodAdapter繼承自MethodVisitor

  • 負(fù)責(zé)調(diào)用Adapter的SecurityWeaveGeneratior

AddSecurityCheckClassAdapter

負(fù)責(zé)修改類文件中的字節(jié)碼

public class AddSecurityCheckClassAdapter extends ClassVisitor {

    public AddSecurityCheckClassAdapter(ClassVisitor classVisitor) {
        super(Opcodes.ASM5, classVisitor);
    }

    @Override
    public MethodVisitor visitMethod(int i, String s, String s1, String s2, String[] strings) {


        MethodVisitor mv = super.visitMethod(i, s, s1, s2, strings);

        MethodVisitor wrappedMv = mv;

        if (mv != null){
            if (s.equals("operation")){
                wrappedMv = new AddSecurityCheckMethodAdapter(mv);
            }
        }
        return wrappedMv;
    }
}

AddSecurityCheckMethodAdapter

負(fù)責(zé)修改某個(gè)method中的字節(jié)碼

public class AddSecurityCheckMethodAdapter extends MethodVisitor {
    public AddSecurityCheckMethodAdapter(MethodVisitor mv) {
        super(Opcodes.ASM5, mv);
    }

    @Override
    public void visitCode() {
        Label continueLabel = new Label();
        visitMethodInsn(Opcodes.INVOKESTATIC, "com/wsqandgy/asm/SecurityChecker", "checkSecurity", "()Z");
        visitJumpInsn(Opcodes.IFNE, continueLabel);
        visitInsn(Opcodes.RETURN);
        visitLabel(continueLabel);
        super.visitCode();
    }
}

SecurityWeaveGeneratior

讀取類信息祸挪,進(jìn)行字節(jié)碼織入

public class SecurityWeaveGeneratior {

    public static void main(String[] args) throws Exception {
        String className = Account.class.getName();
        ClassReader classReader = new ClassReader(className);
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
        AddSecurityCheckClassAdapter classAdapter = new AddSecurityCheckClassAdapter(cw);
        classReader.accept(classAdapter, ClassReader.SKIP_DEBUG);
        byte[] data = cw.toByteArray();
        File file = new File("/Users/gongyan/Documents/home_code/tools/apache/target/classes/" + className.replaceAll("\\.", "/") + ".class");
        if (file.exists()){
            System.out.println("exists");
        }
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        fileOutputStream.write(data);
        fileOutputStream.close();
    }
}

運(yùn)行結(jié)果

安全檢查

還是運(yùn)行原來的main方法锣披,自動(dòng)加入了檢查安全的操作。

對比一下前后的字節(jié)碼

前:


后:


對比前后贿条,明顯可以看到在字節(jié)碼中增加了我們操作ASM寫入的相關(guān)字節(jié)碼雹仿。

寫在最后,最近生病是在身體乏力整以,寫的文章自己認(rèn)為也只講了簡單的如何使用后面再好好補(bǔ)補(bǔ)胧辽,這個(gè)地方會(huì)和前面的服務(wù)保護(hù)有一定的串聯(lián)!請多多期待公黑!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末邑商,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子帆调,更是在濱河造成了極大的恐慌奠骄,老刑警劉巖豆同,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件番刊,死亡現(xiàn)場離奇詭異,居然都是意外死亡影锈,警方通過查閱死者的電腦和手機(jī)芹务,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鸭廷,“玉大人枣抱,你說我怎么就攤上這事×敬玻” “怎么了佳晶?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長讼载。 經(jīng)常有香客問我轿秧,道長中跌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任菇篡,我火速辦了婚禮漩符,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘驱还。我一直安慰自己嗜暴,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布议蟆。 她就那樣靜靜地躺著闷沥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪咐容。 梳的紋絲不亂的頭發(fā)上狐赡,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天,我揣著相機(jī)與錄音疟丙,去河邊找鬼颖侄。 笑死,一個(gè)胖子當(dāng)著我的面吹牛享郊,可吹牛的內(nèi)容都是我干的览祖。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼炊琉,長吁一口氣:“原來是場噩夢啊……” “哼展蒂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起苔咪,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤锰悼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后团赏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體箕般,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年舔清,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了丝里。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,127評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡体谒,死狀恐怖杯聚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情抒痒,我是刑警寧澤幌绍,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響傀广,放射性物質(zhì)發(fā)生泄漏痢虹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一主儡、第九天 我趴在偏房一處隱蔽的房頂上張望奖唯。 院中可真熱鬧,春花似錦糜值、人聲如沸丰捷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽病往。三九已至,卻和暖如春骄瓣,著一層夾襖步出監(jiān)牢的瞬間停巷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工榕栏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留畔勤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓扒磁,卻偏偏與公主長得像庆揪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子妨托,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 前言 很早之前就寫過面向切面的編程思想缸榛,主要學(xué)習(xí)了AOP的思想(參考:AOP簡介)以及使用 AspectJ 實(shí)現(xiàn)簡...
    Whyn閱讀 10,796評論 4 40
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 29,394評論 8 265
  • title: Android AOP之字節(jié)碼插樁author: 陶超description: 實(shí)現(xiàn)數(shù)據(jù)收集SDK時(shí)...
    陶菜菜閱讀 38,179評論 40 182
  • 為毛ins的列表的視頻默認(rèn)是關(guān)聲音的,但自動(dòng)播放兰伤? 自動(dòng)播放是因?yàn)檫@是個(gè)沒有詳情的列表内颗,或者說列表即詳情,所有瀏覽...
    DanisUX閱讀 1,175評論 8 1
  • 對于試水自由市場负懦,這些球員幾乎都是希望追逐總冠軍戒指筒捺,更多的上場時(shí)間柏腻,球權(quán)或是戰(zhàn)術(shù)比重,當(dāng)然系吭,還有大合同五嫂。 但問題...
    zoneball閱讀 214評論 0 0