【字節碼增強ASM3.0】Java正則引發的思考--測試困惑--有解了

1 表情符號源代碼

https://github.com/zly394/EmojiRegex/blob/master/src/main/java/com/zly/utils/EmojiRegexUtil.java

2  測試用例

import java.lang.instrument.Instrumentation;

public class Main2 {
    public static void main(String[] args) {
        String text = "\uD83C\uDDF2\uD83C\uDDEA\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDE8\uD83C\uDDF3\uD83C\uDDEC\uD83C\uDDE7\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73\uDB40\uDC7F\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74\uDB40\uDC7F\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67\uDB40\uDC7F";
        boolean allEmoji = EmojiUtil.isAllEmoji(text);
        System.out.println(allEmoji);
    }
    public static void premain(String args, Instrumentation inst) {
        inst.addTransformer(new MethodCallCountTransformer());
    }

}

// 增強類

import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;

public class MethodCallCountTransformer implements ClassFileTransformer {


    @Override
    public byte[] transform(ClassLoader loader,
                            String className,
                            Class<?> classBeingRedefined,
                            ProtectionDomain protectionDomain,
                            byte[] classfileBuffer) throws
            IllegalClassFormatException {
        try {
            if (!"java/util/regex/Pattern$CharProperty".equals(className)
                    &&
                    !"java/util/regex/Pattern$BmpCharProperty".equals(className)) {
                return classfileBuffer;
            }
            ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
            ClassAdapter adapter = new MethodCallClassAdapter(writer, className);
            ClassReader reader = new ClassReader(classfileBuffer);
            reader.accept(adapter, 0);
            return writer.toByteArray();
        }catch (Exception e){
            return classfileBuffer;
        }
    }

}

// MethodCallClassAdapter
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;

public class MethodCallClassAdapter extends ClassAdapter {
    private String className;
    public MethodCallClassAdapter(ClassVisitor cv, String className) {
        //Responsechain 的下一個 ClassVisitor,這裏我們將傳入 ClassWriter,
        // 負責改寫後代碼的輸出
        super(cv);
        this.className = className;
    }

    // 重寫 visitMethod,訪問到 "operation" 方法時,
    // 給出自定義 MethodVisitor,實際改寫方法內容
    @Override
    public MethodVisitor visitMethod(final int access, final String name,
                                     final String desc, final String signature, final String[] exceptions) {
        MethodVisitor mv = cv.visitMethod(access, name, desc, signature,exceptions);
        MethodVisitor wrappedMv = mv;
        if (mv != null) {
            // 對於 "operation" 方法
            if (name.equals("match")) {
                // 使用自定義 MethodVisitor,實際改寫方法內容
                wrappedMv = new CountCallMethodAdapter(mv,name,name);
            }
        }
        return wrappedMv;
    }
}

// MethodAdapter

import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
 
public class CountCallMethodAdapter extends MethodAdapter {
    private String methodName;
 
    private String className;
 
    public CountCallMethodAdapter(MethodVisitor visitor, String className, String methodName) {
        super(visitor);
 
        this.methodName = methodName;
        this.className = className;
    }
 
    @Override
    public void visitCode() {
        visitMethodInsn(Opcodes.INVOKESTATIC, "com/you/gbrank/asm/counter/Counter", "printAndIncCount", "()V");
    }
}

3 Counter 類

 
import java.util.concurrent.atomic.AtomicInteger;
 
public class Counter {
    private static AtomicInteger methodCallCount = new AtomicInteger(0);
    public static void checkSecurity() {
        System.out.println("SecurityChecker.checkSecurity ...");
        //TODO real security check
    }
    public static void printAndIncCount() {
        System.out.println(methodCallCount.incrementAndGet());
    }
    public static void printAndIncCount1(String className, String methodName) {
        System.out.println(methodCallCount.get());
        System.out.println(className + "." + methodName + " called, total times " + methodCallCount.incrementAndGet());
    }
}

4 結果:增強沒有效果,沒有任何日誌打印。  MARK

https://blog.csdn.net/qfzhangwei/article/details/105117126 給出了一個解決方案

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