java動態代理生成$Proxy0源代碼的操作

  1. $Proxy該類是動態生成的,在運行的時候生成。具體源代碼的提取參考的是:http://www.cnblogs.com/ctgulong/p/5011614.html?utm_source=tuicool&utm_medium=referral的blog


2.根據上面博客的內容詳細寫一下生成源代碼的過程。參考之前的項目http://yinyueml.blog.51cto.com/4841237/1876473

1)首先需要一個agent的生成類。javaagent主要功能如下:

  • 可以在加載class文件之前做攔截,對字節碼做修改

  • 可以在運行期對已加載類的字節碼做變更,但是這種情況下會有很多的限制,後面會詳細說

  • 還有其他一些小衆的功能

    • 獲取所有已經加載過的類,這個功能讓我們可以獲取到動態代理的生成類的class文件,經過反編譯後就可以查看源代碼。

    • 獲取所有已經初始化過的類(執行過clinit方法,是上面的一個子集)

    • 獲取某個對象的大小

    • 將某個jar加入到bootstrap classpath裏作爲高優先級被bootstrapClassloader加載

    • 將某個jar加入到classpath裏供AppClassloard去加載

    • 設置某些native方法的前綴,主要在查找native方法的時候做規則匹配

2)代碼如下

package jdkReview;

import java.io.File;
import java.io.FileOutputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;

public class CustomAgent implements ClassFileTransformer {
 //
    public static void premain(String agentArgs, Instrumentation inst) {
        inst.addTransformer(new CustomAgent());
    }

    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
            ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        if (!className.startsWith("java") && !className.startsWith("sun")) {
            // 既不是java也不是sun開頭的
            // 導出代碼
            int lastIndexOf = className.lastIndexOf("/") + 1;
            String fileName = className.substring(lastIndexOf) + ".class";
            exportClazzToFile("D:/javacode/", fileName, classfileBuffer);
            System.out.println(className + " --> EXPORTED Succeess!");
        }    
        return classfileBuffer;
    }

    /**
     * 
     * @param dirPath
     *目錄以/結尾,且必須存在
     * @param fileName
     * @param data
     */
    private void exportClazzToFile(String dirPath, String fileName, byte[] data) {
        try {
            File file = new File(dirPath + fileName);
            if (!file.exists()) {
                file.createNewFile();    
            }    
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(data);
            fos.close();    
        } catch (Exception e) {
            System.out.println("exception occured while doing some file operation");
            e.printStackTrace();
        }
    }
}

3)將CustomAgent導出爲jar包,並且修改MANIFEST.MF文件內容如下:

Manifest-Version: 1.0
Premain-Class: jdkReview.CustomAgent

該配置主要是爲了Premain-Class的作用就是表示帶有premain靜態方法的Class。

4)在運行使用java動態代理的Client類的時候加上jvm的參數

-javaagent:d:/customAgent.jar

然後運行後如下結果爲:

proxyPattern/Client --> EXPORTED Succeess!
proxyPattern/GamePlayer --> EXPORTED Succeess!
proxyPattern/IGamePlayer --> EXPORTED Succeess!
proxyPattern/GamePlayIH --> EXPORTED Succeess!
com/sun/proxy/$Proxy0 --> EXPORTED Succeess!
有人再用我的賬號登陸
登陸用戶名:yinyueml;玩家:張三上線
張三正在打怪。
張三升級了

現在通過

exportClazzToFile("D:/javacode/", fileName, classfileBuffer);

中的配置路勁就可以找到$Proxy0.class的文件。

5)通過jad.exe反編譯應用對$Proxy0.class進行反編譯就可以獲取到源代碼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章