CodeBlanks Logo Icon CodeBlanks

Birleştirme

Tüm parçaları birleştirerek bir bytecode denetleyici yazarsın.

Proje: birleştirme

Son derste tüm parçaları birleştirip visitor zincirini tamamlayacaksın. ClassVisitor'a void visitEnd(); metodu eklenir; gezinin sonunda çağrılır. ClassReader.accept tüm metotlar gezildikten sonra v.visitEnd() çağırır.

ClassWriter.visitEnd bir kapanış satırı ekler; RenameVisitor.visitEnd bunu delegate'e iletir. Böylece tam bir boru hattı kurulur: ClassReader, RenameVisitor, ClassWriter.

tam boru hattı

Tam boru hattı şöyle çalışır: ClassReader sınıfı ve metotları gezer; her olayı önce RenameVisitor alır, dönüşüm uygular ve ClassWriter'a iletir; ClassWriter metni biriktirir. Gezi sonunda visitEnd kapanış satırını ekler.

Bu model, ASM'nin java ajanlarındaki çalışmasını yansıtır. Gerçek ASM'de ClassReader bayt kodunu ayrıştırır; burada ise ad ve metot listesiyle aynı akışı kurduk.

Uygulama visitEnd ekleyip zinciri tamamla

ClassVisitor arabirimine void visitEnd(); metodunu ekle. ClassReader.accept tüm metotlar gezildikten sonra v.visitEnd(); çağırsın. ClassWriter'a public void visitEnd() { sb.append("End").append("\n"); } ekle. RenameVisitor'a public void visitEnd() { delegate.visitEnd(); } ekle. main aynı kalsın: reader.accept(new RenameVisitor(writer)); ve System.out.println(writer.toString());.

Başlangıç kodu

Main.java
interface ClassVisitor {
    void visitClass(String name);
    void visitMethod(String name);
}

class ClassReader {
    String name;
    String[] methods;
    ClassReader(String name, String[] methods) {
        this.name = name;
        this.methods = methods;
    }
    void accept(ClassVisitor v) {
        v.visitClass(name);
        for (String m : methods) v.visitMethod(m);
    }
}

class ClassWriter implements ClassVisitor {
    StringBuilder sb = new StringBuilder();
    public void visitClass(String n) { sb.append("Class: ").append(n).append("\n"); }
    public void visitMethod(String n) { sb.append("Method: ").append(n).append("\n"); }
    public String toString() { return sb.toString().trim(); }
}

class RenameVisitor implements ClassVisitor {
    ClassVisitor delegate;
    RenameVisitor(ClassVisitor delegate) {
        this.delegate = delegate;
    }
    public void visitClass(String n) { delegate.visitClass(n); }
    public void visitMethod(String n) { delegate.visitMethod(n.replace("main", "start")); }
}

public class Main {
    public static void main(String[] args) {
        ClassReader reader = new ClassReader("Main", new String[]{"main"});
        ClassWriter writer = new ClassWriter();
        reader.accept(new RenameVisitor(writer));
        System.out.println(writer.toString());
    }
}

Örnek çözüm

Main.java
interface ClassVisitor {
    void visitClass(String name);
    void visitMethod(String name);
    void visitEnd();
}

class ClassReader {
    String name;
    String[] methods;
    ClassReader(String name, String[] methods) {
        this.name = name;
        this.methods = methods;
    }
    void accept(ClassVisitor v) {
        v.visitClass(name);
        for (String m : methods) v.visitMethod(m);
        v.visitEnd();
    }
}

class ClassWriter implements ClassVisitor {
    StringBuilder sb = new StringBuilder();
    public void visitClass(String n) { sb.append("Class: ").append(n).append("\n"); }
    public void visitMethod(String n) { sb.append("Method: ").append(n).append("\n"); }
    public void visitEnd() { sb.append("End").append("\n"); }
    public String toString() { return sb.toString().trim(); }
}

class RenameVisitor implements ClassVisitor {
    ClassVisitor delegate;
    RenameVisitor(ClassVisitor delegate) {
        this.delegate = delegate;
    }
    public void visitClass(String n) { delegate.visitClass(n); }
    public void visitMethod(String n) { delegate.visitMethod(n.replace("main", "start")); }
    public void visitEnd() { delegate.visitEnd(); }
}

public class Main {
    public static void main(String[] args) {
        ClassReader reader = new ClassReader("Main", new String[]{"main"});
        ClassWriter writer = new ClassWriter();
        reader.accept(new RenameVisitor(writer));
        System.out.println(writer.toString());
    }
}

Beklenen çıktı

Class: Main
Method: start
End

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 Birleştirme adımında ne eklenir?

  • Yeni thread
  • visitEnd ile kapanış Doğru cevap
  • Veri tabanı
  • Grafik penceresi

Açıklama: visitEnd gezi sonunda kapanış çağrısı yapar.

2 visitEnd bildirisini tamamla

Soru
void ____();
Cevap
void visitEnd();

Açıklama: void visitEnd(); gezi sonunu işaretler.

3 proje parçalarını özetle

Kavram Anlamı
ClassReader Sınıfı gezer
RenameVisitor Adı değiştirir
ClassWriter Metin üretir
visitEnd Geziyi kapatır

Uzman bölümündeki tüm dersler